From 6338b5fb8bd150ee15c84ddbe4925de61504b552 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop Date: Wed, 18 Sep 2024 21:23:42 +0000 Subject: [PATCH 01/21] Apply automatic changes --- .../lib/cape/client/api/ClientCapeUtil.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/net/frozenblock/lib/cape/client/api/ClientCapeUtil.java b/src/main/java/net/frozenblock/lib/cape/client/api/ClientCapeUtil.java index 41bc86dda..b54c64b40 100644 --- a/src/main/java/net/frozenblock/lib/cape/client/api/ClientCapeUtil.java +++ b/src/main/java/net/frozenblock/lib/cape/client/api/ClientCapeUtil.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2024 FrozenBlock + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package net.frozenblock.lib.cape.client.api; import com.google.gson.JsonIOException; From 13d2bc909342d78be9e0ea45dd54113c516f16c2 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:37:02 -0400 Subject: [PATCH 02/21] use cape names from repo --- .../frozenblock/lib/cape/api/CapeUtil.java | 18 ++++++++++-------- .../lib/cape/client/impl/ClientCapeData.java | 19 ++++++++----------- .../net/frozenblock/lib/cape/impl/Cape.java | 3 ++- .../gui/FrozenLibConfigGui.java | 14 +++++++++----- .../lib/registry/api/FrozenRegistry.java | 3 ++- .../assets/frozenlib/lang/en_us.json | 6 ++---- 6 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java index 3037838e4..3ca0ef801 100644 --- a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java +++ b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java @@ -39,6 +39,7 @@ import net.frozenblock.lib.cape.impl.Cape; import net.frozenblock.lib.registry.api.FrozenRegistry; import net.minecraft.core.Registry; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; @@ -61,16 +62,16 @@ public static boolean canPlayerUserCape(UUID uuid, @NotNull Cape cape) { return cape.allowedPlayers().map(uuids -> uuids.contains(uuid)).orElse(true); } - public static @NotNull Cape registerCape(ResourceLocation id) { - return Registry.register(FrozenRegistry.CAPE, id, new Cape(id, buildCapeTextureLocation(id), Optional.empty())); + public static @NotNull Cape registerCape(ResourceLocation id, Component capeName) { + return Registry.register(FrozenRegistry.CAPE, id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.empty())); } - public static @NotNull Cape registerCapeWithWhitelist(ResourceLocation id, List allowedPlayers) { - return Registry.register(FrozenRegistry.CAPE, id, new Cape(id, buildCapeTextureLocation(id), Optional.of(allowedPlayers))); + public static @NotNull Cape registerCapeWithWhitelist(ResourceLocation id, Component capeName, List allowedPlayers) { + return Registry.register(FrozenRegistry.CAPE, id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.of(allowedPlayers))); } - public static @NotNull Cape registerCapeWithWhitelist(ResourceLocation id, UUID... uuids) { - return Registry.register(FrozenRegistry.CAPE, id, new Cape(id, buildCapeTextureLocation(id), Optional.of(ImmutableList.copyOf(uuids)))); + public static @NotNull Cape registerCapeWithWhitelist(ResourceLocation id, Component capeName, UUID... uuids) { + return Registry.register(FrozenRegistry.CAPE, id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.of(ImmutableList.copyOf(uuids)))); } public static void registerCapesFromURL(String urlString) { @@ -98,6 +99,7 @@ private static void registerCapeFromURL(String urlString) { JsonElement parsedJson = JsonParser.parseReader(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element JsonObject capeJson = parsedJson.getAsJsonObject(); String capeId = capeJson.get("id").getAsString(); + Component capeName = Component.literal(capeJson.get("name").getAsString()); String capeTexture = capeJson.get("texture").getAsString(); JsonArray allowedUUIDs = capeJson.get("allowed_uuids").getAsJsonArray(); @@ -110,11 +112,11 @@ private static void registerCapeFromURL(String urlString) { List allowedUUIDList = allowedUUIDs.asList(); if (allowedUUIDList.isEmpty()) { - registerCape(capeLocation); + registerCape(capeLocation, capeName); } else { List uuidList = new ArrayList<>(); allowedUUIDList.forEach(jsonElement -> uuidList.add(UUID.fromString(jsonElement.getAsString()))); - registerCapeWithWhitelist(capeLocation, ImmutableList.copyOf(uuidList)); + registerCapeWithWhitelist(capeLocation, capeName, ImmutableList.copyOf(uuidList)); } } } catch (IOException ignored) { diff --git a/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java b/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java index 3a1ad2212..6af6ef3b2 100644 --- a/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java +++ b/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java @@ -38,10 +38,10 @@ @Environment(EnvType.CLIENT) public class ClientCapeData { - private static final Map CAPES_IN_SERVER = new HashMap<>(); + private static final Map CAPES_IN_WORLD = new HashMap<>(); public static Optional getCapeTexture(UUID uuid) { - return Optional.ofNullable(CAPES_IN_SERVER.get(uuid)).map(Cape::texture); + return Optional.ofNullable(CAPES_IN_WORLD.get(uuid)).map(Cape::texture); } public static void setCapeForUUID(UUID uuid, ResourceLocation capeId) { @@ -49,13 +49,13 @@ public static void setCapeForUUID(UUID uuid, ResourceLocation capeId) { if (cape == null) { removeCapeForUUID(uuid); } else { - CAPES_IN_SERVER.put(uuid, cape); + CAPES_IN_WORLD.put(uuid, cape); setPlayerCapeTexture(uuid, Optional.of(cape)); } } public static void removeCapeForUUID(UUID uuid) { - CAPES_IN_SERVER.remove(uuid); + CAPES_IN_WORLD.remove(uuid); setPlayerCapeTexture(uuid, Optional.empty()); } @@ -67,13 +67,10 @@ private static void setPlayerCapeTexture(UUID uuid, @NotNull Optional cape } public static void init() { - ClientLifecycleEvents.CLIENT_STOPPING.register(client -> { - CAPES_IN_SERVER.clear(); - }); - ClientPlayConnectionEvents.DISCONNECT.register((clientPacketListener, minecraft) -> CAPES_IN_SERVER.clear()); - ClientPlayConnectionEvents.JOIN.register((clientPacketListener, packetSender, minecraft) -> { - ClientPlayNetworking.send(CapeCustomizePacket.createPacket(minecraft.getUser().getProfileId(), ResourceLocation.parse(FrozenLibConfig.get().cape))); - }); + ClientLifecycleEvents.CLIENT_STOPPING.register(client -> CAPES_IN_WORLD.clear()); + ClientPlayConnectionEvents.DISCONNECT.register((clientPacketListener, minecraft) -> CAPES_IN_WORLD.clear()); + ClientPlayConnectionEvents.JOIN.register((clientPacketListener, packetSender, minecraft) -> + ClientPlayNetworking.send(CapeCustomizePacket.createPacket(minecraft.getUser().getProfileId(), ResourceLocation.parse(FrozenLibConfig.get().cape)))); ClientEntityEvents.ENTITY_LOAD.register((entity, clientLevel) -> { if (entity instanceof AbstractClientPlayerCapeInterface capeInterface) { getCapeTexture(entity.getUUID()).ifPresent(capeInterface::frozenLib$setCape); diff --git a/src/main/java/net/frozenblock/lib/cape/impl/Cape.java b/src/main/java/net/frozenblock/lib/cape/impl/Cape.java index e9d7a7a99..fc12b19b6 100644 --- a/src/main/java/net/frozenblock/lib/cape/impl/Cape.java +++ b/src/main/java/net/frozenblock/lib/cape/impl/Cape.java @@ -20,7 +20,8 @@ import java.util.List; import java.util.Optional; import java.util.UUID; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; -public record Cape(ResourceLocation registryId, ResourceLocation texture, Optional> allowedPlayers) { +public record Cape(ResourceLocation registryId, Component capeName, ResourceLocation texture, Optional> allowedPlayers) { } diff --git a/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java b/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java index fa14acddc..3b5a0a5a0 100644 --- a/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java +++ b/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java @@ -29,10 +29,12 @@ import net.fabricmc.loader.api.FabricLoader; import net.frozenblock.lib.FrozenSharedConstants; import net.frozenblock.lib.cape.api.CapeUtil; +import net.frozenblock.lib.cape.impl.Cape; import net.frozenblock.lib.cape.impl.networking.CapeCustomizePacket; import net.frozenblock.lib.config.api.instance.Config; import net.frozenblock.lib.config.clothconfig.FrozenClothConfig; import net.frozenblock.lib.config.frozenlib_config.FrozenLibConfig; +import net.frozenblock.lib.registry.api.FrozenRegistry; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; @@ -137,17 +139,19 @@ private static void setupEntries(@NotNull ConfigCategory category, @NotNull Conf UUID playerUUID = Minecraft.getInstance().getUser().getProfileId(); List usableCapes = new ArrayList<>(); - CapeUtil.getUsableCapes(playerUUID).forEach(cape -> { - usableCapes.add(cape.registryId().toString()); - }); - if (!usableCapes.isEmpty()) { + CapeUtil.getUsableCapes(playerUUID).forEach(cape -> usableCapes.add(cape.registryId().toString())); + if (!usableCapes.isEmpty() && usableCapes.size() > 1) { var capeEntry = category.addEntry( FrozenClothConfig.syncedEntry( entryBuilder.startSelector(text("cape"), usableCapes.toArray(), modifiedConfig.cape) .setDefaultValue(defaultConfig.cape) .setNameProvider(o -> { ResourceLocation capeId = ResourceLocation.parse(((String) o)); - return Component.translatable("cape." + capeId.getNamespace() + "." + capeId.getPath()); + Cape cape = FrozenRegistry.CAPE.get(capeId); + if (cape != null) { + return cape.capeName(); + } + return Component.translatable("cape.frozenlib.invalid"); }) .setSaveConsumer(newValue -> { ResourceLocation capeId = ResourceLocation.parse((String) newValue); diff --git a/src/main/java/net/frozenblock/lib/registry/api/FrozenRegistry.java b/src/main/java/net/frozenblock/lib/registry/api/FrozenRegistry.java index 19347e23d..2136fbb63 100644 --- a/src/main/java/net/frozenblock/lib/registry/api/FrozenRegistry.java +++ b/src/main/java/net/frozenblock/lib/registry/api/FrozenRegistry.java @@ -34,6 +34,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.registries.VanillaRegistries; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import org.jetbrains.annotations.NotNull; @@ -77,7 +78,7 @@ public void init() {} ); public static final MappedRegistry CAPE = createSimple(CAPE_REGISTRY, Lifecycle.stable(), null, - registry -> Registry.register(registry, FrozenSharedConstants.id("dummy"), new Cape(FrozenSharedConstants.id("dummy"), null, Optional.empty())) + registry -> Registry.register(registry, FrozenSharedConstants.id("dummy"), new Cape(FrozenSharedConstants.id("dummy"), Component.translatable("cape.frozenlib.dummy"), null, Optional.empty())) ); diff --git a/src/main/resources/assets/frozenlib/lang/en_us.json b/src/main/resources/assets/frozenlib/lang/en_us.json index 8ed306edf..2a5c29b6f 100644 --- a/src/main/resources/assets/frozenlib/lang/en_us.json +++ b/src/main/resources/assets/frozenlib/lang/en_us.json @@ -46,12 +46,10 @@ "tooltip.frozenlib.warden_spawn_tracker_command": "Enables or disables the Warden Spawn Tracker command.", "option.frozenlib.cape": "Cape", - "tooltip.frozenlib.cape": "Custom FrozenBlock capes that can be used.", + "tooltip.frozenlib.cape": "A list of capes added through FrozenLib.\nClick to select the next cape.", - "cape.frozenlib.none": "§cMissing value!", + "cape.frozenlib.invalid": "§cINVALID", "cape.frozenlib.dummy": "§cNone", - "cape.frozenlib.frozenblock": "FrozenBlock", - "cape.frozenlib.very_blue_cape": "Very Blue Cape", "commands.wind.display.global.success": "The global wind is currently: %s, %s, %s.", "commands.wind.display.pos.success": "The wind at %s, %s, %s currently: %s, %s, %s.", From 74458e7940fa11e844f37d72c425d91c3d551b18 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:07:37 -0400 Subject: [PATCH 03/21] Send server's cape repos to the client upon join --- .../frozenblock/lib/cape/api/CapeUtil.java | 39 +++++++++------ .../lib/cape/client/impl/ClientCapeData.java | 10 +--- .../lib/cape/impl/ServerCapeData.java | 2 + .../impl/networking/CapeCustomizePacket.java | 4 +- .../impl/networking/LoadCapeRepoPacket.java | 48 +++++++++++++++++++ .../gui/FrozenLibConfigGui.java | 9 +--- .../networking/FrozenClientNetworking.java | 9 ++++ .../lib/networking/FrozenNetworking.java | 2 + .../lib/registry/api/FrozenRegistry.java | 9 ---- 9 files changed, 92 insertions(+), 40 deletions(-) create mode 100644 src/main/java/net/frozenblock/lib/cape/impl/networking/LoadCapeRepoPacket.java diff --git a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java index 3ca0ef801..0d18cc5f0 100644 --- a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java +++ b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java @@ -29,7 +29,10 @@ import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.UUID; import net.fabricmc.api.EnvType; @@ -37,24 +40,33 @@ import net.frozenblock.lib.FrozenSharedConstants; import net.frozenblock.lib.cape.client.api.ClientCapeUtil; import net.frozenblock.lib.cape.impl.Cape; -import net.frozenblock.lib.registry.api.FrozenRegistry; -import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; public class CapeUtil { - public static @NotNull @Unmodifiable List getCapes() { - return ImmutableList.copyOf(FrozenRegistry.CAPE); + private static final Map CAPES = new HashMap<>(); + private static final List CAPE_REPOS = new ArrayList<>(); + + public static @NotNull @Unmodifiable List getCapeRepos() { + return ImmutableList.copyOf(CAPE_REPOS); + } + + public static @NotNull @Unmodifiable Collection getCapes() { + return CAPES.values(); } public static @NotNull @Unmodifiable List getUsableCapes(UUID uuid) { return ImmutableList.copyOf(getCapes().stream().filter(cape -> canPlayerUserCape(uuid, cape)).toList()); } + public static Optional getCape(ResourceLocation location) { + return Optional.ofNullable(CAPES.get(location)); + } + public static boolean canPlayerUserCape(UUID uuid, ResourceLocation capeID) { - Optional optionalCape = FrozenRegistry.CAPE.getOptional(capeID); + Optional optionalCape = CapeUtil.getCape(capeID); return optionalCape.map(cape -> canPlayerUserCape(uuid, cape)).orElse(false); } @@ -62,16 +74,16 @@ public static boolean canPlayerUserCape(UUID uuid, @NotNull Cape cape) { return cape.allowedPlayers().map(uuids -> uuids.contains(uuid)).orElse(true); } - public static @NotNull Cape registerCape(ResourceLocation id, Component capeName) { - return Registry.register(FrozenRegistry.CAPE, id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.empty())); + public static void registerCape(ResourceLocation id, Component capeName) { + CAPES.put(id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.empty())); } - public static @NotNull Cape registerCapeWithWhitelist(ResourceLocation id, Component capeName, List allowedPlayers) { - return Registry.register(FrozenRegistry.CAPE, id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.of(allowedPlayers))); + public static void registerCapeWithWhitelist(ResourceLocation id, Component capeName, List allowedPlayers) { + CAPES.put(id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.of(allowedPlayers))); } - public static @NotNull Cape registerCapeWithWhitelist(ResourceLocation id, Component capeName, UUID... uuids) { - return Registry.register(FrozenRegistry.CAPE, id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.of(ImmutableList.copyOf(uuids)))); + public static void registerCapeWithWhitelist(ResourceLocation id, Component capeName, UUID... uuids) { + CAPES.put(id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.of(ImmutableList.copyOf(uuids)))); } public static void registerCapesFromURL(String urlString) { @@ -84,9 +96,8 @@ public static void registerCapesFromURL(String urlString) { JsonObject capeDir = parsedJson.getAsJsonObject(); JsonArray capeArray = capeDir.get("capes").getAsJsonArray(); - capeArray.forEach(jsonElement -> { - registerCapeFromURL(jsonElement.getAsString()); - }); + capeArray.forEach(jsonElement -> registerCapeFromURL(jsonElement.getAsString())); + CAPE_REPOS.add(urlString); } catch (IOException ignored) {} } diff --git a/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java b/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java index 6af6ef3b2..820d669ee 100644 --- a/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java +++ b/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java @@ -27,10 +27,10 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.frozenblock.lib.cape.api.CapeUtil; import net.frozenblock.lib.cape.impl.Cape; import net.frozenblock.lib.cape.impl.networking.CapeCustomizePacket; import net.frozenblock.lib.config.frozenlib_config.FrozenLibConfig; -import net.frozenblock.lib.registry.api.FrozenRegistry; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.resources.ResourceLocation; @@ -45,13 +45,7 @@ public static Optional getCapeTexture(UUID uuid) { } public static void setCapeForUUID(UUID uuid, ResourceLocation capeId) { - Cape cape = FrozenRegistry.CAPE.get(capeId); - if (cape == null) { - removeCapeForUUID(uuid); - } else { - CAPES_IN_WORLD.put(uuid, cape); - setPlayerCapeTexture(uuid, Optional.of(cape)); - } + CapeUtil.getCape(capeId).ifPresentOrElse(cape -> CAPES_IN_WORLD.put(uuid, cape), () -> removeCapeForUUID(uuid)); } public static void removeCapeForUUID(UUID uuid) { diff --git a/src/main/java/net/frozenblock/lib/cape/impl/ServerCapeData.java b/src/main/java/net/frozenblock/lib/cape/impl/ServerCapeData.java index 7c87a3f80..76ba2368f 100644 --- a/src/main/java/net/frozenblock/lib/cape/impl/ServerCapeData.java +++ b/src/main/java/net/frozenblock/lib/cape/impl/ServerCapeData.java @@ -28,6 +28,7 @@ import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.frozenblock.lib.cape.api.CapeUtil; import net.frozenblock.lib.cape.impl.networking.CapeCustomizePacket; +import net.frozenblock.lib.cape.impl.networking.LoadCapeRepoPacket; import net.minecraft.server.level.ServerPlayer; public class ServerCapeData { @@ -35,6 +36,7 @@ public class ServerCapeData { public static void sendAllCapesToPlayer(ServerPlayer recipent) { CAPES_IN_SERVER.forEach((uuid, cape) -> ServerPlayNetworking.send(recipent, CapeCustomizePacket.createPacket(uuid, cape))); + CapeUtil.getCapeRepos().forEach(repoURL -> ServerPlayNetworking.send(recipent, new LoadCapeRepoPacket(repoURL))); } public static void init() { diff --git a/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java b/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java index ce324264d..4f27da774 100644 --- a/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java +++ b/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java @@ -21,8 +21,8 @@ import net.fabricmc.fabric.api.networking.v1.PlayerLookup; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.frozenblock.lib.FrozenSharedConstants; +import net.frozenblock.lib.cape.api.CapeUtil; import net.frozenblock.lib.cape.impl.Cape; -import net.frozenblock.lib.registry.api.FrozenRegistry; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; @@ -71,7 +71,7 @@ public void write(@NotNull FriendlyByteBuf buf) { } public static @NotNull CapeCustomizePacket createPacket(UUID uuid, @Nullable ResourceLocation capeId) { - return new CapeCustomizePacket(uuid, !shouldDisable(FrozenRegistry.CAPE.get(capeId)), capeId); + return new CapeCustomizePacket(uuid, !shouldDisable(CapeUtil.getCape(capeId).orElse(null)), capeId); } @Contract("_, _ -> new") diff --git a/src/main/java/net/frozenblock/lib/cape/impl/networking/LoadCapeRepoPacket.java b/src/main/java/net/frozenblock/lib/cape/impl/networking/LoadCapeRepoPacket.java new file mode 100644 index 000000000..fa3cc169b --- /dev/null +++ b/src/main/java/net/frozenblock/lib/cape/impl/networking/LoadCapeRepoPacket.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 FrozenBlock + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.frozenblock.lib.cape.impl.networking; + +import net.frozenblock.lib.FrozenSharedConstants; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public record LoadCapeRepoPacket(String capeRepo) implements CustomPacketPayload { + public static final Type PACKET_TYPE = new Type<>( + FrozenSharedConstants.id("load_cape_repo") + ); + public static final StreamCodec STREAM_CODEC = StreamCodec.ofMember(LoadCapeRepoPacket::write, LoadCapeRepoPacket::create); + + @Contract("_ -> new") + public static @NotNull LoadCapeRepoPacket create(@NotNull FriendlyByteBuf buf) { + return new LoadCapeRepoPacket(buf.readUtf()); + } + + public void write(@NotNull FriendlyByteBuf buf) { + buf.writeUtf(this.capeRepo()); + } + + @Override + @NotNull + public Type type() { + return PACKET_TYPE; + } +} + diff --git a/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java b/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java index 3b5a0a5a0..23f5aff37 100644 --- a/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java +++ b/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java @@ -34,7 +34,6 @@ import net.frozenblock.lib.config.api.instance.Config; import net.frozenblock.lib.config.clothconfig.FrozenClothConfig; import net.frozenblock.lib.config.frozenlib_config.FrozenLibConfig; -import net.frozenblock.lib.registry.api.FrozenRegistry; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; @@ -140,18 +139,14 @@ private static void setupEntries(@NotNull ConfigCategory category, @NotNull Conf UUID playerUUID = Minecraft.getInstance().getUser().getProfileId(); List usableCapes = new ArrayList<>(); CapeUtil.getUsableCapes(playerUUID).forEach(cape -> usableCapes.add(cape.registryId().toString())); - if (!usableCapes.isEmpty() && usableCapes.size() > 1) { + if (usableCapes.size() > 1) { var capeEntry = category.addEntry( FrozenClothConfig.syncedEntry( entryBuilder.startSelector(text("cape"), usableCapes.toArray(), modifiedConfig.cape) .setDefaultValue(defaultConfig.cape) .setNameProvider(o -> { ResourceLocation capeId = ResourceLocation.parse(((String) o)); - Cape cape = FrozenRegistry.CAPE.get(capeId); - if (cape != null) { - return cape.capeName(); - } - return Component.translatable("cape.frozenlib.invalid"); + return CapeUtil.getCape(capeId).map(Cape::capeName).orElse(Component.translatable("cape.frozenlib.invalid")); }) .setSaveConsumer(newValue -> { ResourceLocation capeId = ResourceLocation.parse((String) newValue); diff --git a/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java b/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java index 3b0be5664..54d3eaf05 100644 --- a/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java +++ b/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java @@ -24,8 +24,10 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; +import net.frozenblock.lib.cape.api.CapeUtil; import net.frozenblock.lib.cape.client.impl.ClientCapeData; import net.frozenblock.lib.cape.impl.networking.CapeCustomizePacket; +import net.frozenblock.lib.cape.impl.networking.LoadCapeRepoPacket; import net.frozenblock.lib.config.api.instance.Config; import net.frozenblock.lib.config.api.registry.ConfigRegistry; import net.frozenblock.lib.config.impl.network.ConfigSyncPacket; @@ -104,6 +106,7 @@ public static void registerClientReceivers() { receiveWindSyncPacket(); receiveWindDisturbancePacket(); receiveCapePacket(); + receiveCapeRepoPacket(); ClientPlayNetworking.registerGlobalReceiver(ConfigSyncPacket.PACKET_TYPE, (packet, ctx) -> ConfigSyncPacket.receive(packet, null) ); @@ -339,6 +342,12 @@ private static void receiveCapePacket() { }); } + private static void receiveCapeRepoPacket() { + ClientPlayNetworking.registerGlobalReceiver(LoadCapeRepoPacket.PACKET_TYPE, (packet, ctx) -> { + CapeUtil.registerCapesFromURL(packet.capeRepo()); + }); + } + public static boolean notConnected() { Minecraft minecraft = Minecraft.getInstance(); ClientPacketListener listener = minecraft.getConnection(); diff --git a/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java b/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java index 8575e197c..a2c676a9e 100644 --- a/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java +++ b/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java @@ -26,6 +26,7 @@ import net.frozenblock.lib.cape.api.CapeUtil; import net.frozenblock.lib.cape.impl.ServerCapeData; import net.frozenblock.lib.cape.impl.networking.CapeCustomizePacket; +import net.frozenblock.lib.cape.impl.networking.LoadCapeRepoPacket; import net.frozenblock.lib.config.impl.network.ConfigSyncPacket; import net.frozenblock.lib.debug.networking.GoalDebugRemovePayload; import net.frozenblock.lib.debug.networking.ImprovedGameEventDebugPayload; @@ -116,6 +117,7 @@ public static void registerNetworking() { registry.register(WindSyncPacket.PACKET_TYPE, WindSyncPacket.CODEC); registry.register(WindDisturbancePacket.PACKET_TYPE, WindDisturbancePacket.CODEC); registry.register(CapeCustomizePacket.PACKET_TYPE, CapeCustomizePacket.CODEC); + registry.register(LoadCapeRepoPacket.PACKET_TYPE, LoadCapeRepoPacket.STREAM_CODEC); c2sRegistry.register(CapeCustomizePacket.PACKET_TYPE, CapeCustomizePacket.CODEC); ServerPlayNetworking.registerGlobalReceiver(CapeCustomizePacket.PACKET_TYPE, (packet, ctx) -> { diff --git a/src/main/java/net/frozenblock/lib/registry/api/FrozenRegistry.java b/src/main/java/net/frozenblock/lib/registry/api/FrozenRegistry.java index 2136fbb63..fb5e5503e 100644 --- a/src/main/java/net/frozenblock/lib/registry/api/FrozenRegistry.java +++ b/src/main/java/net/frozenblock/lib/registry/api/FrozenRegistry.java @@ -18,12 +18,10 @@ package net.frozenblock.lib.registry.api; import com.mojang.serialization.Lifecycle; -import java.util.Optional; import lombok.experimental.UtilityClass; import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder; import net.fabricmc.fabric.api.event.registry.RegistryAttribute; import net.frozenblock.lib.FrozenSharedConstants; -import net.frozenblock.lib.cape.impl.Cape; import net.frozenblock.lib.integration.api.ModIntegration; import net.frozenblock.lib.integration.api.ModIntegrationSupplier; import net.frozenblock.lib.sound.api.predicate.SoundPredicate; @@ -34,7 +32,6 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.registries.VanillaRegistries; -import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import org.jetbrains.annotations.NotNull; @@ -46,7 +43,6 @@ public class FrozenRegistry { public static final ResourceKey>> SPOTTING_ICON_PREDICATE_REGISTRY = ResourceKey.createRegistryKey(FrozenSharedConstants.id("spotting_icon_predicate")); public static final ResourceKey>> WIND_DISTURBANCE_LOGIC_REGISTRY = ResourceKey.createRegistryKey(FrozenSharedConstants.id("wind_disturbance_logic")); public static final ResourceKey>> WIND_DISTURBANCE_LOGIC_UNSYNCED_REGISTRY = ResourceKey.createRegistryKey(FrozenSharedConstants.id("wind_disturbance_logic_unsynced")); - public static final ResourceKey> CAPE_REGISTRY = ResourceKey.createRegistryKey(FrozenSharedConstants.id("cape")); public static final MappedRegistry> MOD_INTEGRATION = createSimple(MOD_INTEGRATION_REGISTRY, Lifecycle.stable(), null, registry -> Registry.register(registry, FrozenSharedConstants.id("dummy"), new ModIntegrationSupplier<>(() -> new ModIntegration("dummy") { @@ -77,11 +73,6 @@ public void init() {} registry -> Registry.register(registry, FrozenSharedConstants.id("dummy"), new WindDisturbanceLogic(WindDisturbanceLogic.defaultPredicate())) ); - public static final MappedRegistry CAPE = createSimple(CAPE_REGISTRY, Lifecycle.stable(), null, - registry -> Registry.register(registry, FrozenSharedConstants.id("dummy"), new Cape(FrozenSharedConstants.id("dummy"), Component.translatable("cape.frozenlib.dummy"), null, Optional.empty())) - ); - - @NotNull public static HolderLookup.Provider vanillaRegistries() { return VanillaRegistries.createLookup(); From 74dff495502a2d07f676ef301ee74a68dd6fa936 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:17:19 -0400 Subject: [PATCH 04/21] fix --- src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java | 4 ++++ .../java/net/frozenblock/lib/cape/impl/ServerCapeData.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java index 0d18cc5f0..f908d3863 100644 --- a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java +++ b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java @@ -74,6 +74,10 @@ public static boolean canPlayerUserCape(UUID uuid, @NotNull Cape cape) { return cape.allowedPlayers().map(uuids -> uuids.contains(uuid)).orElse(true); } + public static void registerCape(ResourceLocation id, ResourceLocation textureId, Component capeName) { + CAPES.put(id, new Cape(id, capeName, textureId, Optional.empty())); + } + public static void registerCape(ResourceLocation id, Component capeName) { CAPES.put(id, new Cape(id, capeName, buildCapeTextureLocation(id), Optional.empty())); } diff --git a/src/main/java/net/frozenblock/lib/cape/impl/ServerCapeData.java b/src/main/java/net/frozenblock/lib/cape/impl/ServerCapeData.java index 76ba2368f..2b615927c 100644 --- a/src/main/java/net/frozenblock/lib/cape/impl/ServerCapeData.java +++ b/src/main/java/net/frozenblock/lib/cape/impl/ServerCapeData.java @@ -26,9 +26,11 @@ import net.fabricmc.fabric.api.networking.v1.PlayerLookup; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.frozenblock.lib.FrozenSharedConstants; import net.frozenblock.lib.cape.api.CapeUtil; import net.frozenblock.lib.cape.impl.networking.CapeCustomizePacket; import net.frozenblock.lib.cape.impl.networking.LoadCapeRepoPacket; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; public class ServerCapeData { @@ -50,6 +52,8 @@ public static void init() { } }); + CapeUtil.registerCape(FrozenSharedConstants.id("dummy"), null, Component.translatable("cape.frozenlib.dummy")); + // FrozenBlock List devs = ImmutableList.of( UUID.fromString("097b76e8-ac32-410f-b81c-38dd4086b97c"), // Lunade From dad9bdc54cc87f3a9fa295b9425548df6313189d Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:30:11 -0400 Subject: [PATCH 05/21] fix again --- .../lib/cape/client/api/ClientCapeUtil.java | 42 +++++++++++-------- .../impl/networking/CapeCustomizePacket.java | 3 +- .../gui/FrozenLibConfigGui.java | 35 +++++++--------- .../lib/networking/FrozenNetworking.java | 6 +-- 4 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/main/java/net/frozenblock/lib/cape/client/api/ClientCapeUtil.java b/src/main/java/net/frozenblock/lib/cape/client/api/ClientCapeUtil.java index b54c64b40..8de8f3c3f 100644 --- a/src/main/java/net/frozenblock/lib/cape/client/api/ClientCapeUtil.java +++ b/src/main/java/net/frozenblock/lib/cape/client/api/ClientCapeUtil.java @@ -19,6 +19,8 @@ import com.google.gson.JsonIOException; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CompletableFuture; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -35,28 +37,32 @@ @Environment(EnvType.CLIENT) public class ClientCapeUtil { public static final Path CAPE_CACHE_PATH = Minecraft.getInstance().gameDirectory.toPath().resolve("frozenlib_cape_cache"); + private static final List REGISTERED_CAPE_LISTENERS = new ArrayList<>(); public static void registerCapeTextureFromURL( @NotNull ResourceLocation capeLocation, ResourceLocation capeTextureLocation, String textureURL ) throws JsonIOException { - ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() { - @Override - public ResourceLocation getFabricId() { - return capeLocation; - } + if (!REGISTERED_CAPE_LISTENERS.contains(capeLocation)) { + ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() { + @Override + public ResourceLocation getFabricId() { + return capeLocation; + } - @Override - public void onResourceManagerReload(@NotNull ResourceManager resourceManager) { - CompletableFuture completableFuture = new CompletableFuture<>(); - HttpTexture httpTexture = new HttpTexture( - CAPE_CACHE_PATH.resolve(capeLocation.getNamespace()).resolve(capeLocation.getPath() + ".png").toFile(), - textureURL, - DefaultPlayerSkin.getDefaultTexture(), - false, - () -> completableFuture.complete(capeTextureLocation) - ); - Minecraft.getInstance().getTextureManager().register(capeTextureLocation, httpTexture); - } - }); + @Override + public void onResourceManagerReload(@NotNull ResourceManager resourceManager) { + CompletableFuture completableFuture = new CompletableFuture<>(); + HttpTexture httpTexture = new HttpTexture( + CAPE_CACHE_PATH.resolve(capeLocation.getNamespace()).resolve(capeLocation.getPath() + ".png").toFile(), + textureURL, + DefaultPlayerSkin.getDefaultTexture(), + false, + () -> completableFuture.complete(capeTextureLocation) + ); + Minecraft.getInstance().getTextureManager().register(capeTextureLocation, httpTexture); + } + }); + REGISTERED_CAPE_LISTENERS.add(capeLocation); + } } } diff --git a/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java b/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java index 4f27da774..ef2043b55 100644 --- a/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java +++ b/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java @@ -70,7 +70,8 @@ public void write(@NotNull FriendlyByteBuf buf) { return new CapeCustomizePacket(uuid, false); } - public static @NotNull CapeCustomizePacket createPacket(UUID uuid, @Nullable ResourceLocation capeId) { + public static @NotNull CapeCustomizePacket createPacket(UUID uuid, @Nullable ResourceLocation capeId) { + FrozenSharedConstants.LOGGER.info("SENDING CAPE {}", capeId); return new CapeCustomizePacket(uuid, !shouldDisable(CapeUtil.getCape(capeId).orElse(null)), capeId); } diff --git a/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java b/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java index 23f5aff37..cdc1bf6e4 100644 --- a/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java +++ b/src/main/java/net/frozenblock/lib/config/frozenlib_config/gui/FrozenLibConfigGui.java @@ -141,26 +141,21 @@ private static void setupEntries(@NotNull ConfigCategory category, @NotNull Conf CapeUtil.getUsableCapes(playerUUID).forEach(cape -> usableCapes.add(cape.registryId().toString())); if (usableCapes.size() > 1) { var capeEntry = category.addEntry( - FrozenClothConfig.syncedEntry( - entryBuilder.startSelector(text("cape"), usableCapes.toArray(), modifiedConfig.cape) - .setDefaultValue(defaultConfig.cape) - .setNameProvider(o -> { - ResourceLocation capeId = ResourceLocation.parse(((String) o)); - return CapeUtil.getCape(capeId).map(Cape::capeName).orElse(Component.translatable("cape.frozenlib.invalid")); - }) - .setSaveConsumer(newValue -> { - ResourceLocation capeId = ResourceLocation.parse((String) newValue); - config.cape = (String) newValue; - if (Minecraft.getInstance().getConnection() != null) { - ClientPlayNetworking.send(CapeCustomizePacket.createPacket(playerUUID, capeId)); - } - }) - .setTooltip(tooltip("cape")) - .build(), - config.getClass(), - "cape", - configInstance - ) + entryBuilder.startSelector(text("cape"), usableCapes.toArray(), modifiedConfig.cape) + .setDefaultValue(defaultConfig.cape) + .setNameProvider(o -> { + ResourceLocation capeId = ResourceLocation.parse(((String) o)); + return CapeUtil.getCape(capeId).map(Cape::capeName).orElse(Component.translatable("cape.frozenlib.invalid")); + }) + .setSaveConsumer(newValue -> { + ResourceLocation capeId = ResourceLocation.parse((String) newValue); + config.cape = (String) newValue; + if (Minecraft.getInstance().getConnection() != null) { + ClientPlayNetworking.send(CapeCustomizePacket.createPacket(playerUUID, capeId)); + } + }) + .setTooltip(tooltip("cape")) + .build() ); } } diff --git a/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java b/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java index a2c676a9e..b11b15156 100644 --- a/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java +++ b/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java @@ -122,9 +122,9 @@ public static void registerNetworking() { ServerPlayNetworking.registerGlobalReceiver(CapeCustomizePacket.PACKET_TYPE, (packet, ctx) -> { UUID uuid = ctx.player().getUUID(); - ResourceLocation capeTexture = packet.getCapeId(); - if (capeTexture == null || CapeUtil.canPlayerUserCape(uuid, capeTexture)) { - CapeCustomizePacket.sendCapeToAll(ctx.server(), uuid, capeTexture); + ResourceLocation capeId = packet.getCapeId(); + if (capeId == null || CapeUtil.canPlayerUserCape(uuid, capeId)) { + CapeCustomizePacket.sendCapeToAll(ctx.server(), uuid, capeId); } } ); From 8971abfad7458ab7bfd284a87c819b1e7cab36b4 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:51:38 -0400 Subject: [PATCH 06/21] fix capes --- src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java | 2 +- .../frozenblock/lib/cape/client/impl/ClientCapeData.java | 8 ++++---- .../lib/cape/impl/networking/CapeCustomizePacket.java | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java index f908d3863..128e8b8a6 100644 --- a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java +++ b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java @@ -67,7 +67,7 @@ public static Optional getCape(ResourceLocation location) { public static boolean canPlayerUserCape(UUID uuid, ResourceLocation capeID) { Optional optionalCape = CapeUtil.getCape(capeID); - return optionalCape.map(cape -> canPlayerUserCape(uuid, cape)).orElse(false); + return optionalCape.map(cape -> canPlayerUserCape(uuid, cape)).orElse(true); } public static boolean canPlayerUserCape(UUID uuid, @NotNull Cape cape) { diff --git a/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java b/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java index 820d669ee..284a83ee3 100644 --- a/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java +++ b/src/main/java/net/frozenblock/lib/cape/client/impl/ClientCapeData.java @@ -45,15 +45,15 @@ public static Optional getCapeTexture(UUID uuid) { } public static void setCapeForUUID(UUID uuid, ResourceLocation capeId) { - CapeUtil.getCape(capeId).ifPresentOrElse(cape -> CAPES_IN_WORLD.put(uuid, cape), () -> removeCapeForUUID(uuid)); + CapeUtil.getCape(capeId).ifPresentOrElse(cape -> setPlayerCape(uuid, Optional.of(cape)), () -> removeCapeForUUID(uuid)); } public static void removeCapeForUUID(UUID uuid) { - CAPES_IN_WORLD.remove(uuid); - setPlayerCapeTexture(uuid, Optional.empty()); + setPlayerCape(uuid, Optional.empty()); } - private static void setPlayerCapeTexture(UUID uuid, @NotNull Optional cape) { + private static void setPlayerCape(UUID uuid, @NotNull Optional cape) { + cape.ifPresentOrElse(cape1 -> CAPES_IN_WORLD.put(uuid, cape1), () -> CAPES_IN_WORLD.remove(uuid)); ClientLevel level = Minecraft.getInstance().level; if (level != null && level.getPlayerByUUID(uuid) instanceof AbstractClientPlayerCapeInterface capeInterface) { capeInterface.frozenLib$setCape(cape.map(Cape::texture).orElse(null)); diff --git a/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java b/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java index ef2043b55..285090430 100644 --- a/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java +++ b/src/main/java/net/frozenblock/lib/cape/impl/networking/CapeCustomizePacket.java @@ -71,7 +71,6 @@ public void write(@NotNull FriendlyByteBuf buf) { } public static @NotNull CapeCustomizePacket createPacket(UUID uuid, @Nullable ResourceLocation capeId) { - FrozenSharedConstants.LOGGER.info("SENDING CAPE {}", capeId); return new CapeCustomizePacket(uuid, !shouldDisable(CapeUtil.getCape(capeId).orElse(null)), capeId); } From 366351b094a2204986aeec28b7d52164b5204cae Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:55:07 -0400 Subject: [PATCH 07/21] make cape whitelist optional --- src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java index 128e8b8a6..0c511655b 100644 --- a/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java +++ b/src/main/java/net/frozenblock/lib/cape/api/CapeUtil.java @@ -116,7 +116,8 @@ private static void registerCapeFromURL(String urlString) { String capeId = capeJson.get("id").getAsString(); Component capeName = Component.literal(capeJson.get("name").getAsString()); String capeTexture = capeJson.get("texture").getAsString(); - JsonArray allowedUUIDs = capeJson.get("allowed_uuids").getAsJsonArray(); + JsonElement allowedUUIDElement = capeJson.get("allowed_uuids"); + boolean whitelisted = allowedUUIDElement != null; ResourceLocation capeLocation = ResourceLocation.tryParse(capeId); if (capeLocation != null) { @@ -125,12 +126,11 @@ private static void registerCapeFromURL(String urlString) { ClientCapeUtil.registerCapeTextureFromURL(capeLocation, capeTextureLocation, capeTexture); } - List allowedUUIDList = allowedUUIDs.asList(); - if (allowedUUIDList.isEmpty()) { + if (!whitelisted) { registerCape(capeLocation, capeName); } else { List uuidList = new ArrayList<>(); - allowedUUIDList.forEach(jsonElement -> uuidList.add(UUID.fromString(jsonElement.getAsString()))); + allowedUUIDElement.getAsJsonArray().asList().forEach(jsonElement -> uuidList.add(UUID.fromString(jsonElement.getAsString()))); registerCapeWithWhitelist(capeLocation, capeName, ImmutableList.copyOf(uuidList)); } } From 53d879af7e48b828b3b070bb5c4409f4de3158d2 Mon Sep 17 00:00:00 2001 From: Treetrain1 Date: Sun, 22 Sep 2024 12:40:36 -0500 Subject: [PATCH 08/21] Kotlin 2.0.20 --- build.gradle.kts | 2 +- gradle.properties | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b95dcd78a..9d0fa76b9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,7 +30,7 @@ plugins { idea `java-library` java - kotlin("jvm") version("2.0.10") + kotlin("jvm") version("2.0.20") } val minecraft_version: String by project diff --git a/gradle.properties b/gradle.properties index a120b7b7b..30974ba79 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ minecraft_version=1.21.1 quilt_mappings=1.21+build.18 parchment_mappings=1.21:2024.07.28 - loader_version=0.16.0 + loader_version=0.16.5 min_loader_version=0.16.0 # Mod Properties @@ -21,7 +21,7 @@ # Dependencies fabric_api_version=0.103.0+1.21.1 - fabric_kotlin_version=1.12.0+kotlin.2.0.10 + fabric_kotlin_version=1.12.2+kotlin.2.0.20 toml4j_version=0.7.2 jankson_version=1.2.3 xjs_data_version=0.6 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9355b4155..0aaefbcaf 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From be0c32eff2a6e58f73f01da64a3f3a1259919571 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Tue, 24 Sep 2024 14:19:27 -0400 Subject: [PATCH 09/21] fake push --- CHANGELOG.md | 2 + .../image_transfer/FileTransferPacket.java | 80 ++++++++++ .../lib/image_transfer/ServerTexture.java | 139 ++++++++++++++++++ .../networking/FrozenClientNetworking.java | 33 +++++ .../lib/networking/FrozenNetworking.java | 3 + 5 files changed, 257 insertions(+) create mode 100644 src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java create mode 100644 src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dd32bf10..48d080da1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,3 +19,5 @@ Put changelog here: - Currently, these capes can only be accessed through FrozenLib's config. - An optional list of allowed UUIDs can be defined for capes. - Fixed the `ColumnWithDiskFeature` not generating as intended. +- Added an API to send and receive images from client and server. + - This is useful in cases where, for example, you want to send a screenshot from Minecraft to the server to be used as a texture. diff --git a/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java b/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java new file mode 100644 index 000000000..f2a467b07 --- /dev/null +++ b/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2024 FrozenBlock + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.frozenblock.lib.image_transfer; + +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.frozenblock.lib.FrozenSharedConstants; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +public record FileTransferPacket(String transferPath, String fileName, boolean request, byte[] bytes) implements CustomPacketPayload { + public static final Type PACKET_TYPE = new Type<>( + FrozenSharedConstants.id("file_transfer") + ); + public static final StreamCodec STREAM_CODEC = StreamCodec.ofMember(FileTransferPacket::write, FileTransferPacket::create); + + public static @NotNull FileTransferPacket create(@NotNull FriendlyByteBuf buf) { + return new FileTransferPacket(buf.readUtf(), buf.readUtf(), buf.readBoolean(), buf.readByteArray()); + } + + public static @NotNull FileTransferPacket create(String destPath, @NotNull File file) throws IOException { + return new FileTransferPacket(destPath, file.getName(), false, readFile(file)); + } + + public static @NotNull FileTransferPacket createRequest(String directory, String fileName) { + return new FileTransferPacket(directory, fileName, true, new byte[0]); + } + + private static byte @Nullable [] readFile(File file) { + try { + FileInputStream fileInputStream = new FileInputStream(file); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + fileInputStream.transferTo(byteArrayOutputStream); + fileInputStream.close(); + return byteArrayOutputStream.toByteArray(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static void sendToPlayer(File file, String transferPath, ServerPlayer player) throws IOException { + ServerPlayNetworking.send(player, create(transferPath, file)); + } + + public void write(@NotNull FriendlyByteBuf buf) { + buf.writeUtf(this.transferPath); + buf.writeUtf(this.fileName); + buf.writeBoolean(this.request); + buf.writeByteArray(this.bytes); + } + + @Override + @NotNull + public Type type() { + return PACKET_TYPE; + } +} + diff --git a/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java b/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java new file mode 100644 index 000000000..7588bc19a --- /dev/null +++ b/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java @@ -0,0 +1,139 @@ +package net.frozenblock.lib.image_transfer; + +import com.mojang.blaze3d.platform.NativeImage; +import com.mojang.blaze3d.platform.TextureUtil; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.logging.LogUtils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.SimpleTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +@Environment(EnvType.CLIENT) +public class ServerTexture extends SimpleTexture { + private static final Logger LOGGER = LogUtils.getLogger(); + public static final Map WAITING_TEXTURES = new HashMap<>(); + private final File file; + private final String destPath; + private final String fileName; + @Nullable + private final Runnable onDownloaded; + @Nullable + private CompletableFuture future; + private boolean uploaded; + + public ServerTexture(String destPath, String fileName, ResourceLocation fallback, @Nullable Runnable callback) { + super(fallback); + this.file = Minecraft.getInstance().gameDirectory.toPath().resolve(destPath).resolve(fileName).toFile(); + this.destPath = destPath; + this.fileName = fileName; + this.onDownloaded = callback; + ClientPlayNetworking.send(FileTransferPacket.createRequest(this.destPath, this.fileName)); + WAITING_TEXTURES.put(this.destPath + "/" + this.fileName, this); + } + + private void loadCallback(NativeImage image) { + if (this.onDownloaded != null) { + this.onDownloaded.run(); + } + + Minecraft.getInstance().execute(() -> { + this.uploaded = true; + if (!RenderSystem.isOnRenderThread()) { + RenderSystem.recordRenderCall(() -> this.upload(image)); + } else { + this.upload(image); + } + }); + } + + private void upload(@NotNull NativeImage image) { + TextureUtil.prepareImage(this.getId(), image.getWidth(), image.getHeight()); + image.upload(0, 0, 0, true); + } + + public void runFutureForTexture() { + if (this.future != null) { + this.future = CompletableFuture.runAsync(() -> { + LOGGER.debug("Downloading server texture {}", this.fileName); + try { + InputStream inputStream = new FileInputStream(this.file); + Minecraft.getInstance().execute(() -> { + NativeImage nativeImagex = this.load(inputStream); + if (nativeImagex != null) { + this.loadCallback(nativeImagex); + } + }); + } catch (Exception e) { + LOGGER.error("Couldn't download server texture", e); + }}, Util.backgroundExecutor()); + } + } + + @Override + public void load(ResourceManager manager) throws IOException { + Minecraft.getInstance().execute(() -> { + if (!this.uploaded) { + try { + super.load(manager); + } catch (IOException var3x) { + LOGGER.warn("Failed to load server texture: {}", this.location, var3x); + } + + this.uploaded = true; + } + }); + NativeImage nativeImage; + if (this.file != null && this.file.exists() && this.file.isFile()) { + LOGGER.debug("Loading server texture from local cache ({})", this.file); + FileInputStream fileInputStream = new FileInputStream(this.file); + nativeImage = this.load(fileInputStream.readAllBytes()); + } else { + nativeImage = null; + } + + if (nativeImage != null) { + this.loadCallback(nativeImage); + } + } + + @Nullable + private NativeImage load(InputStream stream) { + NativeImage nativeImage = null; + + try { + nativeImage = NativeImage.read(stream); + } catch (Exception e) { + LOGGER.warn("Error while loading the skin texture", e); + } + + return nativeImage; + } + + @Nullable + private NativeImage load(byte[] bytes) { + NativeImage nativeImage = null; + + try { + nativeImage = NativeImage.read(bytes); + } catch (Exception e) { + LOGGER.warn("Error while loading server texture", e); + } + + return nativeImage; + } +} diff --git a/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java b/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java index 54d3eaf05..9217c197c 100644 --- a/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java +++ b/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java @@ -17,6 +17,9 @@ package net.frozenblock.lib.networking; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.file.Path; import java.util.Optional; import java.util.UUID; import net.fabricmc.api.EnvType; @@ -24,6 +27,7 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; +import net.frozenblock.lib.FrozenSharedConstants; import net.frozenblock.lib.cape.api.CapeUtil; import net.frozenblock.lib.cape.client.impl.ClientCapeData; import net.frozenblock.lib.cape.impl.networking.CapeCustomizePacket; @@ -31,6 +35,8 @@ import net.frozenblock.lib.config.api.instance.Config; import net.frozenblock.lib.config.api.registry.ConfigRegistry; import net.frozenblock.lib.config.impl.network.ConfigSyncPacket; +import net.frozenblock.lib.image_transfer.FileTransferPacket; +import net.frozenblock.lib.image_transfer.ServerTexture; import net.frozenblock.lib.item.impl.CooldownInterface; import net.frozenblock.lib.item.impl.network.CooldownChangePacket; import net.frozenblock.lib.item.impl.network.CooldownTickCountPacket; @@ -77,6 +83,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemCooldowns; import net.minecraft.world.phys.Vec3; +import org.apache.commons.io.FileUtils; @Environment(EnvType.CLIENT) public final class FrozenClientNetworking { @@ -105,6 +112,7 @@ public static void registerClientReceivers() { receiveIconRemovePacket(); receiveWindSyncPacket(); receiveWindDisturbancePacket(); + receiveTransferImagePacket(); receiveCapePacket(); receiveCapeRepoPacket(); ClientPlayNetworking.registerGlobalReceiver(ConfigSyncPacket.PACKET_TYPE, (packet, ctx) -> @@ -331,6 +339,31 @@ private static void receiveWindDisturbancePacket() { }); } + private static void receiveTransferImagePacket() { + ClientPlayNetworking.registerGlobalReceiver(FileTransferPacket.PACKET_TYPE, (packet, ctx) -> { + if (packet.request()) { + Path path = ctx.client().gameDirectory.toPath().resolve(packet.transferPath()).resolve(packet.fileName()); + try { + FileTransferPacket fileTransferPacket = FileTransferPacket.create(packet.transferPath(), path.toFile()); + ClientPlayNetworking.send(fileTransferPacket); + } catch (IOException ignored) { + FrozenSharedConstants.LOGGER.error("Unable to create and send transfer packet for file {}!", packet.fileName()); + } + } else { + try { + Path path = ctx.client().gameDirectory.toPath().resolve(packet.transferPath()).resolve(packet.fileName()); + FileUtils.copyInputStreamToFile(new ByteArrayInputStream(packet.bytes()), path.toFile()); + ServerTexture serverTexture = ServerTexture.WAITING_TEXTURES.get(packet.transferPath() + "/" + packet.fileName()); + if (serverTexture != null) { + serverTexture.runFutureForTexture(); + } + } catch (IOException ignored) { + FrozenSharedConstants.LOGGER.error("Unable save transferred file {}!", packet.fileName()); + } + } + }); + } + private static void receiveCapePacket() { ClientPlayNetworking.registerGlobalReceiver(CapeCustomizePacket.PACKET_TYPE, (packet, ctx) -> { UUID uuid = packet.getPlayerUUID(); diff --git a/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java b/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java index b11b15156..849a3e84d 100644 --- a/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java +++ b/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java @@ -41,6 +41,7 @@ import net.frozenblock.lib.screenshake.impl.network.RemoveEntityScreenShakePacket; import net.frozenblock.lib.screenshake.impl.network.RemoveScreenShakePacket; import net.frozenblock.lib.screenshake.impl.network.ScreenShakePacket; +import net.frozenblock.lib.image_transfer.FileTransferPacket; import net.frozenblock.lib.sound.api.networking.FadingDistanceSwitchingSoundPacket; import net.frozenblock.lib.sound.api.networking.LocalPlayerSoundPacket; import net.frozenblock.lib.sound.api.networking.LocalSoundPacket; @@ -116,6 +117,8 @@ public static void registerNetworking() { registry.register(SpottingIconRemovePacket.PACKET_TYPE, SpottingIconRemovePacket.CODEC); registry.register(WindSyncPacket.PACKET_TYPE, WindSyncPacket.CODEC); registry.register(WindDisturbancePacket.PACKET_TYPE, WindDisturbancePacket.CODEC); + registry.register(FileTransferPacket.PACKET_TYPE, FileTransferPacket.STREAM_CODEC); + c2sRegistry.register(FileTransferPacket.PACKET_TYPE, FileTransferPacket.STREAM_CODEC); registry.register(CapeCustomizePacket.PACKET_TYPE, CapeCustomizePacket.CODEC); registry.register(LoadCapeRepoPacket.PACKET_TYPE, LoadCapeRepoPacket.STREAM_CODEC); c2sRegistry.register(CapeCustomizePacket.PACKET_TYPE, CapeCustomizePacket.CODEC); From baef25d76dafc5160c776ddae4c9feac183033c4 Mon Sep 17 00:00:00 2001 From: Treetrain1 Date: Tue, 24 Sep 2024 19:39:12 -0500 Subject: [PATCH 10/21] build frozenlib on jitpack --- jitpack.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/jitpack.yml b/jitpack.yml index c7bef7588..727c9abd3 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,6 +1,2 @@ -before_install: - - wget https://github.com/sormuras/bach/raw/releases/11/install-jdk.sh - - source install-jdk.sh --feature 21 - jdk: - - openjdk21 \ No newline at end of file + - openjdk21 From 535faeec8c11fb32e6e73ceb43f006469b108126 Mon Sep 17 00:00:00 2001 From: Treetrain1 Date: Tue, 24 Sep 2024 19:39:27 -0500 Subject: [PATCH 11/21] update lombok --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9d0fa76b9..a1e6b8c91 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -271,7 +271,7 @@ dependencies { relocModApi(files("libs/xjs-data-0.5.jar")) relocModApi("org.exjson:xjs-compat:$xjs_compat_version") relocModApi("com.personthecat:fresult:$fresult_version") - compileOnly("org.projectlombok:lombok:1.18.30")?.let { annotationProcessor(it) } + compileOnly("org.projectlombok:lombok:1.18.34")?.let { annotationProcessor(it) } "testmodImplementation"(sourceSets.main.get().output) } From 41a57d7f2247b119036707cdb17f7ab857a79510 Mon Sep 17 00:00:00 2001 From: Treetrain1 Date: Wed, 25 Sep 2024 00:42:22 +0000 Subject: [PATCH 12/21] Apply automatic changes --- .../lib/image_transfer/ServerTexture.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java b/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java index 7588bc19a..2e763460e 100644 --- a/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java +++ b/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2024 FrozenBlock + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package net.frozenblock.lib.image_transfer; import com.mojang.blaze3d.platform.NativeImage; From 033885b83aec2bea782d8aa7dfcf23ea90c16b37 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Wed, 25 Sep 2024 01:31:33 -0400 Subject: [PATCH 13/21] add --- .../image_transfer/FileTransferPacket.java | 82 ++++----- .../lib/image_transfer/ServerTexture.java | 156 ------------------ .../image_transfer/client/ServerTexture.java | 130 +++++++++++++++ .../networking/FrozenClientNetworking.java | 23 ++- .../lib/networking/FrozenNetworking.java | 30 +++- 5 files changed, 222 insertions(+), 199 deletions(-) delete mode 100644 src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java create mode 100644 src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java diff --git a/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java b/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java index f2a467b07..1b83f1e28 100644 --- a/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java +++ b/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java @@ -18,63 +18,65 @@ package net.frozenblock.lib.image_transfer; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.frozenblock.lib.FrozenSharedConstants; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -public record FileTransferPacket(String transferPath, String fileName, boolean request, byte[] bytes) implements CustomPacketPayload { - public static final Type PACKET_TYPE = new Type<>( - FrozenSharedConstants.id("file_transfer") - ); - public static final StreamCodec STREAM_CODEC = StreamCodec.ofMember(FileTransferPacket::write, FileTransferPacket::create); +public record FileTransferPacket(String transferPath, String fileName, boolean request, + byte[] bytes) implements CustomPacketPayload { + public static final Type PACKET_TYPE = new Type<>( + ResourceLocation.tryBuild("camera_port", "file_transfer") + ); + public static final StreamCodec STREAM_CODEC = StreamCodec.ofMember(FileTransferPacket::write, FileTransferPacket::create); - public static @NotNull FileTransferPacket create(@NotNull FriendlyByteBuf buf) { - return new FileTransferPacket(buf.readUtf(), buf.readUtf(), buf.readBoolean(), buf.readByteArray()); - } + public static @NotNull FileTransferPacket create(@NotNull FriendlyByteBuf buf) { + return new FileTransferPacket(buf.readUtf(), buf.readUtf(), buf.readBoolean(), buf.readByteArray()); + } - public static @NotNull FileTransferPacket create(String destPath, @NotNull File file) throws IOException { - return new FileTransferPacket(destPath, file.getName(), false, readFile(file)); - } + public static @NotNull FileTransferPacket create(String destPath, @NotNull File file) throws IOException { + return new FileTransferPacket(destPath, file.getName(), false, readFile(file)); + } - public static @NotNull FileTransferPacket createRequest(String directory, String fileName) { - return new FileTransferPacket(directory, fileName, true, new byte[0]); - } + public static @NotNull FileTransferPacket createRequest(String directory, String fileName) { + return new FileTransferPacket(directory, fileName, true, new byte[0]); + } - private static byte @Nullable [] readFile(File file) { - try { - FileInputStream fileInputStream = new FileInputStream(file); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - fileInputStream.transferTo(byteArrayOutputStream); - fileInputStream.close(); - return byteArrayOutputStream.toByteArray(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + private static byte @Nullable [] readFile(File file) { + try { + FileInputStream fileInputStream = new FileInputStream(file); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + fileInputStream.transferTo(byteArrayOutputStream); + fileInputStream.close(); + return byteArrayOutputStream.toByteArray(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } - public static void sendToPlayer(File file, String transferPath, ServerPlayer player) throws IOException { - ServerPlayNetworking.send(player, create(transferPath, file)); - } + public static void sendToPlayer(File file, String transferPath, ServerPlayer player) throws IOException { + ServerPlayNetworking.send(player, create(transferPath, file)); + } - public void write(@NotNull FriendlyByteBuf buf) { - buf.writeUtf(this.transferPath); - buf.writeUtf(this.fileName); - buf.writeBoolean(this.request); - buf.writeByteArray(this.bytes); - } + public void write(@NotNull FriendlyByteBuf buf) { + buf.writeUtf(this.transferPath); + buf.writeUtf(this.fileName); + buf.writeBoolean(this.request); + buf.writeByteArray(this.bytes); + } - @Override - @NotNull - public Type type() { - return PACKET_TYPE; - } + @Override + @NotNull + public Type type() { + return PACKET_TYPE; + } } diff --git a/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java b/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java deleted file mode 100644 index 2e763460e..000000000 --- a/src/main/java/net/frozenblock/lib/image_transfer/ServerTexture.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2024 FrozenBlock - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.frozenblock.lib.image_transfer; - -import com.mojang.blaze3d.platform.NativeImage; -import com.mojang.blaze3d.platform.TextureUtil; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.logging.LogUtils; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.minecraft.Util; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.texture.SimpleTexture; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -@Environment(EnvType.CLIENT) -public class ServerTexture extends SimpleTexture { - private static final Logger LOGGER = LogUtils.getLogger(); - public static final Map WAITING_TEXTURES = new HashMap<>(); - private final File file; - private final String destPath; - private final String fileName; - @Nullable - private final Runnable onDownloaded; - @Nullable - private CompletableFuture future; - private boolean uploaded; - - public ServerTexture(String destPath, String fileName, ResourceLocation fallback, @Nullable Runnable callback) { - super(fallback); - this.file = Minecraft.getInstance().gameDirectory.toPath().resolve(destPath).resolve(fileName).toFile(); - this.destPath = destPath; - this.fileName = fileName; - this.onDownloaded = callback; - ClientPlayNetworking.send(FileTransferPacket.createRequest(this.destPath, this.fileName)); - WAITING_TEXTURES.put(this.destPath + "/" + this.fileName, this); - } - - private void loadCallback(NativeImage image) { - if (this.onDownloaded != null) { - this.onDownloaded.run(); - } - - Minecraft.getInstance().execute(() -> { - this.uploaded = true; - if (!RenderSystem.isOnRenderThread()) { - RenderSystem.recordRenderCall(() -> this.upload(image)); - } else { - this.upload(image); - } - }); - } - - private void upload(@NotNull NativeImage image) { - TextureUtil.prepareImage(this.getId(), image.getWidth(), image.getHeight()); - image.upload(0, 0, 0, true); - } - - public void runFutureForTexture() { - if (this.future != null) { - this.future = CompletableFuture.runAsync(() -> { - LOGGER.debug("Downloading server texture {}", this.fileName); - try { - InputStream inputStream = new FileInputStream(this.file); - Minecraft.getInstance().execute(() -> { - NativeImage nativeImagex = this.load(inputStream); - if (nativeImagex != null) { - this.loadCallback(nativeImagex); - } - }); - } catch (Exception e) { - LOGGER.error("Couldn't download server texture", e); - }}, Util.backgroundExecutor()); - } - } - - @Override - public void load(ResourceManager manager) throws IOException { - Minecraft.getInstance().execute(() -> { - if (!this.uploaded) { - try { - super.load(manager); - } catch (IOException var3x) { - LOGGER.warn("Failed to load server texture: {}", this.location, var3x); - } - - this.uploaded = true; - } - }); - NativeImage nativeImage; - if (this.file != null && this.file.exists() && this.file.isFile()) { - LOGGER.debug("Loading server texture from local cache ({})", this.file); - FileInputStream fileInputStream = new FileInputStream(this.file); - nativeImage = this.load(fileInputStream.readAllBytes()); - } else { - nativeImage = null; - } - - if (nativeImage != null) { - this.loadCallback(nativeImage); - } - } - - @Nullable - private NativeImage load(InputStream stream) { - NativeImage nativeImage = null; - - try { - nativeImage = NativeImage.read(stream); - } catch (Exception e) { - LOGGER.warn("Error while loading the skin texture", e); - } - - return nativeImage; - } - - @Nullable - private NativeImage load(byte[] bytes) { - NativeImage nativeImage = null; - - try { - nativeImage = NativeImage.read(bytes); - } catch (Exception e) { - LOGGER.warn("Error while loading server texture", e); - } - - return nativeImage; - } -} diff --git a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java new file mode 100644 index 000000000..2cf546a39 --- /dev/null +++ b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java @@ -0,0 +1,130 @@ +package net.frozenblock.lib.image_transfer.client; + +import com.mojang.blaze3d.platform.NativeImage; +import com.mojang.blaze3d.platform.TextureUtil; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.logging.LogUtils; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.frozenblock.lib.image_transfer.FileTransferPacket; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.SimpleTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; + +@Environment(EnvType.CLIENT) +public class ServerTexture extends SimpleTexture { + public static final Map WAITING_TEXTURES = new HashMap<>(); + private static final Logger LOGGER = LogUtils.getLogger(); + private final File file; + private final String destPath; + private final String fileName; + @Nullable + private final Runnable onDownloaded; + @Nullable + private CompletableFuture future; + private boolean uploaded; + + public ServerTexture(String destPath, String fileName, ResourceLocation fallback, @Nullable Runnable callback) { + super(fallback); + this.file = Minecraft.getInstance().gameDirectory.toPath().resolve(destPath).resolve(fileName).toFile(); + this.destPath = destPath; + this.fileName = fileName; + this.onDownloaded = callback; + WAITING_TEXTURES.put(this.destPath + "/" + this.fileName, this); + } + + private void loadCallback(NativeImage image) { + if (this.onDownloaded != null) { + this.onDownloaded.run(); + } + + Minecraft.getInstance().execute(() -> { + this.uploaded = true; + if (!RenderSystem.isOnRenderThread()) { + RenderSystem.recordRenderCall(() -> this.upload(image)); + } else { + this.upload(image); + } + }); + } + + private void upload(@NotNull NativeImage image) { + TextureUtil.prepareImage(this.getId(), image.getWidth(), image.getHeight()); + image.upload(0, 0, 0, true); + } + + public void runFutureForTexture() { + if (this.future == null) { + this.future = CompletableFuture.runAsync(() -> { + LOGGER.debug("Downloading server texture {}", this.fileName); + try { + InputStream inputStream = new FileInputStream(this.file); + Minecraft.getInstance().execute(() -> { + NativeImage nativeImagex = this.load(inputStream); + if (nativeImagex != null) { + this.loadCallback(nativeImagex); + } + }); + } catch (Exception e) { + LOGGER.error("Couldn't download server texture", e); + } + }, Util.backgroundExecutor()); + } + } + + @Override + public void load(ResourceManager manager) throws IOException { + Minecraft.getInstance().execute(() -> { + if (!this.uploaded) { + try { + super.load(manager); + } catch (IOException var3x) { + LOGGER.warn("Failed to load server texture: {}", this.location, var3x); + } + + this.uploaded = true; + } + }); + + NativeImage nativeImage; + if (this.file != null && this.file.exists() && this.file.isFile()) { + LOGGER.debug("Loading server texture from local cache ({})", this.file); + FileInputStream fileInputStream = new FileInputStream(this.file); + nativeImage = this.load(fileInputStream); + fileInputStream.close(); + } else { + ClientPlayNetworking.send(FileTransferPacket.createRequest(this.destPath, this.fileName)); + nativeImage = null; + } + + if (nativeImage != null) { + this.loadCallback(nativeImage); + } + } + + @Nullable + private NativeImage load(InputStream stream) { + NativeImage nativeImage = null; + + try { + nativeImage = NativeImage.read(stream); + } catch (Exception e) { + LOGGER.warn("Error while loading server texture", e); + } + + return nativeImage; + } +} diff --git a/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java b/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java index 9217c197c..4e8a3c149 100644 --- a/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java +++ b/src/main/java/net/frozenblock/lib/networking/FrozenClientNetworking.java @@ -36,7 +36,7 @@ import net.frozenblock.lib.config.api.registry.ConfigRegistry; import net.frozenblock.lib.config.impl.network.ConfigSyncPacket; import net.frozenblock.lib.image_transfer.FileTransferPacket; -import net.frozenblock.lib.image_transfer.ServerTexture; +import net.frozenblock.lib.image_transfer.client.ServerTexture; import net.frozenblock.lib.item.impl.CooldownInterface; import net.frozenblock.lib.item.impl.network.CooldownChangePacket; import net.frozenblock.lib.item.impl.network.CooldownTickCountPacket; @@ -124,6 +124,27 @@ public static void registerClientReceivers() { config.setSynced(false); } })); + + ClientPlayNetworking.registerGlobalReceiver(FileTransferPacket.PACKET_TYPE, (packet, ctx) -> { + if (packet.request()) { + Path path = ctx.client().gameDirectory.toPath().resolve(packet.transferPath()).resolve(packet.fileName()); + try { + FileTransferPacket fileTransferPacket = FileTransferPacket.create(packet.transferPath(), path.toFile()); + ClientPlayNetworking.send(fileTransferPacket); + } catch (IOException ignored) { + } + } else { + try { + Path path = ctx.client().gameDirectory.toPath().resolve(packet.transferPath()).resolve(packet.fileName()); + FileUtils.copyInputStreamToFile(new ByteArrayInputStream(packet.bytes()), path.toFile()); + ServerTexture serverTexture = ServerTexture.WAITING_TEXTURES.get(packet.transferPath() + "/" + packet.fileName()); + if (serverTexture != null) { + serverTexture.runFutureForTexture(); + } + } catch (IOException ignored) { + } + } + }); } private static void receiveLocalPlayerSoundPacket() { diff --git a/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java b/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java index 849a3e84d..89d912e2b 100644 --- a/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java +++ b/src/main/java/net/frozenblock/lib/networking/FrozenNetworking.java @@ -17,6 +17,9 @@ package net.frozenblock.lib.networking; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.file.Path; import java.util.UUID; import net.fabricmc.api.EnvType; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; @@ -64,6 +67,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; +import org.apache.commons.io.FileUtils; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.frozenblock.resource.loader.api.ResourceLoaderEvents; @@ -117,8 +121,8 @@ public static void registerNetworking() { registry.register(SpottingIconRemovePacket.PACKET_TYPE, SpottingIconRemovePacket.CODEC); registry.register(WindSyncPacket.PACKET_TYPE, WindSyncPacket.CODEC); registry.register(WindDisturbancePacket.PACKET_TYPE, WindDisturbancePacket.CODEC); - registry.register(FileTransferPacket.PACKET_TYPE, FileTransferPacket.STREAM_CODEC); - c2sRegistry.register(FileTransferPacket.PACKET_TYPE, FileTransferPacket.STREAM_CODEC); + + // CAPE registry.register(CapeCustomizePacket.PACKET_TYPE, CapeCustomizePacket.CODEC); registry.register(LoadCapeRepoPacket.PACKET_TYPE, LoadCapeRepoPacket.STREAM_CODEC); c2sRegistry.register(CapeCustomizePacket.PACKET_TYPE, CapeCustomizePacket.CODEC); @@ -132,6 +136,28 @@ public static void registerNetworking() { } ); + // FILE TRANSFER + registry.register(FileTransferPacket.PACKET_TYPE, FileTransferPacket.STREAM_CODEC); + c2sRegistry.register(FileTransferPacket.PACKET_TYPE, FileTransferPacket.STREAM_CODEC); + ServerPlayNetworking.registerGlobalReceiver(FileTransferPacket.PACKET_TYPE, + (packet, ctx) -> { + if (packet.request()) { + Path path = ctx.server().getServerDirectory().resolve(packet.transferPath()).resolve(packet.fileName()); + try { + FileTransferPacket fileTransferPacket = FileTransferPacket.create(packet.transferPath(), path.toFile()); + ServerPlayNetworking.send(ctx.player(), fileTransferPacket); + } catch (IOException ignored) { + } + } else { + try { + Path path = ctx.server().getServerDirectory().resolve(packet.transferPath()).resolve(packet.fileName()); + FileUtils.copyInputStreamToFile(new ByteArrayInputStream(packet.bytes()), path.toFile()); + } catch (IOException ignored) { + } + } + } + ); + // DEBUG registry.register(ImprovedGoalDebugPayload.PACKET_TYPE, ImprovedGoalDebugPayload.STREAM_CODEC); registry.register(GoalDebugRemovePayload.PACKET_TYPE, GoalDebugRemovePayload.STREAM_CODEC); From 9173ff0a7a688d6889c3d0024e5fc2a2992aebd1 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop Date: Wed, 25 Sep 2024 05:34:29 +0000 Subject: [PATCH 14/21] Apply automatic changes --- .../image_transfer/client/ServerTexture.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java index 2cf546a39..83a7235e3 100644 --- a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java +++ b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2024 FrozenBlock + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package net.frozenblock.lib.image_transfer.client; import com.mojang.blaze3d.platform.NativeImage; From bbc4cbc9db6879cf091eecc60ddb052beb935680 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Wed, 25 Sep 2024 03:12:34 -0400 Subject: [PATCH 15/21] Update FileTransferPacket.java --- .../frozenblock/lib/image_transfer/FileTransferPacket.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java b/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java index 1b83f1e28..9e14bca92 100644 --- a/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java +++ b/src/main/java/net/frozenblock/lib/image_transfer/FileTransferPacket.java @@ -18,10 +18,10 @@ package net.frozenblock.lib.image_transfer; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.frozenblock.lib.FrozenSharedConstants; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,10 +31,9 @@ import java.io.FileInputStream; import java.io.IOException; -public record FileTransferPacket(String transferPath, String fileName, boolean request, - byte[] bytes) implements CustomPacketPayload { +public record FileTransferPacket(String transferPath, String fileName, boolean request, byte[] bytes) implements CustomPacketPayload { public static final Type PACKET_TYPE = new Type<>( - ResourceLocation.tryBuild("camera_port", "file_transfer") + FrozenSharedConstants.id("file_transfer") ); public static final StreamCodec STREAM_CODEC = StreamCodec.ofMember(FileTransferPacket::write, FileTransferPacket::create); From 7d39683b1ac58f140e732d07953d3d836f845ac4 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Wed, 25 Sep 2024 03:56:54 -0400 Subject: [PATCH 16/21] Update ServerTexture.java --- .../lib/image_transfer/client/ServerTexture.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java index 83a7235e3..cf1bd6ffb 100644 --- a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java +++ b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java @@ -35,6 +35,7 @@ import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.SimpleTexture; +import net.minecraft.client.renderer.texture.Tickable; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; import org.jetbrains.annotations.NotNull; @@ -42,7 +43,7 @@ import org.slf4j.Logger; @Environment(EnvType.CLIENT) -public class ServerTexture extends SimpleTexture { +public class ServerTexture extends SimpleTexture implements Tickable { public static final Map WAITING_TEXTURES = new HashMap<>(); private static final Logger LOGGER = LogUtils.getLogger(); private final File file; @@ -53,6 +54,7 @@ public class ServerTexture extends SimpleTexture { @Nullable private CompletableFuture future; private boolean uploaded; + private long timeSinceLastReference; public ServerTexture(String destPath, String fileName, ResourceLocation fallback, @Nullable Runnable callback) { super(fallback); @@ -60,6 +62,7 @@ public ServerTexture(String destPath, String fileName, ResourceLocation fallback this.destPath = destPath; this.fileName = fileName; this.onDownloaded = callback; + this.timeSinceLastReference = System.currentTimeMillis(); WAITING_TEXTURES.put(this.destPath + "/" + this.fileName, this); } @@ -144,4 +147,15 @@ private NativeImage load(InputStream stream) { return nativeImage; } + + public void updateReferenceTime() { + this.timeSinceLastReference = System.currentTimeMillis(); + } + + @Override + public void tick() { + if (System.currentTimeMillis() - this.timeSinceLastReference > 5000) { + this.releaseId(); + } + } } From 5046f01982670df6d6a1983c0f8e363c2c37735d Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Wed, 25 Sep 2024 14:49:29 -0400 Subject: [PATCH 17/21] ugh --- .../mixin/client/TextureManagerMixin.java | 20 +++++++++++++++++++ src/main/resources/fabric.mod.json | 1 + .../frozenlib.image_transfer.mixins.json | 12 +++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/main/java/net/frozenblock/lib/image_transfer/mixin/client/TextureManagerMixin.java create mode 100644 src/main/resources/mixin/frozenlib.image_transfer.mixins.json diff --git a/src/main/java/net/frozenblock/lib/image_transfer/mixin/client/TextureManagerMixin.java b/src/main/java/net/frozenblock/lib/image_transfer/mixin/client/TextureManagerMixin.java new file mode 100644 index 000000000..bc1b0a004 --- /dev/null +++ b/src/main/java/net/frozenblock/lib/image_transfer/mixin/client/TextureManagerMixin.java @@ -0,0 +1,20 @@ +package net.frozenblock.lib.image_transfer.mixin.client; + +import net.frozenblock.lib.image_transfer.client.ServerTexture; +import net.minecraft.client.renderer.texture.AbstractTexture; +import net.minecraft.client.renderer.texture.TextureManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(TextureManager.class) +public class TextureManagerMixin { + + @Inject(method = "getTexture*", at = @At("RETURN")) + public void frozenLib$updateServerTextureReferenceTime(CallbackInfoReturnable info) { + if (info.getReturnValue() instanceof ServerTexture serverTexture) { + serverTexture.updateReferenceTime(); + } + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 628f56a3f..c2988d1f9 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -53,6 +53,7 @@ "mixin/frozenlib.event.mixins.json", "mixin/frozenlib.feature_flag.mixins.json", "mixin/frozenlib.gravity.mixins.json", + "mixin/frozenlib.image_transfer.mixins.json", "mixin/frozenlib.item.mixins.json", "mixin/frozenlib.menu.mixins.json", "mixin/frozenlib.mobcategory.mixins.json", diff --git a/src/main/resources/mixin/frozenlib.image_transfer.mixins.json b/src/main/resources/mixin/frozenlib.image_transfer.mixins.json new file mode 100644 index 000000000..c8cf416c5 --- /dev/null +++ b/src/main/resources/mixin/frozenlib.image_transfer.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.frozenblock.lib.image_transfer.mixin", + "compatibilityLevel": "JAVA_21", + "injectors": { + "defaultRequire": 1 + }, + "client": [ + "client.TextureManagerMixin" + ] +} From 9e08930b2e3472b06a235eeb9925991735be294a Mon Sep 17 00:00:00 2001 From: AViewFromTheTop Date: Wed, 25 Sep 2024 18:52:39 +0000 Subject: [PATCH 18/21] Apply automatic changes --- .../mixin/client/TextureManagerMixin.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/net/frozenblock/lib/image_transfer/mixin/client/TextureManagerMixin.java b/src/main/java/net/frozenblock/lib/image_transfer/mixin/client/TextureManagerMixin.java index bc1b0a004..14288db70 100644 --- a/src/main/java/net/frozenblock/lib/image_transfer/mixin/client/TextureManagerMixin.java +++ b/src/main/java/net/frozenblock/lib/image_transfer/mixin/client/TextureManagerMixin.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2024 FrozenBlock + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package net.frozenblock.lib.image_transfer.mixin.client; import net.frozenblock.lib.image_transfer.client.ServerTexture; From f180c896bbfa08eb087a356c6cca546687c72657 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Wed, 25 Sep 2024 15:05:29 -0400 Subject: [PATCH 19/21] better --- .../lib/image_transfer/client/ServerTexture.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java index cf1bd6ffb..9d119845d 100644 --- a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java +++ b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java @@ -55,6 +55,7 @@ public class ServerTexture extends SimpleTexture implements Tickable { private CompletableFuture future; private boolean uploaded; private long timeSinceLastReference; + private boolean isClosed; public ServerTexture(String destPath, String fileName, ResourceLocation fallback, @Nullable Runnable callback) { super(fallback); @@ -150,12 +151,18 @@ private NativeImage load(InputStream stream) { public void updateReferenceTime() { this.timeSinceLastReference = System.currentTimeMillis(); + if (this.isClosed) { + this.isClosed = false; + try { + this.load(Minecraft.getInstance().getResourceManager()); + } catch (Exception ignored) {} + } } @Override public void tick() { if (System.currentTimeMillis() - this.timeSinceLastReference > 5000) { - this.releaseId(); + this.getTextureImage(Minecraft.getInstance().getResourceManager()).close(); } } } From 1a2e73b0caaacffb62bcd14ffa8b303517a960d1 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Wed, 25 Sep 2024 15:07:32 -0400 Subject: [PATCH 20/21] Update ServerTexture.java --- .../frozenblock/lib/image_transfer/client/ServerTexture.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java index 9d119845d..fff69ced0 100644 --- a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java +++ b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java @@ -161,8 +161,9 @@ public void updateReferenceTime() { @Override public void tick() { - if (System.currentTimeMillis() - this.timeSinceLastReference > 5000) { + if (!this.isClosed && System.currentTimeMillis() - this.timeSinceLastReference > 5000) { this.getTextureImage(Minecraft.getInstance().getResourceManager()).close(); + this.isClosed = true; } } } From e8986396cc62c8f3536be2d724d38cbcf2b66843 Mon Sep 17 00:00:00 2001 From: AViewFromTheTop <87103914+AViewFromTheTop@users.noreply.github.com> Date: Wed, 25 Sep 2024 21:48:09 -0400 Subject: [PATCH 21/21] Update ServerTexture.java --- .../lib/image_transfer/client/ServerTexture.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java index fff69ced0..cc7d0277c 100644 --- a/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java +++ b/src/main/java/net/frozenblock/lib/image_transfer/client/ServerTexture.java @@ -25,6 +25,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -46,6 +47,7 @@ public class ServerTexture extends SimpleTexture implements Tickable { public static final Map WAITING_TEXTURES = new HashMap<>(); private static final Logger LOGGER = LogUtils.getLogger(); + public static final String LOCAL_TEXTURE_SOURCE = ".local"; private final File file; private final String destPath; private final String fileName; @@ -56,15 +58,21 @@ public class ServerTexture extends SimpleTexture implements Tickable { private boolean uploaded; private long timeSinceLastReference; private boolean isClosed; + boolean hasLocalSource; public ServerTexture(String destPath, String fileName, ResourceLocation fallback, @Nullable Runnable callback) { super(fallback); - this.file = Minecraft.getInstance().gameDirectory.toPath().resolve(destPath).resolve(fileName).toFile(); + Path path = Minecraft.getInstance().gameDirectory.toPath().resolve(destPath); + File possibleLocalFile = path.resolve(LOCAL_TEXTURE_SOURCE).resolve(fileName).toFile(); + this.hasLocalSource = possibleLocalFile.exists(); + this.file = this.hasLocalSource ? possibleLocalFile : path.resolve(fileName).toFile(); this.destPath = destPath; this.fileName = fileName; this.onDownloaded = callback; this.timeSinceLastReference = System.currentTimeMillis(); - WAITING_TEXTURES.put(this.destPath + "/" + this.fileName, this); + if (!this.hasLocalSource) { + WAITING_TEXTURES.put(this.destPath + "/" + this.fileName, this); + } } private void loadCallback(NativeImage image) {