diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..b406eaf71 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "wiki"] + path = wiki + url = https://github.com/Xiao-MoMi/craft-engine-wiki.git diff --git a/README.md b/README.md index 26b55747f..2f45c4583 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ repositories { ``` ```kotlin dependencies { - compileOnly("net.momirealms:craft-engine-core:0.0.64") - compileOnly("net.momirealms:craft-engine-bukkit:0.0.64") + compileOnly("net.momirealms:craft-engine-core:0.0.65") + compileOnly("net.momirealms:craft-engine-bukkit:0.0.65") } ``` \ No newline at end of file diff --git a/bukkit/compatibility/build.gradle.kts b/bukkit/compatibility/build.gradle.kts index 933d60862..949b79fe4 100644 --- a/bukkit/compatibility/build.gradle.kts +++ b/bukkit/compatibility/build.gradle.kts @@ -37,8 +37,9 @@ dependencies { compileOnly("com.infernalsuite.asp:api:4.0.0-SNAPSHOT") // ModelEngine compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.8") - // BetterModels - compileOnly("io.github.toxicity188:BetterModel:1.7.0") + // BetterModel + compileOnly("io.github.toxicity188:bettermodel:1.14.0") + compileOnly("com.mojang:authlib:${rootProject.properties["authlib_version"]}") // MMOItems compileOnly("net.Indyuce:MMOItems-API:6.10-SNAPSHOT") compileOnly("io.lumine:MythicLib-dist:1.6.2-SNAPSHOT") diff --git a/bukkit/compatibility/legacy/src/main/java/net/momirealms/craftengine/bukkit/compatibility/legacy/slimeworld/LegacySlimeWorldDataStorage.java b/bukkit/compatibility/legacy/src/main/java/net/momirealms/craftengine/bukkit/compatibility/legacy/slimeworld/LegacySlimeWorldDataStorage.java index 4feff8a93..f62ac011f 100644 --- a/bukkit/compatibility/legacy/src/main/java/net/momirealms/craftengine/bukkit/compatibility/legacy/slimeworld/LegacySlimeWorldDataStorage.java +++ b/bukkit/compatibility/legacy/src/main/java/net/momirealms/craftengine/bukkit/compatibility/legacy/slimeworld/LegacySlimeWorldDataStorage.java @@ -26,6 +26,14 @@ public class LegacySlimeWorldDataStorage implements WorldDataStorage { return slimeWorld.get(); } + @Override + public CEChunk readNewChunkAt(CEWorld world, ChunkPos pos) { + SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z); + if (slimeChunk == null) return new CEChunk(world, pos); + slimeChunk.getExtraData().getValue().remove("craftengine"); + return new CEChunk(world, pos); + } + @Override public @NotNull CEChunk readChunkAt(@NotNull CEWorld world, @NotNull ChunkPos pos) { SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z); @@ -57,6 +65,13 @@ public class LegacySlimeWorldDataStorage implements WorldDataStorage { } } + @Override + public void clearChunkAt(@NotNull ChunkPos pos) { + SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z); + if (slimeChunk == null) return; + slimeChunk.getExtraData().getValue().remove("craftengine"); + } + @Override public void flush() { } diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelBlockEntityElement.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelBlockEntityElement.java index 1c9a0e5d3..c30ca33db 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelBlockEntityElement.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelBlockEntityElement.java @@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.compatibility.model.bettermodel; import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.data.renderer.ModelRenderer; import kr.toxicity.model.api.tracker.DummyTracker; +import kr.toxicity.model.api.tracker.TrackerModifier; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.world.BlockPos; @@ -23,11 +24,13 @@ public class BetterModelBlockEntityElement implements BlockEntityElement { } private DummyTracker createDummyTracker() { - ModelRenderer modelRenderer = BetterModel.plugin().modelManager().renderer(this.config.model()); + ModelRenderer modelRenderer = BetterModel.plugin().modelManager().model(this.config.model()); if (modelRenderer == null) { return null; } else { - return modelRenderer.create(this.location); + return modelRenderer.create(this.location, TrackerModifier.builder() + .sightTrace(this.config.sightTrace()) + .build()); } } diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelBlockEntityElementConfig.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelBlockEntityElementConfig.java index 0b31cf939..a6c936826 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelBlockEntityElementConfig.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelBlockEntityElementConfig.java @@ -15,28 +15,38 @@ public class BetterModelBlockEntityElementConfig implements BlockEntityElementCo private final float yaw; private final float pitch; private final String model; + private final boolean sightTrace; - public BetterModelBlockEntityElementConfig(String model, Vector3f position, float yaw, float pitch) { + public BetterModelBlockEntityElementConfig(String model, + Vector3f position, + float yaw, + float pitch, + boolean sightTrace) { this.pitch = pitch; this.position = position; this.yaw = yaw; this.model = model; + this.sightTrace = sightTrace; } public String model() { - return model; + return this.model; } public float pitch() { - return pitch; + return this.pitch; } public Vector3f position() { - return position; + return this.position; } public float yaw() { - return yaw; + return this.yaw; + } + + public boolean sightTrace() { + return this.sightTrace; } @Override @@ -44,6 +54,11 @@ public class BetterModelBlockEntityElementConfig implements BlockEntityElementCo return new BetterModelBlockEntityElement(world, pos, this); } + @Override + public Class elementClass() { + return BetterModelBlockEntityElement.class; + } + public static class Factory implements BlockEntityElementConfigFactory { @SuppressWarnings("unchecked") @@ -54,7 +69,8 @@ public class BetterModelBlockEntityElementConfig implements BlockEntityElementCo model, ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0.5f), "position"), ResourceConfigUtils.getAsFloat(arguments.getOrDefault("yaw", 0f), "yaw"), - ResourceConfigUtils.getAsFloat(arguments.getOrDefault("pitch", 0f), "pitch") + ResourceConfigUtils.getAsFloat(arguments.getOrDefault("pitch", 0f), "pitch"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("sight-trace", true), "sight-trace") ); } } diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelUtils.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelUtils.java index 507901517..dbe86e340 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelUtils.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/bettermodel/BetterModelUtils.java @@ -9,7 +9,7 @@ import org.bukkit.entity.Entity; public class BetterModelUtils { public static void bindModel(Entity base, String id) { - ModelRenderer renderer = BetterModel.plugin().modelManager().renderer(id); + ModelRenderer renderer = BetterModel.plugin().modelManager().model(id); if (renderer == null) { throw new NullPointerException("Could not find BetterModel blueprint " + id); } diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/modelengine/ModelEngineBlockEntityElementConfig.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/modelengine/ModelEngineBlockEntityElementConfig.java index a8dbd2643..0a4c5c41c 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/modelengine/ModelEngineBlockEntityElementConfig.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/model/modelengine/ModelEngineBlockEntityElementConfig.java @@ -44,6 +44,11 @@ public class ModelEngineBlockEntityElementConfig implements BlockEntityElementCo return new ModelEngineBlockEntityElement(world, pos, this); } + @Override + public Class elementClass() { + return ModelEngineBlockEntityElement.class; + } + public static class Factory implements BlockEntityElementConfigFactory { @SuppressWarnings("unchecked") diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/slimeworld/SlimeWorldDataStorage.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/slimeworld/SlimeWorldDataStorage.java index 663689520..6b5f519c9 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/slimeworld/SlimeWorldDataStorage.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/slimeworld/SlimeWorldDataStorage.java @@ -27,6 +27,14 @@ public class SlimeWorldDataStorage implements WorldDataStorage { return slimeWorld.get(); } + @Override + public CEChunk readNewChunkAt(CEWorld world, ChunkPos pos) { + SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z); + if (slimeChunk == null) return new CEChunk(world, pos); + slimeChunk.getExtraData().remove("craftengine"); + return new CEChunk(world, pos); + } + @Override public @NotNull CEChunk readChunkAt(@NotNull CEWorld world, @NotNull ChunkPos pos) { SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z); @@ -42,7 +50,7 @@ public class SlimeWorldDataStorage implements WorldDataStorage { } } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "rawtypes"}) @Override public void writeChunkAt(@NotNull ChunkPos pos, @NotNull CEChunk chunk) { SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z); @@ -53,8 +61,7 @@ public class SlimeWorldDataStorage implements WorldDataStorage { } else { try { Object tag = adaptor.bytesToByteArrayTag(NBT.toBytes(nbt)); - Map data1 = slimeChunk.getExtraData(); - Map data2 = (Map) data1; + Map data2 = (Map) slimeChunk.getExtraData(); data2.put("craftengine", tag); } catch (Exception e) { throw new RuntimeException("Failed to write chunk tag to slime world. " + pos, e); @@ -62,6 +69,13 @@ public class SlimeWorldDataStorage implements WorldDataStorage { } } + @Override + public void clearChunkAt(@NotNull ChunkPos pos) { + SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z); + if (slimeChunk == null) return; + slimeChunk.getExtraData().remove("craftengine"); + } + @Override public void flush() { } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index b650e0a57..10c77c589 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -59,7 +59,7 @@ public final class BukkitBlockManager extends AbstractBlockManager { private Map> clientBoundTags = Map.of(); private Map> previousClientBoundTags = Map.of(); // 缓存的原版方块tag包 - private Object cachedUpdateTagsPacket; + private List cachedUpdateTags = List.of(); // 被移除声音的原版方块 private Set missingPlaceSounds = Set.of(); private Set missingBreakSounds = Set.of(); @@ -150,23 +150,14 @@ public final class BukkitBlockManager extends AbstractBlockManager { } @Override - protected void resendTags() { + protected void updateTags() { // if there's no change if (this.clientBoundTags.equals(this.previousClientBoundTags)) return; List list = new ArrayList<>(); for (Map.Entry> entry : this.clientBoundTags.entrySet()) { list.add(new TagUtils.TagEntry(entry.getKey(), entry.getValue())); } - Object packet = TagUtils.createUpdateTagsPacket(Map.of(MRegistries.BLOCK, list)); - for (BukkitServerPlayer player : this.plugin.networkManager().onlineUsers()) { - player.sendPacket(packet, false); - } - // 如果空,那么新来的玩家就没必要收到更新包了 - if (list.isEmpty()) { - this.cachedUpdateTagsPacket = null; - } else { - this.cachedUpdateTagsPacket = packet; - } + this.cachedUpdateTags = list; } @Nullable @@ -299,6 +290,10 @@ public final class BukkitBlockManager extends AbstractBlockManager { this.burnOdds.put(nmsBlock, settings.fireSpreadChance()); this.burnableBlocks.add(nmsBlock); } + + Key vanillaBlockId = state.vanillaBlockState().ownerId(); + BlockGenerator.field$CraftEngineBlock$isNoteBlock().set(nmsBlock, vanillaBlockId.equals(BlockKeys.NOTE_BLOCK)); + BlockGenerator.field$CraftEngineBlock$isTripwire().set(nmsBlock, vanillaBlockId.equals(BlockKeys.TRIPWIRE)); } catch (ReflectiveOperationException e) { this.plugin.logger().warn("Failed to apply platform block settings for block state " + state, e); } @@ -364,8 +359,8 @@ public final class BukkitBlockManager extends AbstractBlockManager { } } - public Object cachedUpdateTagsPacket() { - return this.cachedUpdateTagsPacket; + public List cachedUpdateTags() { + return this.cachedUpdateTags; } public VisualBlockStatePacket cachedVisualBlockStatePacket() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java index 360e58f38..421e8f94e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.entity; -import net.momirealms.craftengine.bukkit.block.behavior.SeatBlockBehavior; import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeat; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.entity.BlockEntity; @@ -14,8 +13,6 @@ import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.sparrow.nbt.CompoundTag; -import java.util.Optional; - public class SeatBlockEntity extends BlockEntity implements SeatOwner { private final Seat[] seats; @@ -41,25 +38,20 @@ public class SeatBlockEntity extends BlockEntity implements SeatOwner { } public boolean spawnSeat(Player player) { - Optional seatBehavior = super.blockState.behavior().getAs(SeatBlockBehavior.class); - if (seatBehavior.isEmpty()) { - return false; - } - float yRot = 0; - Property directionProperty = seatBehavior.get().directionProperty(); - if (directionProperty != null) { - HorizontalDirection direction = super.blockState.get(directionProperty); - if (direction == HorizontalDirection.NORTH) { - yRot = 180; - } else if (direction == HorizontalDirection.EAST) { - yRot = -90; - } else if (direction == HorizontalDirection.WEST) { - yRot = 90; - } + Property facing = super.blockState.owner().value().getProperty("facing"); + int yRot = 0; + if (facing != null && facing.valueClass() == HorizontalDirection.class) { + HorizontalDirection direction = (HorizontalDirection) super.blockState.get(facing); + yRot = switch (direction) { + case NORTH -> 0; + case SOUTH -> 180; + case WEST -> 270; + case EAST -> 90; + }; } for (Seat seat : this.seats) { if (!seat.isOccupied()) { - if (seat.spawnSeat(player, new WorldPosition(super.world.world(), super.pos.x() + 0.5, super.pos.y(), super.pos.z() + 0.5, 0, 180 - yRot))) { + if (seat.spawnSeat(player, new WorldPosition(super.world.world(), super.pos.x() + 0.5, super.pos.y(), super.pos.z() + 0.5, 0, yRot))) { return true; } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/BukkitBlockEntityElementConfigs.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/BukkitBlockEntityElementConfigs.java index 8553a7c56..ee182e392 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/BukkitBlockEntityElementConfigs.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/BukkitBlockEntityElementConfigs.java @@ -7,6 +7,7 @@ public class BukkitBlockEntityElementConfigs extends BlockEntityElementConfigs { static { register(ITEM_DISPLAY, ItemDisplayBlockEntityElementConfig.FACTORY); register(TEXT_DISPLAY, TextDisplayBlockEntityElementConfig.FACTORY); + register(ITEM, ItemBlockEntityElementConfig.FACTORY); } private BukkitBlockEntityElementConfigs() {} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElement.java new file mode 100644 index 000000000..7cf886977 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElement.java @@ -0,0 +1,65 @@ +package net.momirealms.craftengine.bukkit.block.entity.renderer.element; + +import it.unimi.dsi.fastutil.ints.IntList; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; +import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.world.BlockPos; +import org.joml.Vector3f; + +import java.util.List; +import java.util.UUID; + +public class ItemBlockEntityElement implements BlockEntityElement { + public final ItemBlockEntityElementConfig config; + public final Object cachedSpawnPacket1; + public final Object cachedSpawnPacket2; + public final Object cachedRidePacket; + public final Object cachedDespawnPacket; + public final Object cachedUpdatePosPacket; + public final int entityId1; + public final int entityId2; + + public ItemBlockEntityElement(ItemBlockEntityElementConfig config, BlockPos pos) { + this(config, pos, CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(), CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(), false); + } + + public ItemBlockEntityElement(ItemBlockEntityElementConfig config, BlockPos pos, int entityId1, int entityId2, boolean posChanged) { + this.config = config; + Vector3f position = config.position(); + this.cachedSpawnPacket1 = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityId1, UUID.randomUUID(), pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, + 0, 0, MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0 + ); + this.cachedSpawnPacket2 = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityId2, UUID.randomUUID(), pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, + 0, 0, MEntityTypes.ITEM, 0, CoreReflections.instance$Vec3$Zero, 0 + ); + this.cachedRidePacket = FastNMS.INSTANCE.constructor$ClientboundSetPassengersPacket(entityId1, entityId2); + this.cachedDespawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(IntList.of(entityId1, entityId2)); + this.entityId1 = entityId1; + this.entityId2 = entityId2; + this.cachedUpdatePosPacket = posChanged ? FastNMS.INSTANCE.constructor$ClientboundEntityPositionSyncPacket(this.entityId1, pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, 0, 0, false) : null; + } + + @Override + public void hide(Player player) { + player.sendPacket(this.cachedDespawnPacket, false); + } + + @Override + public void show(Player player) { + player.sendPackets(List.of(this.cachedSpawnPacket1, this.cachedSpawnPacket2, this.cachedRidePacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId2, this.config.metadataValues(player))), false); + } + + @Override + public void transform(Player player) { + if (this.cachedUpdatePosPacket != null) { + player.sendPackets(List.of(this.cachedUpdatePosPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId2, this.config.metadataValues(player))), false); + } else { + player.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId2, this.config.metadataValues(player)), false); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java new file mode 100644 index 000000000..96873d757 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java @@ -0,0 +1,77 @@ +package net.momirealms.craftengine.bukkit.block.entity.renderer.element; + +import net.momirealms.craftengine.bukkit.entity.data.ItemEntityData; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement; +import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig; +import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.World; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +public class ItemBlockEntityElementConfig implements BlockEntityElementConfig { + public static final Factory FACTORY = new Factory(); + private final Function> lazyMetadataPacket; + private final Function> item; + private final Vector3f position; + + public ItemBlockEntityElementConfig(Function> item, Vector3f position) { + this.item = item; + this.position = position; + this.lazyMetadataPacket = player -> { + List dataValues = new ArrayList<>(); + ItemEntityData.Item.addEntityDataIfNotDefaultValue(item.apply(player).getLiteralObject(), dataValues); + ItemEntityData.NoGravity.addEntityDataIfNotDefaultValue(true, dataValues); + return dataValues; + }; + } + + @Override + public ItemBlockEntityElement create(World world, BlockPos pos) { + return new ItemBlockEntityElement(this, pos); + } + + @Override + public ItemBlockEntityElement create(World world, BlockPos pos, ItemBlockEntityElement previous) { + return new ItemBlockEntityElement(this, pos, previous.entityId1, previous.entityId2, !previous.config.position.equals(this.position)); + } + + @Override + public Class elementClass() { + return ItemBlockEntityElement.class; + } + + public Vector3f position() { + return position; + } + + public Item item(Player player) { + return this.item.apply(player); + } + + public List metadataValues(Player player) { + return this.lazyMetadataPacket.apply(player); + } + + public static class Factory implements BlockEntityElementConfigFactory { + + @SuppressWarnings("unchecked") + @Override + public BlockEntityElementConfig create(Map arguments) { + Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.block.state.entity_renderer.item_display.missing_item")); + return (BlockEntityElementConfig) new ItemBlockEntityElementConfig( + player -> BukkitItemManager.instance().createWrappedItem(itemId, player), + ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0.5f), "position") + ); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElement.java index 074bc87c5..558e56ff9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElement.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElement.java @@ -13,13 +13,17 @@ import java.util.List; import java.util.UUID; public class ItemDisplayBlockEntityElement implements BlockEntityElement { - private final ItemDisplayBlockEntityElementConfig config; - private final Object cachedSpawnPacket; - private final Object cachedDespawnPacket; - private final int entityId; + public final ItemDisplayBlockEntityElementConfig config; + public final Object cachedSpawnPacket; + public final Object cachedDespawnPacket; + public final Object cachedUpdatePosPacket; + public final int entityId; public ItemDisplayBlockEntityElement(ItemDisplayBlockEntityElementConfig config, BlockPos pos) { - int entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); + this(config, pos, CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(), false); + } + + public ItemDisplayBlockEntityElement(ItemDisplayBlockEntityElementConfig config, BlockPos pos, int entityId, boolean posChanged) { Vector3f position = config.position(); this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( entityId, UUID.randomUUID(), pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, @@ -28,6 +32,7 @@ public class ItemDisplayBlockEntityElement implements BlockEntityElement { this.config = config; this.cachedDespawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(IntList.of(entityId)); this.entityId = entityId; + this.cachedUpdatePosPacket = posChanged ? FastNMS.INSTANCE.constructor$ClientboundEntityPositionSyncPacket(this.entityId, pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, config.yRot(), config.xRot(), false) : null; } @Override @@ -37,6 +42,15 @@ public class ItemDisplayBlockEntityElement implements BlockEntityElement { @Override public void show(Player player) { - player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), true); + player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), false); + } + + @Override + public void transform(Player player) { + if (this.cachedUpdatePosPacket != null) { + player.sendPackets(List.of(this.cachedUpdatePosPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), false); + } else { + player.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player)), false); + } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElementConfig.java index 53320d84d..d3a2d1dd8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElementConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElementConfig.java @@ -78,6 +78,20 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo return new ItemDisplayBlockEntityElement(this, pos); } + @Override + public ItemDisplayBlockEntityElement create(World world, BlockPos pos, ItemDisplayBlockEntityElement previous) { + Quaternionf previousRotation = previous.config.rotation; + if (previousRotation.x != 0 || previousRotation.y != 0 || previousRotation.z != 0 || previousRotation.w != 1) { + return null; + } + return new ItemDisplayBlockEntityElement(this, pos, previous.entityId, previous.config.yRot != this.yRot || previous.config.xRot != this.xRot || !previous.config.position.equals(this.position)); + } + + @Override + public Class elementClass() { + return ItemDisplayBlockEntityElement.class; + } + public Item item(Player player) { return this.item.apply(player); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElement.java index 45a1c6c9d..9cefef8eb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElement.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElement.java @@ -13,13 +13,17 @@ import java.util.List; import java.util.UUID; public class TextDisplayBlockEntityElement implements BlockEntityElement { - private final TextDisplayBlockEntityElementConfig config; - private final Object cachedSpawnPacket; - private final Object cachedDespawnPacket; - private final int entityId; + public final TextDisplayBlockEntityElementConfig config; + public final Object cachedSpawnPacket; + public final Object cachedDespawnPacket; + public final Object cachedUpdatePosPacket; + public final int entityId; public TextDisplayBlockEntityElement(TextDisplayBlockEntityElementConfig config, BlockPos pos) { - int entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); + this(config, pos, CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(), false); + } + + public TextDisplayBlockEntityElement(TextDisplayBlockEntityElementConfig config, BlockPos pos, int entityId, boolean posChanged) { Vector3f position = config.position(); this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( entityId, UUID.randomUUID(), pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, @@ -28,6 +32,7 @@ public class TextDisplayBlockEntityElement implements BlockEntityElement { this.config = config; this.cachedDespawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(IntList.of(entityId)); this.entityId = entityId; + this.cachedUpdatePosPacket = posChanged ? FastNMS.INSTANCE.constructor$ClientboundEntityPositionSyncPacket(this.entityId, pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, config.yRot(), config.xRot(), false) : null; } @Override @@ -37,6 +42,19 @@ public class TextDisplayBlockEntityElement implements BlockEntityElement { @Override public void show(Player player) { - player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), true); + player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), false); + } + + @Override + public void transform(Player player) { + if (this.cachedUpdatePosPacket != null) { + player.sendPackets(List.of(this.cachedUpdatePosPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), false); + } else { + player.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player)), false); + } + } + + public int entityId() { + return entityId; } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElementConfig.java index e707023ee..14f4a3210 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElementConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElementConfig.java @@ -66,6 +66,20 @@ public class TextDisplayBlockEntityElementConfig implements BlockEntityElementCo return new TextDisplayBlockEntityElement(this, pos); } + @Override + public TextDisplayBlockEntityElement create(World world, BlockPos pos, TextDisplayBlockEntityElement previous) { + Quaternionf previousRotation = previous.config.rotation; + if (previousRotation.x != 0 || previousRotation.y != 0 || previousRotation.z != 0 || previousRotation.w != 1) { + return null; + } + return new TextDisplayBlockEntityElement(this, pos, previous.entityId, previous.config.yRot != this.yRot || previous.config.xRot != this.xRot || !previous.config.position.equals(this.position)); + } + + @Override + public Class elementClass() { + return TextDisplayBlockEntityElement.class; + } + public Component text(Player player) { return AdventureHelper.miniMessage().deserialize(this.text, PlayerOptionalContext.of(player).tagResolvers()); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemEntityData.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemEntityData.java new file mode 100644 index 000000000..a31b2272b --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemEntityData.java @@ -0,0 +1,11 @@ +package net.momirealms.craftengine.bukkit.entity.data; + +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; + +public class ItemEntityData extends BaseEntityData { + public static final ItemEntityData Item = new ItemEntityData<>(ItemEntityData.class, EntityDataValue.Serializers$ITEM_STACK, CoreReflections.instance$ItemStack$EMPTY); + + public ItemEntityData(Class clazz, Object serializer, T defaultValue) { + super(clazz, serializer, defaultValue); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/seat/BukkitSeatManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/seat/BukkitSeatManager.java index 9ebc9577f..2e52d5564 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/seat/BukkitSeatManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/seat/BukkitSeatManager.java @@ -28,7 +28,7 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; -public class BukkitSeatManager implements SeatManager { +public class BukkitSeatManager implements SeatManager, Listener { private static BukkitSeatManager instance; public static final NamespacedKey SEAT_KEY = KeyUtils.toNamespacedKey(SeatManager.SEAT_KEY); public static final NamespacedKey SEAT_EXTRA_DATA_KEY = KeyUtils.toNamespacedKey(SeatManager.SEAT_EXTRA_DATA_KEY); @@ -113,9 +113,9 @@ public class BukkitSeatManager implements SeatManager { if (!isSeat) return; Location location = seat.getLocation(); if (seat instanceof ArmorStand) { - location.add(0, 0.9875,0); + location.add(0, 0.3875,0); } else { - location.add(0,0.25,0); + location.add(0,-0.35,0); } seat.remove(); EntityUtils.safeDismount(player, location); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java index 7a24b32f8..01539c1b0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java @@ -501,10 +501,17 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory behaviorHolder = new ObjectHolder<>(EmptyBlockBehavior.INSTANCE); ObjectHolder shapeHolder = new ObjectHolder<>(STONE_SHAPE); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/WorldStorageInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/WorldStorageInjector.java index b1e7d7ff1..fd65f8003 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/WorldStorageInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/WorldStorageInjector.java @@ -19,6 +19,7 @@ import net.momirealms.craftengine.core.block.DelegatingBlockState; import net.momirealms.craftengine.core.block.EmptyBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.entity.BlockEntity; +import net.momirealms.craftengine.core.block.entity.render.ConstantBlockEntityRenderer; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.util.ReflectionUtils; @@ -226,7 +227,10 @@ public final class WorldStorageInjector { // 处理 自定义块到自定义块或原版块到自定义块 CEChunk chunk = holder.ceChunk(); chunk.setDirty(true); + + ConstantBlockEntityRenderer previousRenderer = null; // 如果两个方块没有相同的主人 且 旧方块有方块实体 + if (!previousImmutableBlockState.isEmpty()) { if (previousImmutableBlockState.owner() != newImmutableBlockState.owner() && previousImmutableBlockState.hasBlockEntity()) { BlockPos pos = new BlockPos(chunk.chunkPos.x * 16 + x, section.sectionY * 16 + y, chunk.chunkPos.z * 16 + z); @@ -242,9 +246,11 @@ public final class WorldStorageInjector { } if (previousImmutableBlockState.hasConstantBlockEntityRenderer()) { BlockPos pos = new BlockPos(chunk.chunkPos.x * 16 + x, section.sectionY * 16 + y, chunk.chunkPos.z * 16 + z); - chunk.removeConstantBlockEntityRenderer(pos); + // 如果新状态没有entity renderer,那么直接移除,否则暂存 + previousRenderer = chunk.removeConstantBlockEntityRenderer(pos, !newImmutableBlockState.hasConstantBlockEntityRenderer()); } } + if (newImmutableBlockState.hasBlockEntity()) { BlockPos pos = new BlockPos(chunk.chunkPos.x * 16 + x, section.sectionY * 16 + y, chunk.chunkPos.z * 16 + z); BlockEntity blockEntity = chunk.getBlockEntity(pos, false); @@ -264,10 +270,13 @@ public final class WorldStorageInjector { chunk.createDynamicBlockEntityRenderer(blockEntity); } } + + // 处理新老entity renderer更替 if (newImmutableBlockState.hasConstantBlockEntityRenderer()) { BlockPos pos = new BlockPos(chunk.chunkPos.x * 16 + x, section.sectionY * 16 + y, chunk.chunkPos.z * 16 + z); - chunk.addConstantBlockEntityRenderer(pos, newImmutableBlockState); + chunk.addConstantBlockEntityRenderer(pos, newImmutableBlockState, previousRenderer); } + // 如果新方块的光照属性和客户端认为的不同 if (Config.enableLightSystem()) { if (previousImmutableBlockState.isEmpty()) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index 6bb11d66e..1ff589e57 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -241,6 +241,19 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes this.c2sGamePacketListeners[id] = new ByteBufferPacketListenerHolder(name, listener); } + @Override + public void delayedLoad() { + this.resendTags(); + } + + @SuppressWarnings("unchecked") + public void resendTags() { + Object packet = TagUtils.createUpdateTagsPacket(Map.of(MRegistries.BLOCK, BukkitBlockManager.instance().cachedUpdateTags()), FastNMS.INSTANCE.method$TagNetworkSerialization$serializeTagsToNetwork()); + for (BukkitServerPlayer player : onlineUsers()) { + player.sendPacket(packet, false); + } + } + public void addFakePlayer(Player player) { FakeBukkitServerPlayer fakePlayer = new FakeBukkitServerPlayer(this.plugin); fakePlayer.setPlayer(player); @@ -1857,11 +1870,17 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes public static class UpdateTagsListener implements NMSPacketListener { + @SuppressWarnings("unchecked") @Override public void onPacketSend(NetWorkUser user, NMSPacketEvent event, Object packet) { - Object modifiedPacket = BukkitBlockManager.instance().cachedUpdateTagsPacket(); - if (packet.equals(modifiedPacket) || modifiedPacket == null) return; - event.replacePacket(modifiedPacket); + List cachedUpdateTags = BukkitBlockManager.instance().cachedUpdateTags(); + if (cachedUpdateTags.isEmpty()) return; + Map tags = FastNMS.INSTANCE.field$ClientboundUpdateTagsPacket$tags(packet); + // 已经替换过了 + if (tags instanceof MarkedHashMap) return; + // 需要虚假的block + if (tags.get(MRegistries.BLOCK) == null) return; + event.replacePacket(TagUtils.createUpdateTagsPacket(Map.of(MRegistries.BLOCK, cachedUpdateTags), tags)); } } @@ -4132,16 +4151,22 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes CompoundTag tag = (CompoundTag) buf.readNbt(named); // todo 刷怪笼里的物品? - // 展示架 - if (VersionHelper.isOrAbove1_21_9() && tag != null && tag.containsKey("Items")) { + // 通用方块实体存储的物品 + if (tag != null && tag.containsKey("Items")) { BukkitItemManager itemManager = BukkitItemManager.instance(); ListTag itemsTag = tag.getList("Items"); List> items = new ArrayList<>(); for (Tag itemTag : itemsTag) { if (itemTag instanceof CompoundTag itemCompoundTag) { byte slot = itemCompoundTag.getByte("Slot"); - Object nmsStack = CoreReflections.instance$ItemStack$CODEC.parse(MRegistryOps.SPARROW_NBT, itemCompoundTag) - .resultOrPartial((error) -> CraftEngine.instance().logger().severe("Tried to parse invalid item: '" + error + "'")).orElse(null); + Object nmsStack; + if (VersionHelper.isOrAbove1_20_5()) { + nmsStack = CoreReflections.instance$ItemStack$CODEC.parse(MRegistryOps.SPARROW_NBT, itemCompoundTag) + .resultOrPartial((error) -> CraftEngine.instance().logger().severe("Tried to parse invalid item: '" + error + "'")).orElse(null); + } else { + Object nmsTag = MRegistryOps.SPARROW_NBT.convertTo(MRegistryOps.NBT, itemTag); + nmsStack = FastNMS.INSTANCE.method$ItemStack$of(nmsTag); + } ItemStack bukkitStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsStack); Optional optional = itemManager.s2c(bukkitStack, (BukkitServerPlayer) user); if (optional.isPresent()) { @@ -4155,8 +4180,14 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes if (changed) { ListTag newItemsTag = new ListTag(); for (Pair pair : items) { - CompoundTag newItemCompoundTag = (CompoundTag) CoreReflections.instance$ItemStack$CODEC.encodeStart(MRegistryOps.SPARROW_NBT, FastNMS.INSTANCE.field$CraftItemStack$handle(pair.right())) - .resultOrPartial((error) -> CraftEngine.instance().logger().severe("Tried to encode invalid item: '" + error + "'")).orElse(null); + CompoundTag newItemCompoundTag; + if (VersionHelper.isOrAbove1_20_5()) { + newItemCompoundTag = (CompoundTag) CoreReflections.instance$ItemStack$CODEC.encodeStart(MRegistryOps.SPARROW_NBT, FastNMS.INSTANCE.field$CraftItemStack$handle(pair.right())) + .resultOrPartial((error) -> CraftEngine.instance().logger().severe("Tried to encode invalid item: '" + error + "'")).orElse(null); + } else { + Object nmsTag = FastNMS.INSTANCE.method$itemStack$save(FastNMS.INSTANCE.field$CraftItemStack$handle(pair.right()), FastNMS.INSTANCE.constructor$CompoundTag()); + newItemCompoundTag = (CompoundTag) MRegistryOps.NBT.convertTo(MRegistryOps.SPARROW_NBT, nmsTag); + } if (newItemCompoundTag != null) { newItemCompoundTag.putByte("Slot", pair.left()); newItemsTag.add(newItemCompoundTag); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/protocol/ClientCustomBlockPacket.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/protocol/ClientCustomBlockPacket.java index eee81789d..e63cfd630 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/protocol/ClientCustomBlockPacket.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/protocol/ClientCustomBlockPacket.java @@ -56,7 +56,7 @@ public record ClientCustomBlockPacket(int vanillaSize, int currentSize) implemen return; } int serverBlockRegistrySize = RegistryUtils.currentBlockRegistrySize(); - if (this.currentSize != serverBlockRegistrySize) { + if (this.currentSize < serverBlockRegistrySize) { user.kick(Component.translatable( "disconnect.craftengine.current_block_registry_mismatch", TranslationArgument.numeric(this.currentSize), diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java index c5beafe9e..5547f8c7d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java @@ -1082,7 +1082,7 @@ public final class CoreReflections { public static final Class clazz$MobEffect = requireNonNull( ReflectionUtils.getClazz( BukkitReflectionUtils.assembleMCClass("world.effect.MobEffectList"), // 这里paper会自动获取到NM.world.effect.MobEffect - BukkitReflectionUtils.assembleMCClass("world.effect.MobEffect") // 如果插件是mojmap就会走这个 + BukkitReflectionUtils.assembleMCClass("world.effect.MobEffect") // paper柠檬酸了 ) ); @@ -1125,7 +1125,7 @@ public final class CoreReflections { public static final Class clazz$Fluid = requireNonNull( ReflectionUtils.getClazz( BukkitReflectionUtils.assembleMCClass("world.level.material.FluidType"), // 这里paper会自动获取到NM.world.level.material.Fluid - BukkitReflectionUtils.assembleMCClass("world.level.material.Fluid") // 如果插件是mojmap就会走这个 + BukkitReflectionUtils.assembleMCClass("world.level.material.Fluid") // paper柠檬酸了 ) ); @@ -3133,9 +3133,9 @@ public final class CoreReflections { ); public static final Class clazz$ChunkMap = requireNonNull( - BukkitReflectionUtils.findReobfOrMojmapClass( - "server.level.PlayerChunkMap", - "server.level.ChunkMap" + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("server.level.PlayerChunkMap"), // 这里paper会自动获取到NM.server.level.ChunkMap + BukkitReflectionUtils.assembleMCClass("server.level.ChunkMap") // paper柠檬酸了 ) ); @@ -3238,7 +3238,7 @@ public final class CoreReflections { public static final Class clazz$ResourceManager = requireNonNull( ReflectionUtils.getClazz( BukkitReflectionUtils.assembleMCClass("server.packs.resources.IResourceManager"), // 这里paper会自动获取到NM.server.packs.resources.ResourceManager - BukkitReflectionUtils.assembleMCClass("server.packs.resources.ResourceManager") // 如果插件是mojmap就会走这个 + BukkitReflectionUtils.assembleMCClass("server.packs.resources.ResourceManager") // paper柠檬酸了 ) ); @@ -4536,4 +4536,16 @@ public final class CoreReflections { public static final Method method$DismountHelper$canDismountTo1 = requireNonNull( ReflectionUtils.getStaticMethod(clazz$DismountHelper, boolean.class, clazz$CollisionGetter, clazz$Vec3, clazz$LivingEntity, clazz$Pose) ); + + public static final Class clazz$WorldGenContext = MiscUtils.requireNonNullIf( + ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("world.level.chunk.status.WorldGenContext")), VersionHelper.isOrAbove1_20_5() + ); + + public static final Field field$ChunkMap$worldGenContext = MiscUtils.requireNonNullIf( + ReflectionUtils.getDeclaredField(clazz$ChunkMap, clazz$WorldGenContext, 0), VersionHelper.isOrAbove1_20_5() + ); + + public static final Field field$ChunkMap$chunkGenerator = MiscUtils.requireNonNullIf( + ReflectionUtils.getDeclaredField(clazz$ChunkMap, clazz$ChunkGenerator, 0), !VersionHelper.isOrAbove1_20_5() + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java index 567234cb1..f5b1e4ee9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java @@ -1720,4 +1720,10 @@ public final class NetworkReflections { "network.protocol.game.ClientboundBlockEntityDataPacket" ) ); + + public static final Field field$ClientboundUpdateTagsPacket$tags = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundUpdateTagsPacket, Map.class, 0 + ) + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityUtils.java index ec227f9cd..05a9600e1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityUtils.java @@ -63,32 +63,34 @@ public final class EntityUtils { BlockPos pos = new BlockPos(MiscUtils.fastFloor(x), MiscUtils.fastFloor(y), MiscUtils.fastFloor(z)); try { double floorHeight = (double) CoreReflections.method$BlockGetter$getBlockFloorHeight.invoke(serverLevel, LocationUtils.toBlockPos(pos)); - if (pos.y() + floorHeight > y + 0.75) { + if (pos.y() + floorHeight > y + 0.75 || !isBlockFloorValid(floorHeight)) { + floorHeight = (double) CoreReflections.method$BlockGetter$getBlockFloorHeight.invoke(serverLevel, LocationUtils.toBlockPos(pos.below())); + if (pos.y() + floorHeight - 1 < y - 0.75 || !isBlockFloorValid(floorHeight)) { + continue; + } + floorHeight -= 1; + } + Object aabb = CoreReflections.method$LivingEntity$getLocalBoundsForPose.invoke(serverPlayer, pose); + Object vec3 = FastNMS.INSTANCE.constructor$Vec3(x, pos.y() + floorHeight, z); + Object newAABB = FastNMS.INSTANCE.method$AABB$move(aabb, vec3); + boolean canDismount = (boolean) CoreReflections.method$DismountHelper$canDismountTo0.invoke(null, serverLevel, serverPlayer, newAABB); + if (!canDismount) { continue; } - if (isBlockFloorValid(floorHeight)) { - Object aabb = CoreReflections.method$LivingEntity$getLocalBoundsForPose.invoke(serverPlayer, pose); - Object vec3 = FastNMS.INSTANCE.constructor$Vec3(x, pos.y() + floorHeight, z); - Object newAABB = FastNMS.INSTANCE.method$AABB$move(aabb, vec3); - boolean canDismount = (boolean) CoreReflections.method$DismountHelper$canDismountTo0.invoke(null, serverLevel, serverPlayer, newAABB); - if (!canDismount) { - continue; - } - if (!FastNMS.INSTANCE.checkEntityCollision(serverLevel, List.of(newAABB))) { - continue; - } - if (VersionHelper.isFolia()) { - player.teleportAsync(new Location(player.getWorld(), x, pos.y() + floorHeight, z, player.getYaw(), player.getPitch())); - } else { - player.teleport(new Location(player.getWorld(), x, pos.y() + floorHeight, z, player.getYaw(), player.getPitch())); - } - if (pose == CoreReflections.instance$Pose$STANDING) { - player.setPose(Pose.STANDING); - } else if (pose == CoreReflections.instance$Pose$CROUCHING) { - player.setPose(Pose.SNEAKING); - } else if (pose == CoreReflections.instance$Pose$SWIMMING) { - player.setPose(Pose.SWIMMING); - } + if (!FastNMS.INSTANCE.checkEntityCollision(serverLevel, List.of(newAABB))) { + continue; + } + if (VersionHelper.isFolia()) { + player.teleportAsync(new Location(player.getWorld(), x, pos.y() + floorHeight, z, player.getYaw(), player.getPitch())); + } else { + player.teleport(new Location(player.getWorld(), x, pos.y() + floorHeight, z, player.getYaw(), player.getPitch())); + } + if (pose == CoreReflections.instance$Pose$STANDING) { + player.setPose(Pose.STANDING); + } else if (pose == CoreReflections.instance$Pose$CROUCHING) { + player.setPose(Pose.SNEAKING); + } else if (pose == CoreReflections.instance$Pose$SWIMMING) { + player.setPose(Pose.SWIMMING); } } catch (ReflectiveOperationException e) { throw new RuntimeException(e); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java index 069deb791..dc44ac1a9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java @@ -34,6 +34,7 @@ import org.bukkit.attribute.AttributeInstance; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; import org.bukkit.block.data.Levelled; import org.bukkit.block.data.Lightable; import org.bukkit.block.data.type.*; @@ -714,6 +715,37 @@ public final class InteractUtils { registerInteraction(BlockKeys.BAMBOO_WALL_HANGING_SIGN, (player, item, blockState, result) -> true); registerInteraction(BlockKeys.CRIMSON_WALL_HANGING_SIGN, (player, item, blockState, result) -> true); registerInteraction(BlockKeys.WARPED_WALL_HANGING_SIGN, (player, item, blockState, result) -> true); + // 展示柜 + registerInteraction(BlockKeys.OAK_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.SPRUCE_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.BIRCH_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.JUNGLE_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.ACACIA_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.DARK_OAK_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.MANGROVE_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.CHERRY_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.PALE_OAK_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.BAMBOO_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.CRIMSON_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + registerInteraction(BlockKeys.WARPED_SHELF, (player, item, blockState, result) -> blockState instanceof Directional directional && DirectionUtils.toBlockFace(result.getDirection()).equals(directional.getFacing())); + // 铜傀儡雕像 + registerInteraction(BlockKeys.COPPER_GOLEM_STATUE, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.EXPOSED_COPPER_GOLEM_STATUE, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WEATHERED_COPPER_GOLEM_STATUE, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.OXIDIZED_COPPER_GOLEM_STATUE, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WAXED_COPPER_GOLEM_STATUE, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WAXED_EXPOSED_COPPER_GOLEM_STATUE, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WAXED_WEATHERED_COPPER_GOLEM_STATUE, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WAXED_OXIDIZED_COPPER_GOLEM_STATUE, ((player, item, blockData, result) -> true)); + // 铜箱子 + registerInteraction(BlockKeys.COPPER_CHEST, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.EXPOSED_COPPER_CHEST, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WEATHERED_COPPER_CHEST, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.OXIDIZED_COPPER_CHEST, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WAXED_COPPER_CHEST, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WAXED_EXPOSED_COPPER_CHEST, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WAXED_WEATHERED_COPPER_CHEST, ((player, item, blockData, result) -> true)); + registerInteraction(BlockKeys.WAXED_OXIDIZED_COPPER_CHEST, ((player, item, blockData, result) -> true)); } static { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/TagUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/TagUtils.java index 530ccc248..9f82073e8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/TagUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/TagUtils.java @@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.core.util.FriendlyByteBuf; +import net.momirealms.craftengine.core.util.MarkedHashMap; import java.util.ArrayList; import java.util.HashMap; @@ -15,6 +16,9 @@ public final class TagUtils { private TagUtils() {} + public record TagEntry(int id, List tags) { + } + /** * 构建模拟标签更新数据包(用于向客户端添加虚拟标签) * @@ -39,11 +43,9 @@ public final class TagUtils { * * @return 可发送给客户端的 ClientboundUpdateTagsPacket 数据包对象 */ - @SuppressWarnings("unchecked") - public static Object createUpdateTagsPacket(Map> tags) { - Map registriesNetworkPayload = (Map) FastNMS.INSTANCE.method$TagNetworkSerialization$serializeTagsToNetwork(); - Map modified = new HashMap<>(); - for (Map.Entry payload : registriesNetworkPayload.entrySet()) { + public static Object createUpdateTagsPacket(Map> tags, Map existingTags) { + Map modified = new MarkedHashMap<>(); + for (Map.Entry payload : existingTags.entrySet()) { List overrides = tags.get(payload.getKey()); if (overrides == null || overrides.isEmpty()) { modified.put(payload.getKey(), payload.getValue()); @@ -83,7 +85,4 @@ public final class TagUtils { } return FastNMS.INSTANCE.constructor$ClientboundUpdateTagsPacket(modified); } - - public record TagEntry(int id, List tags) { - } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java index ea4ab38e3..ba41c8181 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java @@ -92,10 +92,12 @@ public class BukkitWorldManager implements WorldManager, Listener { public void delayedInit() { // load loaded chunks for (World world : Bukkit.getWorlds()) { + BukkitWorld wrappedWorld = new BukkitWorld(world); try { - CEWorld ceWorld = this.worlds.computeIfAbsent(world.getUID(), k -> new BukkitCEWorld(new BukkitWorld(world), this.storageAdaptor)); + CEWorld ceWorld = this.worlds.computeIfAbsent(world.getUID(), k -> new BukkitCEWorld(wrappedWorld, this.storageAdaptor)); + injectChunkGenerator(ceWorld); for (Chunk chunk : world.getLoadedChunks()) { - handleChunkLoad(ceWorld, chunk); + handleChunkLoad(ceWorld, chunk, false); } ceWorld.setTicking(true); } catch (Exception e) { @@ -142,8 +144,9 @@ public class BukkitWorldManager implements WorldManager, Listener { CEWorld ceWorld = new BukkitCEWorld(world, this.storageAdaptor); this.worlds.put(uuid, ceWorld); this.resetWorldArray(); + this.injectChunkGenerator(ceWorld); for (Chunk chunk : ((World) world.platformWorld()).getLoadedChunks()) { - handleChunkLoad(ceWorld, chunk); + handleChunkLoad(ceWorld, chunk, false); } ceWorld.setTicking(true); } @@ -154,12 +157,20 @@ public class BukkitWorldManager implements WorldManager, Listener { if (this.worlds.containsKey(uuid)) return; this.worlds.put(uuid, world); this.resetWorldArray(); + this.injectChunkGenerator(world); for (Chunk chunk : ((World) world.world().platformWorld()).getLoadedChunks()) { - handleChunkLoad(world, chunk); + handleChunkLoad(world, chunk, false); } world.setTicking(true); } + private void injectChunkGenerator(CEWorld world) { + Object serverLevel = world.world.serverWorld(); + Object serverChunkCache = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel); + Object chunkMap = FastNMS.INSTANCE.field$ServerChunkCache$chunkMap(serverChunkCache); + FastNMS.INSTANCE.injectedWorldGen(world, chunkMap); + } + @Override public CEWorld createWorld(net.momirealms.craftengine.core.world.World world, WorldDataStorage storage) { return new BukkitCEWorld(world, storage); @@ -219,7 +230,7 @@ public class BukkitWorldManager implements WorldManager, Listener { if (world == null) { return; } - handleChunkLoad(world, event.getChunk()); + handleChunkLoad(world, event.getChunk(), event.isNewChunk()); } @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) @@ -273,14 +284,42 @@ public class BukkitWorldManager implements WorldManager, Listener { FastNMS.INSTANCE.method$LevelChunk$markUnsaved(levelChunk); } ceChunk.unload(); + ceChunk.deactivateAllBlockEntities(); } } - private void handleChunkLoad(CEWorld ceWorld, Chunk chunk) { + public void handleChunkGenerate(CEWorld ceWorld, ChunkPos chunkPos, Object chunkAccess) { + Object[] sections = FastNMS.INSTANCE.method$ChunkAccess$getSections(chunkAccess); + CEChunk ceChunk; + try { + ceChunk = ceWorld.worldDataStorage().readNewChunkAt(ceWorld, chunkPos); + CESection[] ceSections = ceChunk.sections(); + synchronized (sections) { + for (int i = 0; i < ceSections.length; i++) { + CESection ceSection = ceSections[i]; + Object section = sections[i]; + int finalI = i; + WorldStorageInjector.injectLevelChunkSection(section, ceSection, ceChunk, new SectionPos(chunkPos.x, ceChunk.sectionY(i), chunkPos.z), + (injected) -> sections[finalI] = injected); + } + } + ceChunk.load(); + } catch (IOException e) { + this.plugin.logger().warn("Failed to read new chunk at " + chunkPos.x + " " + chunkPos.z, e); + } + } + + private void handleChunkLoad(CEWorld ceWorld, Chunk chunk, boolean isNew) { int chunkX = chunk.getX(); int chunkZ = chunk.getZ(); ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ); - if (ceWorld.isChunkLoaded(chunkPos.longKey)) return; + CEChunk chunkAtIfLoaded = ceWorld.getChunkAtIfLoaded(chunkPos.longKey); + if (chunkAtIfLoaded != null) { + if (isNew) { + chunkAtIfLoaded.activateAllBlockEntities(); + } + return; + } CEChunk ceChunk; try { ceChunk = ceWorld.worldDataStorage().readChunkAt(ceWorld, chunkPos); @@ -382,5 +421,6 @@ public class BukkitWorldManager implements WorldManager, Listener { return; } ceChunk.load(); + ceChunk.activateAllBlockEntities(); } } diff --git a/common-files/src/main/resources/config.yml b/common-files/src/main/resources/config.yml index 53b288014..c818e6167 100644 --- a/common-files/src/main/resources/config.yml +++ b/common-files/src/main/resources/config.yml @@ -81,6 +81,15 @@ resource-pack: suffix: "minecraft/atlases" resolution: type: merge_atlas + - term: + type: any_of + terms: + - type: exact + path: "assets/minecraft/font/default.json" + - type: exact + path: "assets/minecraft/font/uniform.json" + resolution: + type: merge_font # Validate if there is any error in the resource pack, such as missing textures or models # If your resource pack is compliant with the standard, you can disable validation to improve the resource pack generation speed. validation: diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/amethyst_torch.yml b/common-files/src/main/resources/resources/default/configuration/blocks/amethyst_torch.yml index 773ea9c4e..5abdab95c 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/amethyst_torch.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/amethyst_torch.yml @@ -2,7 +2,7 @@ items: default:amethyst_torch: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/amethyst_torch @@ -20,7 +20,7 @@ items: default:amethyst_standing_torch: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:block/custom/amethyst_torch @@ -31,7 +31,7 @@ items: default:amethyst_wall_torch: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:block/custom/amethyst_wall_torch diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/chessboard_block.yml b/common-files/src/main/resources/resources/default/configuration/blocks/chessboard_block.yml index 7e36d6d45..cb6bfdb18 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/chessboard_block.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/chessboard_block.yml @@ -2,7 +2,7 @@ items: default:chessboard_block: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/chessboard_block diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/chinese_lantern.yml b/common-files/src/main/resources/resources/default/configuration/blocks/chinese_lantern.yml index 420809bc8..1dadb3500 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/chinese_lantern.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/chinese_lantern.yml @@ -2,7 +2,7 @@ items: default:chinese_lantern: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/chinese_lantern diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/copper_coil.yml b/common-files/src/main/resources/resources/default/configuration/blocks/copper_coil.yml index 9d9b8bf83..7615f1fb6 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/copper_coil.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/copper_coil.yml @@ -2,7 +2,7 @@ items: default:copper_coil: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/copper_coil diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/ender_pearl_flower.yml b/common-files/src/main/resources/resources/default/configuration/blocks/ender_pearl_flower.yml index 0847ee653..258f99c92 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/ender_pearl_flower.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/ender_pearl_flower.yml @@ -2,7 +2,7 @@ items: default:ender_pearl_flower_seeds: material: nether_brick data: - item-name: + item-name: model: template: default:model/simplified_generated arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/fairy_flower.yml b/common-files/src/main/resources/resources/default/configuration/blocks/fairy_flower.yml index ef42b7638..08debd5e8 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/fairy_flower.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/fairy_flower.yml @@ -2,7 +2,7 @@ items: default:fairy_flower: material: nether_brick data: - item-name: + item-name: model: template: default:model/simplified_generated arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/flame_cane.yml b/common-files/src/main/resources/resources/default/configuration/blocks/flame_cane.yml index 4213b62bd..dd50822f0 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/flame_cane.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/flame_cane.yml @@ -2,7 +2,7 @@ items: default:flame_cane: material: nether_brick data: - item-name: + item-name: model: template: default:model/simplified_generated arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/gunpowder_block.yml b/common-files/src/main/resources/resources/default/configuration/blocks/gunpowder_block.yml index e114b183c..17bf82ce5 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/gunpowder_block.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/gunpowder_block.yml @@ -2,7 +2,7 @@ items: default:gunpowder_block: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/gunpowder_block @@ -37,7 +37,7 @@ items: default:solid_gunpowder_block: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/solid_gunpowder_block diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/hami_melon.yml b/common-files/src/main/resources/resources/default/configuration/blocks/hami_melon.yml index 03592440a..67de31a05 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/hami_melon.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/hami_melon.yml @@ -2,7 +2,7 @@ items: default:hami_melon_slice: material: melon_slice data: - item-name: + item-name: $$>=1.20.5: food: nutrition: 2 @@ -20,7 +20,7 @@ items: default:hami_melon: material: nether_brick data: - item-name: + item-name: model: path: minecraft:item/custom/hami_melon generation: @@ -31,7 +31,7 @@ items: default:hami_melon_seeds: material: nether_brick data: - item-name: + item-name: model: template: default:model/simplified_generated arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/magma_plant.yml b/common-files/src/main/resources/resources/default/configuration/blocks/magma_plant.yml index 7eb0e196b..b608b57b9 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/magma_plant.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/magma_plant.yml @@ -6,7 +6,7 @@ items: arguments: path: minecraft:item/custom/magma_fruit data: - item-name: + item-name: $$>=1.20.5: food: nutrition: 3 diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/netherite_anvil.yml b/common-files/src/main/resources/resources/default/configuration/blocks/netherite_anvil.yml index 467ff359b..86fbecd35 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/netherite_anvil.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/netherite_anvil.yml @@ -2,7 +2,7 @@ items: default:netherite_anvil: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/netherite_anvil diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/palm_tree.yml b/common-files/src/main/resources/resources/default/configuration/blocks/palm_tree.yml index d628ff0d8..b3835f599 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/palm_tree.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/palm_tree.yml @@ -8,7 +8,7 @@ items: - minecraft:logs - minecraft:logs_that_burn data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/palm_log @@ -40,7 +40,7 @@ items: - minecraft:logs - minecraft:logs_that_burn data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/stripped_palm_log @@ -69,7 +69,7 @@ items: - minecraft:logs - minecraft:logs_that_burn data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/palm_wood @@ -101,7 +101,7 @@ items: - minecraft:logs - minecraft:logs_that_burn data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/stripped_palm_wood @@ -129,7 +129,7 @@ items: - minecraft:planks - minecraft:wooden_tool_materials data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/palm_planks @@ -153,7 +153,7 @@ items: settings: fuel-time: 100 data: - item-name: + item-name: lore: - "Requires the datapack tree configuration to function." - "If not configured, an oak tree will grow by default." @@ -197,7 +197,7 @@ items: default:palm_leaves: material: oak_leaves data: - item-name: + item-name: block-state: default:palm_leaves[persistent=true,waterlogged=false,distance=7] model: type: minecraft:model @@ -227,7 +227,7 @@ items: default:palm_trapdoor: material: nether_brick data: - item-name: + item-name: settings: fuel-time: 300 model: @@ -281,7 +281,7 @@ items: default:palm_door: material: nether_brick data: - item-name: + item-name: settings: fuel-time: 200 model: @@ -355,7 +355,7 @@ items: default:palm_fence_gate: material: nether_brick data: - item-name: + item-name: settings: fuel-time: 300 model: @@ -411,7 +411,7 @@ items: default:palm_slab: material: nether_brick data: - item-name: + item-name: settings: fuel-time: 150 model: @@ -462,7 +462,7 @@ items: generation: parent: minecraft:block/custom/palm_stairs data: - item-name: + item-name: settings: fuel-time: 300 behavior: @@ -511,7 +511,7 @@ items: generation: parent: minecraft:block/custom/palm_pressure_plate data: - item-name: + item-name: settings: fuel-time: 300 behavior: @@ -560,7 +560,7 @@ items#pfence: default:palm_fence: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/palm_fence_inventory @@ -632,7 +632,7 @@ items#button: textures: texture: minecraft:block/custom/palm_planks data: - item-name: + item-name: settings: fuel-time: 100 behavior: diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/pebble.yml b/common-files/src/main/resources/resources/default/configuration/blocks/pebble.yml index 6f267d5ad..d9dd1ef1f 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/pebble.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/pebble.yml @@ -2,7 +2,7 @@ items: default:pebble: material: nether_brick data: - item-name: + item-name: model: template: default:model/simplified_generated arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/reed.yml b/common-files/src/main/resources/resources/default/configuration/blocks/reed.yml index de1e00be9..49ce9b22d 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/reed.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/reed.yml @@ -2,7 +2,7 @@ items: default:reed: material: nether_brick data: - item-name: + item-name: model: template: default:model/simplified_generated arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/safe_block.yml b/common-files/src/main/resources/resources/default/configuration/blocks/safe_block.yml index 63b13e353..103c0a95c 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/safe_block.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/safe_block.yml @@ -2,7 +2,7 @@ items: default:safe_block: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/safe_block @@ -31,7 +31,7 @@ items: step: minecraft:block.stone.step behavior: type: simple_storage_block - title: "" + title: "" rows: 1 sounds: open: minecraft:block.iron_trapdoor.open @@ -58,6 +58,7 @@ items: front: minecraft:block/custom/safe_block_front side: minecraft:block/custom/safe_block_side top: minecraft:block/custom/safe_block_top + bottom: minecraft:block/custom/safe_block_bottom east_open: auto-state: note_block model: @@ -69,6 +70,7 @@ items: front: minecraft:block/custom/safe_block_front_open side: minecraft:block/custom/safe_block_side top: minecraft:block/custom/safe_block_top + bottom: minecraft:block/custom/safe_block_bottom north: auto-state: note_block model: diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/sofa.yml b/common-files/src/main/resources/resources/default/configuration/blocks/sofa.yml index d0b126ea1..bd5e72fd3 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/sofa.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/sofa.yml @@ -2,7 +2,7 @@ items: default:sleeper_sofa: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/sleeper_sofa @@ -50,7 +50,7 @@ items: default:sofa: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/sofa diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/table_lamp.yml b/common-files/src/main/resources/resources/default/configuration/blocks/table_lamp.yml index 7f7165c56..adb60844a 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/table_lamp.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/table_lamp.yml @@ -2,7 +2,7 @@ items: default:table_lamp: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/table_lamp diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/topaz_ore.yml b/common-files/src/main/resources/resources/default/configuration/blocks/topaz_ore.yml index f120a9776..00d5621a5 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/topaz_ore.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/topaz_ore.yml @@ -2,7 +2,7 @@ items: default:topaz_ore: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/topaz_ore @@ -14,7 +14,7 @@ items: default:deepslate_topaz_ore: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/deepslate_topaz_ore @@ -31,7 +31,7 @@ items: - '#default:topaz_tools' percent: 0.25 data: - item-name: <#FF8C00> + item-name: <#FF8C00> model: template: default:model/simplified_generated arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/categories.yml b/common-files/src/main/resources/resources/default/configuration/categories.yml index e86e20116..2f9c69cb6 100644 --- a/common-files/src/main/resources/resources/default/configuration/categories.yml +++ b/common-files/src/main/resources/resources/default/configuration/categories.yml @@ -1,16 +1,16 @@ categories: default:default: priority: 1 - name: + name: lore: - - + - icon: default:topaz list: - '#default:palm_tree' - '#default:topaz' - '#default:misc' default:palm_tree: - name: + name: hidden: true icon: default:palm_log list: @@ -30,7 +30,7 @@ categories: - default:palm_pressure_plate - default:palm_button default:topaz: - name: <#FF8C00> + name: <#FF8C00> hidden: true icon: default:topaz list: @@ -51,7 +51,7 @@ categories: - default:topaz_leggings - default:topaz_boots default:misc: - name: + name: hidden: true icon: default:chinese_lantern list: diff --git a/common-files/src/main/resources/resources/default/configuration/emoji.yml b/common-files/src/main/resources/resources/default/configuration/emoji.yml index 4fe4b0e69..aa001996e 100644 --- a/common-files/src/main/resources/resources/default/configuration/emoji.yml +++ b/common-files/src/main/resources/resources/default/configuration/emoji.yml @@ -1,6 +1,6 @@ templates: default:emoji/basic: - content: '> + content: '> emoji: default:emoji_smiley: template: default:emoji/basic diff --git a/common-files/src/main/resources/resources/default/configuration/furniture/bench.yml b/common-files/src/main/resources/resources/default/configuration/furniture/bench.yml index cf5688160..3b4b68471 100644 --- a/common-files/src/main/resources/resources/default/configuration/furniture/bench.yml +++ b/common-files/src/main/resources/resources/default/configuration/furniture/bench.yml @@ -2,7 +2,7 @@ items: default:bench: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/bench diff --git a/common-files/src/main/resources/resources/default/configuration/furniture/flower_basket.yml b/common-files/src/main/resources/resources/default/configuration/furniture/flower_basket.yml index 63c508fde..0dd2ac5c2 100644 --- a/common-files/src/main/resources/resources/default/configuration/furniture/flower_basket.yml +++ b/common-files/src/main/resources/resources/default/configuration/furniture/flower_basket.yml @@ -2,7 +2,7 @@ items: default:flower_basket: material: nether_brick data: - item-name: + item-name: model: template: default:model/simplified_generated arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/furniture/wooden_chair.yml b/common-files/src/main/resources/resources/default/configuration/furniture/wooden_chair.yml index 5d62051b1..24471cfb1 100644 --- a/common-files/src/main/resources/resources/default/configuration/furniture/wooden_chair.yml +++ b/common-files/src/main/resources/resources/default/configuration/furniture/wooden_chair.yml @@ -2,7 +2,7 @@ items: default:wooden_chair: material: nether_brick data: - item-name: + item-name: model: type: minecraft:model path: minecraft:item/custom/wooden_chair diff --git a/common-files/src/main/resources/resources/default/configuration/items/cap.yml b/common-files/src/main/resources/resources/default/configuration/items/cap.yml index aaa7a88b3..4f03b1dee 100644 --- a/common-files/src/main/resources/resources/default/configuration/items/cap.yml +++ b/common-files/src/main/resources/resources/default/configuration/items/cap.yml @@ -4,7 +4,7 @@ items: $$<=1.21.1: client-bound-material: leather_horse_armor data: - item-name: + item-name: unbreakable: true remove-components: - attribute_modifiers diff --git a/common-files/src/main/resources/resources/default/configuration/items/flame_elytra.yml b/common-files/src/main/resources/resources/default/configuration/items/flame_elytra.yml index 43425ae92..e89cc0f4e 100644 --- a/common-files/src/main/resources/resources/default/configuration/items/flame_elytra.yml +++ b/common-files/src/main/resources/resources/default/configuration/items/flame_elytra.yml @@ -8,7 +8,7 @@ items: asset-id: flame wings: flame_elytra data: - item-name: <#FF8C00> + item-name: <#FF8C00> model: template: default:model/simplified_elytra arguments: diff --git a/common-files/src/main/resources/resources/default/configuration/items/topaz_armor.yml b/common-files/src/main/resources/resources/default/configuration/items/topaz_armor.yml index fcbaf8c86..8d624a490 100644 --- a/common-files/src/main/resources/resources/default/configuration/items/topaz_armor.yml +++ b/common-files/src/main/resources/resources/default/configuration/items/topaz_armor.yml @@ -2,7 +2,7 @@ templates: default:armor/topaz: material: chainmail_${part} data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz settings: tags: diff --git a/common-files/src/main/resources/resources/default/configuration/items/topaz_tool_weapon.yml b/common-files/src/main/resources/resources/default/configuration/items/topaz_tool_weapon.yml index 3eb60e3d0..04a893078 100644 --- a/common-files/src/main/resources/resources/default/configuration/items/topaz_tool_weapon.yml +++ b/common-files/src/main/resources/resources/default/configuration/items/topaz_tool_weapon.yml @@ -5,7 +5,7 @@ items: tags: - default:topaz_tools data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz model: template: default:model/simplified_fishing_rod_2d @@ -18,7 +18,7 @@ items: tags: - default:topaz_tools data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz model: template: default:model/simplified_bow_2d @@ -33,7 +33,7 @@ items: tags: - default:topaz_tools data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz model: template: default:model/simplified_crossbow_2d @@ -50,7 +50,7 @@ items: tags: - default:topaz_tools data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz max-damage: 64 model: @@ -63,7 +63,7 @@ items: tags: - default:topaz_tools data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz max-damage: 64 model: @@ -76,7 +76,7 @@ items: tags: - default:topaz_tools data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz max-damage: 64 model: @@ -89,7 +89,7 @@ items: tags: - default:topaz_tools data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz max-damage: 64 model: @@ -102,7 +102,7 @@ items: tags: - default:topaz_tools data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz max-damage: 64 model: @@ -122,7 +122,7 @@ items: tags: - default:topaz_tools data: - item-name: <#FF8C00> + item-name: <#FF8C00> tooltip-style: minecraft:topaz max-damage: 300 model: @@ -163,7 +163,7 @@ items: $$1.20.1~1.21.1: bow $$1.21.2~1.21.3: honey_bottle data: - item-name: <#FF8C00> + item-name: <#FF8C00> components: minecraft:max_damage: 300 $$>=1.21.2: diff --git a/common-files/src/main/resources/resources/default/configuration/templates.yml b/common-files/src/main/resources/resources/default/configuration/templates.yml index 82fc59d30..d22288ef0 100644 --- a/common-files/src/main/resources/resources/default/configuration/templates.yml +++ b/common-files/src/main/resources/resources/default/configuration/templates.yml @@ -2682,354 +2682,354 @@ templates#block_states: state: ${base_block}[east=false,north=false,south=false,waterlogged=false,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 east=true,north=false,south=false,waterlogged=false,west=false: state: ${base_block}[east=true,north=false,south=false,waterlogged=false,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=false,north=true,south=false,waterlogged=false,west=false: state: ${base_block}[east=false,north=true,south=false,waterlogged=false,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 180 + yaw: 180 east=false,north=false,south=true,waterlogged=false,west=false: state: ${base_block}[east=false,north=false,south=true,waterlogged=false,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 east=false,north=false,south=false,waterlogged=false,west=true: state: ${base_block}[east=false,north=false,south=false,waterlogged=false,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 east=true,north=true,south=false,waterlogged=false,west=false: state: ${base_block}[east=true,north=true,south=false,waterlogged=false,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 180 + yaw: 180 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=true,north=false,south=true,waterlogged=false,west=false: state: ${base_block}[east=true,north=false,south=true,waterlogged=false,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=true,north=false,south=false,waterlogged=false,west=true: state: ${base_block}[east=true,north=false,south=false,waterlogged=false,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=false,north=true,south=true,waterlogged=false,west=false: state: ${base_block}[east=false,north=true,south=true,waterlogged=false,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 180 + yaw: 180 east=false,north=true,south=false,waterlogged=false,west=true: state: ${base_block}[east=false,north=true,south=false,waterlogged=false,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 180 + yaw: 180 east=false,north=false,south=true,waterlogged=false,west=true: state: ${base_block}[east=false,north=false,south=true,waterlogged=false,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 east=true,north=true,south=true,waterlogged=false,west=false: state: ${base_block}[east=true,north=true,south=true,waterlogged=false,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 180 + yaw: 180 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=true,north=true,south=false,waterlogged=false,west=true: state: ${base_block}[east=true,north=true,south=false,waterlogged=false,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 180 + yaw: 180 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=true,north=false,south=true,waterlogged=false,west=true: state: ${base_block}[east=true,north=false,south=true,waterlogged=false,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=false,north=true,south=true,waterlogged=false,west=true: state: ${base_block}[east=false,north=true,south=true,waterlogged=false,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 180 + yaw: 180 east=true,north=true,south=true,waterlogged=false,west=true: state: ${base_block}[east=true,north=true,south=true,waterlogged=false,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 180 + yaw: 180 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=false,north=false,south=false,waterlogged=true,west=false: state: ${base_block}[east=false,north=false,south=false,waterlogged=true,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 east=true,north=false,south=false,waterlogged=true,west=false: state: ${base_block}[east=true,north=false,south=false,waterlogged=true,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=false,north=true,south=false,waterlogged=true,west=false: state: ${base_block}[east=false,north=true,south=false,waterlogged=true,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 180 + yaw: 180 east=false,north=false,south=true,waterlogged=true,west=false: state: ${base_block}[east=false,north=false,south=true,waterlogged=true,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 east=false,north=false,south=false,waterlogged=true,west=true: state: ${base_block}[east=false,north=false,south=false,waterlogged=true,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 east=true,north=true,south=false,waterlogged=true,west=false: state: ${base_block}[east=true,north=true,south=false,waterlogged=true,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 180 + yaw: 180 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=true,north=false,south=true,waterlogged=true,west=false: state: ${base_block}[east=true,north=false,south=true,waterlogged=true,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=true,north=false,south=false,waterlogged=true,west=true: state: ${base_block}[east=true,north=false,south=false,waterlogged=true,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=false,north=true,south=true,waterlogged=true,west=false: state: ${base_block}[east=false,north=true,south=true,waterlogged=true,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 180 + yaw: 180 east=false,north=true,south=false,waterlogged=true,west=true: state: ${base_block}[east=false,north=true,south=false,waterlogged=true,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 180 + yaw: 180 east=false,north=false,south=true,waterlogged=true,west=true: state: ${base_block}[east=false,north=false,south=true,waterlogged=true,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 east=true,north=true,south=true,waterlogged=true,west=false: state: ${base_block}[east=true,north=true,south=true,waterlogged=true,west=false] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 180 + yaw: 180 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=true,north=true,south=false,waterlogged=true,west=true: state: ${base_block}[east=true,north=true,south=false,waterlogged=true,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 180 + yaw: 180 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=true,north=false,south=true,waterlogged=true,west=true: state: ${base_block}[east=true,north=false,south=true,waterlogged=true,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 270 + yaw: 270 east=false,north=true,south=true,waterlogged=true,west=true: state: ${base_block}[east=false,north=true,south=true,waterlogged=true,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 180 + yaw: 180 east=true,north=true,south=true,waterlogged=true,west=true: state: ${base_block}[east=true,north=true,south=true,waterlogged=true,west=true] entity-renderer: - item: ${fence_post_item} - rotation: 180 + yaw: 180 scale: 1.0003 translation: 0,0.0001,0 - item: ${fence_side_item} - rotation: 0 + yaw: 0 - item: ${fence_side_item} - rotation: 90 + yaw: 90 - item: ${fence_side_item} - rotation: 180 + yaw: 180 - item: ${fence_side_item} - rotation: 270 + yaw: 270 variants: waterlogged=true: settings: diff --git a/common-files/src/main/resources/resources/legacy_armor/pack.yml b/common-files/src/main/resources/resources/legacy_armor/pack.yml index f73b20dc9..86e3cb1cf 100644 --- a/common-files/src/main/resources/resources/legacy_armor/pack.yml +++ b/common-files/src/main/resources/resources/legacy_armor/pack.yml @@ -2,6 +2,4 @@ author: XiaoMoMi version: 0.0.1 description: Fix broken vanilla armor namespace: minecraft -enable: - $$>=1.21.2: false - $$<1.21.2: true +enable: false diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index 13f426037..93b5e5c72 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -374,6 +374,7 @@ warning.config.loot_table.function.apply_bonus.missing_enchantment: "Iss warning.config.loot_table.function.apply_bonus.missing_formula: "Issue found in file - '' has a misconfigured loot table, function 'apply_bonus' is missing the required 'formula' argument." warning.config.loot_table.function.drop_exp.missing_count: "Issue found in file - '' has a misconfigured loot table, function 'drop_exp' is missing the required 'count' argument." warning.config.loot_table.function.set_count.missing_count: "Issue found in file - '' has a misconfigured loot table, function 'set_count' is missing the required 'count' argument." +warning.config.loot_table.function.apply_data.missing_data: "Issue found in file - '' has a misconfigured loot table, function 'apply_data' is missing the required 'data' argument." warning.config.loot_table.entry.missing_type: "Issue found in file - '' has a misconfigured loot table, one of the entries is missing the required 'type' argument." warning.config.loot_table.entry.invalid_type: "Issue found in file - '' has a misconfigured loot table, one of the entries is using an invalid entry type ''." warning.config.loot_table.entry.exp.missing_count: "Issue found in file - '' has a misconfigured loot table, entry 'exp' is missing the required 'count' argument." diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index 95a857b0e..b2a6c3685 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -65,6 +65,9 @@ command.upload.failure.not_supported: "当前托管模式 '' 不支 command.upload.on_progress: "已开始上传进程. 检查控制台以获取详细信息" command.send_resource_pack.success.single: "发送资源包给 " command.send_resource_pack.success.multiple: "发送资源包给 个玩家" +command.locale.set.failure: "区域设置格式无效: " +command.locale.set.success: "已为 更新选定区域设置为 " +command.locale.unset.success: "已清除 的选定区域设置" warning.network.resource_pack.unverified_uuid: "玩家 使用未经服务器验证的 UUID () 尝试请求获取资源包" warning.config.pack.duplicated_files: "发现重复文件 请通过 config.yml 的 'resource-pack.duplicated-files-handler' 部分解决" warning.config.yaml.duplicated_key: "在文件 发现问题 - 在第行发现重复的键 '', 这可能会导致一些意料之外的问题" @@ -160,10 +163,10 @@ warning.config.recipe.result.post_processor.missing_type: "在文件 在文件 发现问题 - 配方 '' 使用了无效结果后处理器类型 ''" warning.config.translation.unknown_locale: "在文件 发现问题 - 未知的语言环境 ''" warning.config.template.duplicate: "在文件 发现问题 - 重复的模板 '' 请检查其他文件中是否存在相同配置" -warning.config.template.invalid: "在文件 发现问题 - 配置 '' 使用了无效的模板 ''" +warning.config.template.invalid: "在文件 发现问题 - 配置项 '' 使用了无效的模板 ''" warning.config.template.argument.self_increase_int.invalid_range: "在文件 发现问题 - 模板 '' 在 'self_increase_int' 参数中使用了一个起始值 '' 大于终止值 ''" warning.config.template.argument.list.invalid_type: "在文件 发现问题 - 模板 '' 的 'list' 参数需要列表类型 但输入参数类型为 ''" -warning.config.template.argument.missing_value: "在文件 发现问题 - 配置 '' 缺少了 '' 必要的模板参数值. 请使用 arguments 选项进行配置或为此参数设定默认值" +warning.config.template.argument.missing_value: "在文件 发现问题 - 配置项 '' 缺少了 '' 必要的模板参数值. 请使用 arguments 选项进行配置或为此参数设定默认值" warning.config.vanilla_loot.missing_type: "在文件 发现问题 - 原版战利品 '' 缺少必需的 'type' 参数" warning.config.vanilla_loot.invalid_type: "在文件 发现问题 - 原版战利品 '' 使用了无效类型 '' 允许的类型: []" warning.config.vanilla_loot.block.invalid_target: "在文件 发现问题 - 原版战利品 '' 中存在无效的方块目标 ''" @@ -184,6 +187,10 @@ warning.config.item.settings.invulnerable.invalid_damage_source: "在文 warning.config.item.settings.equipment.missing_asset_id: "在文件 发现问题 - 物品 '' 缺少 'equipment' 设置所需的 'asset-id' 参数" warning.config.item.settings.equipment.invalid_asset_id: "在文件 发现问题 - 物品 '' 为 'equipment' 设置配置了无效的 'asset-id'. 这可能是因为你没有创建装备配置或是错误地拼写了 asset-id" warning.config.item.settings.projectile.missing_item: "在文件 发现问题 - 物品 '' 缺少 'projectile' 设置所需的 'item' 参数" +warning.config.item.settings.craft_remainder.missing_type: "在文件 发现问题 - 物品 '' 缺少 'craft-remainder' 所需的 'type' 参数" +warning.config.item.settings.craft_remainder.invalid_type: "在文件 发现问题 - 物品 '' 使用了无效的合成剩余物品类型 ''" +warning.config.item.settings.craft_remainder.fixed.missing_item: "在文件 发现问题 - 物品 '' 的固定 'craft-remainder' 缺少所需的 'item' 参数" +warning.config.item.settings.craft_remainder.recipe_based.missing_terms: "在文件 发现问题 - 物品 '' 缺少基于配方的 'craft-remainder' 所需的 'terms' 参数" warning.config.item.data.attribute_modifiers.missing_type: "在文件 发现问题 - 物品 '' 缺少 'attribute-modifiers' 数据所需的 'type' 参数" warning.config.item.data.attribute_modifiers.missing_amount: "在文件 发现问题 - 物品 '' 缺少 'attribute-modifiers' 数据所需的 'amount' 参数" warning.config.item.data.attribute_modifiers.missing_operation: "在文件 发现问题 - 物品 '' 缺少 'attribute-modifiers' 数据所需的 'operation' 参数" @@ -263,8 +270,8 @@ warning.config.item.model.special.copper_golem_statue.missing_texture: " warning.config.item.updater.missing_type: "在文件 发现问题 - 物品 '' 缺少物品更新器必需的参数 'type'" warning.config.item.updater.invalid_type: "在文件 发现问题 - 物品 '' 在物品更新器中使用了无效的 'type' 参数值 ''" warning.config.item.updater.transmute.missing_material: "在文件 发现问题 - 物品 '' 缺少物品转换更新所需的 'material' 参数" -warning.config.block_state_mapping.invalid_state: "在文件 发现问题 - 配置 '' 使用了无效的方块状态 ''" -warning.config.block_state_mapping.conflict: "在文件 发现问题 - 配置 '' 无法将方块状态 映射到方块状态 , 因为该状态已被映射到 " +warning.config.block_state_mapping.invalid_state: "在文件 发现问题 - 配置项 '' 使用了无效的方块状态 ''" +warning.config.block_state_mapping.conflict: "在文件 发现问题 - 配置项 '' 无法将方块状态 映射到方块状态 , 因为该状态已被映射到 " warning.config.block.duplicate: "在文件 发现问题 - 重复的方块 '' 请检查其他文件中是否存在相同配置" warning.config.block.missing_state: "在文件 发现问题 - 方块 '' 缺少必需的 'state' 参数" warning.config.block.state.property.missing_type: "在文件 发现问题 - 方块 '' 的属性 '' 缺少必需的 'type' 参数" @@ -454,14 +461,21 @@ warning.config.function.remove_cooldown.missing_id: "在文件 warning.config.function.mythic_mobs_skill.missing_skill: "在文件 发现问题 - 配置项 '' 缺少 'mythic_mobs_skill' 函数必需的 'skill' 参数" warning.config.function.spawn_furniture.missing_furniture_id: "在文件 发现问题 - 配置项 '' 缺少 'spawn_furniture' 函数必需的 'furniture-id' 参数" warning.config.function.replace_furniture.missing_furniture_id: "在文件 发现问题 - 配置项 '' 缺少 'replace_furniture' 函数必需的 'furniture-id' 参数" -warning.config.function.teleport.missing_x: "在文件 发现问题 - 配置 '' 缺少 'teleport' 函数所需的 'x' 参数" -warning.config.function.teleport.missing_y: "在文件 发现问题 - 配置 '' 缺少 'teleport' 函数所需的 'y' 参数" -warning.config.function.teleport.missing_z: "在文件 发现问题 - 配置 '' 缺少 'teleport' 函数所需的 'z' 参数" -warning.config.function.set_variable.missing_name: "在文件 发现问题 - 配置 '' 缺少 'set_variable' 函数所需的 'name' 参数" -warning.config.function.set_variable.missing_value: "在文件 发现问题 - 配置 '' 缺少 'set_variable' 函数所需的 'number' 或 'text' 参数" -warning.config.function.toast.missing_toast: "在文件 发现问题 - 配置 '' 缺少 'toast' 函数所需的 'toast' 参数" -warning.config.function.toast.missing_icon: "在文件 发现问题 - 配置 '' 缺少 'toast' 函数所需的 'icon' 参数" -warning.config.function.toast.invalid_advancement_type: "在文件 发现问题 - 配置 '' 为 'toast' 函数使用了无效的进度类型 ''. 允许的类型: []" +warning.config.function.teleport.missing_x: "在文件 发现问题 - 配置项 '' 缺少 'teleport' 函数所需的 'x' 参数" +warning.config.function.teleport.missing_y: "在文件 发现问题 - 配置项 '' 缺少 'teleport' 函数所需的 'y' 参数" +warning.config.function.teleport.missing_z: "在文件 发现问题 - 配置项 '' 缺少 'teleport' 函数所需的 'z' 参数" +warning.config.function.set_variable.missing_name: "在文件 发现问题 - 配置项 '' 缺少 'set_variable' 函数所需的 'name' 参数" +warning.config.function.set_variable.missing_value: "在文件 发现问题 - 配置项 '' 缺少 'set_variable' 函数所需的 'number' 或 'text' 参数" +warning.config.function.toast.missing_toast: "在文件 发现问题 - 配置项 '' 缺少 'toast' 函数所需的 'toast' 参数" +warning.config.function.toast.missing_icon: "在文件 发现问题 - 配置项 '' 缺少 'toast' 函数所需的 'icon' 参数" +warning.config.function.toast.invalid_advancement_type: "在文件 发现问题 - 配置项 '' 为 'toast' 函数使用了无效的进度类型 ''. 允许的类型: []" +warning.config.function.merchant_trade.missing_offers: "在文件 发现问题 - 配置项 '' 缺少 'merchant_trade' 函数所需的 'offers' 参数" +warning.config.function.merchant_trade.offer.missing_cost_1: "在文件 发现问题 - 配置项 '' 缺少'merchant_trade' 函数所需的 'cost-1' 参数" +warning.config.function.merchant_trade.offer.missing_result: "在文件 发现问题 - 配置项 '' 缺少'merchant_trade' 函数所需的 'result' 参数" +warning.config.function.when.missing_source: "在文件 发现问题 - 配置项 '' 缺少 'when' 函数所需的 'source' 参数" +warning.config.function.if_else.missing_rules: "在文件 发现问题 - 配置项 '' 缺少 'if_else' 函数所需的 'rules' 参数" +warning.config.function.update_block_property.missing_properties: "在文件 发现问题 - 配置项 '' 缺少 'update_block_property' 函数所需的 'properties' 参数" +warning.config.function.transform_block.missing_block: "在文件 发现问题 - 配置项 '' 缺少 'transform_block' 函数所需的 'block' 参数" warning.config.selector.missing_type: "在文件 发现问题 - 配置项 '' 缺少选择器必需的 'type' 参数" warning.config.selector.invalid_type: "在文件 发现问题 - 配置项 '' 使用了无效的选择器类型 ''" warning.config.selector.invalid_target: "在文件 发现问题 - 配置项 '' 使用了无效的选择器目标 ''" @@ -474,6 +488,7 @@ warning.config.resource_pack.generation.missing_item_model: "物品'方块状态''缺少模型文件: ''" warning.config.resource_pack.generation.missing_parent_model: "模型''找不到父级模型文件: ''" warning.config.resource_pack.generation.missing_equipment_texture: "装备 '' 缺少纹理 ''" +warning.config.resource_pack.generation.missing_sound: "声音事件 '' 缺少 ogg 文件 ''" warning.config.resource_pack.generation.texture_not_in_atlas: "纹理''不在图集内. 你需要将纹理路径或文件夹前缀添加到图集内, 或者启用 config.yml 中的 'fix-atlas' 选项" warning.config.resource_pack.invalid_overlay_format: "在 config.yml 的 'resource-pack.overlay-format' 处发现问题 - 无效的overlay格式 ''. Overlay格式必须包含占位符 '{version}'" warning.config.equipment.duplicate: "在文件 发现问题 - 重复的装备配置 ''. 请检查其他文件中是否存在相同配置" diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java index fffa626dd..59941bb1f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java @@ -143,7 +143,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem @Override public void delayedLoad() { this.initSuggestions(); - this.resendTags(); + this.updateTags(); this.processSounds(); this.clearCache(); } @@ -232,7 +232,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem public abstract BlockBehavior createBlockBehavior(CustomBlock customBlock, List> behaviorConfig); - protected abstract void resendTags(); + protected abstract void updateTags(); protected abstract boolean isVanillaBlock(Key id); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockKeys.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockKeys.java index 84a6e13f0..f6c63e383 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockKeys.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockKeys.java @@ -330,6 +330,37 @@ public final class BlockKeys { public static final Key CHERRY_SAPLING = Key.of("minecraft:cherry_sapling"); public static final Key PALE_OAK_SAPLING = Key.of("minecraft:pale_oak_sapling"); + public static final Key OAK_SHELF = Key.of("minecraft:oak_shelf"); + public static final Key SPRUCE_SHELF = Key.of("minecraft:spruce_shelf"); + public static final Key BIRCH_SHELF = Key.of("minecraft:birch_shelf"); + public static final Key JUNGLE_SHELF = Key.of("minecraft:jungle_shelf"); + public static final Key ACACIA_SHELF = Key.of("minecraft:acacia_shelf"); + public static final Key DARK_OAK_SHELF = Key.of("minecraft:dark_oak_shelf"); + public static final Key MANGROVE_SHELF = Key.of("minecraft:mangrove_shelf"); + public static final Key CHERRY_SHELF = Key.of("minecraft:cherry_shelf"); + public static final Key PALE_OAK_SHELF = Key.of("minecraft:pale_oak_shelf"); + public static final Key BAMBOO_SHELF = Key.of("minecraft:bamboo_shelf"); + public static final Key CRIMSON_SHELF = Key.of("minecraft:crimson_shelf"); + public static final Key WARPED_SHELF = Key.of("minecraft:warped_shelf"); + + public static final Key COPPER_GOLEM_STATUE = Key.of("minecraft:copper_golem_statue"); + public static final Key EXPOSED_COPPER_GOLEM_STATUE = Key.of("minecraft:exposed_copper_golem_statue"); + public static final Key WEATHERED_COPPER_GOLEM_STATUE = Key.of("minecraft:weathered_copper_golem_statue"); + public static final Key OXIDIZED_COPPER_GOLEM_STATUE = Key.of("minecraft:oxidized_copper_golem_statue"); + public static final Key WAXED_COPPER_GOLEM_STATUE = Key.of("minecraft:waxed_copper_golem_statue"); + public static final Key WAXED_EXPOSED_COPPER_GOLEM_STATUE = Key.of("minecraft:waxed_exposed_copper_golem_statue"); + public static final Key WAXED_WEATHERED_COPPER_GOLEM_STATUE = Key.of("minecraft:waxed_weathered_copper_golem_statue"); + public static final Key WAXED_OXIDIZED_COPPER_GOLEM_STATUE = Key.of("minecraft:waxed_oxidized_copper_golem_statue"); + + public static final Key COPPER_CHEST = Key.of("minecraft:copper_chest"); + public static final Key EXPOSED_COPPER_CHEST = Key.of("minecraft:exposed_copper_chest"); + public static final Key WEATHERED_COPPER_CHEST = Key.of("minecraft:weathered_copper_chest"); + public static final Key OXIDIZED_COPPER_CHEST = Key.of("minecraft:oxidized_copper_chest"); + public static final Key WAXED_COPPER_CHEST = Key.of("minecraft:waxed_copper_chest"); + public static final Key WAXED_EXPOSED_COPPER_CHEST = Key.of("minecraft:waxed_exposed_copper_chest"); + public static final Key WAXED_WEATHERED_COPPER_CHEST = Key.of("minecraft:waxed_weathered_copper_chest"); + public static final Key WAXED_OXIDIZED_COPPER_CHEST = Key.of("minecraft:waxed_oxidized_copper_chest"); + public static final Key[] BUTTONS = new Key[]{ OAK_BUTTON, SPRUCE_BUTTON, BIRCH_BUTTON, JUNGLE_BUTTON, ACACIA_BUTTON, DARK_OAK_BUTTON, MANGROVE_BUTTON, CHERRY_BUTTON, PALE_OAK_BUTTON, BAMBOO_BUTTON, CRIMSON_BUTTON, WARPED_BUTTON, STONE_BUTTON, POLISHED_BLACKSTONE_BUTTON diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/ConstantBlockEntityRenderer.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/ConstantBlockEntityRenderer.java index f28ab579f..4b45900a0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/ConstantBlockEntityRenderer.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/ConstantBlockEntityRenderer.java @@ -14,25 +14,37 @@ public class ConstantBlockEntityRenderer { public void show(Player player) { for (BlockEntityElement element : this.elements) { - element.show(player); + if (element != null) { + element.show(player); + } } } public void hide(Player player) { for (BlockEntityElement element : this.elements) { - element.hide(player); + if (element != null) { + element.hide(player); + } } } public void deactivate() { for (BlockEntityElement element : this.elements) { - element.deactivate(); + if (element != null) { + element.deactivate(); + } } } public void activate() { for (BlockEntityElement element : this.elements) { - element.activate(); + if (element != null) { + element.activate(); + } } } + + public BlockEntityElement[] elements() { + return this.elements; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElement.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElement.java index eaf5d605c..a0c0fb321 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElement.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElement.java @@ -10,6 +10,8 @@ public interface BlockEntityElement { void hide(Player player); + default void transform(Player player) {} + default void deactivate() {} default void activate() {} diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfig.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfig.java index a61f0b030..0d3c320ad 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfig.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfig.java @@ -6,4 +6,10 @@ import net.momirealms.craftengine.core.world.World; public interface BlockEntityElementConfig { E create(World world, BlockPos pos); + + default E create(World world, BlockPos pos, E previous) { + return null; + } + + Class elementClass(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java index 910c56f56..1dabfa3be 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java @@ -13,6 +13,7 @@ import java.util.Optional; public abstract class BlockEntityElementConfigs { public static final Key ITEM_DISPLAY = Key.of("craftengine:item_display"); public static final Key TEXT_DISPLAY = Key.of("craftengine:text_display"); + public static final Key ITEM = Key.of("craftengine:item"); public static void register(Key key, BlockEntityElementConfigFactory type) { ((WritableRegistry) BuiltInRegistries.BLOCK_ENTITY_ELEMENT_TYPE) diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java b/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java index f89787fa1..b0eb72d4b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.HorizontalDirection; +import net.momirealms.craftengine.core.util.SegmentedAngle; import net.momirealms.sparrow.nbt.Tag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,7 +34,7 @@ public abstract class Property> { Property directionProperty = (Property) property; return (context, state) -> state.with(directionProperty, context.getNearestLookingDirection().opposite()); } else { - throw new IllegalArgumentException("Unsupported property type used in hard-coded `facing` property: " + property.valueClass()); + return (context, state) -> state; } })); HARD_CODED_PLACEMENTS.put("facing_clockwise", (property -> { @@ -41,13 +42,26 @@ public abstract class Property> { Property directionProperty = (Property) property; return (context, state) -> state.with(directionProperty, context.getHorizontalDirection().clockWise().toHorizontalDirection()); } else { - throw new IllegalArgumentException("Unsupported property type used in hard-coded `facing_clockwise` property: " + property.valueClass()); + return (context, state) -> state; } })); HARD_CODED_PLACEMENTS.put("waterlogged", (property -> { Property waterloggedProperty = (Property) property; return (context, state) -> state.with(waterloggedProperty, context.isWaterSource()); })); + HARD_CODED_PLACEMENTS.put("rotation", property -> { + if (property.valueClass() == Integer.class) { + IntegerProperty rotationProperty = (IntegerProperty) property; + if (rotationProperty.min == 0 && rotationProperty.max > 0) { + return (context, state) -> { + float rotation = context.getRotation(); + SegmentedAngle segmentedAngle = new SegmentedAngle(rotationProperty.max + 1); + return state.with(rotationProperty, segmentedAngle.fromDegrees(rotation + 180)); + }; + } + } + return (context, state) -> state; + }); } private final Class clazz; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java b/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java index dc59e38aa..21a4ae92e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java @@ -73,6 +73,10 @@ public class UseOnContext { return this.level; } + public World getWorld() { + return this.level; + } + public Direction getHorizontalDirection() { return this.player == null ? Direction.NORTH : this.player.getDirection(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemDataModifiers.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemDataModifiers.java index 055746d59..e35e432fb 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemDataModifiers.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemDataModifiers.java @@ -28,6 +28,7 @@ public final class ItemDataModifiers { public static final Key CUSTOM_NAME = Key.of("craftengine:custom-name"); public static final Key CUSTOM_MODEL_DATA = Key.of("craftengine:custom-model-data"); public static final Key COMPONENTS = Key.of("craftengine:components"); + public static final Key COMPONENT = Key.of("craftengine:component"); public static final Key ATTRIBUTE_MODIFIERS = Key.of("craftengine:attribute-modifiers"); public static final Key ATTRIBUTES = Key.of("craftengine:attributes"); public static final Key ARGUMENTS = Key.of("craftengine:arguments"); @@ -37,6 +38,7 @@ public final class ItemDataModifiers { public static final Key OVERWRITABLE_ITEM_NAME = Key.of("craftengine:overwritable-item-name"); public static final Key JUKEBOX_PLAYABLE = Key.of("craftengine:jukebox-playable"); public static final Key REMOVE_COMPONENTS = Key.of("craftengine:remove-components"); + public static final Key REMOVE_COMPONENT = Key.of("craftengine:remove-component"); public static final Key TAGS = Key.of("craftengine:tags"); public static final Key NBT = Key.of("craftengine:nbt"); public static final Key TOOLTIP_STYLE = Key.of("craftengine:tooltip-style"); @@ -84,7 +86,9 @@ public final class ItemDataModifiers { register(ITEM_NAME, ItemNameModifier.FACTORY); register(DISPLAY_NAME, ItemNameModifier.FACTORY); register(COMPONENTS, ComponentsModifier.FACTORY); + register(COMPONENT, ComponentsModifier.FACTORY); register(REMOVE_COMPONENTS, RemoveComponentModifier.FACTORY); + register(REMOVE_COMPONENT, RemoveComponentModifier.FACTORY); register(FOOD, FoodModifier.FACTORY); register(MAX_DAMAGE, MaxDamageModifier.FACTORY); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/entry/SingleItemLootEntryContainer.java b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/SingleItemLootEntryContainer.java index 4eaffd83c..57929f117 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/entry/SingleItemLootEntryContainer.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/SingleItemLootEntryContainer.java @@ -43,7 +43,7 @@ public class SingleItemLootEntryContainer extends AbstractSingleLootEntryCont @SuppressWarnings("unchecked") @Override public LootEntryContainer create(Map arguments) { - String itemObj = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.loot_table.entry.item.missing_item"); + String itemObj = ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "item", "id"), "warning.config.loot_table.entry.item.missing_item"); Key item = Key.from(itemObj); int weight = ResourceConfigUtils.getAsInt(arguments.getOrDefault("weight", 1), "weight"); int quality = ResourceConfigUtils.getAsInt(arguments.getOrDefault("quality", 0), "quality"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyDataFunction.java b/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyDataFunction.java new file mode 100644 index 000000000..168d9e6fa --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyDataFunction.java @@ -0,0 +1,58 @@ +package net.momirealms.craftengine.core.loot.function; + +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemBuildContext; +import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; +import net.momirealms.craftengine.core.item.recipe.result.ApplyItemDataPostProcessor; +import net.momirealms.craftengine.core.loot.LootConditions; +import net.momirealms.craftengine.core.loot.LootContext; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.*; + +public class ApplyDataFunction extends AbstractLootConditionalFunction { + public static final Factory FACTORY = new Factory<>(); + private final ItemDataModifier[] modifiers; + + public ApplyDataFunction(List> conditions, ItemDataModifier[] modifiers) { + super(conditions); + this.modifiers = modifiers; + } + + @Override + public Key type() { + return LootFunctions.APPLY_DATA; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + protected Item applyInternal(Item item, LootContext context) { + ItemBuildContext ctx = ItemBuildContext.of(context.player()); + for (ItemDataModifier modifier : this.modifiers) { + item = modifier.apply(item, ctx); + } + return item; + } + + public static class Factory implements LootFunctionFactory { + @SuppressWarnings("unchecked") + @Override + public LootFunction create(Map arguments) { + List> modifiers = new ArrayList<>(); + Map data = ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(arguments.get("data"), "warning.config.loot_table.function.apply_data.missing_data"), "data"); + for (Map.Entry entry : data.entrySet()) { + Optional.ofNullable(BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY.getValue(Key.withDefaultNamespace(entry.getKey(), Key.DEFAULT_NAMESPACE))) + .ifPresent(factory -> modifiers.add(factory.create(entry.getValue()))); + } + List> conditions = Optional.ofNullable(arguments.get("conditions")) + .map(it -> LootConditions.fromMapList((List>) it)) + .orElse(Collections.emptyList()); + return new ApplyDataFunction<>(conditions, modifiers.toArray(new ItemDataModifier[0])); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/function/LootFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/loot/function/LootFunctions.java index c9d221c95..854e741e1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/function/LootFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/function/LootFunctions.java @@ -17,6 +17,7 @@ import java.util.function.BiFunction; public class LootFunctions { public static final Key APPLY_BONUS = Key.from("craftengine:apply_bonus"); + public static final Key APPLY_DATA = Key.from("craftengine:apply_data"); public static final Key SET_COUNT = Key.from("craftengine:set_count"); public static final Key EXPLOSION_DECAY = Key.from("craftengine:explosion_decay"); public static final Key DROP_EXP = Key.from("craftengine:drop_exp"); @@ -24,6 +25,7 @@ public class LootFunctions { static { register(SET_COUNT, SetCountFunction.FACTORY); + register(APPLY_DATA, ApplyDataFunction.FACTORY); register(EXPLOSION_DECAY, ExplosionDecayFunction.FACTORY); register(APPLY_BONUS, ApplyBonusCountFunction.FACTORY); register(DROP_EXP, DropExpFunction.FACTORY); diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index e43115a29..6981623e8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -40,10 +40,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.parser.ParserException; import org.yaml.snakeyaml.scanner.ScannerException; import javax.imageio.ImageIO; -import javax.imageio.ImageReader; import java.awt.image.BufferedImage; import java.io.*; import java.nio.charset.StandardCharsets; @@ -620,6 +620,9 @@ public abstract class AbstractPackManager implements PackManager { AbstractPackManager.this.plugin.logger().severe("Error found while reading config file: " + path, e); } return FileVisitResult.CONTINUE; + } catch (ParserException e) { + AbstractPackManager.this.plugin.logger().severe("Invalid YAML file found: " + path + ".\n" + e.getMessage() + "\nIt is recommended to use Visual Studio Code as your YAML editor to fix problems more quickly."); + return FileVisitResult.CONTINUE; } catch (LocalizedException e) { e.setArgument(0, path.toString()); TranslationManager.instance().log(e.node(), e.arguments()); @@ -734,10 +737,6 @@ public abstract class AbstractPackManager implements PackManager { this.plugin.logger().info("Optimized resource pack in " + (time4 - time3) + "ms"); Path finalPath = resourcePackPath(); Files.createDirectories(finalPath.getParent()); - if (!VersionHelper.PREMIUM && Config.enableObfuscation()) { - Config.instance().setObf(false); - this.plugin.logger().warn("Resource pack obfuscation requires Premium Edition."); - } try { this.zipGenerator.accept(generatedPackPath, finalPath); } catch (Exception e) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeAltas.java b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeAltas.java index 65e0daf81..4d1547ab5 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeAltas.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeAltas.java @@ -38,7 +38,7 @@ public class ResolutionMergeAltas implements Resolution { j3.add("sources", ja3); GsonHelper.writeJsonFile(j3, existing.path()); } catch (Exception e) { - CraftEngine.instance().logger().severe("Failed to merge json when resolving file conflicts", e); + CraftEngine.instance().logger().severe("Failed to merge altas when resolving file conflicts", e); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeFont.java b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeFont.java new file mode 100644 index 000000000..c8beb26dc --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeFont.java @@ -0,0 +1,57 @@ +package net.momirealms.craftengine.core.pack.conflict.resolution; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.momirealms.craftengine.core.pack.conflict.PathContext; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.GsonHelper; +import net.momirealms.craftengine.core.util.Key; + +import java.util.HashSet; +import java.util.Map; + +public class ResolutionMergeFont implements Resolution { + public static final Factory FACTORY = new Factory(); + public static final ResolutionMergeFont INSTANCE = new ResolutionMergeFont(); + + @Override + public void run(PathContext existing, PathContext conflict) { + try { + JsonObject j1 = GsonHelper.readJsonFile(existing.path()).getAsJsonObject(); + JsonObject j2 = GsonHelper.readJsonFile(conflict.path()).getAsJsonObject(); + JsonObject j3 = new JsonObject(); + JsonArray ja1 = j1.getAsJsonArray("providers"); + JsonArray ja2 = j2.getAsJsonArray("providers"); + JsonArray ja3 = new JsonArray(); + HashSet elements = new HashSet<>(); + for (JsonElement je : ja1) { + if (elements.add(je.toString())) { + ja3.add(je); + } + } + for (JsonElement je : ja2) { + if (elements.add(je.toString())) { + ja3.add(je); + } + } + j3.add("providers", ja3); + GsonHelper.writeJsonFile(j3, existing.path()); + } catch (Exception e) { + CraftEngine.instance().logger().severe("Failed to merge font when resolving file conflicts", e); + } + } + + @Override + public Key type() { + return Resolutions.MERGE_FONT; + } + + public static class Factory implements ResolutionFactory { + + @Override + public Resolution create(Map arguments) { + return INSTANCE; + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/Resolutions.java b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/Resolutions.java index f7651d881..ca5e761b0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/Resolutions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/Resolutions.java @@ -14,6 +14,7 @@ public class Resolutions { public static final Key RETAIN_MATCHING = Key.of("craftengine:retain_matching"); public static final Key MERGE_JSON = Key.of("craftengine:merge_json"); public static final Key MERGE_ATLAS = Key.of("craftengine:merge_atlas"); + public static final Key MERGE_FONT = Key.of("craftengine:merge_font"); public static final Key CONDITIONAL = Key.of("craftengine:conditional"); public static final Key MERGE_PACK_MCMETA = Key.of("craftengine:merge_pack_mcmeta"); public static final Key MERGE_LEGACY_MODEL = Key.of("craftengine:merge_legacy_model"); @@ -25,6 +26,7 @@ public class Resolutions { register(MERGE_PACK_MCMETA, ResolutionMergePackMcMeta.FACTORY); register(MERGE_ATLAS, ResolutionMergeAltas.FACTORY); register(MERGE_LEGACY_MODEL, ResolutionMergeLegacyModel.FACTORY); + register(MERGE_FONT, ResolutionMergeFont.FACTORY); } public static void register(Key key, ResolutionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java index c72a2f0b2..918c4dcb5 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java @@ -184,6 +184,8 @@ public abstract class CraftEngine implements Plugin { delayedLoadTasks.add(CompletableFuture.runAsync(() -> this.recipeManager.delayedLoad(), this.scheduler.async())); } CompletableFutures.allOf(delayedLoadTasks).join(); + // 重新发送tags,需要等待tags更新完成 + this.networkManager.delayedLoad(); long time2 = System.currentTimeMillis(); asyncTime = time2 - time1; } finally { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/MatchBlockCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/MatchBlockCondition.java index 769e849fa..a26f015e2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/MatchBlockCondition.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/MatchBlockCondition.java @@ -2,22 +2,32 @@ package net.momirealms.craftengine.core.plugin.context.condition; import net.momirealms.craftengine.core.plugin.context.Condition; import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.world.ExistingBlock; +import net.momirealms.craftengine.core.world.World; +import net.momirealms.craftengine.core.world.WorldPosition; import java.util.*; public class MatchBlockCondition implements Condition { private final Set ids; private final boolean regexMatch; + private final NumberProvider x; + private final NumberProvider y; + private final NumberProvider z; - public MatchBlockCondition(Collection ids, boolean regexMatch) { + public MatchBlockCondition(Collection ids, boolean regexMatch, NumberProvider x, NumberProvider y, NumberProvider z) { this.ids = new HashSet<>(ids); this.regexMatch = regexMatch; + this.x = x; + this.y = y; + this.z = z; } @Override @@ -27,8 +37,13 @@ public class MatchBlockCondition implements Condition @Override public boolean test(CTX ctx) { - Optional block = ctx.getOptionalParameter(DirectContextParameters.BLOCK); - return block.filter(blockInWorld -> MiscUtils.matchRegex(blockInWorld.id().asString(), this.ids, this.regexMatch)).isPresent(); + Optional optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION); + if (optionalWorldPosition.isPresent()) { + World world = optionalWorldPosition.get().world(); + ExistingBlock blockAt = world.getBlockAt(MiscUtils.fastFloor(this.x.getDouble(ctx)), MiscUtils.fastFloor(this.y.getDouble(ctx)), MiscUtils.fastFloor(this.z.getDouble(ctx))); + return MiscUtils.matchRegex(blockAt.id().asString(), this.ids, this.regexMatch); + } + return false; } public static class FactoryImpl implements ConditionFactory { @@ -40,7 +55,10 @@ public class MatchBlockCondition implements Condition throw new LocalizedResourceConfigException("warning.config.condition.match_block.missing_id"); } boolean regex = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("regex", false), "regex"); - return new MatchBlockCondition<>(ids, regex); + return new MatchBlockCondition<>(ids, regex, + NumberProviders.fromObject(arguments.getOrDefault("x", "")), + NumberProviders.fromObject(arguments.getOrDefault("y", "")), + NumberProviders.fromObject(arguments.getOrDefault("z", ""))); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DropLootFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DropLootFunction.java index 216c1c511..8fa3930ac 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DropLootFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DropLootFunction.java @@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldPosition; @@ -22,13 +23,15 @@ public class DropLootFunction extends AbstractConditionalFu private final NumberProvider y; private final NumberProvider z; private final LootTable lootTable; + private final boolean toInv; - public DropLootFunction(NumberProvider x, NumberProvider y, NumberProvider z, LootTable lootTable, List> predicates) { + public DropLootFunction(List> predicates, NumberProvider x, NumberProvider y, NumberProvider z, LootTable lootTable, boolean toInv) { super(predicates); this.x = x; this.y = y; this.z = z; this.lootTable = lootTable; + this.toInv = toInv; } @Override @@ -39,8 +42,14 @@ public class DropLootFunction extends AbstractConditionalFu WorldPosition position = new WorldPosition(world, x.getDouble(ctx), y.getDouble(ctx), z.getDouble(ctx)); Player player = ctx.getOptionalParameter(DirectContextParameters.PLAYER).orElse(null); List> items = lootTable.getRandomItems(ctx.contexts(), world, player); - for (Item item : items) { - world.dropItemNaturally(position, item); + if (this.toInv && player != null) { + for (Item item : items) { + player.giveItem(item); + } + } else { + for (Item item : items) { + world.dropItemNaturally(position, item); + } } } } @@ -62,7 +71,8 @@ public class DropLootFunction extends AbstractConditionalFu NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); LootTable loots = LootTable.fromMap(MiscUtils.castToMap(arguments.get("loot"), true)); - return new DropLootFunction<>(x, y, z, loots, getPredicates(arguments)); + boolean toInv = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("to-inventory", false), "to-inventory"); + return new DropLootFunction<>(getPredicates(arguments), x, y, z, loots, toInv); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/MarkedHashMap.java b/core/src/main/java/net/momirealms/craftengine/core/util/MarkedHashMap.java new file mode 100644 index 000000000..5acda9dda --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/util/MarkedHashMap.java @@ -0,0 +1,6 @@ +package net.momirealms.craftengine.core.util; + +import java.util.HashMap; + +public class MarkedHashMap extends HashMap { +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/SegmentedAngle.java b/core/src/main/java/net/momirealms/craftengine/core/util/SegmentedAngle.java new file mode 100644 index 000000000..9d1aea132 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/util/SegmentedAngle.java @@ -0,0 +1,58 @@ +package net.momirealms.craftengine.core.util; + +public class SegmentedAngle { + private final int segments; + private final float degreeToAngle; + private final float angleToDegree; + + public SegmentedAngle(int segments) { + if (segments < 2) { + throw new IllegalArgumentException("Segments cannot be less than 2"); + } else if (segments > 360) { + throw new IllegalArgumentException("Segments cannot be greater than 360"); + } else { + this.segments = segments; + this.degreeToAngle = (float) segments / 360.0F; + this.angleToDegree = 360.0F / (float) segments; + } + } + + public boolean isSameAxis(int alpha, int beta) { + int halfSegments = this.segments / 2; + return (alpha % halfSegments) == (beta % halfSegments); + } + + public int fromDirection(Direction direction) { + if (direction.axis().isVertical()) { + return 0; + } else { + int i = direction.data2d(); + return i * (this.segments / 4); + } + } + + public int fromDegreesWithTurns(float degrees) { + return Math.round(degrees * this.degreeToAngle); + } + + public int fromDegrees(float degrees) { + return this.normalize(this.fromDegreesWithTurns(degrees)); + } + + public float toDegreesWithTurns(int rotation) { + return (float) rotation * this.angleToDegree; + } + + public float toDegrees(int rotation) { + float f = this.toDegreesWithTurns(this.normalize(rotation)); + return f >= 180.0F ? f - 360.0F : f; + } + + public int normalize(int rotationBits) { + return ((rotationBits % this.segments) + this.segments) % this.segments; + } + + public int getSegments() { + return this.segments; + } +} \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/VersionHelper.java b/core/src/main/java/net/momirealms/craftengine/core/util/VersionHelper.java index 2df529251..65acf2db1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/VersionHelper.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/VersionHelper.java @@ -5,6 +5,7 @@ import com.google.gson.JsonObject; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.Objects; public class VersionHelper { public static final boolean PREMIUM = false; @@ -35,20 +36,30 @@ public class VersionHelper { private static final boolean v1_21_8; private static final boolean v1_21_9; private static final boolean v1_21_10; + private static final Class UNOBFUSCATED_CLAZZ = Objects.requireNonNull(ReflectionUtils.getClazz( + "net.minecraft.obfuscate.DontObfuscate", // 因为无混淆版本没有这个类所以说多写几个防止找不到了 + "net.minecraft.data.Main", + "net.minecraft.server.Main", + "net.minecraft.gametest.Main", + "net.minecraft.client.main.Main", + "net.minecraft.client.data.Main" + )); static { - try (InputStream inputStream = Class.forName("net.minecraft.obfuscate.DontObfuscate").getResourceAsStream("/version.json")) { + try (InputStream inputStream = UNOBFUSCATED_CLAZZ.getResourceAsStream("/version.json")) { if (inputStream == null) { throw new IOException("Failed to load version.json"); } JsonObject json = GsonHelper.parseJsonToJsonObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8)); - String versionString = json.getAsJsonPrimitive("id").getAsString().split("-", 2)[0]; + String versionString = json.getAsJsonPrimitive("id").getAsString() + .split("-", 2)[0] // 1.21.10-rc1 -> 1.21.10 + .split("_", 2)[0]; // 1.21.11_unobfuscated -> 1.21.11 MINECRAFT_VERSION = new MinecraftVersion(versionString); String[] split = versionString.split("\\."); int major = Integer.parseInt(split[1]); - int minor = split.length == 3 ? Integer.parseInt(split[2].split("-", 2)[0]) : 0; + int minor = split.length == 3 ? Integer.parseInt(split[2]) : 0; // 12001 = 1.20.1 // 12104 = 1.21.4 diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/World.java b/core/src/main/java/net/momirealms/craftengine/core/world/World.java index 6bf1e2eed..c8b94cdc4 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/World.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/World.java @@ -39,6 +39,14 @@ public interface World { this.setBlockAt(x, y, z, blockState.customBlockState(), flags); } + default void setBlockAt(BlockPos pos, BlockStateWrapper blockState, int flags) { + this.setBlockAt(pos.x(), pos.y(), pos.z(), blockState, flags); + } + + default void setBlockAt(BlockPos pos, ImmutableBlockState blockState, int flags) { + this.setBlockAt(pos.x(), pos.y(), pos.z(), blockState, flags); + } + String name(); Path directory(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java index d48e09472..a0babe284 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java @@ -35,6 +35,7 @@ public class CEChunk { private final ReentrantReadWriteLock renderLock = new ReentrantReadWriteLock(); private volatile boolean dirty; private volatile boolean loaded; + private volatile boolean activated; public CEChunk(CEWorld world, ChunkPos chunkPos) { this.world = world; @@ -115,40 +116,129 @@ public class CEChunk { } } - public void addConstantBlockEntityRenderer(BlockPos pos) { - this.addConstantBlockEntityRenderer(pos, this.getBlockState(pos)); + public ConstantBlockEntityRenderer addConstantBlockEntityRenderer(BlockPos pos) { + return this.addConstantBlockEntityRenderer(pos, this.getBlockState(pos), null); } - public void addConstantBlockEntityRenderer(BlockPos pos, ImmutableBlockState state) { + public ConstantBlockEntityRenderer addConstantBlockEntityRenderer(BlockPos pos, ImmutableBlockState state) { + return this.addConstantBlockEntityRenderer(pos, state, null); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public ConstantBlockEntityRenderer addConstantBlockEntityRenderer(BlockPos pos, ImmutableBlockState state, @Nullable ConstantBlockEntityRenderer previous) { BlockEntityElementConfig[] renderers = state.constantRenderers(); if (renderers != null && renderers.length > 0) { BlockEntityElement[] elements = new BlockEntityElement[renderers.length]; - World wrappedWorld = this.world.world(); - for (int i = 0; i < elements.length; i++) { - elements[i] = renderers[i].create(wrappedWorld, pos); - } ConstantBlockEntityRenderer renderer = new ConstantBlockEntityRenderer(elements); - for (Player player : getTrackedBy()) { - renderer.show(player); + World wrappedWorld = this.world.world(); + List trackedBy = getTrackedBy(); + boolean hasTrackedBy = trackedBy != null && !trackedBy.isEmpty(); + // 处理旧到新的转换 + if (previous != null) { + // 由于entity-render的体量基本都很小,所以考虑一个特殊情况,即前后都是1个renderer,对此情况进行简化和优化 + BlockEntityElement[] previousElements = previous.elements().clone(); + if (previousElements.length == 1 && renderers.length == 1) { + BlockEntityElement previousElement = previousElements[0]; + BlockEntityElementConfig config = renderers[0]; + outer: { + if (config.elementClass().isInstance(previousElement)) { + BlockEntityElement element = ((BlockEntityElementConfig) config).create(wrappedWorld, pos, previousElement); + if (element != null) { + elements[0] = element; + if (hasTrackedBy) { + for (Player player : trackedBy) { + element.transform(player); + } + } + break outer; + } + } + BlockEntityElement element = config.create(wrappedWorld, pos); + elements[0] = element; + if (hasTrackedBy) { + for (Player player : trackedBy) { + previousElement.hide(player); + element.show(player); + } + } + } + } else { + outer: for (int i = 0; i < elements.length; i++) { + BlockEntityElementConfig config = renderers[i]; + for (int j = 0; j < previousElements.length; j++) { + BlockEntityElement previousElement = previousElements[j]; + if (previousElement != null && config.elementClass().isInstance(previousElement)) { + BlockEntityElement newElement = ((BlockEntityElementConfig) config).create(wrappedWorld, pos, previousElement); + if (newElement != null) { + previousElements[j] = null; + elements[i] = newElement; + if (hasTrackedBy) { + for (Player player : trackedBy) { + newElement.transform(player); + } + } + continue outer; + } + } + } + BlockEntityElement newElement = config.create(wrappedWorld, pos); + elements[i] = newElement; + if (hasTrackedBy) { + for (Player player : trackedBy) { + newElement.show(player); + } + } + } + if (hasTrackedBy) { + for (int i = 0; i < previousElements.length; i++) { + BlockEntityElement previousElement = previousElements[i]; + if (previousElement != null) { + for (Player player : trackedBy) { + previousElement.hide(player); + } + } + } + } + } + } else { + for (int i = 0; i < elements.length; i++) { + elements[i] = renderers[i].create(wrappedWorld, pos); + } + if (hasTrackedBy) { + for (Player player : trackedBy) { + renderer.show(player); + } + } } try { this.renderLock.writeLock().lock(); this.constantBlockEntityRenderers.put(pos, renderer); + return renderer; } finally { this.renderLock.writeLock().unlock(); } } + return null; } - public void removeConstantBlockEntityRenderer(BlockPos pos) { + @Nullable + public ConstantBlockEntityRenderer removeConstantBlockEntityRenderer(BlockPos pos) { + return this.removeConstantBlockEntityRenderer(pos, true); + } + + @Nullable + public ConstantBlockEntityRenderer removeConstantBlockEntityRenderer(BlockPos pos, boolean hide) { try { this.renderLock.writeLock().lock(); ConstantBlockEntityRenderer removed = this.constantBlockEntityRenderers.remove(pos); if (removed != null) { - for (Player player : getTrackedBy()) { - removed.hide(player); + if (hide) { + for (Player player : getTrackedBy()) { + removed.hide(player); + } } } + return removed; } finally { this.renderLock.writeLock().unlock(); } @@ -183,7 +273,12 @@ public class CEChunk { this.removeDynamicBlockEntityRenderer(blockPos); } + public List getTrackedBy() { + return this.world.world.getTrackedBy(this.chunkPos); + } + public void activateAllBlockEntities() { + if (this.activated) return; for (BlockEntity blockEntity : this.blockEntities.values()) { blockEntity.setValid(true); this.replaceOrCreateTickingBlockEntity(blockEntity); @@ -192,13 +287,11 @@ public class CEChunk { for (ConstantBlockEntityRenderer renderer : this.constantBlockEntityRenderers.values()) { renderer.activate(); } - } - - public List getTrackedBy() { - return this.world.world.getTrackedBy(this.chunkPos); + this.activated = true; } public void deactivateAllBlockEntities() { + if (!this.activated) return; this.blockEntities.values().forEach(e -> e.setValid(false)); this.constantBlockEntityRenderers.values().forEach(ConstantBlockEntityRenderer::deactivate); this.dynamicBlockEntityRenderers.clear(); @@ -206,6 +299,7 @@ public class CEChunk { this.tickingSyncBlockEntitiesByPos.clear(); this.tickingAsyncBlockEntitiesByPos.values().forEach((ticker) -> ticker.setTicker(DummyTickingBlockEntity.INSTANCE)); this.tickingAsyncBlockEntitiesByPos.clear(); + this.activated = false; } @SuppressWarnings("unchecked") @@ -452,14 +546,12 @@ public class CEChunk { public void load() { if (this.loaded) return; this.world.addLoadedChunk(this); - this.activateAllBlockEntities(); this.loaded = true; } public void unload() { if (!this.loaded) return; this.world.removeLoadedChunk(this); - this.deactivateAllBlockEntities(); this.loaded = false; } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/CachedStorage.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/CachedStorage.java index 23fd7cd94..0bb78e303 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/CachedStorage.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/CachedStorage.java @@ -26,6 +26,11 @@ public class CachedStorage implements WorldDataStora .build(); } + @Override + public CEChunk readNewChunkAt(CEWorld world, ChunkPos pos) throws IOException { + return this.storage.readNewChunkAt(world, pos); + } + @Override public @NotNull CEChunk readChunkAt(@NotNull CEWorld world, @NotNull ChunkPos pos) throws IOException { CEChunk chunk = this.chunkCache.getIfPresent(pos); @@ -42,6 +47,12 @@ public class CachedStorage implements WorldDataStora this.storage.writeChunkAt(pos, chunk); } + @Override + public void clearChunkAt(@NotNull ChunkPos pos) throws IOException { + this.storage.clearChunkAt(pos); + this.chunkCache.invalidate(pos); + } + @Override public void close() throws IOException { this.storage.close(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/DefaultRegionFileStorage.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/DefaultRegionFileStorage.java index bfeef7a58..9010eab47 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/DefaultRegionFileStorage.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/DefaultRegionFileStorage.java @@ -120,6 +120,19 @@ public class DefaultRegionFileStorage implements WorldDataStorage { } } + @Override + public CEChunk readNewChunkAt(CEWorld world, ChunkPos pos) throws IOException { + RegionFile regionFile = this.getRegionFile(pos, false, true); + try { + if (regionFile.doesChunkExist(pos)) { + regionFile.clear(pos); + } + return new CEChunk(world, pos); + } finally { + regionFile.fileLock.unlock(); + } + } + @Override public @NotNull CEChunk readChunkAt(@NotNull CEWorld world, @NotNull ChunkPos pos) throws IOException { RegionFile regionFile = this.getRegionFile(pos, false, true); @@ -152,6 +165,11 @@ public class DefaultRegionFileStorage implements WorldDataStorage { writeChunkTagAt(pos, nbt); } + @Override + public void clearChunkAt(@NotNull ChunkPos pos) throws IOException { + this.writeChunkTagAt(pos, null); + } + public void writeChunkTagAt(@NotNull ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { RegionFile regionFile = this.getRegionFile(pos, nbt == null, true); try { diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/WorldDataStorage.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/WorldDataStorage.java index bd44492a9..47dff58fe 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/WorldDataStorage.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/WorldDataStorage.java @@ -9,11 +9,18 @@ import java.io.IOException; public interface WorldDataStorage { + default CEChunk readNewChunkAt(CEWorld world, ChunkPos pos) throws IOException { + this.clearChunkAt(pos); + return this.readChunkAt(world, pos); + } + @NotNull CEChunk readChunkAt(@NotNull CEWorld world, @NotNull ChunkPos pos) throws IOException; void writeChunkAt(@NotNull ChunkPos pos, @NotNull CEChunk chunk) throws IOException; + void clearChunkAt(@NotNull ChunkPos pos) throws IOException; + void flush() throws IOException; void close() throws IOException; diff --git a/gradle.properties b/gradle.properties index 25deb2efa..0ec0adef5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,9 +2,9 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.65 -config_version=52 -lang_version=36 +project_version=0.0.65.6 +config_version=53 +lang_version=37 project_group=net.momirealms latest_supported_version=1.21.10 @@ -49,7 +49,7 @@ byte_buddy_version=1.17.8 ahocorasick_version=0.6.3 snake_yaml_version=2.5 anti_grief_version=1.0.4 -nms_helper_version=1.0.123 +nms_helper_version=1.0.127 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.34.5 diff --git a/wiki b/wiki new file mode 160000 index 000000000..bec8bb7cf --- /dev/null +++ b/wiki @@ -0,0 +1 @@ +Subproject commit bec8bb7cf8c4331dd54bdc4bb27edfa664805e66