From 251995f385ab0fe297c090897fb987cc1a0a667d Mon Sep 17 00:00:00 2001 From: Patbox Date: Sat, 9 Dec 2023 20:57:03 +0100 Subject: [PATCH] Update to 1.20.4 --- build.gradle | 26 ++- gradle.properties | 8 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../nucleoid/plasmid/PlasmidWebServer.java | 37 +++- .../nucleoid/plasmid/command/GameCommand.java | 2 +- .../plasmid/command/GamePortalCommand.java | 4 +- .../xyz/nucleoid/plasmid/game/GameSpace.java | 4 - .../plasmid/game/common/GameResourcePack.java | 80 ++++++-- .../plasmid/game/common/team/TeamManager.java | 4 +- .../game/manager/ManagedGameSpace.java | 8 - .../menu/AdvancedMenuPortalBackend.java | 3 +- .../game/portal/menu/MenuPortalBackend.java | 3 +- .../GameResourcePackManager.java | 177 ------------------ .../resource_packs/ResourcePackStates.java | 110 ----------- .../mixin/game/rule/TridentEntityMixin.java | 5 +- .../plasmid/util/IdentityHashStrategy.java | 17 ++ .../plasmid/util/ItemStackBuilder.java | 2 +- .../nucleoid/plasmid/util/PlasmidCodecs.java | 3 +- .../plasmid/test/TestInitializer.java | 5 +- 19 files changed, 138 insertions(+), 362 deletions(-) delete mode 100644 src/main/java/xyz/nucleoid/plasmid/game/resource_packs/GameResourcePackManager.java delete mode 100644 src/main/java/xyz/nucleoid/plasmid/game/resource_packs/ResourcePackStates.java create mode 100644 src/main/java/xyz/nucleoid/plasmid/util/IdentityHashStrategy.java diff --git a/build.gradle b/build.gradle index 6a9cd4cc..e9c4a401 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.1.+' + id 'fabric-loom' version '1.4.+' id 'maven-publish' id "com.modrinth.minotaur" version "2.+" } @@ -84,32 +84,30 @@ dependencies { modApi "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modApi include('xyz.nucleoid:server-translations-api:2.1.0+1.20.2-rc2') + modApi include('xyz.nucleoid:server-translations-api:2.2.0+1.20.3-rc1') modApi include('xyz.nucleoid:packet-tweaker:0.5.0+1.20.2-rc1') - modApi include('xyz.nucleoid:fantasy:0.4.11+1.20-rc1') + modApi include('xyz.nucleoid:fantasy:0.5.0+1.20.4') modApi include('xyz.nucleoid:more-codecs:0.3.3+1.20.2') - modApi include('xyz.nucleoid:stimuli:0.4.9+1.20.2') + modApi include('xyz.nucleoid:stimuli:0.4.10+1.20.4') modApi include('xyz.nucleoid:map-templates:0.1.8+1.20') modApi include('xyz.nucleoid:substrate:0.2.2+1.20.1') - modApi 'eu.pb4:polymer-core:0.6.0+1.20.2' - modApi 'eu.pb4:polymer-resource-pack:0.6.0+1.20.2' - modApi 'eu.pb4:polymer-blocks:0.6.0+1.20.2' - modApi 'eu.pb4:polymer-virtual-entity:0.6.0+1.20.2' + modApi 'eu.pb4:polymer-core:0.7.1+1.20.4' + modApi 'eu.pb4:polymer-resource-pack:0.7.1+1.20.4' + modApi 'eu.pb4:polymer-blocks:0.7.1+1.20.4' + modApi 'eu.pb4:polymer-virtual-entity:0.7.1+1.20.4' modApi include('eu.pb4:hologram-api:0.2.5+1.20.2') modApi include('eu.pb4:sgui:1.3.0+1.20.2') - modApi include('eu.pb4:sidebar-api:0.2.0+1.20.2') - modApi include("eu.pb4:placeholder-api:2.2.0+1.20.2") + modApi include('eu.pb4:sidebar-api:0.3.0+1.20.3') + modApi include("eu.pb4:placeholder-api:2.3.0+1.20.3") modApi include("eu.pb4:map-canvas-api:0.2.2+1.19.4") - modApi include("eu.pb4:player-data-api:0.3.0+1.20.2") + modApi include("eu.pb4:player-data-api:0.4.0+1.20.3") modApi include("eu.pb4:predicate-api:0.3.0+1.20.2") modCompileOnly('xyz.nucleoid:disguiselib-fabric:1.3.2') modCompileOnly('maven.modrinth:afkdisplay:1.1.0') - modCompileOnly('eu.pb4:polymer-autohost:0.6.0+1.20.2') + modCompileOnly('eu.pb4:polymer-autohost:0.7.1+1.20.4') modCompileOnly("dev.emi:trinkets:3.7.1") - implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${project.mixin_extras_version}")) - testmodImplementation sourceSets.main.output } diff --git a/gradle.properties b/gradle.properties index 115ce5ed..8dff6e21 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,9 +2,9 @@ org.gradle.jvmargs=-Xmx2G # Fabric Properties -minecraft_version=1.20.2 -yarn_mappings=1.20.2+build.1 -loader_version=0.14.22 +minecraft_version=1.20.4 +yarn_mappings=1.20.4+build.1 +loader_version=0.15.1 #Fabric api fabric_version=0.89.2+1.20.2 @@ -13,5 +13,3 @@ fabric_version=0.89.2+1.20.2 mod_version=0.5 maven_group=xyz.nucleoid archives_base_name=plasmid - -mixin_extras_version=0.2.0-rc.2 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e750102e..e411586a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/xyz/nucleoid/plasmid/PlasmidWebServer.java b/src/main/java/xyz/nucleoid/plasmid/PlasmidWebServer.java index a7ff38d3..0b51445d 100644 --- a/src/main/java/xyz/nucleoid/plasmid/PlasmidWebServer.java +++ b/src/main/java/xyz/nucleoid/plasmid/PlasmidWebServer.java @@ -6,19 +6,31 @@ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.MinecraftServer; -import org.apache.commons.io.IOUtils; +import net.minecraft.util.Util; import org.apache.http.HttpStatus; import org.jetbrains.annotations.Nullable; -import xyz.nucleoid.plasmid.game.resource_packs.GameResourcePackManager; import java.io.IOException; import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.Executors; public class PlasmidWebServer { public static final String RESOURCE_PACKS_ENDPOINT = "resource-packs"; + private static final Map RESOURCE_PACKS = new HashMap<>(); + + private static final String WEB_URL = Util.make(() -> { + var path = PlasmidConfig.get().userFacingPackAddress().orElse(""); + return path.endsWith("/") ? path : path + "/"; + + }); + @Nullable public static HttpServer start(MinecraftServer minecraftServer, Config config) { try { @@ -46,35 +58,40 @@ private static InetSocketAddress createBindAddress(MinecraftServer server, Confi } } + public static String registerResourcePack(String s, Path path) { + RESOURCE_PACKS.put(s, path); + return WEB_URL + s; + } + private record ResourcePacksHandler(String endpoint) implements HttpHandler { @Override public void handle(HttpExchange exchange) throws IOException { try (exchange) { - var resourcePacks = GameResourcePackManager.get(); - if (resourcePacks.isEmpty() || !this.tryHandle(exchange, resourcePacks.get())) { + if (!this.tryHandle(exchange)) { exchange.sendResponseHeaders(HttpStatus.SC_NOT_FOUND, 0); } } } - private boolean tryHandle(HttpExchange exchange, GameResourcePackManager resourcePacks) throws IOException { + private boolean tryHandle(HttpExchange exchange) throws IOException { if ("GET".equals(exchange.getRequestMethod())) { - return this.tryHandleGet(exchange, resourcePacks); + return this.tryHandleGet(exchange); } return false; } - private boolean tryHandleGet(HttpExchange exchange, GameResourcePackManager resourcePacks) throws IOException { + private boolean tryHandleGet(HttpExchange exchange) throws IOException { var path = exchange.getRequestURI().getPath().substring(this.endpoint.length() + 2); - var pack = resourcePacks.load(path); + var pack = RESOURCE_PACKS.get(path); if (pack != null) { + var size = Files.size(pack); try ( - var input = pack.openInputStream(); + var input = Files.newInputStream(pack); var output = exchange.getResponseBody() ) { exchange.getResponseHeaders().add("Server", "plasmid"); exchange.getResponseHeaders().add("Content-Type", "application/zip"); - exchange.sendResponseHeaders(HttpStatus.SC_OK, pack.getSize()); + exchange.sendResponseHeaders(HttpStatus.SC_OK, size); input.transferTo(output); output.flush(); diff --git a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java index 9367c0b1..99d5644e 100644 --- a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java +++ b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java @@ -319,7 +319,7 @@ private static int locatePlayer(CommandContext context) thr var gameSpace = GameSpaceManager.get().byPlayer(player); if (gameSpace == null) { - throw PLAYER_NOT_IN_GAME.create(player.getEntityName()); + throw PLAYER_NOT_IN_GAME.create(player.getName()); } context.getSource().sendFeedback(() -> GameTexts.Command.located(player, gameSpace), false); diff --git a/src/main/java/xyz/nucleoid/plasmid/command/GamePortalCommand.java b/src/main/java/xyz/nucleoid/plasmid/command/GamePortalCommand.java index afc8c5e3..4212679f 100644 --- a/src/main/java/xyz/nucleoid/plasmid/command/GamePortalCommand.java +++ b/src/main/java/xyz/nucleoid/plasmid/command/GamePortalCommand.java @@ -66,7 +66,7 @@ private static int connectEntity(CommandContext context) th } context.getSource().sendFeedback(() -> { - var message = Text.translatable("text.plasmid.game.portal.connect.entity", portal.getId(), entity.getEntityName()); + var message = Text.translatable("text.plasmid.game.portal.connect.entity", portal.getId(), entity.getName()); return message.formatted(Formatting.GRAY); }, false); @@ -107,7 +107,7 @@ private static int disconnectEntity(CommandContext context) portalInterface.invalidatePortal(); context.getSource().sendFeedback(() -> { - var message = Text.translatable("text.plasmid.game.portal.disconnect.entity", entity.getEntityName()); + var message = Text.translatable("text.plasmid.game.portal.disconnect.entity", entity.getName()); return message.formatted(Formatting.GRAY); }, false); diff --git a/src/main/java/xyz/nucleoid/plasmid/game/GameSpace.java b/src/main/java/xyz/nucleoid/plasmid/game/GameSpace.java index f219298c..24474036 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/GameSpace.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/GameSpace.java @@ -8,7 +8,6 @@ import xyz.nucleoid.plasmid.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; import xyz.nucleoid.plasmid.game.player.PlayerSet; -import xyz.nucleoid.plasmid.game.resource_packs.ResourcePackStates; import xyz.nucleoid.plasmid.game.world.GameSpaceWorlds; import java.util.function.Consumer; @@ -111,9 +110,6 @@ public interface GameSpace { */ boolean isClosed(); - ResourcePackStates getResourcePackStates(); - - @Nullable T getAttachment(String key); void setAttachment(String key, @Nullable Object obj); diff --git a/src/main/java/xyz/nucleoid/plasmid/game/common/GameResourcePack.java b/src/main/java/xyz/nucleoid/plasmid/game/common/GameResourcePack.java index eb0b18f9..6e355d98 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/common/GameResourcePack.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/common/GameResourcePack.java @@ -1,18 +1,26 @@ package xyz.nucleoid.plasmid.game.common; +import com.google.common.hash.Hashing; +import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils; import eu.pb4.polymer.resourcepack.api.ResourcePackCreator; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.network.packet.s2c.common.ResourcePackRemoveS2CPacket; import net.minecraft.network.packet.s2c.common.ResourcePackSendS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; -import org.jetbrains.annotations.ApiStatus; +import net.minecraft.util.Identifier; import xyz.nucleoid.plasmid.Plasmid; +import xyz.nucleoid.plasmid.PlasmidConfig; +import xyz.nucleoid.plasmid.PlasmidWebServer; import xyz.nucleoid.plasmid.game.GameActivity; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; -import xyz.nucleoid.plasmid.game.resource_packs.GameResourcePackManager; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; import java.util.Optional; - -// TODO: prevent resource-pack soft-lock +import java.util.UUID; /** * A very simple utility to apply a resource pack for all players within a {@link GameActivity}. @@ -20,14 +28,40 @@ * @see GameResourcePack#addTo(GameActivity) */ public final class GameResourcePack { + private static final Path RESOURCE_PACKS_ROOT = FabricLoader.getInstance().getGameDir() + .resolve("plasmid-generated/resource-packs"); + private final UUID uuid; + private final String url; private final String hash; private boolean required; private Text prompt; + private boolean isLocal; + public GameResourcePack(String url, String hash) { this.url = url; + this.uuid = UUID.nameUUIDFromBytes(hash.getBytes()); + this.hash = hash; + this.isLocal = false; + } + + public GameResourcePack(UUID uuid, String url, String hash) { + this.url = url; + this.uuid = uuid; + this.hash = hash; + this.isLocal = false; + } + + private GameResourcePack(UUID uuid, String url, String hash, Void unused) { + this.url = url; + this.uuid = uuid; this.hash = hash; + this.isLocal = true; + } + + public boolean isLocal() { + return this.isLocal; } /** @@ -57,26 +91,32 @@ public GameResourcePack setPrompt(Text prompt) { * @param activity the activity to add to */ public void addTo(GameActivity activity) { - var gameSpace = activity.getGameSpace(); + activity.listen(GamePlayerEvents.ADD, this::sendTo); + activity.listen(GamePlayerEvents.REMOVE, this::unload); + } - activity.listen(GamePlayerEvents.ADD, player -> { - gameSpace.getResourcePackStates().setFor(player, this); - }); + private void sendTo(ServerPlayerEntity player) { + player.networkHandler.sendPacket(new ResourcePackSendS2CPacket(this.uuid, this.url, this.hash, this.required, this.prompt)); } - @ApiStatus.Internal - public void sendTo(ServerPlayerEntity player) { - player.networkHandler.sendPacket(new ResourcePackSendS2CPacket(this.url, this.hash, this.required, this.prompt)); + private void unload(ServerPlayerEntity player) { + player.networkHandler.sendPacket(new ResourcePackRemoveS2CPacket(Optional.of(this.uuid))); } - public static Optional tryRegister(ResourcePackCreator creator) { - return GameResourcePackManager.get().flatMap(packs -> { - try { - return Optional.of(packs.register(creator)); - } catch (Exception e) { - Plasmid.LOGGER.error("Failed to generate resource pack", e); - return Optional.empty(); - } - }); + public static Optional from(Identifier identifier, ResourcePackCreator creator) { + try { + var relative = identifier.getNamespace() + "/" + identifier.getPath() + ".zip"; + var path = RESOURCE_PACKS_ROOT.resolve(relative); + Files.createDirectories(path.getParent()); + creator.build(path); + + var hash = com.google.common.io.Files.asByteSource(path.toFile()).hash(Hashing.sha1()).toString(); + + var url = PlasmidWebServer.registerResourcePack(relative, path); + return Optional.of(new GameResourcePack(UUID.nameUUIDFromBytes(hash.getBytes(StandardCharsets.UTF_8)), url, hash, null)); + } catch (Throwable e) { + Plasmid.LOGGER.error("Failed to create a resource pack '" + identifier + "'!", e); + return Optional.empty(); + } } } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/common/team/TeamManager.java b/src/main/java/xyz/nucleoid/plasmid/game/common/team/TeamManager.java index c469d788..e7c6f7ce 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/common/team/TeamManager.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/common/team/TeamManager.java @@ -363,7 +363,7 @@ private void sendRemoveTeamsForPlayer(ServerPlayerEntity player) { private void addOnlinePlayer(ServerPlayerEntity player, State state) { state.onlinePlayers.add(player); - state.scoreboardTeam.getPlayerList().add(player.getEntityName()); + state.scoreboardTeam.getPlayerList().add(player.getNameForScoreboard()); this.sendPacketToAll(this.changePlayerTeam(player, state, TeamS2CPacket.Operation.ADD)); this.sendPacketToAll(this.resetPlayerName(player)); @@ -371,7 +371,7 @@ private void addOnlinePlayer(ServerPlayerEntity player, State state) { private void removeOnlinePlayer(ServerPlayerEntity player, State state) { state.onlinePlayers.remove(player); - state.scoreboardTeam.getPlayerList().remove(player.getEntityName()); + state.scoreboardTeam.getPlayerList().remove(player.getNameForScoreboard()); this.sendPacketToAll(this.changePlayerTeam(player, state, TeamS2CPacket.Operation.REMOVE)); this.sendPacketToAll(this.resetPlayerName(player)); diff --git a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java index 160465ac..8572fdf5 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java @@ -15,7 +15,6 @@ import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; import xyz.nucleoid.plasmid.game.player.PlayerOffer; import xyz.nucleoid.plasmid.game.player.PlayerOfferResult; -import xyz.nucleoid.plasmid.game.resource_packs.ResourcePackStates; import java.util.Collection; import java.util.HashMap; @@ -36,7 +35,6 @@ public final class ManagedGameSpace implements GameSpace { private final long openTime; private final GameActivityState state = new GameActivityState(this); - private final ResourcePackStates resourcePackStateManager = new ResourcePackStates(this); private boolean closed; private final GameSpaceStatistics statistics = new GameSpaceStatistics(); @@ -171,12 +169,6 @@ public GameSpaceStatistics getStatistics() { public boolean isClosed() { return this.closed; } - - @Override - public ResourcePackStates getResourcePackStates() { - return this.resourcePackStateManager; - } - @Override public T getAttachment(String key) { //noinspection unchecked diff --git a/src/main/java/xyz/nucleoid/plasmid/game/portal/menu/AdvancedMenuPortalBackend.java b/src/main/java/xyz/nucleoid/plasmid/game/portal/menu/AdvancedMenuPortalBackend.java index e7c93d8e..1e4d1629 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/portal/menu/AdvancedMenuPortalBackend.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/portal/menu/AdvancedMenuPortalBackend.java @@ -15,6 +15,7 @@ import xyz.nucleoid.plasmid.game.portal.GamePortalBackend; import xyz.nucleoid.plasmid.game.portal.GamePortalDisplay; import xyz.nucleoid.plasmid.util.Guis; +import xyz.nucleoid.plasmid.util.IdentityHashStrategy; import java.util.ArrayList; import java.util.HashSet; @@ -58,7 +59,7 @@ public ItemStack getIcon() { @Override public int getPlayerCount() { int count = 0; - var list = new ObjectOpenCustomHashSet(Util.identityHashStrategy()); + var list = new ObjectOpenCustomHashSet(IdentityHashStrategy.INSTANCE); provideGameSpaces(list::add); for (var entry : list) { count += Math.max(0, entry.getPlayers().size()); diff --git a/src/main/java/xyz/nucleoid/plasmid/game/portal/menu/MenuPortalBackend.java b/src/main/java/xyz/nucleoid/plasmid/game/portal/menu/MenuPortalBackend.java index fecc4f83..02658b93 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/portal/menu/MenuPortalBackend.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/portal/menu/MenuPortalBackend.java @@ -17,6 +17,7 @@ import xyz.nucleoid.plasmid.game.portal.GamePortalDisplay; import xyz.nucleoid.plasmid.game.portal.game.ConcurrentGamePortalBackend; import xyz.nucleoid.plasmid.util.Guis; +import xyz.nucleoid.plasmid.util.IdentityHashStrategy; import java.util.ArrayList; import java.util.List; @@ -55,7 +56,7 @@ public ItemStack getIcon() { @Override public int getPlayerCount() { int count = 0; - var list = new ObjectOpenCustomHashSet(Util.identityHashStrategy()); + var list = new ObjectOpenCustomHashSet(IdentityHashStrategy.INSTANCE); provideGameSpaces(list::add); for (var entry : list) { count += Math.max(0, entry.getPlayers().size()); diff --git a/src/main/java/xyz/nucleoid/plasmid/game/resource_packs/GameResourcePackManager.java b/src/main/java/xyz/nucleoid/plasmid/game/resource_packs/GameResourcePackManager.java deleted file mode 100644 index 28a70eb1..00000000 --- a/src/main/java/xyz/nucleoid/plasmid/game/resource_packs/GameResourcePackManager.java +++ /dev/null @@ -1,177 +0,0 @@ -package xyz.nucleoid.plasmid.game.resource_packs; - -import com.google.common.hash.Hashing; -import com.google.gson.JsonObject; -import eu.pb4.polymer.resourcepack.api.ResourcePackCreator; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.SharedConstants; -import net.minecraft.util.Util; -import org.jetbrains.annotations.Nullable; -import xyz.nucleoid.plasmid.Plasmid; -import xyz.nucleoid.plasmid.PlasmidConfig; -import xyz.nucleoid.plasmid.game.common.GameResourcePack; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.nio.file.StandardOpenOption; -import java.util.Map; -import java.util.Optional; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -/** - * Manager for all resource packs tracked by the server. - * - * @see GameResourcePack - */ -public final class GameResourcePackManager { - private static final Path ROOT = FabricLoader.getInstance().getGameDir() - .resolve("plasmid-generated/resource-packs"); - - private static final Path TEMPORARY = ROOT.resolve("tmp.zip"); - - private static GameResourcePackManager instance; - - private final String packEndpoint; - - private final Map hashToServedPack = new Object2ObjectOpenHashMap<>(); - private GameResourcePack emptyPack; - - private GameResourcePackManager(String packEndpoint) { - this.packEndpoint = packEndpoint; - } - - public static Optional get() { - var instance = GameResourcePackManager.instance; - if (instance == null) { - var packEndpoint = PlasmidConfig.get().userFacingPackAddress(); - if (packEndpoint.isPresent()) { - GameResourcePackManager.instance = instance = new GameResourcePackManager(packEndpoint.get()); - } - } - - return Optional.ofNullable(instance); - } - - public static Optional emptyPack() { - return get().flatMap(packs -> { - try { - return Optional.of(packs.getEmptyPack()); - } catch (Exception e) { - Plasmid.LOGGER.error("Failed to build empty resource pack", e); - return Optional.empty(); - } - }); - } - - @Nullable - public GameResourcePackManager.ServedPack load(String query) { - var pack = this.hashToServedPack.get(query); - if (pack == null) { - return null; - } - - if (!Files.exists(pack.path)) { - this.hashToServedPack.remove(query); - return null; - } - - return pack; - } - - /** - * Generates resource pack from Polymer's {@link ResourcePackCreator} - * Created GameResourcePack instance should be stored and used for multiple GameActivities - * - * @param creator Polymer {@link ResourcePackCreator} - * @return Instance of {@link GameResourcePack} - */ - public GameResourcePack register(ResourcePackCreator creator) throws Exception { - return this.register(creator::build); - } - - public GameResourcePack register(Builder builder) throws Exception { - Files.createDirectories(ROOT); - - synchronized (TEMPORARY) { - Files.deleteIfExists(TEMPORARY); - builder.accept(TEMPORARY); - - var hash = hash(TEMPORARY); - var path = this.getPathFor(hash); - - Files.move(TEMPORARY, path, StandardCopyOption.REPLACE_EXISTING); - - var pack = new ServedPack(path, Files.size(path)); - this.hashToServedPack.put(hash, pack); - - return new GameResourcePack(this.getUrlFor(hash), hash); - } - } - - private String getUrlFor(String hash) { - return this.packEndpoint + "/" + hash; - } - - public GameResourcePack getEmptyPack() throws Exception { - var emptyPack = this.emptyPack; - if (emptyPack == null) { - this.emptyPack = emptyPack = this.register(this::buildEmptyPack); - } - - return emptyPack; - } - - private Path getPathFor(String hash) { - return ROOT.resolve(hash + ".zip"); - } - - private void buildEmptyPack(Path path) throws Exception { - try (var output = new ZipOutputStream(Files.newOutputStream(path, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING))) { - var json = new JsonObject(); - json.add("pack", Util.make(() -> { - var pack = new JsonObject(); - pack.addProperty("pack_format", SharedConstants.RESOURCE_PACK_VERSION); - pack.addProperty("description", "Empty Resource Pack"); - return pack; - })); - - var entry = new ZipEntry("pack.mcmeta"); - entry.setTime(0); - output.putNextEntry(entry); - output.write(json.toString().getBytes(StandardCharsets.UTF_8)); - output.closeEntry(); - } - } - - private static String hash(Path path) throws IOException { - return com.google.common.io.Files.asByteSource(path.toFile()).hash(Hashing.sha1()).toString(); - } - - public interface Builder { - void accept(Path path) throws Exception; - } - - public static final class ServedPack { - private final Path path; - private final long size; - - private ServedPack(Path path, long size) { - this.path = path; - this.size = size; - } - - public InputStream openInputStream() throws IOException { - return Files.newInputStream(this.path); - } - - public long getSize() { - return this.size; - } - } -} diff --git a/src/main/java/xyz/nucleoid/plasmid/game/resource_packs/ResourcePackStates.java b/src/main/java/xyz/nucleoid/plasmid/game/resource_packs/ResourcePackStates.java deleted file mode 100644 index 93646b24..00000000 --- a/src/main/java/xyz/nucleoid/plasmid/game/resource_packs/ResourcePackStates.java +++ /dev/null @@ -1,110 +0,0 @@ -package xyz.nucleoid.plasmid.game.resource_packs; - -import eu.pb4.polymer.autohost.api.ResourcePackDataProvider; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.network.packet.s2c.common.ResourcePackSendS2CPacket; -import net.minecraft.server.network.ServerPlayerEntity; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; -import xyz.nucleoid.plasmid.game.GameActivity; -import xyz.nucleoid.plasmid.game.GameLifecycle; -import xyz.nucleoid.plasmid.game.GameSpace; -import xyz.nucleoid.plasmid.game.common.GameResourcePack; - -import java.util.Map; -import java.util.UUID; - -public final class ResourcePackStates { - private static final boolean IS_AUTOHOST_PRESENT = FabricLoader.getInstance().isModLoaded("polymer-autohost"); - - private Map resourcePacks = new Object2ObjectOpenHashMap<>(); - private Map oldResourcePacks = new Object2ObjectOpenHashMap<>(); - private boolean active = false; - - @ApiStatus.Internal - public ResourcePackStates(GameSpace gameSpace) { - gameSpace.getLifecycle().addListeners(new GameLifecycle.Listeners() { - @Override - public void onRemovePlayer(GameSpace gameSpace, ServerPlayerEntity player) { - ResourcePackStates.this.setFor(player, null); - } - - @Override - public void beforeActivityChange(GameSpace gameSpace, GameActivity newActivity, @Nullable GameActivity oldActivity) { - ResourcePackStates.this.oldResourcePacks = ResourcePackStates.this.resourcePacks; - ResourcePackStates.this.resourcePacks = new Object2ObjectOpenHashMap<>(); - - ResourcePackStates.this.active = false; - } - - @Override - public void afterActivityChange(GameSpace gameSpace, GameActivity newActivity, @Nullable GameActivity oldActivity) { - var oldPacks = ResourcePackStates.this.oldResourcePacks; - var newPacks = ResourcePackStates.this.resourcePacks; - - for (var player : gameSpace.getPlayers()) { - var previousPack = oldPacks.get(player.getUuid()); - var currentPack = newPacks.get(player.getUuid()); - - if (currentPack != previousPack) { - if (currentPack == null) { - resetPack(player); - } else { - currentPack.sendTo(player); - } - } - } - - ResourcePackStates.this.active = true; - } - }); - } - - private static void resetPack(ServerPlayerEntity player) { - if (IS_AUTOHOST_PRESENT) { - var current = ResourcePackDataProvider.getActive(); - - if (current != null && current.isReady()) { - player.networkHandler.sendPacket(new ResourcePackSendS2CPacket(current.getAddress(), current.getHash(), true, null)); - return; - } - } - - player.getServer().getResourcePackProperties().ifPresentOrElse( - properties -> player.networkHandler.sendPacket(new ResourcePackSendS2CPacket(properties.url(), properties.hash(), true, properties.prompt())), - () -> GameResourcePackManager.emptyPack().ifPresent(pack -> pack.sendTo(player)) - ); - } - - /** - * Gets player's current {@link GameResourcePack} - * - * @param player player - * @return {@link GameResourcePack} or null - */ - @Nullable - public GameResourcePack getFor(ServerPlayerEntity player) { - return this.resourcePacks.get(player.getUuid()); - } - - /** - * Sets resource pack state for player, used to limit resource pack reloads on activity changes - * - * @param player the player to set the resource pack for - * @param pack {@link GameResourcePack}'s of player - */ - public void setFor(ServerPlayerEntity player, GameResourcePack pack) { - if (pack == null) { - var oldPack = this.resourcePacks.remove(player.getUuid()); - if (this.active && oldPack != null && !player.isDisconnected()) { - resetPack(player); - } - } else if (this.getFor(player) != pack) { - this.resourcePacks.put(player.getUuid(), pack); - if (this.active) { - pack.sendTo(player); - } - } - } -} diff --git a/src/main/java/xyz/nucleoid/plasmid/mixin/game/rule/TridentEntityMixin.java b/src/main/java/xyz/nucleoid/plasmid/mixin/game/rule/TridentEntityMixin.java index 5fe7b195..48eb79d4 100644 --- a/src/main/java/xyz/nucleoid/plasmid/mixin/game/rule/TridentEntityMixin.java +++ b/src/main/java/xyz/nucleoid/plasmid/mixin/game/rule/TridentEntityMixin.java @@ -3,6 +3,7 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.projectile.PersistentProjectileEntity; import net.minecraft.entity.projectile.TridentEntity; +import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; @@ -18,8 +19,8 @@ public abstract class TridentEntityMixin extends PersistentProjectileEntity { @Shadow private boolean dealtDamage; - private TridentEntityMixin(EntityType type, World world) { - super(type, world); + protected TridentEntityMixin(EntityType type, World world, ItemStack stack) { + super(type, world, stack); } @Inject(method = "tick", at = @At("HEAD")) diff --git a/src/main/java/xyz/nucleoid/plasmid/util/IdentityHashStrategy.java b/src/main/java/xyz/nucleoid/plasmid/util/IdentityHashStrategy.java new file mode 100644 index 00000000..fa63d951 --- /dev/null +++ b/src/main/java/xyz/nucleoid/plasmid/util/IdentityHashStrategy.java @@ -0,0 +1,17 @@ +package xyz.nucleoid.plasmid.util; + +import it.unimi.dsi.fastutil.Hash; + +public enum IdentityHashStrategy implements Hash.Strategy { + INSTANCE; + + @Override + public int hashCode(Object o) { + return System.identityHashCode(o); + } + + @Override + public boolean equals(Object o, Object k1) { + return false; + } +} diff --git a/src/main/java/xyz/nucleoid/plasmid/util/ItemStackBuilder.java b/src/main/java/xyz/nucleoid/plasmid/util/ItemStackBuilder.java index 2d428ccb..c5c471c8 100644 --- a/src/main/java/xyz/nucleoid/plasmid/util/ItemStackBuilder.java +++ b/src/main/java/xyz/nucleoid/plasmid/util/ItemStackBuilder.java @@ -131,7 +131,7 @@ public ItemStackBuilder addLore(Text text) { display.put("Lore", loreList); } - loreList.add(NbtString.of(Text.Serializer.toJson(text))); + loreList.add(NbtString.of(Text.Serialization.toJsonString(text))); return this; } diff --git a/src/main/java/xyz/nucleoid/plasmid/util/PlasmidCodecs.java b/src/main/java/xyz/nucleoid/plasmid/util/PlasmidCodecs.java index a15d2d03..5ae3266e 100644 --- a/src/main/java/xyz/nucleoid/plasmid/util/PlasmidCodecs.java +++ b/src/main/java/xyz/nucleoid/plasmid/util/PlasmidCodecs.java @@ -4,12 +4,13 @@ import com.mojang.serialization.Codec; import eu.pb4.placeholders.api.TextParserUtils; import net.minecraft.text.Text; +import net.minecraft.text.TextCodecs; import net.minecraft.util.dynamic.Codecs; import java.util.function.Function; public final class PlasmidCodecs { - public static Codec TEXT = Codec.either(Codec.STRING, Codecs.TEXT) + public static Codec TEXT = Codec.either(Codec.STRING, TextCodecs.CODEC) .xmap(either -> either.map(TextParserUtils::formatTextSafe, Function.identity()), Either::right); private PlasmidCodecs() {} diff --git a/src/testmod/java/xyz/nucleoid/plasmid/test/TestInitializer.java b/src/testmod/java/xyz/nucleoid/plasmid/test/TestInitializer.java index 71903059..7606a13d 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/TestInitializer.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/TestInitializer.java @@ -36,7 +36,7 @@ public class TestInitializer implements ModInitializer { CREATOR.requestModel(Items.NOTE_BLOCK, id("block/chair")) ); - public static Optional resourcePack = Optional.empty(); + public static Optional resourcePack; @Override public void onInitialize() { @@ -49,7 +49,8 @@ public void onInitialize() { CREATOR.addAssetSource("plasmid-test-mod"); - resourcePack = GameResourcePack.tryRegister(CREATOR); + resourcePack = GameResourcePack.from(new Identifier(ID, "test"), CREATOR); + } private static final Identifier id(String path) {