From d5a6594ac6b912fd1c9704c27250214e275e629f Mon Sep 17 00:00:00 2001 From: Patbox <39821509+Patbox@users.noreply.github.com> Date: Sun, 11 Jun 2023 17:52:21 +0200 Subject: [PATCH] Bump version to 0.5.0, fix compatibility with Immersive Portals for Virtual Entity API --- gradle.properties | 4 +- polymer-autohost/build.gradle | 8 +-- polymer-blocks/build.gradle | 1 - polymer-common/build.gradle | 4 +- .../common/api/PolymerCommonUtils.java | 2 +- polymer-core/build.gradle | 7 ++- .../impl/compat/ImmersivePortalsUtils.java | 9 ++- .../core/impl/networking/PacketPatcher.java | 4 +- .../polymer/resourcepack/api/AssetPaths.java | 62 +++++++++++++++++++ .../api/PolymerResourcePackUtils.java | 1 + .../resourcepack/api/ResourcePackBuilder.java | 2 + .../impl/generation/DefaultRPBuilder.java | 49 +++++++++------ polymer-virtual-entity/build.gradle | 3 + .../virtualentity/api/ElementHolder.java | 16 +++++ .../virtualentity/api/VirtualEntityUtils.java | 36 ++++++++++- .../api/attachment/ChunkAttachment.java | 26 +++++--- .../impl/compat/ImmersivePortalsUtils.java | 20 ++++++ ...PolymerVirtualEntityMixinConfigPlugin.java | 1 - .../mixin/ServerPlayerEntityMixin.java | 4 +- .../block/ThreadedAnvilChunkStorageMixin.java | 2 +- .../compat/ip_ChunkDataSyncManagerMixin.java | 59 ++++++++++++++++++ .../polymer-virtual-entity.mixins.json | 3 +- 22 files changed, 268 insertions(+), 55 deletions(-) create mode 100644 polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/AssetPaths.java create mode 100644 polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/impl/compat/ImmersivePortalsUtils.java create mode 100644 polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/compat/ip_ChunkDataSyncManagerMixin.java diff --git a/gradle.properties b/gradle.properties index 43fb0319..f45f6938 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,10 +12,10 @@ fabric_version=0.82.1+1.20 maven_group = eu.pb4 -mod_version = 0.5.0-rc.3 +mod_version = 0.5.0 minecraft_version_supported = ">=1.20-" packet_tweaker_version = 0.4.0+1.19.4 -is_stable = false +is_stable = true diff --git a/polymer-autohost/build.gradle b/polymer-autohost/build.gradle index d9ea8f52..b231baf5 100644 --- a/polymer-autohost/build.gradle +++ b/polymer-autohost/build.gradle @@ -23,13 +23,11 @@ loom { dependencies { modRuntimeOnly "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_version}" //modCompileOnly "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_version}" - - modImplementation "xyz.nucleoid:packet-tweaker:0.3.0+1.18.2" //modCompileOnly "me.lucko:fabric-permissions-api:0.1-SNAPSHOT" - implementation (project(path: ':polymer-common', configuration: 'namedElements')) - implementation (project(path: ':polymer-resource-pack', configuration: 'namedElements')) - implementation (project(path: ':polymer-networking', configuration: 'namedElements')) + api (project(path: ':polymer-common', configuration: 'namedElements')) + api (project(path: ':polymer-resource-pack', configuration: 'namedElements')) + api (project(path: ':polymer-networking', configuration: 'namedElements')) testmodImplementation sourceSets.main.output diff --git a/polymer-blocks/build.gradle b/polymer-blocks/build.gradle index f7459c48..aab7b315 100644 --- a/polymer-blocks/build.gradle +++ b/polymer-blocks/build.gradle @@ -33,7 +33,6 @@ dependencies { implementation(project(path: ':polymer-core', configuration: 'namedElements')) implementation(project(path: ':polymer-common', configuration: 'namedElements')) implementation(project(path: ':polymer-resource-pack', configuration: 'namedElements')) - modImplementation "xyz.nucleoid:packet-tweaker:0.3.0+1.18.2" modCompileOnly "me.lucko:fabric-permissions-api:0.1-SNAPSHOT" //modLocalRuntime "fr.catcore:server-translations-api:1.4.9+1.18.2-rc1" diff --git a/polymer-common/build.gradle b/polymer-common/build.gradle index 10801a94..f03287a7 100644 --- a/polymer-common/build.gradle +++ b/polymer-common/build.gradle @@ -8,7 +8,9 @@ loom { dependencies { modCompileOnly ("me.lucko:fabric-permissions-api:0.1-SNAPSHOT") - modApi include("xyz.nucleoid:packet-tweaker:${packet_tweaker_version}") + modApi include("xyz.nucleoid:packet-tweaker:${packet_tweaker_version}") { + transitive(false) + } modCompileOnly "xyz.nucleoid:disguiselib-fabric:1.2.2" } diff --git a/polymer-common/src/main/java/eu/pb4/polymer/common/api/PolymerCommonUtils.java b/polymer-common/src/main/java/eu/pb4/polymer/common/api/PolymerCommonUtils.java index 7ed93d35..2f378002 100644 --- a/polymer-common/src/main/java/eu/pb4/polymer/common/api/PolymerCommonUtils.java +++ b/polymer-common/src/main/java/eu/pb4/polymer/common/api/PolymerCommonUtils.java @@ -24,7 +24,7 @@ private PolymerCommonUtils(){} public static final SimpleEvent ON_RESOURCE_PACK_STATUS_CHANGE = new SimpleEvent<>(); - private final static String SAFE_CLIENT_SHA1 = "958928a560c9167687bea0cefeb7375da1e552a8"; + private final static String SAFE_CLIENT_SHA1 = "e575a48efda46cf88111ba05b624ef90c520eef1"; private final static String SAFE_CLIENT_URL = "https://piston-data.mojang.com/v1/objects/" + SAFE_CLIENT_SHA1 + "/client.jar"; @Nullable public static Path getClientJar() { diff --git a/polymer-core/build.gradle b/polymer-core/build.gradle index b22f4052..5a8869f7 100644 --- a/polymer-core/build.gradle +++ b/polymer-core/build.gradle @@ -81,9 +81,12 @@ dependencies { modCompileOnly("xyz.nucleoid:server-translations-api:2.0.0-beta.2+1.19.4-pre2") modLocalRuntime("xyz.nucleoid:server-translations-api:2.0.0-beta.2+1.19.4-pre2") - modCompileOnly 'com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:v2.5.1-mc1.19.3' - modCompileOnly 'com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:v2.5.1-mc1.19.3' + modCompileOnly 'com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:v3.0.2-mc1.20' + //modLocalRuntime 'com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:v3.0.2-mc1.20' + modCompileOnly 'com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:v3.0.2-mc1.20' + //modLocalRuntime 'com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:v3.0.2-mc1.20' + //modLocalRuntime 'maven.modrinth:immersiveportals:v3.0.2-mc1.20' // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. // You may need to force-disable transitiveness on them. diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/compat/ImmersivePortalsUtils.java b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/compat/ImmersivePortalsUtils.java index d93017ca..b6271300 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/compat/ImmersivePortalsUtils.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/compat/ImmersivePortalsUtils.java @@ -1,6 +1,5 @@ package eu.pb4.polymer.core.impl.compat; -import eu.pb4.polymer.common.api.PolymerCommonUtils; import eu.pb4.polymer.core.impl.networking.BlockPacketUtil; import net.minecraft.network.packet.Packet; import net.minecraft.server.network.ServerPlayNetworkHandler; @@ -10,11 +9,11 @@ public class ImmersivePortalsUtils { public static void sendBlockPackets(ServerPlayNetworkHandler handler, Packet packet) { if (packet instanceof IECustomPayloadPacket attachedPacket && attachedPacket.ip_getRedirectedPacket() != null && attachedPacket.ip_getRedirectedDimension() != null) { - PolymerCommonUtils.executeWithPlayerContext(handler.player, () -> { - PacketRedirection.withForceRedirect(handler.player.getServer().getWorld(attachedPacket.ip_getRedirectedDimension()), () -> { - BlockPacketUtil.sendFromPacket(attachedPacket.ip_getRedirectedPacket(), handler); - }); + PacketRedirection.withForceRedirect(handler.player.getServer().getWorld(attachedPacket.ip_getRedirectedDimension()), () -> { + BlockPacketUtil.sendFromPacket(attachedPacket.ip_getRedirectedPacket(), handler); }); + } else { + BlockPacketUtil.sendFromPacket(packet, handler); } } } diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/PacketPatcher.java b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/PacketPatcher.java index ef6e6b18..35e09e01 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/PacketPatcher.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/PacketPatcher.java @@ -76,9 +76,9 @@ public static Packet replace(ServerPlayNetworkHandler public static void sendExtra(ServerPlayNetworkHandler handler, Packet packet) { if (CompatStatus.IMMERSIVE_PORTALS) { ImmersivePortalsUtils.sendBlockPackets(handler, packet); + } else { + BlockPacketUtil.sendFromPacket(packet, handler); } - - BlockPacketUtil.sendFromPacket(packet, handler); } public static boolean prevent(ServerPlayNetworkHandler handler, Packet packet) { diff --git a/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/AssetPaths.java b/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/AssetPaths.java new file mode 100644 index 00000000..7e5a9ba4 --- /dev/null +++ b/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/AssetPaths.java @@ -0,0 +1,62 @@ +package eu.pb4.polymer.resourcepack.api; + +import net.minecraft.util.Identifier; + +public final class AssetPaths { + public static String PACK_METADATA = "pack.mcmeta"; + public static String PACK_ICON = "pack.png"; + + private AssetPaths() {} + + public static String texture(String namespace, String path) { + return "assets/" + namespace + "/textures/" + path; + } + + public static String model(String namespace, String path) { + return "assets/" + namespace + "/models/" + path; + } + + public static String model(Identifier id) { + return model(id.getNamespace(), id.getPath()); + } + + public static String texture(Identifier id) { + return texture(id.getNamespace(), id.getPath()); + } + + public static String blockModel(Identifier id) { + return model(id.getNamespace(), "block/" + id.getPath() + ".json"); + } + + public static String blockTexture(Identifier id) { + return texture(id.getNamespace(), "block/" + id.getPath() + ".png"); + } + + public static String blockTextureMetadata(Identifier id) { + return texture(id.getNamespace(), "block/" + id.getPath() + ".png.mcmeta"); + } + + public static String itemModel(Identifier id) { + return model(id.getNamespace(), "item/" + id.getPath() + ".json"); + } + + public static String itemTexture(Identifier id) { + return texture(id.getNamespace(), "item/" + id.getPath() + ".png"); + } + + public static String itemTextureMetadata(Identifier id) { + return texture(id.getNamespace(), "item/" + id.getPath() + ".png.mcmeta"); + } + + public static String armorTexture(Identifier id, int layer) { + return texture(id.getNamespace(), "models/armor/" + id.getPath() + "_layer_" + layer + ".png"); + } + + public static String armorOverlayTexture(Identifier id, int layer) { + return texture(id.getNamespace(), "models/armor/" + id.getPath() + "_layer_" + layer + "_overlay.png"); + } + + public static String armorTexturePolymerMetadata(Identifier id, int layer) { + return texture(id.getNamespace(), "models/armor/" + id.getPath() + "_layer_" + layer + ".polymer.json"); + } +} diff --git a/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/PolymerResourcePackUtils.java b/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/PolymerResourcePackUtils.java index d87c4a6c..c28004ec 100644 --- a/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/PolymerResourcePackUtils.java +++ b/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/PolymerResourcePackUtils.java @@ -32,6 +32,7 @@ private PolymerResourcePackUtils() { private static final ResourcePackCreator INSTANCE = new ResourcePackCreator(PolymerResourcePackImpl.USE_OFFSET ? PolymerResourcePackImpl.OFFSET_VALUES : 1); public static final SimpleEvent> RESOURCE_PACK_CREATION_EVENT = INSTANCE.creationEvent; + public static final SimpleEvent> RESOURCE_PACK_AFTER_INITIAL_CREATION_EVENT = INSTANCE.afterInitialCreationEvent; public static final SimpleEvent RESOURCE_PACK_FINISHED_EVENT = INSTANCE.finishedEvent; private static boolean REQUIRED = PolymerResourcePackImpl.FORCE_REQUIRE; private static boolean DEFAULT_CHECK = true; diff --git a/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/ResourcePackBuilder.java b/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/ResourcePackBuilder.java index 95220f02..40ff19d7 100644 --- a/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/ResourcePackBuilder.java +++ b/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/api/ResourcePackBuilder.java @@ -17,4 +17,6 @@ default boolean copyFromPath(Path path) { boolean addArmorModel(PolymerArmorModel model); @Nullable byte[] getData(String path); + @Nullable + byte[] getDataOrVanilla(String path); } diff --git a/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/impl/generation/DefaultRPBuilder.java b/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/impl/generation/DefaultRPBuilder.java index af5109ad..78e44c25 100644 --- a/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/impl/generation/DefaultRPBuilder.java +++ b/polymer-resource-pack/src/main/java/eu/pb4/polymer/resourcepack/impl/generation/DefaultRPBuilder.java @@ -6,6 +6,7 @@ import eu.pb4.polymer.common.api.events.SimpleEvent; import eu.pb4.polymer.common.impl.CommonImpl; import eu.pb4.polymer.common.impl.CommonImplUtils; +import eu.pb4.polymer.resourcepack.api.AssetPaths; import eu.pb4.polymer.resourcepack.api.PolymerArmorModel; import eu.pb4.polymer.resourcepack.api.PolymerModelData; import eu.pb4.polymer.resourcepack.impl.ArmorTextureMetadata; @@ -34,6 +35,9 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import static eu.pb4.polymer.resourcepack.api.AssetPaths.armorOverlayTexture; +import static eu.pb4.polymer.resourcepack.api.AssetPaths.armorTexture; + @SuppressWarnings("ResultOfMethodCallIgnored") @ApiStatus.Internal public class DefaultRPBuilder implements InternalRPBuilder { @@ -200,7 +204,7 @@ public boolean addCustomModelData(PolymerModelData cmdInfo) { jsonArray.add(jsonObject); } JsonObject modelObject = null; - var modelPath = "assets/" + cmdInfo.modelPath().getNamespace() + "/models/" + cmdInfo.modelPath().getPath() + ".json"; + var modelPath = AssetPaths.model(cmdInfo.modelPath().getNamespace(), cmdInfo.modelPath().getPath() + ".json"); if (this.fileMap.containsKey(modelPath)) { modelObject = JsonParser.parseString(new String(this.fileMap.get(modelPath), StandardCharsets.UTF_8)).getAsJsonObject(); @@ -249,6 +253,7 @@ public byte[] getData(String path) { return this.fileMap.get(path); } + @Override @Nullable public byte[] getDataOrVanilla(String path) { if (this.fileMap.containsKey(path)) { @@ -266,7 +271,7 @@ private byte[] getVanillaData(String path) { return stream.readAllBytes(); } } catch (Throwable e) { - CommonImpl.LOGGER.warn("Error occurred while getting data from vanilla jar! {}", e); + CommonImpl.LOGGER.warn("Error occurred while getting data from vanilla jar!", e); } return null; } @@ -275,16 +280,17 @@ private byte[] getVanillaData(String path) { private InputStream getVanillaStream(String path) { try { if (this.clientJar == null) { + //noinspection ConstantConditions this.clientJar = FileSystems.newFileSystem(PolymerCommonUtils.getClientJar()); } var entry = this.clientJar.getPath(path); - if (entry != null && Files.exists(entry)) { + if (Files.exists(entry)) { return Files.newInputStream(entry); } } catch (Exception e) { - CommonImpl.LOGGER.warn("Error occurred while getting data from vanilla jar! {}", e); + CommonImpl.LOGGER.warn("Error occurred while getting data from vanilla jar!", e); } return null; @@ -418,7 +424,7 @@ public CompletableFuture buildResourcePack() { images[i] = bi; } { - var path = "assets/" + entry.modelPath().getNamespace() + "/textures/models/armor/" + entry.modelPath().getPath() + "_layer_" + (i + 1) + ".polymer.json"; + var path = AssetPaths.armorTexturePolymerMetadata(entry.modelPath(), i + 1); var data = this.fileMap.get(path); if (data != null) { @@ -448,11 +454,10 @@ public CompletableFuture buildResourcePack() { list.sort(Comparator.comparing(e -> -e.color())); this.fileMap.put("assets/polymer/armors.json", GSON.toJson(armorDataMap).getBytes(StandardCharsets.UTF_8)); - this.fileMap.put("assets/minecraft/textures/models/armor/vanilla_leather_layer_1.png", this.getVanillaData("assets/minecraft/textures/models/armor/leather_layer_1.png")); - this.fileMap.put("assets/minecraft/textures/models/armor/vanilla_leather_layer_1_overlay.png", this.getVanillaData("assets/minecraft/textures/models/armor/leather_layer_1_overlay.png")); - this.fileMap.put("assets/minecraft/textures/models/armor/vanilla_leather_layer_2.png", this.getVanillaData("assets/minecraft/textures/models/armor/leather_layer_2.png")); - this.fileMap.put("assets/minecraft/textures/models/armor/vanilla_leather_layer_2_overlay.png", this.getVanillaData("assets/minecraft/textures/models/armor/leather_layer_2_overlay.png")); - + this.fileMap.put(armorTexture(vId("vanilla_leather"), 1), this.getVanillaData(armorTexture(new Identifier("leather"), 1))); + this.fileMap.put(armorOverlayTexture(vId("vanilla_leather"), 1), this.getVanillaData(armorOverlayTexture(vId("leather"), 1))); + this.fileMap.put(armorTexture(vId("vanilla_leather"), 2), this.getVanillaData(armorTexture(new Identifier("leather"), 2))); + this.fileMap.put(armorOverlayTexture(vId("vanilla_leather"), 2), this.getVanillaData(armorOverlayTexture(vId("leather"), 2))); int[] width = new int[]{64 * globalScale, 64 * globalScale}; int[] height = new int[]{32 * globalScale, 32 * globalScale}; @@ -489,11 +494,13 @@ public CompletableFuture buildResourcePack() { try { for (int i = 0; i <= 1; i++) { { - var tex = ImageIO.read(this.getVanillaStream("assets/minecraft/textures/models/armor/leather_layer_" + (i + 1) + ".png")); + //noinspection ConstantConditions + var tex = ImageIO.read(this.getVanillaStream(armorTexture(vId("leather"), i + 1))); graphics[i].drawImage(tex, 0, 0, tex.getWidth() * globalScale, tex.getHeight() * globalScale, null); } { - var tex = ImageIO.read(this.getVanillaStream("assets/minecraft/textures/models/armor/leather_layer_" + (i + 1) + "_overlay.png")); + //noinspection ConstantConditions + var tex = ImageIO.read(this.getVanillaStream(armorOverlayTexture(vId("leather"), i + 1))); graphics[i].drawImage(tex, 0, 0, tex.getWidth() * globalScale, tex.getHeight() * globalScale, null); } graphics[i].setColor(Color.WHITE); @@ -535,12 +542,12 @@ public CompletableFuture buildResourcePack() { { var out = new ByteArrayOutputStream(); ImageIO.write(image[i], "png", out); - this.fileMap.put("assets/minecraft/textures/models/armor/leather_layer_" + (i + 1) + ".png", out.toByteArray()); + this.fileMap.put(armorTexture(vId("leather"), i + 1), out.toByteArray()); } { var out = new ByteArrayOutputStream(); ImageIO.write(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB), "png", out); - this.fileMap.put("assets/minecraft/textures/models/armor/leather_layer_" + (i + 1) + "_overlay.png", out.toByteArray()); + this.fileMap.put(armorOverlayTexture(vId("leather"), i + 1), out.toByteArray()); } } } catch (Throwable e) { @@ -559,8 +566,8 @@ public CompletableFuture buildResourcePack() { } - if (!this.fileMap.containsKey("pack.mcmeta")) { - this.fileMap.put("pack.mcmeta", ("" + + if (!this.fileMap.containsKey(AssetPaths.PACK_METADATA)) { + this.fileMap.put(AssetPaths.PACK_METADATA, ("" + "{\n" + " \"pack\":{\n" + " \"pack_format\":" + SharedConstants.RESOURCE_PACK_VERSION + ",\n" + @@ -570,13 +577,13 @@ public CompletableFuture buildResourcePack() { } - if (!this.fileMap.containsKey("pack.png")) { + if (!this.fileMap.containsKey(AssetPaths.PACK_ICON)) { var filePath = FabricLoader.getInstance().getGameDir().resolve("server-icon.png"); if (filePath.toFile().exists()) { - this.fileMap.put("pack.png", Files.readAllBytes(filePath)); + this.fileMap.put(AssetPaths.PACK_ICON, Files.readAllBytes(filePath)); } else { - this.fileMap.put("pack.png", Files.readAllBytes(getSelfPath("assets/icon.png"))); + this.fileMap.put(AssetPaths.PACK_ICON, Files.readAllBytes(getSelfPath("assets/icon.png"))); } } @@ -630,6 +637,10 @@ public CompletableFuture buildResourcePack() { }); } + private Identifier vId(String path) { + return new Identifier(path); + } + private record ArmorData(Identifier identifier, int color, BufferedImage[] images, ArmorTextureMetadata[] metadata) { diff --git a/polymer-virtual-entity/build.gradle b/polymer-virtual-entity/build.gradle index 5c468f18..131aa6d6 100644 --- a/polymer-virtual-entity/build.gradle +++ b/polymer-virtual-entity/build.gradle @@ -16,6 +16,9 @@ loom { dependencies { //modCompileOnly ('nl.theepicblock:PolyMc:5.1.0+1.19') api include(project(path: ':polymer-common', configuration: 'namedElements')) + + modCompileOnly 'com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:v3.0.2-mc1.20' + modCompileOnly 'com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:v3.0.2-mc1.20' } afterEvaluate { diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/ElementHolder.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/ElementHolder.java index b2de562c..a288ad14 100644 --- a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/ElementHolder.java +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/ElementHolder.java @@ -12,6 +12,8 @@ import net.minecraft.network.packet.s2c.play.EntitiesDestroyS2CPacket; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.Vec3d; import org.jetbrains.annotations.Nullable; @@ -25,6 +27,8 @@ public class ElementHolder { private final List elements = new ObjectArrayList<>(); private final List players = new ArrayList<>(); protected Vec3d currentPos = Vec3d.ZERO; + private ChunkPos currentChunkPos = null; + private final IntList entityIds = new IntArrayList(); public boolean isPartOf(int entityId) { @@ -161,7 +165,19 @@ protected void updatePosition() { var delta = newPos.subtract(newPos); this.notifyElementsOfPositionUpdate(newPos, delta); this.currentPos = newPos; + this.currentChunkPos = null; + } + } + + protected void invalidateCaches() { + this.currentChunkPos = null; + } + + public ChunkPos getChunkPos() { + if (this.currentChunkPos == null) { + this.currentChunkPos = new ChunkPos(BlockPos.ofFloored(this.currentPos)); } + return this.currentChunkPos; } protected void notifyElementsOfPositionUpdate(Vec3d newPos, Vec3d delta) { diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/VirtualEntityUtils.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/VirtualEntityUtils.java index d1e4022f..666ad719 100644 --- a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/VirtualEntityUtils.java +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/VirtualEntityUtils.java @@ -1,11 +1,14 @@ package eu.pb4.polymer.virtualentity.api; +import eu.pb4.polymer.common.impl.CompatStatus; +import eu.pb4.polymer.virtualentity.api.attachment.HolderAttachment; import eu.pb4.polymer.virtualentity.impl.EntityExt; import eu.pb4.polymer.virtualentity.impl.VirtualEntityImplUtils; +import eu.pb4.polymer.virtualentity.impl.compat.ImmersivePortalsUtils; import eu.pb4.polymer.virtualentity.mixin.EntityPassengersSetS2CPacketAccessor; import eu.pb4.polymer.virtualentity.mixin.accessors.EntityAccessor; import eu.pb4.polymer.virtualentity.mixin.accessors.EntityPositionS2CPacketAccessor; -import it.unimi.dsi.fastutil.ints.IntArrayList; +import eu.pb4.polymer.virtualentity.mixin.accessors.ThreadedAnvilChunkStorageAccessor; import it.unimi.dsi.fastutil.ints.IntList; import net.minecraft.entity.Entity; import net.minecraft.network.listener.ClientPlayPacketListener; @@ -13,10 +16,15 @@ import net.minecraft.network.packet.s2c.play.EntityPassengersSetS2CPacket; import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket; import net.minecraft.network.packet.s2c.play.EntityS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.server.world.ThreadedAnvilChunkStorage; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.chunk.WorldChunk; import org.jetbrains.annotations.Nullable; + public final class VirtualEntityUtils { private VirtualEntityUtils() {} public static int requestEntityId() { @@ -92,4 +100,30 @@ public static EntityPassengersSetS2CPacket createRidePacket(int id, IntList list ((EntityPassengersSetS2CPacketAccessor) packet).setPassengerIds(list.toIntArray()); return packet; } + + public static boolean isPlayerTracking(ServerPlayerEntity player, WorldChunk chunk) { + if (CompatStatus.IMMERSIVE_PORTALS) { + return ImmersivePortalsUtils.isPlayerTracking(player, chunk); + } + + if (player.getWorld() != chunk.getWorld()) { + return false; + } + + + var tacs = ((ServerWorld) chunk.getWorld()).getChunkManager().threadedAnvilChunkStorage; + var section = player.getWatchedSection(); + return ThreadedAnvilChunkStorage.isWithinDistance(chunk.getPos().x, chunk.getPos().z, section.getX(), section.getZ(), ((ThreadedAnvilChunkStorageAccessor) tacs).getWatchDistance()); + } + + /** + * Purely for compatibility with immersive portals. + */ + public static void wrapCallWithContext(ServerWorld world, Runnable call) { + if (CompatStatus.IMMERSIVE_PORTALS) { + ImmersivePortalsUtils.callRedirected(world, call); + } else { + call.run(); + } + } } diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/attachment/ChunkAttachment.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/attachment/ChunkAttachment.java index e5778eba..06e2a986 100644 --- a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/attachment/ChunkAttachment.java +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/attachment/ChunkAttachment.java @@ -2,8 +2,8 @@ import eu.pb4.polymer.common.impl.CommonImpl; import eu.pb4.polymer.virtualentity.api.ElementHolder; +import eu.pb4.polymer.virtualentity.api.VirtualEntityUtils; import eu.pb4.polymer.virtualentity.impl.HolderAttachmentHolder; -import eu.pb4.polymer.virtualentity.mixin.accessors.ThreadedAnvilChunkStorageAccessor; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerChunkManager; @@ -112,18 +112,25 @@ public void updateCurrentlyTracking(Collection current @Override public void updateTracking(ServerPlayNetworkHandler tracking) { - if (tracking.player.getWorld() != this.chunk.getWorld() || tracking.player.isDead()) { - this.stopWatching(tracking); - return; + //System.out.println("UPDATE-WATCHING: " + this.chunk.getWorld().getRegistryKey().getValue() + " | " + this.pos + " | " + tracking.player.isDead() + " | " + StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass()); + if (tracking.player.isDead() || !VirtualEntityUtils.isPlayerTracking(tracking.getPlayer(), this.chunk)) { + VirtualEntityUtils.wrapCallWithContext(this.getWorld(), () -> this.stopWatching(tracking)); } + } + /* - var tacs = tracking.player.getServerWorld().getChunkManager().threadedAnvilChunkStorage; - var section = tracking.getPlayer().getWatchedSection(); - if (!tacs.isWithinDistance(this.chunk.getPos().x, this.chunk.getPos().z, section.getX(), section.getZ(), ((ThreadedAnvilChunkStorageAccessor) tacs).getWatchDistance())) { - this.stopWatching(tracking); - } + @Override + public void startWatching(ServerPlayNetworkHandler tracking) { + System.out.println("START-WATCHING: " + this.chunk.getWorld().getRegistryKey().getValue() + " | " + this.pos + " | " + tracking.player.isDead() + " | " + StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass()); + HolderAttachment.super.startWatching(tracking); } + @Override + public void stopWatching(ServerPlayNetworkHandler handler) { + System.out.println("STOP-WATCHING: " + this.chunk.getWorld().getRegistryKey().getValue() + " | " + this.pos + " | " + handler.player.isDead() + " | " + StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass()); + HolderAttachment.super.stopWatching(handler); + }*/ + @Override public Vec3d getPos() { return this.pos; @@ -133,5 +140,4 @@ public Vec3d getPos() { public ServerWorld getWorld() { return (ServerWorld) this.chunk.getWorld(); } - } diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/impl/compat/ImmersivePortalsUtils.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/impl/compat/ImmersivePortalsUtils.java new file mode 100644 index 00000000..7295f917 --- /dev/null +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/impl/compat/ImmersivePortalsUtils.java @@ -0,0 +1,20 @@ +package eu.pb4.polymer.virtualentity.impl.compat; + +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.chunk.WorldChunk; +import org.jetbrains.annotations.ApiStatus; +import qouteall.imm_ptl.core.chunk_loading.NewChunkTrackingGraph; +import qouteall.imm_ptl.core.network.PacketRedirection; + + +@ApiStatus.Internal +public class ImmersivePortalsUtils { + public static boolean isPlayerTracking(ServerPlayerEntity player, WorldChunk chunk) { + return NewChunkTrackingGraph.isPlayerWatchingChunk(player, chunk.getWorld().getRegistryKey(), chunk.getPos().x, chunk.getPos().z); + } + + public static void callRedirected(ServerWorld world, Runnable runnable) { + PacketRedirection.withForceRedirect(world, runnable); + } +} diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/PolymerVirtualEntityMixinConfigPlugin.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/PolymerVirtualEntityMixinConfigPlugin.java index 35e8e388..6c41b540 100644 --- a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/PolymerVirtualEntityMixinConfigPlugin.java +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/PolymerVirtualEntityMixinConfigPlugin.java @@ -23,7 +23,6 @@ public String getRefMapperConfig() { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { var name = mixinClassName.substring(PACKAGE_ROOT.length()); - return CommonImpl.shouldApplyMixin("polymer-virtual-entity", name); } diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/ServerPlayerEntityMixin.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/ServerPlayerEntityMixin.java index 488465ed..7cfa59f0 100644 --- a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/ServerPlayerEntityMixin.java +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/ServerPlayerEntityMixin.java @@ -7,12 +7,10 @@ import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -32,7 +30,7 @@ public class ServerPlayerEntityMixin { @Inject(method = "sendUnloadChunkPacket", at = @At("HEAD")) private void polymerVE$chunkUnload(ChunkPos chunkPos, CallbackInfo ci) { for (var holder : new ArrayList<>(((HolderHolder) this.networkHandler).polymer$getHolders())) { - if (holder.getAttachment() != null && new ChunkPos(BlockPos.ofFloored(holder.getPos())).equals(chunkPos)) { + if (holder.getAttachment() != null && holder.getChunkPos().equals(chunkPos)) { holder.getAttachment().updateTracking(this.networkHandler); } } diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/block/ThreadedAnvilChunkStorageMixin.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/block/ThreadedAnvilChunkStorageMixin.java index 26d2d191..d4a82f24 100644 --- a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/block/ThreadedAnvilChunkStorageMixin.java +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/block/ThreadedAnvilChunkStorageMixin.java @@ -22,7 +22,7 @@ @Mixin(ThreadedAnvilChunkStorage.class) public abstract class ThreadedAnvilChunkStorageMixin { - @Inject(method = "sendChunkDataPackets", at = @At("TAIL")) + @Inject(method = "sendChunkDataPackets", at = @At("TAIL"), require = 0) private void polymerVE$addToHolograms(ServerPlayerEntity player, MutableObject cachedDataPacket, WorldChunk chunk, CallbackInfo ci) { for (var hologram : ((HolderAttachmentHolder) chunk).polymerVE$getHolders()) { hologram.startWatching(player.networkHandler); diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/compat/ip_ChunkDataSyncManagerMixin.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/compat/ip_ChunkDataSyncManagerMixin.java new file mode 100644 index 00000000..446e3f66 --- /dev/null +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/mixin/compat/ip_ChunkDataSyncManagerMixin.java @@ -0,0 +1,59 @@ +package eu.pb4.polymer.virtualentity.mixin.compat; + +import eu.pb4.polymer.virtualentity.impl.HolderAttachmentHolder; +import eu.pb4.polymer.virtualentity.impl.HolderHolder; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ChunkHolder; +import net.minecraft.world.chunk.WorldChunk; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import qouteall.imm_ptl.core.chunk_loading.ChunkDataSyncManager; +import qouteall.imm_ptl.core.chunk_loading.DimensionalChunkPos; +import qouteall.imm_ptl.core.ducks.IEThreadedAnvilChunkStorage; +import qouteall.imm_ptl.core.network.PacketRedirection; + +import java.util.ArrayList; +import java.util.function.Supplier; + +@Pseudo +@Mixin(value = ChunkDataSyncManager.class) +public class ip_ChunkDataSyncManagerMixin { + @Inject(method = "lambda$onChunkProvidedDeferred$1", at = @At("TAIL"), require = 0) + private static void polymerVE$addToPlayerPlayer(Supplier chunkDataPacketRedirected, IEThreadedAnvilChunkStorage ieStorage, WorldChunk chunk, ServerPlayerEntity player, CallbackInfo ci) { + if (!player.isDead()) { + PacketRedirection.withForceRedirect(ieStorage.ip_getWorld(), () -> { + for (var hologram : ((HolderAttachmentHolder) chunk).polymerVE$getHolders()) { + hologram.startWatching(player.networkHandler); + } + }); + } + } + + @Inject(method = "sendChunkDataPacketNow", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;pop()V", shift = At.Shift.BEFORE), require = 0, locals = LocalCapture.CAPTURE_FAILHARD) + private void polymerVE$addToSinglePlayer(ServerPlayerEntity player, DimensionalChunkPos chunkPos, IEThreadedAnvilChunkStorage ieStorage, CallbackInfo ci, ChunkHolder chunkHolder) { + if (!player.isDead()) { + var chunk = chunkHolder.getWorldChunk(); + PacketRedirection.withForceRedirect(ieStorage.ip_getWorld(), () -> { + for (var hologram : ((HolderAttachmentHolder) chunk).polymerVE$getHolders()) { + hologram.startWatching(player.networkHandler); + } + }); + } + } + + @Inject(method = "onEndWatch", at = @At("RETURN"), require = 0) + private void polymerVE$removeFromPlayer(ServerPlayerEntity player, DimensionalChunkPos chunkPos, CallbackInfo ci) { + var actualPos = chunkPos.getChunkPos(); + for (var holder : new ArrayList<>(((HolderHolder) player.networkHandler).polymer$getHolders())) { + if (holder.getAttachment() != null && holder.getAttachment().getWorld().getRegistryKey().equals(chunkPos.dimension) && holder.getChunkPos().equals(actualPos)) { + PacketRedirection.withForceRedirect(holder.getAttachment().getWorld(), () -> { + holder.getAttachment().updateTracking(player.networkHandler); + }); + } + } + } +} diff --git a/polymer-virtual-entity/src/main/resources/polymer-virtual-entity.mixins.json b/polymer-virtual-entity/src/main/resources/polymer-virtual-entity.mixins.json index dd6782a7..0509bc1a 100644 --- a/polymer-virtual-entity/src/main/resources/polymer-virtual-entity.mixins.json +++ b/polymer-virtual-entity/src/main/resources/polymer-virtual-entity.mixins.json @@ -24,7 +24,8 @@ "accessors.ThreadedAnvilChunkStorageAccessor", "block.ServerWorldMixin", "block.ThreadedAnvilChunkStorageMixin", - "block.WorldChunkMixin" + "block.WorldChunkMixin", + "compat.ip_ChunkDataSyncManagerMixin" ], "client": [ ],