diff --git a/gradle.properties b/gradle.properties index ae6eda1b..b21e76d9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check https://fabricmc.net/develop/ - minecraft_version=1.21.4 - loader_version=0.16.9 + minecraft_version=25w02a + loader_version=0.16.10 jsr305_version=3.0.2 fabric_version=0.110.5+1.21.4 @@ -17,7 +17,7 @@ org.gradle.jvmargs=-Xmx1G # The Curseforge versions "names" or ids for the main branch (comma separated: 1.16.4,1.16.5) # This is needed because CF uses too vague names for prereleases and release candidates # Can also be the version ID directly coming from https://minecraft.curseforge.com/api/game/versions?token=[API_TOKEN] - release-curse-versions = Minecraft 1.21:1.21.4 + release-curse-versions = Minecraft 1.21:1.21.5-Snapshot # Whether or not to build another branch on release release-extra-branch = false # The name of the second branch to release diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index df2e544c..d362544a 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -240,7 +240,7 @@ public class DrawCommand } if (CarpetSettings.fillUpdates) { - list.forEach(blockpos1 -> world.blockUpdated(blockpos1, world.getBlockState(blockpos1).getBlock())); + list.forEach(blockpos1 -> world.updateNeighborsAt(blockpos1, world.getBlockState(blockpos1).getBlock())); } Messenger.m(ctx.getSource(), "gi Filled " + affected + " blocks"); return affected; @@ -290,7 +290,7 @@ public class DrawCommand if (CarpetSettings.fillUpdates) { - list.forEach(p -> world.blockUpdated(p, world.getBlockState(p).getBlock())); + list.forEach(p -> world.updateNeighborsAt(p, world.getBlockState(p).getBlock())); } Messenger.m(source, "gi Filled " + affected + " blocks"); @@ -389,7 +389,7 @@ public class DrawCommand for (BlockPos blockpos1 : list) { Block blokc = world.getBlockState(blockpos1).getBlock(); - world.blockUpdated(blockpos1, blokc); + world.updateNeighborsAt(blockpos1, blokc); } } @@ -440,7 +440,7 @@ public class DrawCommand for (BlockPos blockpos1 : list) { Block blokc = world.getBlockState(blockpos1).getBlock(); - world.blockUpdated(blockpos1, blokc); + world.updateNeighborsAt(blockpos1, blokc); } } diff --git a/src/main/java/carpet/fakes/ChunkTicketManagerInterface.java b/src/main/java/carpet/fakes/ChunkTicketManagerInterface.java deleted file mode 100644 index 2a01ed8c..00000000 --- a/src/main/java/carpet/fakes/ChunkTicketManagerInterface.java +++ /dev/null @@ -1,16 +0,0 @@ -package carpet.fakes; - -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.Ticket; -import net.minecraft.util.SortedArraySet; -import net.minecraft.world.level.ChunkPos; - -public interface ChunkTicketManagerInterface -{ - void changeSpawnChunks(ChunkPos pos, int distance); - - Long2ObjectOpenHashMap>> getTicketsByPosition(); - - void replaceHolder(ChunkHolder oldHolder, ChunkHolder newHolder); -} diff --git a/src/main/java/carpet/fakes/TicketsFetcherInterface.java b/src/main/java/carpet/fakes/TicketsFetcherInterface.java new file mode 100644 index 00000000..7bc6055a --- /dev/null +++ b/src/main/java/carpet/fakes/TicketsFetcherInterface.java @@ -0,0 +1,11 @@ +package carpet.fakes; + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.server.level.Ticket; + +import java.util.List; + +public interface TicketsFetcherInterface +{ + Long2ObjectOpenHashMap> getTicketsByPosition(); +} diff --git a/src/main/java/carpet/fakes/WorldChunkInterface.java b/src/main/java/carpet/fakes/WorldChunkInterface.java index d93b0a1d..22a8c1db 100644 --- a/src/main/java/carpet/fakes/WorldChunkInterface.java +++ b/src/main/java/carpet/fakes/WorldChunkInterface.java @@ -6,5 +6,5 @@ import net.minecraft.world.level.block.state.BlockState; public interface WorldChunkInterface { - BlockState setBlockStateWithBlockEntity(BlockPos blockPos, BlockState newBlockState, BlockEntity newBlockEntity, boolean boolean1); + BlockState setBlockStateWithBlockEntity(BlockPos blockPos, BlockState newBlockState, BlockEntity newBlockEntity, int flags); } diff --git a/src/main/java/carpet/mixins/BuddingAmethystBlock_movableAmethystMixin.java b/src/main/java/carpet/mixins/BuddingAmethystBlock_movableAmethystMixin.java index af5670b2..f1adfc67 100644 --- a/src/main/java/carpet/mixins/BuddingAmethystBlock_movableAmethystMixin.java +++ b/src/main/java/carpet/mixins/BuddingAmethystBlock_movableAmethystMixin.java @@ -3,10 +3,10 @@ package carpet.mixins; import carpet.CarpetSettings; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; +import net.minecraft.tags.ItemTags; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.PickaxeItem; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.Level; @@ -14,12 +14,8 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.BuddingAmethystBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.PushReaction; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(BuddingAmethystBlock.class) public class BuddingAmethystBlock_movableAmethystMixin extends Block { @@ -33,7 +29,7 @@ public class BuddingAmethystBlock_movableAmethystMixin extends Block { // doing it here rather than though loottables since loottables are loaded on reload // drawback - not controlled via loottables, but hey if (CarpetSettings.movableAmethyst && - stack.getItem() instanceof PickaxeItem && + stack.is(ItemTags.PICKAXES) && EnchantmentHelper.getItemEnchantmentLevel(world.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(Enchantments.SILK_TOUCH), stack) > 0 ) popResource(world, pos, Items.BUDDING_AMETHYST.getDefaultInstance()); diff --git a/src/main/java/carpet/mixins/ChunkGenerator_customMobSpawnsMixin.java b/src/main/java/carpet/mixins/ChunkGenerator_customMobSpawnsMixin.java index 06868170..71f9b48d 100644 --- a/src/main/java/carpet/mixins/ChunkGenerator_customMobSpawnsMixin.java +++ b/src/main/java/carpet/mixins/ChunkGenerator_customMobSpawnsMixin.java @@ -3,6 +3,7 @@ package carpet.mixins; import carpet.utils.SpawnOverrides; import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.core.Holder; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.levelgen.structure.Structure; import org.spongepowered.asm.mixin.Mixin; @@ -11,7 +12,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.core.BlockPos; -import net.minecraft.util.random.WeightedRandomList; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.MobSpawnSettings; @@ -31,10 +31,10 @@ public abstract class ChunkGenerator_customMobSpawnsMixin target = "Ljava/util/Map$Entry;getKey()Ljava/lang/Object;" ), cancellable = true) private void checkCMSpawns(Holder holder, StructureManager structureFeatureManager, MobCategory mobCategory, BlockPos blockPos, - CallbackInfoReturnable> cir, + CallbackInfoReturnable> cir, Map map, Iterator var6, Map.Entry entry) { - WeightedRandomList res = SpawnOverrides.test(structureFeatureManager, entry.getValue(), mobCategory, entry.getKey(), blockPos); + WeightedList res = SpawnOverrides.test(structureFeatureManager, entry.getValue(), mobCategory, entry.getKey(), blockPos); if (res != null) { cir.setReturnValue(res); diff --git a/src/main/java/carpet/mixins/ChunkMap_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/ChunkMap_scarpetChunkCreationMixin.java index c19738a8..a66e8167 100644 --- a/src/main/java/carpet/mixins/ChunkMap_scarpetChunkCreationMixin.java +++ b/src/main/java/carpet/mixins/ChunkMap_scarpetChunkCreationMixin.java @@ -46,7 +46,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import carpet.fakes.ChunkHolderInterface; -import carpet.fakes.ChunkTicketManagerInterface; import carpet.fakes.ServerLightingProviderInterface; import carpet.fakes.ThreadedAnvilChunkStorageInterface; import carpet.script.utils.WorldTools; @@ -165,7 +164,6 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi this.world.getServer().execute(() -> CHUNK_LOADED.onChunkEvent(this.world, chpos, generated)); } } - */ @Unique private void addTicket(ChunkPos pos, ChunkStatus status) @@ -180,7 +178,6 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi } - /* @Unique private void addRelightTicket(ChunkPos pos) { @@ -195,7 +192,7 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi () -> "release relight ticket " + pos )); } - */ + @Unique private void tickTicketManager() { @@ -220,7 +217,7 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi } - /* + @Unique private Set loadExistingChunksFromDisk(Set requestedChunks) { diff --git a/src/main/java/carpet/mixins/CloneCommands_fillUpdatesMixin.java b/src/main/java/carpet/mixins/CloneCommands_fillUpdatesMixin.java index 7a172441..8e3db97c 100644 --- a/src/main/java/carpet/mixins/CloneCommands_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/CloneCommands_fillUpdatesMixin.java @@ -14,10 +14,10 @@ public abstract class CloneCommands_fillUpdatesMixin { @Redirect(method = "clone", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/server/level/ServerLevel;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" )) private static void conditionalUpdating(ServerLevel serverWorld, BlockPos blockPos_1, Block block_1) { - if (CarpetSettings.fillUpdates) serverWorld.blockUpdated(blockPos_1, block_1); + if (CarpetSettings.fillUpdates) serverWorld.updateNeighborsAt(blockPos_1, block_1); } } diff --git a/src/main/java/carpet/mixins/DistanceManager_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/DistanceManager_scarpetChunkCreationMixin.java deleted file mode 100644 index 694aed49..00000000 --- a/src/main/java/carpet/mixins/DistanceManager_scarpetChunkCreationMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package carpet.mixins; - -import java.util.Set; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.DistanceManager; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import carpet.fakes.ChunkTicketManagerInterface; - -@Mixin(DistanceManager.class) -public abstract class DistanceManager_scarpetChunkCreationMixin implements ChunkTicketManagerInterface -{ - @Shadow - @Final - private Set chunksToUpdateFutures; - - @Override - public void replaceHolder(final ChunkHolder oldHolder, final ChunkHolder newHolder) - { - this.chunksToUpdateFutures.remove(oldHolder); - this.chunksToUpdateFutures.add(newHolder); - } -} diff --git a/src/main/java/carpet/mixins/DistanceManager_scarpetMixin.java b/src/main/java/carpet/mixins/DistanceManager_scarpetMixin.java index 120f1f4a..8cd13ce5 100644 --- a/src/main/java/carpet/mixins/DistanceManager_scarpetMixin.java +++ b/src/main/java/carpet/mixins/DistanceManager_scarpetMixin.java @@ -1,23 +1,25 @@ package carpet.mixins; -import carpet.fakes.ChunkTicketManagerInterface; +import carpet.fakes.TicketsFetcherInterface; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.Ticket; -import net.minecraft.util.SortedArraySet; +import net.minecraft.world.level.TicketStorage; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import java.util.List; + @Mixin(DistanceManager.class) -public abstract class DistanceManager_scarpetMixin implements ChunkTicketManagerInterface +public abstract class DistanceManager_scarpetMixin implements TicketsFetcherInterface { - @Shadow @Final private Long2ObjectOpenHashMap>> tickets; + @Shadow @Final private TicketStorage ticketStorage; @Override - public Long2ObjectOpenHashMap>> getTicketsByPosition() + public Long2ObjectOpenHashMap> getTicketsByPosition() { - return tickets; + return ((TicketsFetcherInterface)ticketStorage).getTicketsByPosition(); } } diff --git a/src/main/java/carpet/mixins/DistanceManager_spawnChunksMixin.java b/src/main/java/carpet/mixins/DistanceManager_spawnChunksMixin.java deleted file mode 100644 index e4a24c65..00000000 --- a/src/main/java/carpet/mixins/DistanceManager_spawnChunksMixin.java +++ /dev/null @@ -1,55 +0,0 @@ -package carpet.mixins; - -import carpet.fakes.ChunkTicketManagerInterface; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import net.minecraft.server.level.DistanceManager; -import net.minecraft.server.level.Ticket; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.SortedArraySet; -import net.minecraft.util.Unit; -import net.minecraft.world.level.ChunkPos; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Iterator; - -@Mixin(DistanceManager.class) -public abstract class DistanceManager_spawnChunksMixin implements ChunkTicketManagerInterface -{ - @Shadow @Final private Long2ObjectOpenHashMap>> tickets; - - @Shadow protected abstract void removeTicket(long pos, Ticket ticket); - - @Shadow public abstract void addRegionTicket(TicketType type, ChunkPos pos, int radius, T argument); - - @Override - public void changeSpawnChunks(ChunkPos chunkPos, int distance) - { - long pos = chunkPos.toLong(); - SortedArraySet> set = tickets.get(pos); - Ticket existingTicket = null; - if (set != null) - { - Iterator> iter = set.iterator(); - while(iter.hasNext()) - { - Ticket ticket = iter.next(); - if (ticket.getType() == TicketType.START) - { - existingTicket = ticket; - iter.remove(); - } - } - set.add(existingTicket); - } - // the reason we are removing the ticket this way is that there are sideeffects of removal - if (existingTicket != null) - { - removeTicket(pos, existingTicket); - } - // set optionally new spawn ticket - if (distance > 0) - addRegionTicket(TicketType.START, chunkPos, distance, Unit.INSTANCE); - } -} diff --git a/src/main/java/carpet/mixins/EntityMixin.java b/src/main/java/carpet/mixins/EntityMixin.java index 6c2223ad..589f5111 100644 --- a/src/main/java/carpet/mixins/EntityMixin.java +++ b/src/main/java/carpet/mixins/EntityMixin.java @@ -32,7 +32,7 @@ public abstract class EntityMixin implements EntityInterface return partialTicks == 1.0F ? this.yRot : Mth.lerp(partialTicks, this.yRotO, this.yRot); } - @Inject(method = "isControlledByLocalInstance", at = @At("HEAD"), cancellable = true) + @Inject(method = "isLocalInstanceAuthoritative", at = @At("HEAD"), cancellable = true) private void isFakePlayer(CallbackInfoReturnable cir) { if (getControllingPassenger() instanceof EntityPlayerMPFake) cir.setReturnValue(!level.isClientSide); diff --git a/src/main/java/carpet/mixins/FillCommandMixin.java b/src/main/java/carpet/mixins/FillCommandMixin.java index 344f5ff3..6ab7079e 100644 --- a/src/main/java/carpet/mixins/FillCommandMixin.java +++ b/src/main/java/carpet/mixins/FillCommandMixin.java @@ -14,10 +14,10 @@ public abstract class FillCommandMixin { @Redirect(method = "fillBlocks", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/server/level/ServerLevel;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" )) private static void conditionalUpdating(ServerLevel serverWorld, BlockPos blockPos_1, Block block_1) { - if (CarpetSettings.fillUpdates) serverWorld.blockUpdated(blockPos_1, block_1); + if (CarpetSettings.fillUpdates) serverWorld.updateNeighborsAt(blockPos_1, block_1); } } diff --git a/src/main/java/carpet/mixins/Item_missingToolsMixin.java b/src/main/java/carpet/mixins/Item_missingToolsMixin.java new file mode 100644 index 00000000..90445ad7 --- /dev/null +++ b/src/main/java/carpet/mixins/Item_missingToolsMixin.java @@ -0,0 +1,30 @@ +package carpet.mixins; + +import carpet.CarpetSettings; +import net.minecraft.core.component.DataComponents; +import net.minecraft.tags.ItemTags; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.Tool; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Item.class) +public class Item_missingToolsMixin +{ + @Inject(method = "getDestroySpeed", at = @At("HEAD"), cancellable = true) + public void getDestroySpeed(ItemStack itemStack, BlockState blockState, CallbackInfoReturnable cir) { + if (CarpetSettings.missingTools && blockState.getSoundType() == SoundType.GLASS && itemStack.is(ItemTags.PICKAXES)) + { + Tool tool = itemStack.get(DataComponents.TOOL); + if (tool != null) { + cir.setReturnValue(tool.getMiningSpeed(Blocks.STONE.defaultBlockState())); + } + } + } +} diff --git a/src/main/java/carpet/mixins/LevelChunk_fillUpdatesMixin.java b/src/main/java/carpet/mixins/LevelChunk_fillUpdatesMixin.java index 52b345a8..d0eec071 100644 --- a/src/main/java/carpet/mixins/LevelChunk_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/LevelChunk_fillUpdatesMixin.java @@ -2,7 +2,9 @@ package carpet.mixins; import carpet.CarpetSettings; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import org.spongepowered.asm.mixin.Mixin; @@ -25,20 +27,25 @@ public class LevelChunk_fillUpdatesMixin @Redirect(method = "setBlockState", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;onRemove(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Z)V" + target = "Lnet/minecraft/world/level/block/entity/BlockEntity;preRemoveSideEffects(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Z)V" )) - private void onRemovedBlock(BlockState blockState, Level world, BlockPos pos, BlockState state, boolean moved) + private void onPreRemoveSideEffects(BlockEntity blockEntity, BlockPos blockPos_1, BlockState blockState_1, boolean boolean_1) { - if (CarpetSettings.impendingFillSkipUpdates.get()) // doing due dilligence from AbstractBlock onStateReplaced + if (!CarpetSettings.impendingFillSkipUpdates.get()) { - if (blockState.hasBlockEntity() && !blockState.is(state.getBlock())) - { - world.removeBlockEntity(pos); - } + blockEntity.preRemoveSideEffects(blockPos_1, blockState_1, boolean_1); } - else + } + + @Redirect(method = "setBlockState", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/state/BlockState;affectNeighborsAfterRemoval(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Z)V" + )) + private void onAffectNeighborsAfterRemoval(final BlockState instance, final ServerLevel serverLevel, final BlockPos blockPos, final boolean b) + { + if (!CarpetSettings.impendingFillSkipUpdates.get()) { - blockState.onRemove(world, pos, state, moved); + instance.affectNeighborsAfterRemoval(serverLevel, blockPos, b); } } } diff --git a/src/main/java/carpet/mixins/LevelChunk_movableBEMixin.java b/src/main/java/carpet/mixins/LevelChunk_movableBEMixin.java index 77a099a1..43a7d36f 100644 --- a/src/main/java/carpet/mixins/LevelChunk_movableBEMixin.java +++ b/src/main/java/carpet/mixins/LevelChunk_movableBEMixin.java @@ -4,6 +4,10 @@ import carpet.CarpetSettings; import carpet.fakes.WorldChunkInterface; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; +import net.minecraft.core.SectionPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelHeightAccessor; @@ -19,6 +23,7 @@ import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.blending.BlendingData; +import net.minecraft.world.level.lighting.LightEngine; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -74,90 +79,119 @@ public abstract class LevelChunk_movableBEMixin extends ChunkAccess implements W // todo update me to the new version @Override public BlockState setBlockStateWithBlockEntity(BlockPos blockPos_1, BlockState newBlockState, BlockEntity newBlockEntity, - boolean boolean_1) + int flags) { - int x = blockPos_1.getX() & 15; + boolean boolean_1 = (flags & 64) != 0; int y = blockPos_1.getY(); - int z = blockPos_1.getZ() & 15; + LevelChunkSection chunkSection = this.getSection(this.getSectionIndex(y)); - if (chunkSection.hasOnlyAir()) + + boolean hadOnlyAir = chunkSection.hasOnlyAir(); + + if (hadOnlyAir && newBlockState.isAir()) { - if (newBlockState.isAir()) - { - return null; - } + return null; } - - boolean boolean_2 = chunkSection.hasOnlyAir(); - BlockState oldBlockState = chunkSection.setBlockState(x, y & 15, z, newBlockState); + + int x = blockPos_1.getX() & 15; + int chunkY = blockPos_1.getY() & 15; + int z = blockPos_1.getZ() & 15; + BlockState oldBlockState = chunkSection.setBlockState(x, chunkY, z, newBlockState); if (oldBlockState == newBlockState) { return null; } - else + Block newBlock = newBlockState.getBlock(); + this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(x, y, z, newBlockState); + this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(x, y, z, newBlockState); + this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(x, y, z, newBlockState); + this.heightmaps.get(Heightmap.Types.WORLD_SURFACE).update(x, y, z, newBlockState); + boolean hasOnlyAir = chunkSection.hasOnlyAir(); + if (hadOnlyAir != hasOnlyAir) { - Block newBlock = newBlockState.getBlock(); - Block oldBlock = oldBlockState.getBlock(); - ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING)).update(x, y, z, newBlockState); - ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES)).update(x, y, z, newBlockState); - ((Heightmap) this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR)).update(x, y, z, newBlockState); - ((Heightmap) this.heightmaps.get(Heightmap.Types.WORLD_SURFACE)).update(x, y, z, newBlockState); - boolean boolean_3 = chunkSection.hasOnlyAir(); - if (boolean_2 != boolean_3) - { - this.level.getChunkSource().getLightEngine().updateSectionStatus(blockPos_1, boolean_3); + this.level.getChunkSource().getLightEngine().updateSectionStatus(blockPos_1, hasOnlyAir); + this.level.getChunkSource().onSectionEmptinessChanged(chunkPos.x, SectionPos.blockToSectionCoord(y), chunkPos.z, hasOnlyAir); + } + + if (LightEngine.hasDifferentLightProperties(oldBlockState, newBlockState)) { + ProfilerFiller profiler = Profiler.get(); + profiler.push("updateSkyLightSources"); + skyLightSources.update(this, x, chunkY, z); + profiler.popPush("queueCheckLight"); + level.getChunkSource().getLightEngine().checkBlock(blockPos_1); + profiler.pop(); + } + + boolean hadBlockEntity = oldBlockState.hasBlockEntity(); + boolean blockChanged = !oldBlockState.is(newBlock); + + boolean sideEffects = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0; + + if (blockChanged) { + if (level instanceof ServerLevel serverLevel && !(oldBlockState.getBlock() instanceof MovingPistonBlock)) { + if (hadBlockEntity && sideEffects) { + final BlockEntity blockEntity = level.getBlockEntity(blockPos_1); + if (blockEntity != null) { + blockEntity.preRemoveSideEffects(blockPos_1, oldBlockState, boolean_1); + } + } + + if (hadBlockEntity) { + removeBlockEntity(blockPos_1); + } + if ((flags & Block.UPDATE_NEIGHBORS) != 0) { // scary change // so many other places that used to call this regardless if the UPDATE_NEIGHBORS flag was set + oldBlockState.affectNeighborsAfterRemoval(serverLevel, blockPos_1, boolean_1); + } + } else if (hadBlockEntity) { + removeBlockEntity(blockPos_1); } - - if (!this.level.isClientSide) + } + + + + + + + if (chunkSection.getBlockState(x, chunkY, z).getBlock() != newBlock) + { + return null; + } + + if (!level.isClientSide && sideEffects) { + // this updates stuff, schedule ticks - do we want that since its only be called from MovingPistonBlock really? + newBlockState.onPlace(level, blockPos_1, oldBlockState, boolean_1); + } + + BlockEntity oldBlockEntity = null; + if (oldBlockState.hasBlockEntity()) + { + oldBlockEntity = this.getBlockEntity(blockPos_1, LevelChunk.EntityCreationType.CHECK); + if (oldBlockEntity != null && !oldBlockEntity.isValidBlockState(oldBlockState)) { - if (!(oldBlock instanceof MovingPistonBlock))//this is a movableTE special case, if condition wasn't there it would remove the blockentity that was carried for some reason - oldBlockState.onRemove(this.level, blockPos_1, newBlockState, boolean_1);//this kills it - } - else if (oldBlock != newBlock && oldBlock instanceof EntityBlock) - { - this.level.removeBlockEntity(blockPos_1); - } - - if (chunkSection.getBlockState(x, y & 15, z).getBlock() != newBlock) - { - return null; + oldBlockEntity.setBlockState(oldBlockState); + updateBlockEntityTicker(oldBlockEntity); } else { - BlockEntity oldBlockEntity = null; - if (oldBlockState.hasBlockEntity()) + if (newBlockEntity == null) { - oldBlockEntity = this.getBlockEntity(blockPos_1, LevelChunk.EntityCreationType.CHECK); - if (oldBlockEntity != null) + newBlockEntity = ((EntityBlock) newBlock).newBlockEntity(blockPos_1, newBlockState); + if (newBlockEntity != null) { - oldBlockEntity.setBlockState(oldBlockState); - updateBlockEntityTicker(oldBlockEntity); + addAndRegisterBlockEntity(newBlockEntity); } } - - if (oldBlockState.hasBlockEntity()) + if (newBlockEntity != oldBlockEntity && newBlockEntity != null) { - if (newBlockEntity == null) - { - newBlockEntity = ((EntityBlock) newBlock).newBlockEntity(blockPos_1, newBlockState); - } - if (newBlockEntity != oldBlockEntity && newBlockEntity != null) - { - newBlockEntity.clearRemoved(); - this.level.setBlockEntity(newBlockEntity); - newBlockEntity.setBlockState(newBlockState); - updateBlockEntityTicker(newBlockEntity); - } + newBlockEntity.clearRemoved(); + this.level.setBlockEntity(newBlockEntity); + newBlockEntity.setBlockState(newBlockState); + updateBlockEntityTicker(newBlockEntity); } - - if (!this.level.isClientSide) - { - newBlockState.onPlace(this.level, blockPos_1, oldBlockState, boolean_1); //This can call setblockstate! (e.g. hopper does) - } - - markUnsaved(); - return oldBlockState; } } + + markUnsaved(); + return oldBlockState; } } diff --git a/src/main/java/carpet/mixins/Level_fillUpdatesMixin.java b/src/main/java/carpet/mixins/Level_fillUpdatesMixin.java index cb050c7a..0b141729 100644 --- a/src/main/java/carpet/mixins/Level_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/Level_fillUpdatesMixin.java @@ -23,11 +23,11 @@ public abstract class Level_fillUpdatesMixin @Redirect(method = "setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;II)Z", at = @At( //setBlockState main value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/world/level/Level;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" )) private void updateNeighborsMaybe(Level world, BlockPos blockPos, Block block) { - if (!CarpetSettings.impendingFillSkipUpdates.get()) world.blockUpdated(blockPos, block); + if (!CarpetSettings.impendingFillSkipUpdates.get()) world.updateNeighborsAt(blockPos, block); } } diff --git a/src/main/java/carpet/mixins/Level_movableBEMixin.java b/src/main/java/carpet/mixins/Level_movableBEMixin.java index 0f98fde7..d774f158 100644 --- a/src/main/java/carpet/mixins/Level_movableBEMixin.java +++ b/src/main/java/carpet/mixins/Level_movableBEMixin.java @@ -33,17 +33,13 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces @Shadow public abstract void sendBlockUpdated(BlockPos var1, BlockState var2, BlockState var3, int var4); - - @Shadow - public abstract void updateNeighborsAt(BlockPos blockPos_1, Block block_1); - - @Shadow - public abstract void onBlockStateChange(BlockPos blockPos_1, BlockState blockState_1, BlockState blockState_2); @Shadow public abstract void updateNeighbourForOutputSignal(BlockPos pos, Block block); @Shadow public abstract boolean isDebug(); + @Shadow public abstract void updatePOIOnBlockStateChange(final BlockPos blockPos, final BlockState blockState, final BlockState blockState2); + /** * @author 2No2Name */ @@ -57,7 +53,7 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces BlockState blockState_2; if (newBlockEntity != null && block_1 instanceof EntityBlock) { - blockState_2 = ((WorldChunkInterface) worldChunk_1).setBlockStateWithBlockEntity(blockPos_1, blockState_1, newBlockEntity, (int_1 & 64) != 0); + blockState_2 = ((WorldChunkInterface) worldChunk_1).setBlockStateWithBlockEntity(blockPos_1, blockState_1, newBlockEntity, int_1); if (newBlockEntity instanceof LidBlockEntity) { scheduleTick(blockPos_1, block_1, 5); @@ -65,56 +61,46 @@ public abstract class Level_movableBEMixin implements LevelInterface, LevelAcces } else { - blockState_2 = worldChunk_1.setBlockState(blockPos_1, blockState_1, (int_1 & 64) != 0); + blockState_2 = worldChunk_1.setBlockState(blockPos_1, blockState_1, int_1); } if (blockState_2 == null) { return false; } - else + + BlockState blockState_3 = this.getBlockState(blockPos_1); + + if (blockState_3 == blockState_1) { - BlockState blockState_3 = this.getBlockState(blockPos_1); - - if (blockState_3 != blockState_2 && (blockState_3.getLightBlock() != blockState_2.getLightBlock() || blockState_3.getLightEmission() != blockState_2.getLightEmission() || blockState_3.useShapeForLightOcclusion() || blockState_2.useShapeForLightOcclusion())) + if (blockState_2 != blockState_3) { - ProfilerFiller profiler = Profiler.get(); - profiler.push("queueCheckLight"); - this.getChunkSource().getLightEngine().checkBlock(blockPos_1); - profiler.pop(); + this.setBlocksDirty(blockPos_1, blockState_2, blockState_3); } - if (blockState_3 == blockState_1) + if ((int_1 & 2) != 0 && (!this.isClientSide || (int_1 & 4) == 0) && (this.isClientSide || worldChunk_1.getFullStatus() != null && worldChunk_1.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) { - if (blockState_2 != blockState_3) - { - this.setBlocksDirty(blockPos_1, blockState_2, blockState_3); - } - - if ((int_1 & 2) != 0 && (!this.isClientSide || (int_1 & 4) == 0) && (this.isClientSide || worldChunk_1.getFullStatus() != null && worldChunk_1.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) - { - this.sendBlockUpdated(blockPos_1, blockState_2, blockState_1, int_1); - } - - if (!this.isClientSide && (int_1 & 1) != 0) - { - this.updateNeighborsAt(blockPos_1, blockState_2.getBlock()); - if (blockState_1.hasAnalogOutputSignal()) - { - updateNeighbourForOutputSignal(blockPos_1, block_1); - } - } - - if ((int_1 & 16) == 0) - { - int int_2 = int_1 & -34; - blockState_2.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare - blockState_1.updateNeighbourShapes(this, blockPos_1, int_2); // updateNeighbours - blockState_1.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare - } - this.onBlockStateChange(blockPos_1, blockState_2, blockState_3); + this.sendBlockUpdated(blockPos_1, blockState_2, blockState_1, int_1); } - return true; + + if (!this.isClientSide && (int_1 & 1) != 0) + { + this.updateNeighborsAt(blockPos_1, blockState_2.getBlock()); + if (blockState_1.hasAnalogOutputSignal()) + { + updateNeighbourForOutputSignal(blockPos_1, block_1); + } + } + + if ((int_1 & 16) == 0) + { + int int_2 = int_1 & -34; + blockState_2.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare + blockState_1.updateNeighbourShapes(this, blockPos_1, int_2); // updateNeighbours + blockState_1.updateIndirectNeighbourShapes(this, blockPos_1, int_2); // prepare + } + updatePOIOnBlockStateChange(blockPos_1, blockState_2, blockState_3); } + return true; } } diff --git a/src/main/java/carpet/mixins/PickaxeItem_missingToolsMixin.java b/src/main/java/carpet/mixins/PickaxeItem_missingToolsMixin.java deleted file mode 100644 index 201c34df..00000000 --- a/src/main/java/carpet/mixins/PickaxeItem_missingToolsMixin.java +++ /dev/null @@ -1,36 +0,0 @@ -package carpet.mixins; - -import carpet.CarpetSettings; -import net.minecraft.core.component.DataComponents; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.DiggerItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.PickaxeItem; -import net.minecraft.world.item.ToolMaterial; -import net.minecraft.world.item.component.Tool; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(PickaxeItem.class) -public class PickaxeItem_missingToolsMixin extends DiggerItem -{ - - - protected PickaxeItem_missingToolsMixin(final ToolMaterial toolMaterial, final TagKey tagKey, final float f, final float g, final Properties properties) - { - super(toolMaterial, tagKey, f, g, properties); - } - - @Override - public float getDestroySpeed(ItemStack stack, BlockState state) { - if (CarpetSettings.missingTools && state.getSoundType() == SoundType.GLASS) - { - final Tool tool = stack.get(DataComponents.TOOL); - return tool != null ? tool.getMiningSpeed(Blocks.STONE.defaultBlockState()) : super.getDestroySpeed(stack, state); - } - return super.getDestroySpeed(stack, state); - } -} diff --git a/src/main/java/carpet/mixins/RedstoneWireBlock_fastMixin.java b/src/main/java/carpet/mixins/RedstoneWireBlock_fastMixin.java index ec5caaf7..5cdceb9a 100644 --- a/src/main/java/carpet/mixins/RedstoneWireBlock_fastMixin.java +++ b/src/main/java/carpet/mixins/RedstoneWireBlock_fastMixin.java @@ -119,7 +119,7 @@ public abstract class RedstoneWireBlock_fastMixin implements RedstoneWireBlockIn fastUpdate(world_1, blockPos_1, blockState_1, o, sup); } - @Redirect(method = "onRemove", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/redstone/Orientation;Z)V")) + @Redirect(method = "affectNeighborsAfterRemoval", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/redstone/Orientation;Z)V")) private void redirectOnStateReplacedUpdate(RedStoneWireBlock self, Level world_1, BlockPos blockPos_1, BlockState blockState_1, Orientation o, boolean sup) { fastUpdate(world_1, blockPos_1, blockState_1, o, sup); } diff --git a/src/main/java/carpet/mixins/SetBlockCommand_fillUpdatesMixin.java b/src/main/java/carpet/mixins/SetBlockCommand_fillUpdatesMixin.java index 95df92ef..20c3998a 100644 --- a/src/main/java/carpet/mixins/SetBlockCommand_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/SetBlockCommand_fillUpdatesMixin.java @@ -14,10 +14,10 @@ public class SetBlockCommand_fillUpdatesMixin { @Redirect(method = "setBlock", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/server/level/ServerLevel;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" )) private static void conditionalUpdating(ServerLevel serverWorld, BlockPos blockPos_1, Block block_1) { - if (CarpetSettings.fillUpdates) serverWorld.blockUpdated(blockPos_1, block_1); + if (CarpetSettings.fillUpdates) serverWorld.updateNeighborsAt(blockPos_1, block_1); } } diff --git a/src/main/java/carpet/mixins/StructureTemplate_fillUpdatesMixin.java b/src/main/java/carpet/mixins/StructureTemplate_fillUpdatesMixin.java index bd9cbb44..8d2938b7 100644 --- a/src/main/java/carpet/mixins/StructureTemplate_fillUpdatesMixin.java +++ b/src/main/java/carpet/mixins/StructureTemplate_fillUpdatesMixin.java @@ -15,12 +15,12 @@ public class StructureTemplate_fillUpdatesMixin { @Redirect( method = "placeInWorld", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/ServerLevelAccessor;blockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" + target = "Lnet/minecraft/world/level/ServerLevelAccessor;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V" )) private void skipUpdateNeighbours(ServerLevelAccessor serverWorldAccess, BlockPos pos, Block block) { if (!CarpetSettings.impendingFillSkipUpdates.get()) - serverWorldAccess.blockUpdated(pos, block); + serverWorldAccess.updateNeighborsAt(pos, block); } @Redirect(method = "placeInWorld", at = @At( diff --git a/src/main/java/carpet/mixins/TicketStorage_scarpetMixin.java b/src/main/java/carpet/mixins/TicketStorage_scarpetMixin.java new file mode 100644 index 00000000..08cd3d0d --- /dev/null +++ b/src/main/java/carpet/mixins/TicketStorage_scarpetMixin.java @@ -0,0 +1,23 @@ +package carpet.mixins; + +import carpet.fakes.TicketsFetcherInterface; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.server.level.Ticket; +import net.minecraft.world.level.TicketStorage; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; + +@Mixin(TicketStorage.class) +public class TicketStorage_scarpetMixin implements TicketsFetcherInterface +{ + @Shadow @Final private Long2ObjectOpenHashMap> tickets; + + @Override + public Long2ObjectOpenHashMap> getTicketsByPosition() + { + return tickets; + } +} diff --git a/src/main/java/carpet/script/ScriptCommand.java b/src/main/java/carpet/script/ScriptCommand.java index e8bc716a..d551f5bd 100644 --- a/src/main/java/carpet/script/ScriptCommand.java +++ b/src/main/java/carpet/script/ScriptCommand.java @@ -675,10 +675,7 @@ public class ScriptCommand if (replacement == null || replacement.test( new BlockInWorld(world, mbpos, true))) { - BlockEntity tileentity = world.getBlockEntity(mbpos); - Clearable.tryClear(tileentity); - - if (block.place(world, mbpos, 2)) + if (block.place(world, mbpos, 2 & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS)) { ++affected; } @@ -701,7 +698,7 @@ public class ScriptCommand { mbpos.set(x + area.minX(), y + area.minY(), z + area.minZ()); Block blokc = world.getBlockState(mbpos).getBlock(); - world.blockUpdated(mbpos, blokc); + world.updateNeighborsAt(mbpos, blokc); } } } diff --git a/src/main/java/carpet/script/api/WorldAccess.java b/src/main/java/carpet/script/api/WorldAccess.java index 4144d325..5f173ee4 100644 --- a/src/main/java/carpet/script/api/WorldAccess.java +++ b/src/main/java/carpet/script/api/WorldAccess.java @@ -50,6 +50,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.Ticket; import net.minecraft.server.level.TicketType; import net.minecraft.sounds.SoundEvents; +import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; import net.minecraft.world.level.ServerExplosion; import net.minecraft.world.level.chunk.ChunkGenerator; @@ -99,12 +100,10 @@ import net.minecraft.world.entity.ai.village.poi.PoiRecord; import net.minecraft.world.entity.ai.village.poi.PoiType; import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.DiggerItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.ShearsItem; -import net.minecraft.world.item.SwordItem; import net.minecraft.world.item.TridentItem; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; @@ -149,7 +148,7 @@ public class WorldAccess DIRECTION_MAP.put("x", Direction.EAST); } - private static final Map> ticketTypes = Map.of( + private static final Map ticketTypes = Map.of( "portal", TicketType.PORTAL, "teleport", TicketType.ENDER_PEARL, "unknown", TicketType.UNKNOWN @@ -646,7 +645,7 @@ public class WorldAccess { ServerLevel world = ((CarpetContext) c).level(); DistanceManager foo = world.getChunkSource().chunkMap.getDistanceManager(); - Long2ObjectOpenHashMap>> levelTickets = Vanilla.ChunkTicketManager_getTicketsByPosition(foo); + Long2ObjectOpenHashMap> levelTickets = Vanilla.ChunkTicketManager_getTicketsByPosition(foo); List res = new ArrayList<>(); if (lv.isEmpty()) @@ -654,7 +653,7 @@ public class WorldAccess for (long key : levelTickets.keySet()) { ChunkPos chpos = new ChunkPos(key); - for (Ticket ticket : levelTickets.get(key)) + for (Ticket ticket : levelTickets.get(key)) { res.add(ListValue.of( new StringValue(ticket.getType().toString()), @@ -669,10 +668,10 @@ public class WorldAccess { BlockArgument blockArgument = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockPos pos = blockArgument.block.getPos(); - SortedArraySet> tickets = levelTickets.get(new ChunkPos(pos).toLong()); + List tickets = levelTickets.get(new ChunkPos(pos).toLong()); if (tickets != null) { - for (Ticket ticket : tickets) + for (Ticket ticket : tickets) { res.add(ListValue.of( new StringValue(ticket.getType().toString()), @@ -819,8 +818,7 @@ public class WorldAccess Boolean[] result = new Boolean[]{true}; cc.server().executeBlocking(() -> { - Clearable.tryClear(world.getBlockEntity(targetPos)); - boolean success = world.setBlock(targetPos, finalSourceBlockState, 2); + boolean success = world.setBlock(targetPos, finalSourceBlockState, Block.UPDATE_CLIENTS | Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS ); if (finalData != null) { BlockEntity be = world.getBlockEntity(targetPos); @@ -914,11 +912,11 @@ public class WorldAccess //postMine() durability from item classes float hardness = state.getDestroySpeed(world, where); int damageAmount = 0; - if ((item instanceof DiggerItem && hardness > 0.0) || item instanceof ShearsItem) + if ((tool.is(ItemTags.PICKAXES) && hardness > 0.0) || item instanceof ShearsItem) { damageAmount = 1; } - else if (item instanceof TridentItem || item instanceof SwordItem) + else if (item instanceof TridentItem || tool.is(ItemTags.SWORDS)) { damageAmount = 2; } @@ -1678,7 +1676,7 @@ public class WorldAccess throw new InternalExpressionException("'add_chunk_ticket' requires block position, ticket type and radius"); } String type = lv.get(locator.offset).getString(); - TicketType ticket = ticketTypes.get(type.toLowerCase(Locale.ROOT)); + TicketType ticket = ticketTypes.get(type.toLowerCase(Locale.ROOT)); if (ticket == null) { throw new InternalExpressionException("Unknown ticket type: " + type); @@ -1692,15 +1690,15 @@ public class WorldAccess ChunkPos target = new ChunkPos(pos); if (ticket == TicketType.PORTAL) // portal { - cc.level().getChunkSource().addRegionTicket(TicketType.PORTAL, target, radius, pos); + cc.level().getChunkSource().addTicketWithRadius(TicketType.PORTAL, target, radius); } else if (ticket == TicketType.ENDER_PEARL) // post teleport { - cc.level().getChunkSource().addRegionTicket(TicketType.ENDER_PEARL, target, radius, target); + cc.level().getChunkSource().addTicketWithRadius(TicketType.ENDER_PEARL, target, radius); } else { - cc.level().getChunkSource().addRegionTicket(TicketType.UNKNOWN, target, radius, target); + cc.level().getChunkSource().addTicketWithRadius(TicketType.UNKNOWN, target, radius); } return new NumericValue(ticket.timeout()); }); diff --git a/src/main/java/carpet/script/external/Vanilla.java b/src/main/java/carpet/script/external/Vanilla.java index 96ec1a26..fc5b338b 100644 --- a/src/main/java/carpet/script/external/Vanilla.java +++ b/src/main/java/carpet/script/external/Vanilla.java @@ -4,7 +4,7 @@ import carpet.CarpetSettings; import carpet.fakes.BiomeInterface; import carpet.fakes.BlockPredicateInterface; import carpet.fakes.BlockStateArgumentInterface; -import carpet.fakes.ChunkTicketManagerInterface; +import carpet.fakes.TicketsFetcherInterface; import carpet.fakes.CommandDispatcherInterface; import carpet.fakes.EntityInterface; import carpet.fakes.InventoryBearerInterface; @@ -122,9 +122,9 @@ public class Vanilla return ((ServerWorldInterface) world).getWorldPropertiesCM(); } - public static Long2ObjectOpenHashMap>> ChunkTicketManager_getTicketsByPosition(DistanceManager ticketManager) + public static Long2ObjectOpenHashMap> ChunkTicketManager_getTicketsByPosition(DistanceManager ticketManager) { - return ((ChunkTicketManagerInterface) ticketManager).getTicketsByPosition(); + return ((TicketsFetcherInterface) ticketManager).getTicketsByPosition(); } public static DensityFunction.Visitor RandomState_getVisitor(RandomState randomState) diff --git a/src/main/java/carpet/script/utils/EntityTools.java b/src/main/java/carpet/script/utils/EntityTools.java index 5849e50a..0b7e1cb6 100644 --- a/src/main/java/carpet/script/utils/EntityTools.java +++ b/src/main/java/carpet/script/utils/EntityTools.java @@ -12,7 +12,7 @@ public class EntityTools */ public static void genericJump(Entity e) { - if (!e.onGround() && !e.isInWaterOrBubble() && !e.isInLava()) + if (!e.onGround() && !e.isInLiquid()) { return; } diff --git a/src/main/java/carpet/utils/Messenger.java b/src/main/java/carpet/utils/Messenger.java index fc7695fc..18dabb68 100644 --- a/src/main/java/carpet/utils/Messenger.java +++ b/src/main/java/carpet/utils/Messenger.java @@ -17,6 +17,7 @@ import net.minecraft.world.phys.Vec3; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -147,11 +148,11 @@ public class Messenger Style previousStyle = previousMessage.getStyle(); MutableComponent ret = previousMessage; previousMessage.setStyle(switch (desc.charAt(0)) { - case '?' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, message.substring(1))); - case '!' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, message.substring(1))); - case '^' -> previousStyle.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, c(message.substring(1)))); - case '@' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, message.substring(1))); - case '&' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, message.substring(1))); + case '?' -> previousStyle.withClickEvent(new ClickEvent.SuggestCommand(message.substring(1))); + case '!' -> previousStyle.withClickEvent(new ClickEvent.RunCommand(message.substring(1))); + case '^' -> previousStyle.withHoverEvent(new HoverEvent.ShowText(c(message.substring(1)))); + case '@' -> previousStyle.withClickEvent(new ClickEvent.OpenUrl(URI.create(message.substring(1)))); + case '&' -> previousStyle.withClickEvent(new ClickEvent.CopyToClipboard(message.substring(1))); default -> { // Create a new component ret = Component.literal(str); ret.setStyle(parseStyle(desc)); diff --git a/src/main/java/carpet/utils/PerimeterDiagnostics.java b/src/main/java/carpet/utils/PerimeterDiagnostics.java index 4c3d754d..416fd702 100644 --- a/src/main/java/carpet/utils/PerimeterDiagnostics.java +++ b/src/main/java/carpet/utils/PerimeterDiagnostics.java @@ -5,6 +5,7 @@ import java.util.List; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.FluidTags; +import net.minecraft.util.random.Weighted; import net.minecraft.world.entity.AgeableMob; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; @@ -162,9 +163,10 @@ public class PerimeterDiagnostics if (sle == null || !worldServer.getChunkSource().getGenerator().getMobsAt(worldServer.getBiome(pos), worldServer.structureManager(), ctype, pos).unwrap().contains(sle)) { sle = null; - for (MobSpawnSettings.SpawnerData sle: worldServer.getChunkSource().getGenerator().getMobsAt(worldServer.getBiome(pos), worldServer.structureManager(), ctype, pos).unwrap()) + for (Weighted wsle: worldServer.getChunkSource().getGenerator().getMobsAt(worldServer.getBiome(pos), worldServer.structureManager(), ctype, pos).unwrap()) { - if (el.getType() == sle.type) + MobSpawnSettings.SpawnerData sle = wsle.value(); + if (el.getType() == sle.type()) { this.sle = sle; break; @@ -176,7 +178,7 @@ public class PerimeterDiagnostics } } - if (SpawnPlacements.isSpawnPositionOk(sle.type, worldServer, pos)) + if (SpawnPlacements.isSpawnPositionOk(sle.type(), worldServer, pos)) { el.moveTo(pos.getX() + 0.5F, pos.getY(), pos.getZ()+0.5F, 0.0F, 0.0F); return el.checkSpawnObstruction(worldServer) && el.checkSpawnRules(worldServer, EntitySpawnReason.NATURAL) && diff --git a/src/main/java/carpet/utils/SpawnOverrides.java b/src/main/java/carpet/utils/SpawnOverrides.java index f12d783d..d4c05f40 100644 --- a/src/main/java/carpet/utils/SpawnOverrides.java +++ b/src/main/java/carpet/utils/SpawnOverrides.java @@ -8,7 +8,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.random.WeightedRandomList; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.StructureManager; @@ -32,28 +32,28 @@ public class SpawnOverrides { static { addOverride(() -> CarpetSettings.huskSpawningInTemples, MobCategory.MONSTER, BuiltinStructures.DESERT_PYRAMID, StructureSpawnOverride.BoundingBoxType.STRUCTURE, - WeightedRandomList.create(new MobSpawnSettings.SpawnerData(EntityType.HUSK, 1, 1, 1)) + WeightedList.of(new MobSpawnSettings.SpawnerData(EntityType.HUSK, 1, 1)) ); addOverride(() -> CarpetSettings.shulkerSpawningInEndCities, MobCategory.MONSTER, BuiltinStructures.END_CITY, StructureSpawnOverride.BoundingBoxType.PIECE, - WeightedRandomList.create(new MobSpawnSettings.SpawnerData(EntityType.SHULKER, 10, 4, 4)) + WeightedList.of(new MobSpawnSettings.SpawnerData(EntityType.SHULKER, 4, 4)) ); addOverride(() -> CarpetSettings.piglinsSpawningInBastions, MobCategory.MONSTER, BuiltinStructures.BASTION_REMNANT, StructureSpawnOverride.BoundingBoxType.PIECE, - WeightedRandomList.create( - new MobSpawnSettings.SpawnerData(EntityType.PIGLIN_BRUTE, 5, 1, 2), - new MobSpawnSettings.SpawnerData(EntityType.PIGLIN, 10, 2, 4), - new MobSpawnSettings.SpawnerData(EntityType.HOGLIN, 2, 1, 2) - ) + WeightedList.builder() + .add(new MobSpawnSettings.SpawnerData(EntityType.PIGLIN_BRUTE,1, 2), 5) + .add(new MobSpawnSettings.SpawnerData(EntityType.PIGLIN, 2, 4), 10) + .add(new MobSpawnSettings.SpawnerData(EntityType.HOGLIN, 1, 2), 2) + .build() ); } public static void addOverride(BooleanSupplier when, MobCategory cat, ResourceKey poo, - StructureSpawnOverride.BoundingBoxType type, WeightedRandomList spawns) { + StructureSpawnOverride.BoundingBoxType type, WeightedList spawns) { carpetOverrides.put(Pair.of(cat, poo), Pair.of(when, new StructureSpawnOverride(type, spawns))); } - public static WeightedRandomList test(StructureManager structureFeatureManager, LongSet foo, - MobCategory cat, Structure confExisting, BlockPos where) { + public static WeightedList test(StructureManager structureFeatureManager, LongSet foo, + MobCategory cat, Structure confExisting, BlockPos where) { ResourceLocation resource = structureFeatureManager.registryAccess().lookupOrThrow(Registries.STRUCTURE).getKey(confExisting); ResourceKey key = ResourceKey.create(Registries.STRUCTURE, resource); final Pair spawnData = carpetOverrides.get(Pair.of(cat, key)); diff --git a/src/main/java/carpet/utils/SpawnReporter.java b/src/main/java/carpet/utils/SpawnReporter.java index 106786b3..0b21446e 100644 --- a/src/main/java/carpet/utils/SpawnReporter.java +++ b/src/main/java/carpet/utils/SpawnReporter.java @@ -12,6 +12,8 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.BlockTags; import net.minecraft.util.Mth; +import net.minecraft.util.random.Weighted; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; @@ -389,8 +391,8 @@ public class SpawnReporter } // yeeted from NaturalSpawner - temporary access fix - private static List getSpawnEntries(ServerLevel serverLevel, StructureManager structureManager, ChunkGenerator chunkGenerator, MobCategory mobCategory, BlockPos blockPos, @Nullable Holder holder) { - return NaturalSpawner.isInNetherFortressBounds(blockPos, serverLevel, mobCategory, structureManager) ? NetherFortressStructure.FORTRESS_ENEMIES.unwrap() : chunkGenerator.getMobsAt(holder != null ? holder : serverLevel.getBiome(blockPos), structureManager, mobCategory, blockPos).unwrap(); + private static WeightedList getSpawnEntries(ServerLevel serverLevel, StructureManager structureManager, ChunkGenerator chunkGenerator, MobCategory mobCategory, BlockPos blockPos, @Nullable Holder holder) { + return NaturalSpawner.isInNetherFortressBounds(blockPos, serverLevel, mobCategory, structureManager) ? NetherFortressStructure.FORTRESS_ENEMIES : chunkGenerator.getMobsAt(holder != null ? holder : serverLevel.getBiome(blockPos), structureManager, mobCategory, blockPos); } public static List report(BlockPos pos, ServerLevel worldIn) @@ -407,21 +409,22 @@ public class SpawnReporter for (MobCategory category : cachedMobCategories()) { String categoryCode = String.valueOf(category).substring(0, 3); - List lst = getSpawnEntries(worldIn, worldIn.structureManager(), worldIn.getChunkSource().getGenerator(), category, pos, worldIn.getBiome(pos)); + WeightedList lst = getSpawnEntries(worldIn, worldIn.structureManager(), worldIn.getChunkSource().getGenerator(), category, pos, worldIn.getBiome(pos)); if (lst != null && !lst.isEmpty()) { - for (MobSpawnSettings.SpawnerData spawnEntry : lst) + for (Weighted wspawnEntry : lst.unwrap()) { - if (SpawnPlacements.getPlacementType(spawnEntry.type) == null) + MobSpawnSettings.SpawnerData spawnEntry = wspawnEntry.value(); + if (SpawnPlacements.getPlacementType(spawnEntry.type()) == null) continue; // vanilla bug - boolean canSpawn = SpawnPlacements.isSpawnPositionOk(spawnEntry.type, worldIn, pos); + boolean canSpawn = SpawnPlacements.isSpawnPositionOk(spawnEntry.type(), worldIn, pos); int willSpawn = -1; boolean fits = false; Mob mob; try { - mob = (Mob) spawnEntry.type.create(worldIn, EntitySpawnReason.NATURAL); + mob = (Mob) spawnEntry.type().create(worldIn, EntitySpawnReason.NATURAL); } catch (Exception e) { @@ -467,7 +470,7 @@ public class SpawnReporter try { - mob = (Mob) spawnEntry.type.create(worldIn, EntitySpawnReason.NATURAL); + mob = (Mob) spawnEntry.type().create(worldIn, EntitySpawnReason.NATURAL); } catch (Exception e) { @@ -479,12 +482,12 @@ public class SpawnReporter String mobTypeName = mob.getType().getDescription().getString(); //String pack_size = Integer.toString(mob.getMaxSpawnClusterSize());//String.format("%d-%d", animal.minGroupCount, animal.maxGroupCount); - int weight = spawnEntry.getWeight().asInt(); + int weight = wspawnEntry.weight(); if (canSpawn) { String color = (fits && willSpawn > 0) ? "e" : "gi"; rep.add(Messenger.c( - String.format("%s %s: %s (%d:%d-%d/%d), can: ", color, categoryCode, mobTypeName, weight, spawnEntry.minCount, spawnEntry.maxCount, mob.getMaxSpawnClusterSize()), + String.format("%s %s: %s (%d:%d-%d/%d), can: ", color, categoryCode, mobTypeName, weight, spawnEntry.minCount(), spawnEntry.maxCount(), mob.getMaxSpawnClusterSize()), "l YES", color + " , fit: ", (fits ? "l YES" : "r NO"), @@ -494,7 +497,7 @@ public class SpawnReporter } else { - rep.add(Messenger.c(String.format("gi %s: %s (%d:%d-%d/%d), can: ", categoryCode, mobTypeName, weight, spawnEntry.minCount, spawnEntry.maxCount, mob.getMaxSpawnClusterSize()), "n NO")); + rep.add(Messenger.c(String.format("gi %s: %s (%d:%d-%d/%d), can: ", categoryCode, mobTypeName, weight, spawnEntry.minCount(), spawnEntry.maxCount(), mob.getMaxSpawnClusterSize()), "n NO")); } killEntity(mob); } diff --git a/src/main/resources/carpet.accesswidener b/src/main/resources/carpet.accesswidener index de24c461..fda730bd 100644 --- a/src/main/resources/carpet.accesswidener +++ b/src/main/resources/carpet.accesswidener @@ -13,7 +13,6 @@ accessible class net/minecraft/world/level/block/entity/SculkSensorBlockEntity$V accessible method net/minecraft/world/level/border/WorldBorder getListeners ()Ljava/util/List; accessible method net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator calculateTargetStrength (Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)I -accessible method net/minecraft/server/level/DistanceManager purgeStaleTickets ()V #cause I don't want to deal with the interfaces until stuff is stable accessible method net/minecraft/world/level/block/entity/SkullBlockEntity fetchGameProfile (Ljava/lang/String;)Ljava/util/concurrent/CompletableFuture; diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index dee7b167..240d70e5 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -42,11 +42,9 @@ "ChunkHolder_scarpetChunkCreationMixin", "ThreadedLevelLightEngine_scarpetMixin", "DynamicGraphMinFixedPoint_resetChunkInterface", - "DistanceManager_scarpetChunkCreationMixin", "LevelLightEngine_scarpetChunkCreationMixin", "LayerLightEngine_scarpetChunkCreationMixin", "LayerLightSectionStorage_scarpetChunkCreationMixin", - "DistanceManager_spawnChunksMixin", "ThreadedLevelLightEngine_scarpetChunkCreationMixin", "LivingEntity_cleanLogsMixin", "MobMixin", @@ -117,8 +115,7 @@ "InfestedBlock_gravelMixin", "PistonBaseBlock_qcMixin", "DispenserBlock_qcMixin", - - "PickaxeItem_missingToolsMixin", + "Item_missingToolsMixin", "WitherBoss_moreBlueMixin", "ArmorStand_scarpetMarkerMixin", "Entity_scarpetEventsMixin", @@ -142,6 +139,7 @@ "AbstractCraftingMenu_scarpetMixin", "AbstractFurnaceMenu_scarpetMixin", "DistanceManager_scarpetMixin", + "TicketStorage_scarpetMixin", "PoiRecord_scarpetMixin", "ServerLevel_scarpetMixin", "PersistentEntitySectionManager_scarpetMixin",