Skip to content

Commit

Permalink
Merge pull request #7 from Gml-Launcher/develop
Browse files Browse the repository at this point in the history
Update to v1.0.3
  • Loading branch information
GamerVII-NET authored Dec 28, 2024
2 parents 7713028 + 6fd551d commit 0722296
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 50 deletions.
1 change: 1 addition & 0 deletions Gml.Web.Skin.Service.sln
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{3E651A
Dockerfile = Dockerfile
.dockerignore = .dockerignore
.gitignore = .gitignore
compose.yaml = compose.yaml
EndProjectSection
EndProject
Global
Expand Down
16 changes: 16 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
services:
gml.web.skin.service:
image: gml.web.skin.service
container_name: gml-web-skins
build:
context: src/Gml.Web.Skin.Service
dockerfile: Dockerfile
ports:
- 5000:8085
restart: always
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://+:8085;
user: "${UID}:${GID}"
volumes:
- ./data/TextureService:/app/Storage
Binary file added data/TextureService/Skins/default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ private static WebApplication AddRoutes(this WebApplication app)
app.MapGet("/{userName}", TextureRequests.GetUserTexture);

app.MapPost("/skin/{userName}", TextureRequests.LoadSkin).DisableAntiforgery();
app.MapDelete("/skin/{userName}", TextureRequests.DeleteSkin);
app.MapGet("/skin/{userName}/{uuid?}", TextureRequests.GetSkin);
app.MapGet("/skin/{userName}/head/{size}", TextureRequests.GetSkinHead);
app.MapGet("/skin/{userName}/front/{size}", TextureRequests.GetSkinFront);
Expand All @@ -66,6 +67,7 @@ private static WebApplication AddRoutes(this WebApplication app)

app.MapGet("/cloak/{userName}", TextureRequests.GetCloakTexture);
app.MapPost("/cloak/{userName}", TextureRequests.LoadCloak).DisableAntiforgery();;
app.MapDelete("/cloak/{userName}", TextureRequests.DeleteCloak);
app.MapGet("/cloak/{userName}/front/{size}", TextureRequests.GetCloak);

app.MapGet("/refresh/{userName}", TextureRequests.RefreshCache);
Expand Down
25 changes: 25 additions & 0 deletions src/Gml.Web.Skin.Service/Core/Requests/TextureRequests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ internal static async Task<IResult> LoadSkin(HttpRequest request, [FromForm] IFo

return Results.Ok(mapper.Map<UserTextureReadDto>(texture));
}
internal static async Task<IResult> DeleteSkin(HttpRequest request, IMapper mapper,
string userName)
{

var filePath = Path.Combine(SkinHelper.SkinTextureDirectory, $"{userName}.png");

if (!File.Exists(filePath))
return Results.NotFound();

File.Delete(filePath);
return Results.Ok();

}

internal static async Task<IResult> LoadCloak(HttpRequest request, [FromForm] IFormFile file, IMapper mapper,
string userName)
Expand All @@ -41,6 +54,18 @@ internal static async Task<IResult> LoadCloak(HttpRequest request, [FromForm] IF
return Results.Ok(mapper.Map<UserTextureReadDto>(texture));
}

internal static async Task<IResult> DeleteCloak(HttpRequest request, IMapper mapper,
string userName)
{
var filePath = Path.Combine(SkinHelper.CloakTextureDirectory, $"{userName}.png");

if (!File.Exists(filePath))
return Results.NotFound();

File.Delete(filePath);
return Results.Ok();
}

internal static Task<IResult> GetSkin(HttpRequest request, string userName, string? uuid)
{
var user = SkinHelper.Create($"http://{request.Host.Value}", userName.Substring(2, userName.Length - 2));
Expand Down
130 changes: 81 additions & 49 deletions src/Gml.Web.Skin.Service/Core/SkinViewer/SkinViewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ public abstract class SkinViewer
{
public static byte[] GetHead(string skinPath, UserTexture userTexture, int size)
{
if (!File.Exists(skinPath))
{
return [];
}

using var inputImage = Image.Load(skinPath);

var scaleFactor = inputImage.Width / 64;
Expand Down Expand Up @@ -44,104 +49,124 @@ public static byte[] GetFront(string skinPath, UserTexture user, int size)
using var inputImage = Image.Load(skinPath);

var scaleFactor = inputImage.Width / 64;
var extendedSkin = inputImage.Height / scaleFactor >= 64;

var croppedHead = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(8 * scaleFactor, 8 * scaleFactor, 8 * scaleFactor, 8 * scaleFactor)));

var croppedBody = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(20 * scaleFactor, 20 * scaleFactor, 8 * scaleFactor, 12 * scaleFactor)));

var croppedLeg = inputImage.Clone(ctx =>
var leftCroppedLeg = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(4 * scaleFactor, 20 * scaleFactor, 4 * scaleFactor, 12 * scaleFactor)));

var croppedArm = inputImage.Clone(ctx =>
var leftCroppedArm = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(44 * scaleFactor, 20 * scaleFactor, 4 * scaleFactor, 12 * scaleFactor)));

var newWidth = croppedArm.Width * 2 + croppedBody.Width;
var newHeight = croppedHead.Height + croppedBody.Height + croppedArm.Height;

var rightCroppedLeg = extendedSkin
? inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(20 * scaleFactor, 52 * scaleFactor, 4 * scaleFactor, 12 * scaleFactor)))
: leftCroppedLeg.Clone(x => x.Flip(FlipMode.Horizontal));

var rightCroppedArm = extendedSkin
? inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(36 * scaleFactor, 52 * scaleFactor, 4 * scaleFactor, 12 * scaleFactor)))
: leftCroppedArm.Clone(x => x.Flip(FlipMode.Horizontal));

var secondLayerHead = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(40 * scaleFactor, 8 * scaleFactor, 8 * scaleFactor, 8 * scaleFactor)));

// var secondLayerArm = inputImage.Clone(ctx =>
// ctx.Crop(new Rectangle(44 * scaleFactor, 52 * scaleFactor, 4 * scaleFactor, 12 * scaleFactor)));

var newWidth = leftCroppedArm.Width * 2 + croppedBody.Width;
var newHeight = croppedHead.Height + croppedBody.Height + leftCroppedArm.Height;

var combinedImage = new Image<Rgba32>(newWidth, newHeight);

combinedImage.Mutate(context =>
{
var headPosition = new Rectangle(croppedArm.Width, 0, croppedHead.Width, croppedHead.Height);
var headPosition = new Rectangle(leftCroppedArm.Width, 0, croppedHead.Width, croppedHead.Height);
var bodyPosition = new Rectangle(headPosition.X, croppedHead.Height, croppedBody.Width, croppedBody.Height);

var leftArmPosition = new Rectangle(0, bodyPosition.Y, croppedArm.Width, croppedArm.Height);
var leftArmPosition = new Rectangle(0, bodyPosition.Y, leftCroppedArm.Width, leftCroppedArm.Height);
var rightArmPosition = new Rectangle(leftArmPosition.Width + bodyPosition.Width, leftArmPosition.Y,
leftArmPosition.Width, leftArmPosition.Height);

var leftLegPosition = new Rectangle(leftArmPosition.Width, headPosition.Height + bodyPosition.Height,
croppedLeg.Width, croppedLeg.Height);
leftCroppedLeg.Width, leftCroppedLeg.Height);
var rightLegPosition = new Rectangle(leftArmPosition.Width + leftLegPosition.Width,
headPosition.Height + bodyPosition.Height, leftLegPosition.Width, leftLegPosition.Height);

context.DrawImage(croppedHead, new Point(headPosition.X, headPosition.Y), 1f);
context.DrawImage(croppedBody, new Point(bodyPosition.X, bodyPosition.Y), 1f);
context.DrawImage(croppedArm, new Point(leftArmPosition.X, leftArmPosition.Y), 1f);
context.DrawImage(croppedArm, new Point(rightArmPosition.X, rightArmPosition.Y), 1f);
context.DrawImage(croppedLeg, new Point(leftLegPosition.X, leftLegPosition.Y), 1f);
context.DrawImage(croppedLeg, new Point(rightLegPosition.X, rightLegPosition.Y), 1f);
context.DrawImage(leftCroppedArm, new Point(leftArmPosition.X, leftArmPosition.Y), 1f);
context.DrawImage(rightCroppedArm, new Point(rightArmPosition.X, rightArmPosition.Y), 1f);
context.DrawImage(leftCroppedLeg, new Point(leftLegPosition.X, leftLegPosition.Y), 1f);
context.DrawImage(rightCroppedLeg, new Point(rightLegPosition.X, rightLegPosition.Y), 1f);

// context.DrawImage(croppedArm, new Point(0, 8 * scaleFactor), 1f);
// context.DrawImage(croppedLeg, new Point(200, 200), 1f);
context.DrawImage(secondLayerHead, new Point(headPosition.X, headPosition.Y), 1f);
});

using var memoryStream = new MemoryStream();
if (inputImage.Metadata.DecodedImageFormat != null)
combinedImage.Save(memoryStream, inputImage.Metadata.DecodedImageFormat);
else
combinedImage.Save(memoryStream, new PngEncoder());

// var image = ResizeImage(size, inputImage, combinedImage);

if (size != combinedImage.Width)
{
var scaleSize = GetScaleSize(size, combinedImage.Width);

if (scaleSize != 0)
combinedImage = combinedImage.Clone(ctx => ctx.Resize(combinedImage.Width * scaleSize,
combinedImage.Height * scaleSize, KnownResamplers.Box));
}

using var resizeMemoryStream = new MemoryStream();

if (inputImage.Metadata.DecodedImageFormat != null)
combinedImage.Save(resizeMemoryStream, inputImage.Metadata.DecodedImageFormat);
else
combinedImage.Save(resizeMemoryStream, new PngEncoder());

return resizeMemoryStream.ToArray();
using var memoryStream = new MemoryStream();
combinedImage.Save(memoryStream, new PngEncoder());
return memoryStream.ToArray();
}

public static byte[] GetBack(UserTexture user, int size, bool includeCloak = false)
{
using var inputImage = Image.Load(user.SkinFullPath);
using var cloakImage = includeCloak && user.HasCloak ? Image.Load(user.CloakFullPath) : null;

var scaleFactor = inputImage.Width / 64;

var skinScaleFactor = inputImage.Width / 64;
var cloakScaleFactor = cloakImage?.Width >= 64 ? cloakImage.Width / 64 : 1;
var needSkinResizeToCloakSize = cloakScaleFactor > skinScaleFactor;
var extendedSkin = inputImage.Height / skinScaleFactor >= 64;

var croppedHead = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(24 * scaleFactor, 8 * scaleFactor, 8 * scaleFactor, 8 * scaleFactor)));
ctx.Crop(new Rectangle(24 * skinScaleFactor, 8 * skinScaleFactor, 8 * skinScaleFactor, 8 * skinScaleFactor)));

var croppedBody = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(32 * scaleFactor, 20 * scaleFactor, 8 * scaleFactor, 12 * scaleFactor)));

var croppedLeftLeg = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(12 * scaleFactor, 20 * scaleFactor, 4 * scaleFactor, 12 * scaleFactor)));

var croppedRightLeg = croppedLeftLeg.Clone(x => x.Flip(FlipMode.Horizontal));

var croppedLeftArm = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(52 * scaleFactor, 20 * scaleFactor, 4 * scaleFactor, 12 * scaleFactor)));

var croppedRightArm = croppedLeftArm.Clone(x => x.Flip(FlipMode.Horizontal));
ctx.Crop(new Rectangle(32 * skinScaleFactor, 20 * skinScaleFactor, 8 * skinScaleFactor, 12 * skinScaleFactor)));

var croppedRightLeg = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(12 * skinScaleFactor, 20 * skinScaleFactor, 4 * skinScaleFactor, 12 * skinScaleFactor)));

var croppedRightArm = inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(52 * skinScaleFactor, 20 * skinScaleFactor, 4 * skinScaleFactor, 12 * skinScaleFactor)));

var croppedLeftLeg = extendedSkin
? inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(28 * skinScaleFactor, 52 * skinScaleFactor, 4 * skinScaleFactor, 12 * skinScaleFactor)))
: croppedRightLeg.Clone(x => x.Flip(FlipMode.Horizontal));

var croppedLeftArm = extendedSkin
? inputImage.Clone(ctx =>
ctx.Crop(new Rectangle(44 * skinScaleFactor, 52 * skinScaleFactor, 4 * skinScaleFactor, 12 * skinScaleFactor)))
: croppedRightArm.Clone(x => x.Flip(FlipMode.Horizontal));

// var croppedRightArm = croppedLeftArm.Clone(x => x.Flip(FlipMode.Horizontal));

if (needSkinResizeToCloakSize)
{
croppedHead = ResizeImage(croppedHead, cloakScaleFactor);
croppedBody = ResizeImage(croppedBody, cloakScaleFactor);
croppedLeftLeg = ResizeImage(croppedLeftLeg, cloakScaleFactor);
croppedRightLeg = ResizeImage(croppedRightLeg, cloakScaleFactor);
croppedLeftArm = ResizeImage(croppedLeftArm, cloakScaleFactor);
croppedRightArm = ResizeImage(croppedRightArm, cloakScaleFactor);
}

Image croppedCloak = null;

if (includeCloak && cloakImage != null)
croppedCloak = cloakImage.Clone(ctx =>
ctx.Crop(new Rectangle(0, 0, 11, 17)))
ctx.Crop(new Rectangle(0, 0, 11 * cloakScaleFactor, 17 * cloakScaleFactor)))
.Clone(ctx => ctx.Resize(croppedBody.Width, croppedBody.Height, KnownResamplers.Box));

var newWidth = croppedLeftArm.Width * 2 + croppedBody.Width;
Expand Down Expand Up @@ -206,6 +231,13 @@ public static byte[] GetBack(UserTexture user, int size, bool includeCloak = fal
return resizeMemoryStream.ToArray();
}

private static Image ResizeImage(Image croppedHead, int cloakScaleFactor)
{
var newSize = croppedHead.Size;
croppedHead = croppedHead.Clone(ctx => ctx.Resize(newSize.Width * cloakScaleFactor, newSize.Height * cloakScaleFactor, KnownResamplers.Box));
return croppedHead;
}


private static MemoryStream ResizeImage(int size, Image inputImage, Image croppedImage)
{
Expand Down
23 changes: 23 additions & 0 deletions src/Gml.Web.Skin.Service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER $APP_UID
WORKDIR /app
EXPOSE 8080
EXPOSE 8081

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["src/Gml.Web.Skin.Service/Gml.Web.Skin.Service.csproj", "src/Gml.Web.Skin.Service/"]
RUN dotnet restore "src/Gml.Web.Skin.Service/Gml.Web.Skin.Service.csproj"
COPY . .
WORKDIR "/src/src/Gml.Web.Skin.Service"
RUN dotnet build "Gml.Web.Skin.Service.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "Gml.Web.Skin.Service.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Gml.Web.Skin.Service.dll"]
3 changes: 3 additions & 0 deletions src/Gml.Web.Skin.Service/Gml.Web.Skin.Service.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
<Content Update="appsettings.Development.json">
<DependentUpon>appsettings.json</DependentUpon>
</Content>
<Content Include="..\..\.dockerignore">
<Link>.dockerignore</Link>
</Content>
</ItemGroup>


Expand Down
2 changes: 1 addition & 1 deletion src/Gml.Web.Skin.Service/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"launchBrowser": false,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
Expand Down
Binary file removed src/Gml.Web.Skin.Service/Storage/Cloak/GamerVII.png
Binary file not shown.
Binary file removed src/Gml.Web.Skin.Service/Storage/Skins/GamerVII.png
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0722296

Please sign in to comment.