diff --git a/patches/server/0006-Leaves-Server-Config-And-Command.patch b/patches/server/0006-Leaves-Server-Config-And-Command.patch index 6698251..eed3d13 100644 --- a/patches/server/0006-Leaves-Server-Config-And-Command.patch +++ b/patches/server/0006-Leaves-Server-Config-And-Command.patch @@ -85,10 +85,10 @@ index 44bbfc4eba78dfa268696c79b1d15c8f1271bbb1..a88ff89928c322fa1c42987a06991a56 .withRequiredArg() diff --git a/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/src/main/java/org/leavesmc/leaves/LeavesConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..313beaa7eef481bfc42d89959e227dac6558fab9 +index 0000000000000000000000000000000000000000..86738f2520d055ea556d03eacfdfb1b852993710 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/LeavesConfig.java -@@ -0,0 +1,901 @@ +@@ -0,0 +1,905 @@ +package org.leavesmc.leaves; + +import com.destroystokyo.paper.util.SneakyThrow; @@ -810,9 +810,13 @@ index 0000000000000000000000000000000000000000..313beaa7eef481bfc42d89959e227dac + } + } + -+ @GlobalConfig(name = "appleskin-protocol", category = "protocol") ++ @RemovedConfig(name = "appleskin-protocol", category = "protocol") ++ @GlobalConfig(name = "protocol", category = {"protocol", "appleskin"}) + public static boolean appleskinProtocol = false; + ++ @GlobalConfig(name = "sync-tick-interval", category = {"protocol", "appleskin"}) ++ public static int appleskinSyncTickInterval = 20; ++ + @GlobalConfig(name = "xaero-map-protocol", category = "protocol") + public static boolean xaeroMapProtocol = false; + diff --git a/patches/server/0007-Leaves-Protocol-Core.patch b/patches/server/0007-Leaves-Protocol-Core.patch index 62a9445..cd91739 100644 --- a/patches/server/0007-Leaves-Protocol-Core.patch +++ b/patches/server/0007-Leaves-Protocol-Core.patch @@ -179,10 +179,10 @@ index 0000000000000000000000000000000000000000..986d2a6641ff8017dddf3e5f2655adfc +} diff --git a/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java b/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java new file mode 100644 -index 0000000000000000000000000000000000000000..e5eb67c0bbdf4953ed0ccc3281f06eda26a7956e +index 0000000000000000000000000000000000000000..ea94da3a2332cf23fc8753129e546a6f5a5af395 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java -@@ -0,0 +1,435 @@ +@@ -0,0 +1,434 @@ +package org.leavesmc.leaves.protocol.core; + +import com.google.common.collect.ImmutableSet; @@ -470,10 +470,9 @@ index 0000000000000000000000000000000000000000..e5eb67c0bbdf4953ed0ccc3281f06eda + + Map map = MINECRAFT_REGISTER.get(protocol); + for (ProtocolHandler.MinecraftRegister register : map.keySet()) { -+ if (register.ignoreId() || register.channelId().equals(channel[1]) || -+ ArrayUtils.contains(register.channelIds(), channel[1])) { ++ if (register.ignoreId() || ArrayUtils.contains(register.channelId(), channel[1])) { + try { -+ map.get(register).invoke(null, player); ++ map.get(register).invoke(null, player, channel[1]); + } catch (InvocationTargetException | IllegalAccessException exception) { + LOGGER.warning("Failed to handle minecraft register, " + exception.getCause() + ": " + exception.getMessage()); + } @@ -620,10 +619,10 @@ index 0000000000000000000000000000000000000000..e5eb67c0bbdf4953ed0ccc3281f06eda +} diff --git a/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolHandler.java b/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolHandler.java new file mode 100644 -index 0000000000000000000000000000000000000000..9d71f8e6af24301bedf60f5c87e0bb3c1697d5e3 +index 0000000000000000000000000000000000000000..202fb0717734aa8948ff8307420bf9aaf77d63ca --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolHandler.java -@@ -0,0 +1,63 @@ +@@ -0,0 +1,55 @@ +package org.leavesmc.leaves.protocol.core; + +import java.lang.annotation.ElementType; @@ -636,13 +635,11 @@ index 0000000000000000000000000000000000000000..9d71f8e6af24301bedf60f5c87e0bb3c + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface Init { -+ + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface PayloadReceiver { -+ + Class> payload(); + + String[] payloadId() default ""; @@ -661,28 +658,22 @@ index 0000000000000000000000000000000000000000..9d71f8e6af24301bedf60f5c87e0bb3c + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface PlayerJoin { -+ + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface PlayerLeave { -+ + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface ReloadServer { -+ + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface MinecraftRegister { -+ -+ String channelId() default ""; -+ -+ String[] channelIds() default {}; ++ String[] channelId() default ""; + + boolean ignoreId() default false; + } diff --git a/patches/server/0031-BBOR-Protocol.patch b/patches/server/0031-BBOR-Protocol.patch index 0afdefb..8f1ee6f 100644 --- a/patches/server/0031-BBOR-Protocol.patch +++ b/patches/server/0031-BBOR-Protocol.patch @@ -34,7 +34,7 @@ index 4640baec5bed6c2d53cc0f8ca1d273cc115abe9b..2fea5a46bba27578366c36f594472c3e public Level getLevel() { diff --git a/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java b/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java new file mode 100644 -index 0000000000000000000000000000000000000000..16ef00dde5a1c502449378829b1b6b85d6d145fd +index 0000000000000000000000000000000000000000..7c48c0a5ac7e53e52ca06f72e6f58472aad5d4a3 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java @@ -0,0 +1,227 @@ @@ -144,7 +144,7 @@ index 0000000000000000000000000000000000000000..16ef00dde5a1c502449378829b1b6b85 + public static void onChunkLoaded(@NotNull LevelChunk chunk) { + if (LeavesConfig.bborProtocol) { + Map structures = new HashMap<>(); -+ final Registry structureFeatureRegistry = chunk.getLevel().registryAccess().registryOrThrow(Registries.STRUCTURE); ++ final Registry structureFeatureRegistry = chunk.getLevel().registryAccess().lookupOrThrow(Registries.STRUCTURE); + for (var es : chunk.getAllStarts().entrySet()) { + final var optional = structureFeatureRegistry.getResourceKey(es.getKey()); + optional.ifPresent(key -> structures.put(key.location().toString(), es.getValue())); @@ -184,8 +184,8 @@ index 0000000000000000000000000000000000000000..16ef00dde5a1c502449378829b1b6b85 + return new BBoundingBox(type, min, max); + } + -+ private static void sendStructureList(ServerPlayer player) { -+ final Registry structureRegistry = player.server.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ private static void sendStructureList(@NotNull ServerPlayer player) { ++ final Registry structureRegistry = player.server.registryAccess().lookupOrThrow(Registries.STRUCTURE); + final Set structureIds = structureRegistry.entrySet().stream() + .map(e -> e.getKey().location().toString()).collect(Collectors.toSet()); + ProtocolUtils.sendPayloadPacket(player, STRUCTURE_LIST_SYNC, buf -> { diff --git a/patches/server/0033-Jade-Protocol.patch b/patches/server/0033-Jade-Protocol.patch index c11d65c..236c015 100644 --- a/patches/server/0033-Jade-Protocol.patch +++ b/patches/server/0033-Jade-Protocol.patch @@ -124,10 +124,10 @@ index 30d0133a42ce990352f5c492fcf9beb105364848..1ab2eab686b3a89d406f127a6036c0e2 protected CompositeLootItemCondition(List terms, Predicate predicate) { diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java b/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java new file mode 100644 -index 0000000000000000000000000000000000000000..438dfee78f7114e7c8d3d57c5dcc90e1fcc75a4c +index 0000000000000000000000000000000000000000..c72d6eeb61cda12e49939deebb9791d5c7f36f0a --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java -@@ -0,0 +1,311 @@ +@@ -0,0 +1,312 @@ +package org.leavesmc.leaves.protocol.jade; + +import com.google.common.base.Suppliers; @@ -290,8 +290,9 @@ index 0000000000000000000000000000000000000000..438dfee78f7114e7c8d3d57c5dcc90e1 + + try { + shearableBlocks = Collections.unmodifiableList(LootTableMineableCollector.execute( -+ MinecraftServer.getServer().reloadableRegistries().get().registryOrThrow(Registries.LOOT_TABLE), -+ Items.SHEARS.getDefaultInstance())); ++ MinecraftServer.getServer().reloadableRegistries().lookup().lookupOrThrow(Registries.LOOT_TABLE), ++ Items.SHEARS.getDefaultInstance() ++ )); + } catch (Throwable ignore) { + shearableBlocks = List.of(); + LeavesLogger.LOGGER.severe("Failed to collect shearable blocks"); @@ -1231,7 +1232,7 @@ index 0000000000000000000000000000000000000000..6e32eed15f028020223e2500849b4db3 \ No newline at end of file diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java new file mode 100644 -index 0000000000000000000000000000000000000000..797558f3804a1a8143eafafd5dc46cc72ea19a42 +index 0000000000000000000000000000000000000000..3efa3ceb9654bc53adb61ded96c0ad08eb9b083d --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java @@ -0,0 +1,138 @@ @@ -1285,7 +1286,7 @@ index 0000000000000000000000000000000000000000..797558f3804a1a8143eafafd5dc46cc7 + case RandomizableContainer te when te.getLootTable() != null -> { + return List.of(); + } -+ case ContainerEntity containerEntity when containerEntity.getLootTable() != null -> { ++ case ContainerEntity containerEntity when containerEntity.getContainerLootTable() != null -> { + return List.of(); + } + default -> { @@ -3097,15 +3098,16 @@ index 0000000000000000000000000000000000000000..a046ae4e542efcadd0001b7225440c30 +} diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/util/LootTableMineableCollector.java b/src/main/java/org/leavesmc/leaves/protocol/jade/util/LootTableMineableCollector.java new file mode 100644 -index 0000000000000000000000000000000000000000..63f4d0a31232525db3620095fc662f0225c5f306 +index 0000000000000000000000000000000000000000..81575cfa4c5a6f1a1aadbf9ea7743cd1d053f925 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/util/LootTableMineableCollector.java -@@ -0,0 +1,105 @@ +@@ -0,0 +1,109 @@ +package org.leavesmc.leaves.protocol.jade.util; + +import com.google.common.collect.Lists; +import net.minecraft.advancements.critereon.ItemPredicate; -+import net.minecraft.core.Registry; ++import net.minecraft.core.Holder; ++import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; @@ -3121,19 +3123,20 @@ index 0000000000000000000000000000000000000000..63f4d0a31232525db3620095fc662f02 +import org.leavesmc.leaves.protocol.jade.tool.ShearsToolHandler; + +import java.util.List; ++import java.util.Optional; +import java.util.function.Function; + +public class LootTableMineableCollector { + -+ private final Registry lootRegistry; ++ private final HolderGetter lootRegistry; + private final ItemStack toolItem; + -+ public LootTableMineableCollector(Registry lootRegistry, ItemStack toolItem) { ++ public LootTableMineableCollector(HolderGetter lootRegistry, ItemStack toolItem) { + this.lootRegistry = lootRegistry; + this.toolItem = toolItem; + } + -+ public static @NotNull List execute(Registry lootRegistry, ItemStack toolItem) { ++ public static @NotNull List execute(HolderGetter lootRegistry, ItemStack toolItem) { + LootTableMineableCollector collector = new LootTableMineableCollector(lootRegistry, toolItem); + List list = Lists.newArrayList(); + for (Block block : BuiltInRegistries.BLOCK) { @@ -3141,9 +3144,11 @@ index 0000000000000000000000000000000000000000..63f4d0a31232525db3620095fc662f02 + continue; + } + -+ LootTable lootTable = lootRegistry.get(block.getLootTable()); -+ if (collector.doLootTable(lootTable)) { -+ list.add(block); ++ if (block.getLootTable().isPresent()) { ++ LootTable lootTable = lootRegistry.get(block.getLootTable().get()).map(Holder::value).orElse(null); ++ if (collector.doLootTable(lootTable)) { ++ list.add(block); ++ } + } + } + return list; @@ -3179,7 +3184,7 @@ index 0000000000000000000000000000000000000000..63f4d0a31232525db3620095fc662f02 + } + } + } else if (entry instanceof NestedLootTable nestedLootTable) { -+ LootTable lootTable = nestedLootTable.contents.map(lootRegistry::get, Function.identity()); ++ LootTable lootTable = nestedLootTable.contents.map($ -> lootRegistry.get($).map(Holder::value).orElse(null), Function.identity()); + return doLootTable(lootTable); + } else { + return isCorrectConditions(entry.conditions, toolItem); @@ -3193,8 +3198,8 @@ index 0000000000000000000000000000000000000000..63f4d0a31232525db3620095fc662f02 + } + + LootItemCondition condition = conditions.getFirst(); -+ if (condition instanceof MatchTool matchTool) { -+ ItemPredicate itemPredicate = matchTool.predicate().orElse(null); ++ if (condition instanceof MatchTool(Optional predicate)) { ++ ItemPredicate itemPredicate = predicate.orElse(null); + return itemPredicate != null && itemPredicate.test(toolItem); + } else if (condition instanceof AnyOfCondition anyOfCondition) { + for (LootItemCondition child : anyOfCondition.terms) { diff --git a/patches/server/0040-Appleskin-Protocol.patch b/patches/server/0040-Appleskin-Protocol.patch index 687a20f..5d2545b 100644 --- a/patches/server/0040-Appleskin-Protocol.patch +++ b/patches/server/0040-Appleskin-Protocol.patch @@ -6,16 +6,17 @@ Subject: [PATCH] Appleskin Protocol diff --git a/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java b/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java new file mode 100644 -index 0000000000000000000000000000000000000000..6662ecf8a9342db2e0ded507d7420319388f9974 +index 0000000000000000000000000000000000000000..26aa98a402772a69d11d394537c5b21da702aefd --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java -@@ -0,0 +1,106 @@ +@@ -0,0 +1,127 @@ +package org.leavesmc.leaves.protocol; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.food.FoodData; ++import net.minecraft.world.level.GameRules; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; @@ -27,22 +28,23 @@ index 0000000000000000000000000000000000000000..6662ecf8a9342db2e0ded507d7420319 +import java.util.HashSet; +import java.util.Map; +import java.util.Set; -+import java.util.UUID; + +@LeavesProtocol(namespace = "appleskin") +public class AppleSkinProtocol { + + public static final String PROTOCOL_ID = "appleskin"; + -+ private static final ResourceLocation SATURATION_KEY = id("saturation_sync"); -+ private static final ResourceLocation EXHAUSTION_KEY = id("exhaustion_sync"); -+ -+ private static final Map previousSaturationLevels = new HashMap<>(); -+ private static final Map previousExhaustionLevels = new HashMap<>(); ++ private static final ResourceLocation SATURATION_KEY = id("saturation"); ++ private static final ResourceLocation EXHAUSTION_KEY = id("exhaustion"); ++ private static final ResourceLocation NATURAL_REGENERATION_KEY = id("natural_regeneration"); + + private static final float MINIMUM_EXHAUSTION_CHANGE_THRESHOLD = 0.01F; + -+ private static final Set players = new HashSet<>(); ++ private static final Map previousSaturationLevels = new HashMap<>(); ++ private static final Map previousExhaustionLevels = new HashMap<>(); ++ private static final Map previousNaturalRegeneration = new HashMap<>(); ++ ++ private static final Map> subscribedChannels = new HashMap<>(); + + @Contract("_ -> new") + public static @NotNull ResourceLocation id(String path) { @@ -59,40 +61,58 @@ index 0000000000000000000000000000000000000000..6662ecf8a9342db2e0ded507d7420319 + @ProtocolHandler.PlayerLeave + public static void onPlayerLoggedOut(@NotNull ServerPlayer player) { + if (LeavesConfig.appleskinProtocol) { -+ players.remove(player); ++ subscribedChannels.remove(player); + resetPlayerData(player); + } + } + + @ProtocolHandler.MinecraftRegister(ignoreId = true) -+ public static void onPlayerSubscribed(@NotNull ServerPlayer player) { ++ public static void onPlayerSubscribed(@NotNull ServerPlayer player, String channel) { + if (LeavesConfig.appleskinProtocol) { -+ players.add(player); ++ subscribedChannels.computeIfAbsent(player, k -> new HashSet<>()).add(channel); + } + } + + @ProtocolHandler.Ticker + public static void tick() { + if (LeavesConfig.appleskinProtocol) { -+ for (ServerPlayer player : players) { -+ FoodData data = player.getFoodData(); ++ if (MinecraftServer.getServer().getTickCount() % LeavesConfig.appleskinSyncTickInterval != 0) { ++ return; ++ } + -+ float saturation = data.getSaturationLevel(); -+ Float previousSaturation = previousSaturationLevels.get(player.getUUID()); -+ if (previousSaturation == null || saturation != previousSaturation) { -+ ProtocolUtils.sendPayloadPacket(player, SATURATION_KEY, buf -> { -+ buf.writeFloat(saturation); -+ }); -+ previousSaturationLevels.put(player.getUUID(), saturation); -+ } ++ for (Map.Entry> entry : subscribedChannels.entrySet()) { ++ ServerPlayer player = entry.getKey(); ++ FoodData data = player.getFoodData(); + -+ float exhaustion = data.getExhaustionLevel(); -+ Float previousExhaustion = previousExhaustionLevels.get(player.getUUID()); -+ if (previousExhaustion == null || Math.abs(exhaustion - previousExhaustion) >= MINIMUM_EXHAUSTION_CHANGE_THRESHOLD) { -+ ProtocolUtils.sendPayloadPacket(player, EXHAUSTION_KEY, buf -> { -+ buf.writeFloat(exhaustion); -+ }); -+ previousExhaustionLevels.put(player.getUUID(), exhaustion); ++ for (String channel : entry.getValue()) { ++ switch (channel) { ++ case "saturation" -> { ++ float saturation = data.getSaturationLevel(); ++ Float previousSaturation = previousSaturationLevels.get(player); ++ if (previousSaturation == null || saturation != previousSaturation) { ++ ProtocolUtils.sendPayloadPacket(player, SATURATION_KEY, buf -> buf.writeFloat(saturation)); ++ previousSaturationLevels.put(player, saturation); ++ } ++ } ++ ++ case "exhaustion" -> { ++ float exhaustion = data.exhaustionLevel; ++ Float previousExhaustion = previousExhaustionLevels.get(player); ++ if (previousExhaustion == null || Math.abs(exhaustion - previousExhaustion) >= MINIMUM_EXHAUSTION_CHANGE_THRESHOLD) { ++ ProtocolUtils.sendPayloadPacket(player, EXHAUSTION_KEY, buf -> buf.writeFloat(exhaustion)); ++ previousExhaustionLevels.put(player, exhaustion); ++ } ++ } ++ ++ case "natural_regeneration" -> { ++ boolean regeneration = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION); ++ Boolean previousRegeneration = previousNaturalRegeneration.get(player); ++ if (previousRegeneration == null || regeneration != previousRegeneration) { ++ ProtocolUtils.sendPayloadPacket(player, NATURAL_REGENERATION_KEY, buf -> buf.writeBoolean(regeneration)); ++ previousNaturalRegeneration.put(player, regeneration); ++ } ++ } ++ } + } + } + } @@ -112,7 +132,8 @@ index 0000000000000000000000000000000000000000..6662ecf8a9342db2e0ded507d7420319 + } + + private static void resetPlayerData(@NotNull ServerPlayer player) { -+ previousExhaustionLevels.remove(player.getUUID()); -+ previousSaturationLevels.remove(player.getUUID()); ++ previousExhaustionLevels.remove(player); ++ previousSaturationLevels.remove(player); ++ previousNaturalRegeneration.remove(player); + } +} diff --git a/patches/server/0067-Faster-chunk-serialization.patch b/patches/server/0067-Faster-chunk-serialization.patch index 2881a83..156526e 100644 --- a/patches/server/0067-Faster-chunk-serialization.patch +++ b/patches/server/0067-Faster-chunk-serialization.patch @@ -298,7 +298,7 @@ index 8b84bf2272556ac3321cbf16361d7f48a1cc6873..d73c38c030daabdf9a85a265b23d39f7 static record Configuration(Palette.Factory factory, int bits) { diff --git a/src/main/java/org/leavesmc/leaves/lithium/common/world/chunk/LithiumHashPalette.java b/src/main/java/org/leavesmc/leaves/lithium/common/world/chunk/LithiumHashPalette.java new file mode 100644 -index 0000000000000000000000000000000000000000..3a110e892dafa965274597018265fc5b9d9a9640 +index 0000000000000000000000000000000000000000..da32fdd8bbb9a966bd17c7457d94bb676f28c60d --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/lithium/common/world/chunk/LithiumHashPalette.java @@ -0,0 +1,197 @@ @@ -474,8 +474,8 @@ index 0000000000000000000000000000000000000000..3a110e892dafa965274597018265fc5b + + @NotNull + @Override -+ public Palette copy() { -+ return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size); ++ public Palette copy(@NotNull PaletteResize resizeListener) { ++ return new LithiumHashPalette<>(this.idList, resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size); + } + + private void clear() { diff --git a/patches/server/0089-Replay-Mod-API.patch b/patches/server/0089-Replay-Mod-API.patch index aabd09f..7cb6e32 100644 --- a/patches/server/0089-Replay-Mod-API.patch +++ b/patches/server/0089-Replay-Mod-API.patch @@ -1309,7 +1309,7 @@ index 0000000000000000000000000000000000000000..1568f6928d5d4f38ca1919c6de6ec9bb +} diff --git a/src/main/java/org/leavesmc/leaves/replay/ServerPhotographer.java b/src/main/java/org/leavesmc/leaves/replay/ServerPhotographer.java new file mode 100644 -index 0000000000000000000000000000000000000000..f5c6e823d7ab9a61307e27e7b859e76bdfdd1e58 +index 0000000000000000000000000000000000000000..d8f8f071c67cd0e29411d3f0f3b5e931abe86f65 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/replay/ServerPhotographer.java @@ -0,0 +1,222 @@ @@ -1417,12 +1417,12 @@ index 0000000000000000000000000000000000000000..f5c6e823d7ab9a61307e27e7b859e76b + } + + @Override -+ public boolean isInvulnerableTo(@NotNull DamageSource damageSource) { ++ public boolean isInvulnerableTo(@NotNull ServerLevel world, @NotNull DamageSource damageSource) { + return true; + } + + @Override -+ public boolean hurt(@NotNull DamageSource source, float amount) { ++ public boolean hurtServer(@NotNull ServerLevel world, @NotNull DamageSource source, float amount) { + return false; + } + diff --git a/patches/server/0093-Wool-Hopper-Counter.patch b/patches/server/0093-Wool-Hopper-Counter.patch index 6c4ad3f..f36c8f5 100644 --- a/patches/server/0093-Wool-Hopper-Counter.patch +++ b/patches/server/0093-Wool-Hopper-Counter.patch @@ -189,10 +189,10 @@ index 0000000000000000000000000000000000000000..06b4d287bf545a51b9eeb7cd24fdc6a0 +} diff --git a/src/main/java/org/leavesmc/leaves/util/HopperCounter.java b/src/main/java/org/leavesmc/leaves/util/HopperCounter.java new file mode 100644 -index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a556c17a3 +index 0000000000000000000000000000000000000000..a53ed2b8eb5645b0c3432f3f66cb58368d49f0ee --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/util/HopperCounter.java -@@ -0,0 +1,338 @@ +@@ -0,0 +1,337 @@ +package org.leavesmc.leaves.util; + +import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap; @@ -203,11 +203,15 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; ++import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; ++import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; ++import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; ++import net.minecraft.util.context.ContextMap; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.DyeItem; @@ -216,9 +220,10 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.Recipe; -+import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.RecipeManager; -+import net.minecraft.world.item.crafting.RecipeType; ++import net.minecraft.world.item.crafting.display.RecipeDisplay; ++import net.minecraft.world.item.crafting.display.SlotDisplayContext; ++import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.AbstractBannerBlock; +import net.minecraft.world.level.block.BeaconBeamBlock; +import net.minecraft.world.level.block.Block; @@ -229,15 +234,16 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a +import org.leavesmc.leaves.LeavesConfig; + +import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; ++import java.util.Optional; + +import static java.util.Map.entry; + ++// Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet) ++ +public class HopperCounter { + + private static boolean enabled = false; @@ -278,6 +284,15 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a + startMillis = System.currentTimeMillis(); + } + ++ public static void resetAll(MinecraftServer server, boolean fresh) { ++ for (HopperCounter counter : COUNTERS.values()) { ++ counter.reset(server); ++ if (fresh) { ++ counter.startTick = -1; ++ } ++ } ++ } ++ + public List format(MinecraftServer server, boolean realTime) { + long ticks = Math.max(realTime ? (System.currentTimeMillis() - startMillis) / 50 : server.overworld().getGameTime() - startTick, -1); + @@ -288,23 +303,23 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a + long total = getTotalItems(); + if (total <= 0) { + return Collections.singletonList(Component.text() -+ .append(Component.text("No items for "), coloredName) -+ .append(Component.text(" yet ("), Component.text(String.format("%.2f ", ticks / (20.0 * 60.0)), Style.style(TextDecoration.BOLD))) -+ .append(Component.text("min"), Component.text(realTime ? " - real time" : ""), Component.text(")")) -+ .build()); ++ .append(Component.text("No items for "), coloredName) ++ .append(Component.text(" yet ("), Component.text(String.format("%.2f ", ticks / (20.0 * 60.0)), Style.style(TextDecoration.BOLD))) ++ .append(Component.text("min"), Component.text(realTime ? " - real time" : ""), Component.text(")")) ++ .build()); + } + + List items = new ArrayList<>(); + items.add(Component.text() -+ .append(Component.text("Items for "), coloredName, Component.text(" ")) -+ .append(Component.text("("), Component.text(String.format("%.2f ", ticks * 1.0 / (20 * 60)), Style.style(TextDecoration.BOLD))) -+ .append(Component.text("min"), Component.text(realTime ? " - real time" : ""), Component.text("), ")) -+ .append(Component.text("total: "), Component.text(total, Style.style(TextDecoration.BOLD)), Component.text(", ")) -+ .append(Component.text("("), Component.text(String.format("%.1f", total * 1.0 * (20 * 60 * 60) / ticks), Style.style(TextDecoration.BOLD))) -+ .append(Component.text("/h):")) -+ .build()); -+ -+ counter.object2LongEntrySet().forEach(entry -> { ++ .append(Component.text("Items for "), coloredName, Component.text(" ")) ++ .append(Component.text("("), Component.text(String.format("%.2f ", ticks * 1.0 / (20 * 60)), Style.style(TextDecoration.BOLD))) ++ .append(Component.text("min"), Component.text(realTime ? " - real time" : ""), Component.text("), ")) ++ .append(Component.text("total: "), Component.text(total, Style.style(TextDecoration.BOLD)), Component.text(", ")) ++ .append(Component.text("("), Component.text(String.format("%.1f", total * 1.0 * (20 * 60 * 60) / ticks), Style.style(TextDecoration.BOLD))) ++ .append(Component.text("/h):")) ++ .build()); ++ ++ items.addAll(counter.object2LongEntrySet().stream().sorted((e, f) -> Long.compare(f.getLongValue(), e.getLongValue())).map(entry -> { + Item item = entry.getKey(); + Component name = Component.translatable(item.getDescriptionId()); + TextColor textColor = guessColor(server, item); @@ -316,103 +331,103 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a + } + + long count = entry.getLongValue(); -+ items.add(Component.text() -+ .append(Component.text("- ", NamedTextColor.GRAY)) -+ .append(name) -+ .append(Component.text(": ", NamedTextColor.GRAY)) -+ .append(Component.text(count, Style.style(TextDecoration.BOLD)), Component.text(", ", NamedTextColor.GRAY)) -+ .append(Component.text(String.format("%.1f", count * (20.0 * 60.0 * 60.0) / ticks), Style.style(TextDecoration.BOLD))) -+ .append(Component.text("/h")) -+ .build()); -+ }); ++ return Component.text() ++ .append(Component.text("- ", NamedTextColor.GRAY)) ++ .append(name) ++ .append(Component.text(": ", NamedTextColor.GRAY)) ++ .append(Component.text(count, Style.style(TextDecoration.BOLD)), Component.text(", ", NamedTextColor.GRAY)) ++ .append(Component.text(String.format("%.1f", count * (20.0 * 60.0 * 60.0) / ticks), Style.style(TextDecoration.BOLD))) ++ .append(Component.text("/h")) ++ .build(); ++ }).toList()); + return items; + } + + private static final Map DEFAULTS = Map.ofEntries( -+ entry(Items.DANDELION, Blocks.YELLOW_WOOL), -+ entry(Items.POPPY, Blocks.RED_WOOL), -+ entry(Items.BLUE_ORCHID, Blocks.LIGHT_BLUE_WOOL), -+ entry(Items.ALLIUM, Blocks.MAGENTA_WOOL), -+ entry(Items.AZURE_BLUET, Blocks.SNOW_BLOCK), -+ entry(Items.RED_TULIP, Blocks.RED_WOOL), -+ entry(Items.ORANGE_TULIP, Blocks.ORANGE_WOOL), -+ entry(Items.WHITE_TULIP, Blocks.SNOW_BLOCK), -+ entry(Items.PINK_TULIP, Blocks.PINK_WOOL), -+ entry(Items.OXEYE_DAISY, Blocks.SNOW_BLOCK), -+ entry(Items.CORNFLOWER, Blocks.BLUE_WOOL), -+ entry(Items.WITHER_ROSE, Blocks.BLACK_WOOL), -+ entry(Items.LILY_OF_THE_VALLEY, Blocks.WHITE_WOOL), -+ entry(Items.BROWN_MUSHROOM, Blocks.BROWN_MUSHROOM_BLOCK), -+ entry(Items.RED_MUSHROOM, Blocks.RED_MUSHROOM_BLOCK), -+ entry(Items.STICK, Blocks.OAK_PLANKS), -+ entry(Items.GOLD_INGOT, Blocks.GOLD_BLOCK), -+ entry(Items.IRON_INGOT, Blocks.IRON_BLOCK), -+ entry(Items.DIAMOND, Blocks.DIAMOND_BLOCK), -+ entry(Items.NETHERITE_INGOT, Blocks.NETHERITE_BLOCK), -+ entry(Items.SUNFLOWER, Blocks.YELLOW_WOOL), -+ entry(Items.LILAC, Blocks.MAGENTA_WOOL), -+ entry(Items.ROSE_BUSH, Blocks.RED_WOOL), -+ entry(Items.PEONY, Blocks.PINK_WOOL), -+ entry(Items.CARROT, Blocks.ORANGE_WOOL), -+ entry(Items.APPLE, Blocks.RED_WOOL), -+ entry(Items.WHEAT, Blocks.HAY_BLOCK), -+ entry(Items.PORKCHOP, Blocks.PINK_WOOL), -+ entry(Items.RABBIT, Blocks.PINK_WOOL), -+ entry(Items.CHICKEN, Blocks.WHITE_TERRACOTTA), -+ entry(Items.BEEF, Blocks.NETHERRACK), -+ entry(Items.ENCHANTED_GOLDEN_APPLE, Blocks.GOLD_BLOCK), -+ entry(Items.COD, Blocks.WHITE_TERRACOTTA), -+ entry(Items.SALMON, Blocks.ACACIA_PLANKS), -+ entry(Items.ROTTEN_FLESH, Blocks.BROWN_WOOL), -+ entry(Items.PUFFERFISH, Blocks.YELLOW_TERRACOTTA), -+ entry(Items.TROPICAL_FISH, Blocks.ORANGE_WOOL), -+ entry(Items.POTATO, Blocks.WHITE_TERRACOTTA), -+ entry(Items.MUTTON, Blocks.RED_WOOL), -+ entry(Items.BEETROOT, Blocks.NETHERRACK), -+ entry(Items.MELON_SLICE, Blocks.MELON), -+ entry(Items.POISONOUS_POTATO, Blocks.SLIME_BLOCK), -+ entry(Items.SPIDER_EYE, Blocks.NETHERRACK), -+ entry(Items.GUNPOWDER, Blocks.GRAY_WOOL), -+ entry(Items.TURTLE_SCUTE, Blocks.LIME_WOOL), -+ entry(Items.ARMADILLO_SCUTE, Blocks.ANCIENT_DEBRIS), -+ entry(Items.FEATHER, Blocks.WHITE_WOOL), -+ entry(Items.FLINT, Blocks.BLACK_WOOL), -+ entry(Items.LEATHER, Blocks.SPRUCE_PLANKS), -+ entry(Items.GLOWSTONE_DUST, Blocks.GLOWSTONE), -+ entry(Items.PAPER, Blocks.WHITE_WOOL), -+ entry(Items.BRICK, Blocks.BRICKS), -+ entry(Items.INK_SAC, Blocks.BLACK_WOOL), -+ entry(Items.SNOWBALL, Blocks.SNOW_BLOCK), -+ entry(Items.WATER_BUCKET, Blocks.WATER), -+ entry(Items.LAVA_BUCKET, Blocks.LAVA), -+ entry(Items.MILK_BUCKET, Blocks.WHITE_WOOL), -+ entry(Items.CLAY_BALL, Blocks.CLAY), -+ entry(Items.COCOA_BEANS, Blocks.COCOA), -+ entry(Items.BONE, Blocks.BONE_BLOCK), -+ entry(Items.COD_BUCKET, Blocks.BROWN_TERRACOTTA), -+ entry(Items.PUFFERFISH_BUCKET, Blocks.YELLOW_TERRACOTTA), -+ entry(Items.SALMON_BUCKET, Blocks.PINK_TERRACOTTA), -+ entry(Items.TROPICAL_FISH_BUCKET, Blocks.ORANGE_TERRACOTTA), -+ entry(Items.SUGAR, Blocks.WHITE_WOOL), -+ entry(Items.BLAZE_POWDER, Blocks.GOLD_BLOCK), -+ entry(Items.ENDER_PEARL, Blocks.WARPED_PLANKS), -+ entry(Items.NETHER_STAR, Blocks.DIAMOND_BLOCK), -+ entry(Items.PRISMARINE_CRYSTALS, Blocks.SEA_LANTERN), -+ entry(Items.PRISMARINE_SHARD, Blocks.PRISMARINE), -+ entry(Items.RABBIT_HIDE, Blocks.OAK_PLANKS), -+ entry(Items.CHORUS_FRUIT, Blocks.PURPUR_BLOCK), -+ entry(Items.SHULKER_SHELL, Blocks.SHULKER_BOX), -+ entry(Items.NAUTILUS_SHELL, Blocks.BONE_BLOCK), -+ entry(Items.HEART_OF_THE_SEA, Blocks.CONDUIT), -+ entry(Items.HONEYCOMB, Blocks.HONEYCOMB_BLOCK), -+ entry(Items.NAME_TAG, Blocks.BONE_BLOCK), -+ entry(Items.TOTEM_OF_UNDYING, Blocks.YELLOW_TERRACOTTA), -+ entry(Items.TRIDENT, Blocks.PRISMARINE), -+ entry(Items.GHAST_TEAR, Blocks.WHITE_WOOL), -+ entry(Items.PHANTOM_MEMBRANE, Blocks.BONE_BLOCK), -+ entry(Items.EGG, Blocks.BONE_BLOCK), -+ entry(Items.COPPER_INGOT, Blocks.COPPER_BLOCK), -+ entry(Items.AMETHYST_SHARD, Blocks.AMETHYST_BLOCK) ++ entry(Items.DANDELION, Blocks.YELLOW_WOOL), ++ entry(Items.POPPY, Blocks.RED_WOOL), ++ entry(Items.BLUE_ORCHID, Blocks.LIGHT_BLUE_WOOL), ++ entry(Items.ALLIUM, Blocks.MAGENTA_WOOL), ++ entry(Items.AZURE_BLUET, Blocks.SNOW_BLOCK), ++ entry(Items.RED_TULIP, Blocks.RED_WOOL), ++ entry(Items.ORANGE_TULIP, Blocks.ORANGE_WOOL), ++ entry(Items.WHITE_TULIP, Blocks.SNOW_BLOCK), ++ entry(Items.PINK_TULIP, Blocks.PINK_WOOL), ++ entry(Items.OXEYE_DAISY, Blocks.SNOW_BLOCK), ++ entry(Items.CORNFLOWER, Blocks.BLUE_WOOL), ++ entry(Items.WITHER_ROSE, Blocks.BLACK_WOOL), ++ entry(Items.LILY_OF_THE_VALLEY, Blocks.WHITE_WOOL), ++ entry(Items.BROWN_MUSHROOM, Blocks.BROWN_MUSHROOM_BLOCK), ++ entry(Items.RED_MUSHROOM, Blocks.RED_MUSHROOM_BLOCK), ++ entry(Items.STICK, Blocks.OAK_PLANKS), ++ entry(Items.GOLD_INGOT, Blocks.GOLD_BLOCK), ++ entry(Items.IRON_INGOT, Blocks.IRON_BLOCK), ++ entry(Items.DIAMOND, Blocks.DIAMOND_BLOCK), ++ entry(Items.NETHERITE_INGOT, Blocks.NETHERITE_BLOCK), ++ entry(Items.SUNFLOWER, Blocks.YELLOW_WOOL), ++ entry(Items.LILAC, Blocks.MAGENTA_WOOL), ++ entry(Items.ROSE_BUSH, Blocks.RED_WOOL), ++ entry(Items.PEONY, Blocks.PINK_WOOL), ++ entry(Items.CARROT, Blocks.ORANGE_WOOL), ++ entry(Items.APPLE, Blocks.RED_WOOL), ++ entry(Items.WHEAT, Blocks.HAY_BLOCK), ++ entry(Items.PORKCHOP, Blocks.PINK_WOOL), ++ entry(Items.RABBIT, Blocks.PINK_WOOL), ++ entry(Items.CHICKEN, Blocks.WHITE_TERRACOTTA), ++ entry(Items.BEEF, Blocks.NETHERRACK), ++ entry(Items.ENCHANTED_GOLDEN_APPLE, Blocks.GOLD_BLOCK), ++ entry(Items.COD, Blocks.WHITE_TERRACOTTA), ++ entry(Items.SALMON, Blocks.ACACIA_PLANKS), ++ entry(Items.ROTTEN_FLESH, Blocks.BROWN_WOOL), ++ entry(Items.PUFFERFISH, Blocks.YELLOW_TERRACOTTA), ++ entry(Items.TROPICAL_FISH, Blocks.ORANGE_WOOL), ++ entry(Items.POTATO, Blocks.WHITE_TERRACOTTA), ++ entry(Items.MUTTON, Blocks.RED_WOOL), ++ entry(Items.BEETROOT, Blocks.NETHERRACK), ++ entry(Items.MELON_SLICE, Blocks.MELON), ++ entry(Items.POISONOUS_POTATO, Blocks.SLIME_BLOCK), ++ entry(Items.SPIDER_EYE, Blocks.NETHERRACK), ++ entry(Items.GUNPOWDER, Blocks.GRAY_WOOL), ++ entry(Items.TURTLE_SCUTE, Blocks.LIME_WOOL), ++ entry(Items.ARMADILLO_SCUTE, Blocks.ANCIENT_DEBRIS), ++ entry(Items.FEATHER, Blocks.WHITE_WOOL), ++ entry(Items.FLINT, Blocks.BLACK_WOOL), ++ entry(Items.LEATHER, Blocks.SPRUCE_PLANKS), ++ entry(Items.GLOWSTONE_DUST, Blocks.GLOWSTONE), ++ entry(Items.PAPER, Blocks.WHITE_WOOL), ++ entry(Items.BRICK, Blocks.BRICKS), ++ entry(Items.INK_SAC, Blocks.BLACK_WOOL), ++ entry(Items.SNOWBALL, Blocks.SNOW_BLOCK), ++ entry(Items.WATER_BUCKET, Blocks.WATER), ++ entry(Items.LAVA_BUCKET, Blocks.LAVA), ++ entry(Items.MILK_BUCKET, Blocks.WHITE_WOOL), ++ entry(Items.CLAY_BALL, Blocks.CLAY), ++ entry(Items.COCOA_BEANS, Blocks.COCOA), ++ entry(Items.BONE, Blocks.BONE_BLOCK), ++ entry(Items.COD_BUCKET, Blocks.BROWN_TERRACOTTA), ++ entry(Items.PUFFERFISH_BUCKET, Blocks.YELLOW_TERRACOTTA), ++ entry(Items.SALMON_BUCKET, Blocks.PINK_TERRACOTTA), ++ entry(Items.TROPICAL_FISH_BUCKET, Blocks.ORANGE_TERRACOTTA), ++ entry(Items.SUGAR, Blocks.WHITE_WOOL), ++ entry(Items.BLAZE_POWDER, Blocks.GOLD_BLOCK), ++ entry(Items.ENDER_PEARL, Blocks.WARPED_PLANKS), ++ entry(Items.NETHER_STAR, Blocks.DIAMOND_BLOCK), ++ entry(Items.PRISMARINE_CRYSTALS, Blocks.SEA_LANTERN), ++ entry(Items.PRISMARINE_SHARD, Blocks.PRISMARINE), ++ entry(Items.RABBIT_HIDE, Blocks.OAK_PLANKS), ++ entry(Items.CHORUS_FRUIT, Blocks.PURPUR_BLOCK), ++ entry(Items.SHULKER_SHELL, Blocks.SHULKER_BOX), ++ entry(Items.NAUTILUS_SHELL, Blocks.BONE_BLOCK), ++ entry(Items.HEART_OF_THE_SEA, Blocks.CONDUIT), ++ entry(Items.HONEYCOMB, Blocks.HONEYCOMB_BLOCK), ++ entry(Items.NAME_TAG, Blocks.BONE_BLOCK), ++ entry(Items.TOTEM_OF_UNDYING, Blocks.YELLOW_TERRACOTTA), ++ entry(Items.TRIDENT, Blocks.PRISMARINE), ++ entry(Items.GHAST_TEAR, Blocks.WHITE_WOOL), ++ entry(Items.PHANTOM_MEMBRANE, Blocks.BONE_BLOCK), ++ entry(Items.EGG, Blocks.BONE_BLOCK), ++ entry(Items.COPPER_INGOT, Blocks.COPPER_BLOCK), ++ entry(Items.AMETHYST_SHARD, Blocks.AMETHYST_BLOCK) + ); + + @Nullable @@ -423,24 +438,39 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a + return direct; + } + -+ ResourceLocation id = registryAccess.registryOrThrow(Registries.ITEM).getKey(item); -+ for (RecipeType type : registryAccess.registryOrThrow(Registries.RECIPE_TYPE)) { -+ for (Recipe r : getAllMatching(server.getRecipeManager(), type, id, registryAccess)) { -+ for (Ingredient ingredient : r.getIngredients()) { -+ for (Collection stacks : getRecipeStacks(ingredient)) { -+ for (ItemStack itemStack : stacks) { -+ TextColor textColor = fromItem(itemStack.getItem(), registryAccess); -+ if (textColor != null) { -+ return textColor; -+ } -+ } -+ } ++ ResourceLocation id = registryAccess.lookupOrThrow(Registries.ITEM).getKey(item); ++ if (id == null) { ++ return null; ++ } ++ ++ ++ for (Recipe recipe : getRecipesForOutput(server.getRecipeManager(), id, server.overworld())) { ++ for (Ingredient ingredient : recipe.placementInfo().ingredients()) { ++ Optional> match = ingredient.items().stream().filter(stack -> fromItem(stack.value(), registryAccess) != null).findFirst(); ++ if (match.isPresent()) { ++ return fromItem(match.get().value(), registryAccess); + } + } + } + return null; + } + ++ @NotNull ++ public static List> getRecipesForOutput(@NotNull RecipeManager recipeManager, ResourceLocation id, Level level) { ++ List> results = new ArrayList<>(); ++ ContextMap context = SlotDisplayContext.fromLevel(level); ++ recipeManager.getRecipes().forEach(recipe -> { ++ for (RecipeDisplay recipeDisplay : recipe.value().display()) { ++ recipeDisplay.result().resolveForStacks(context).forEach(stack -> { ++ if (BuiltInRegistries.ITEM.wrapAsHolder(stack.getItem()).unwrapKey().map(ResourceKey::location).orElseThrow(IllegalStateException::new).equals(id)) { ++ results.add(recipe.value()); ++ } ++ }); ++ } ++ }); ++ return results; ++ } ++ + @Nullable + public static TextColor fromItem(Item item, RegistryAccess registryAccess) { + if (DEFAULTS.containsKey(item)) { @@ -451,13 +481,13 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a + } + + Block block = null; -+ final Registry itemRegistry = registryAccess.registryOrThrow(Registries.ITEM); -+ final Registry blockRegistry = registryAccess.registryOrThrow(Registries.BLOCK); ++ final Registry itemRegistry = registryAccess.lookupOrThrow(Registries.ITEM); ++ final Registry blockRegistry = registryAccess.lookupOrThrow(Registries.BLOCK); + ResourceLocation id = itemRegistry.getKey(item); + if (item instanceof BlockItem blockItem) { + block = blockItem.getBlock(); + } else if (blockRegistry.getOptional(id).isPresent()) { -+ block = blockRegistry.get(id); ++ block = blockRegistry.getValue(id); + } + + if (block != null) { @@ -471,28 +501,6 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a + return null; + } + -+ public static List> getAllMatching(@NotNull RecipeManager manager, RecipeType type, ResourceLocation output, final RegistryAccess registryAccess) { -+ RecipeHolder recipe = manager.byName.get(output); -+ if (recipe != null && recipe.value().getType().equals(type)) { -+ return List.of(recipe.value()); -+ } -+ if (!manager.byType.containsKey(type)) { -+ return List.of(); -+ } -+ -+ Collection> typeRecipes = manager.byType.get(type); -+ Registry regs = registryAccess.registryOrThrow(Registries.ITEM); -+ Item item = regs.get(output); -+ return typeRecipes.stream() -+ .>map(RecipeHolder::value) -+ .filter(r -> r.getResultItem(registryAccess).getItem() == item) -+ .toList(); -+ } -+ -+ public static List> getRecipeStacks(@NotNull Ingredient ingredient) { -+ return Arrays.stream(ingredient.values).map(Ingredient.Value::getItems).toList(); -+ } -+ + public static int appropriateColor(int color) { + if (color == 0) { + return MapColor.SNOW.col; @@ -510,15 +518,6 @@ index 0000000000000000000000000000000000000000..1a83b3918bc040ab32e648b54b498e9a + return counter.isEmpty() ? 0 : counter.values().longStream().sum(); + } + -+ public static void resetAll(MinecraftServer server, boolean fresh) { -+ for (HopperCounter counter : COUNTERS.values()) { -+ counter.reset(server); -+ if (fresh) { -+ counter.startTick = -1; -+ } -+ } -+ } -+ + public static HopperCounter getCounter(DyeColor color) { + return COUNTERS.get(color); + } diff --git a/patches/server/0058-Spawn-ignore-lc.patch b/patches/unapplied/server/0058-Spawn-ignore-lc.patch similarity index 100% rename from patches/server/0058-Spawn-ignore-lc.patch rename to patches/unapplied/server/0058-Spawn-ignore-lc.patch