diff --git a/common/src/main/java/me/shedaniel/architectury/event/events/EntityEvent.java b/common/src/main/java/me/shedaniel/architectury/event/events/EntityEvent.java index c60cc221..a01a7b90 100644 --- a/common/src/main/java/me/shedaniel/architectury/event/events/EntityEvent.java +++ b/common/src/main/java/me/shedaniel/architectury/event/events/EntityEvent.java @@ -53,9 +53,9 @@ public interface EntityEvent { */ Event ADD = EventFactory.createInteractionResult(); /** - * Invoked when an entity enters a chunk, equivalent to forge's {@code EnteringChunk} + * Invoked when an entity enters a new section */ - Event ENTER_CHUNK = EventFactory.createLoop(); + Event ENTER_SECTION = EventFactory.createLoop(); interface LivingDeath { InteractionResult die(LivingEntity entity, DamageSource source); @@ -73,8 +73,8 @@ public interface EntityEvent { InteractionResult add(Entity entity, Level world); } - interface EnterChunk { - void enterChunk(Entity entity, int chunkX, int chunkZ, int prevX, int prevZ); + interface EnterSection { + void enterSection(Entity entity, int sectionX, int sectionY, int sectionZ, int prevX, int prevY, int prevZ); } } diff --git a/fabric/build.gradle b/fabric/build.gradle index bb5feb50..2f97ceb2 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -93,9 +93,7 @@ curseforge { releaseType = "$rootProject.cf_type" changelogType = "html" changelog = releaseChangelog() - addGameVersion "1.16-Snapshot" - addGameVersion "1.16.4" - addGameVersion "1.16.5" + addGameVersion "1.17-Snapshot" addGameVersion "Java 8" addGameVersion "Fabric" relations { diff --git a/fabric/src/main/java/me/shedaniel/architectury/hooks/fabric/EntityHooksImpl.java b/fabric/src/main/java/me/shedaniel/architectury/hooks/fabric/EntityHooksImpl.java index f2524632..b8e0cfd3 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/hooks/fabric/EntityHooksImpl.java +++ b/fabric/src/main/java/me/shedaniel/architectury/hooks/fabric/EntityHooksImpl.java @@ -19,7 +19,10 @@ package me.shedaniel.architectury.hooks.fabric; +import me.shedaniel.architectury.event.events.EntityEvent; +import net.minecraft.core.SectionPos; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.entity.EntityInLevelCallback; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.EntityCollisionContext; import org.jetbrains.annotations.Nullable; @@ -33,4 +36,29 @@ public class EntityHooksImpl { public static Entity fromCollision(CollisionContext ctx) { return ctx instanceof EntityCollisionContext ? ((EntityCollisionContext) ctx).getEntity().orElse(null) : null; } + + public static EntityInLevelCallback wrapEntityInLevelCallback(Entity entity, EntityInLevelCallback callback) { + if (callback == EntityInLevelCallback.NULL) return callback; + if (callback == null) return callback; + return new EntityInLevelCallback() { + private long lastSectionKey = SectionPos.asLong(entity.blockPosition()); + + @Override + public void onMove() { + callback.onMove(); + long currentSectionKey = SectionPos.asLong(entity.blockPosition()); + if (currentSectionKey != lastSectionKey) { + EntityEvent.ENTER_SECTION.invoker().enterSection(entity, SectionPos.x(lastSectionKey), SectionPos.y(lastSectionKey), + SectionPos.z(lastSectionKey), SectionPos.x(currentSectionKey), SectionPos.y(currentSectionKey), + SectionPos.z(currentSectionKey)); + lastSectionKey = currentSectionKey; + } + } + + @Override + public void onRemove(Entity.RemovalReason removalReason) { + callback.onRemove(removalReason); + } + }; + } } diff --git a/fabric/src/main/java/me/shedaniel/architectury/impl/fabric/ChatComponentImpl.java b/fabric/src/main/java/me/shedaniel/architectury/impl/fabric/ChatComponentImpl.java index 256c426a..8fdd226d 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/impl/fabric/ChatComponentImpl.java +++ b/fabric/src/main/java/me/shedaniel/architectury/impl/fabric/ChatComponentImpl.java @@ -1,6 +1,6 @@ /* * This file is part of architectury. - * Copyright (C) 2020, 2021 shedaniel + * Copyright (C) 2020, 2021 architectury * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinBaseSpawner.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinBaseSpawner.java index 9dbe6640..ed0ddec9 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinBaseSpawner.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinBaseSpawner.java @@ -33,7 +33,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(BaseSpawner.class) public abstract class MixinBaseSpawner { @Redirect( - method = "tick", + method = "serverTick", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z", @@ -50,7 +50,7 @@ public abstract class MixinBaseSpawner { } @Redirect( - method = "tick", + method = "serverTick", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;checkSpawnObstruction(Lnet/minecraft/world/level/LevelReader;)Z", diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinBucketItem.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinBucketItem.java index da207df4..e02f16a1 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinBucketItem.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinBucketItem.java @@ -27,6 +27,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BucketItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -41,13 +42,13 @@ public class MixinBucketItem { method = "use", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/phys/HitResult;getType()Lnet/minecraft/world/phys/HitResult$Type;", + target = "Lnet/minecraft/world/phys/BlockHitResult;getType()Lnet/minecraft/world/phys/HitResult$Type;", ordinal = 0 ), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true ) - public void fillBucket(Level level, Player player, InteractionHand hand, CallbackInfoReturnable> cir, ItemStack stack, HitResult target) { + public void fillBucket(Level level, Player player, InteractionHand hand, CallbackInfoReturnable> cir, ItemStack stack, BlockHitResult target) { CompoundEventResult result = PlayerEvent.FILL_BUCKET.invoker().fill(player, level, stack, target); if (result.interruptsFurtherEvaluation() && result.value() != null) { cir.setReturnValue(result.asMinecraft()); diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinMob.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinEntity.java similarity index 53% rename from fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinMob.java rename to fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinEntity.java index a58a6a93..03031e92 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinMob.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinEntity.java @@ -19,26 +19,18 @@ package me.shedaniel.architectury.mixin.fabric; -import me.shedaniel.architectury.extensions.ItemExtension; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; +import me.shedaniel.architectury.hooks.fabric.EntityHooksImpl; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.entity.EntityInLevelCallback; 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; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.ModifyVariable; -@Mixin(Mob.class) -public class MixinMob { - @Inject(method = "getEquipmentSlotForItem", at = @At("HEAD"), cancellable = true) - private static void getEquipmentSlotForItem(ItemStack stack, CallbackInfoReturnable cir) { - Item item = stack.getItem(); - if (item instanceof ItemExtension) { - EquipmentSlot slot = ((ItemExtension) item).getCustomEquipmentSlot(stack); - if (slot != null) { - cir.setReturnValue(slot); - } - } +@Mixin(Entity.class) +public class MixinEntity { + @ModifyVariable(method = "setLevelCallback", argsOnly = true, ordinal = 0, at = @At("HEAD")) + public EntityInLevelCallback modifyLevelCallback_setLevelCallback(EntityInLevelCallback callback) { + return EntityHooksImpl.wrapEntityInLevelCallback((Entity) (Object) this, callback); } } diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinExplosion.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinExplosion.java index f1e9b00e..0e4d7241 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinExplosion.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinExplosion.java @@ -47,7 +47,7 @@ public class MixinExplosion implements ExplosionHooksImpl.ExplosionExtensions { @Unique Vec3 position; @Inject(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;(DDD)V", ordinal = 0), - locals = LocalCapture.CAPTURE_FAILHARD) + locals = LocalCapture.PRINT) private void explodePost(CallbackInfo ci, Set set, float q, int r, int s, int t, int u, int v, int w, List list) { ExplosionEvent.DETONATE.invoker().explode(level, (Explosion) (Object) this, list); } diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinFarmBlock.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinFarmBlock.java index 43a491e9..c2e27c85 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinFarmBlock.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinFarmBlock.java @@ -48,7 +48,7 @@ public abstract class MixinFarmBlock { target = "Lnet/minecraft/world/level/block/FarmBlock;turnToDirt(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V" ) ) - private void fallOn(Level level, BlockPos blockPos, Entity entity, float f, CallbackInfo ci) { + private void fallOn(Level level, BlockState blockState, BlockPos blockPos, Entity entity, float f, CallbackInfo ci) { turnToDirtLocal.set(Triple.of(blockPos.asLong(), f, entity)); } diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinLevelChunk.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinLevelChunk.java deleted file mode 100644 index 957d6917..00000000 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinLevelChunk.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of architectury. - * Copyright (C) 2020, 2021 architectury - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -package me.shedaniel.architectury.mixin.fabric; - -import me.shedaniel.architectury.event.events.EntityEvent; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.LevelChunk; -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(LevelChunk.class) -public class MixinLevelChunk { - @Shadow @Final private ChunkPos chunkPos; - - @Inject( - method = "addEntity", - at = @At( - value = "FIELD", - opcode = Opcodes.PUTFIELD, - target = "Lnet/minecraft/world/entity/Entity;inChunk:Z", - shift = At.Shift.BY, - by = -1 - ) - ) - public void enterChunk(Entity entity, CallbackInfo ci) { - EntityEvent.ENTER_CHUNK.invoker().enterChunk(entity, this.chunkPos.x, this.chunkPos.z, entity.xChunk, entity.zChunk); - } -} diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinLivingEntity.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinLivingEntity.java index cc3d16b3..c38f79bc 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinLivingEntity.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinLivingEntity.java @@ -20,10 +20,14 @@ package me.shedaniel.architectury.mixin.fabric; import me.shedaniel.architectury.event.events.EntityEvent; +import me.shedaniel.architectury.extensions.ItemExtension; import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -38,4 +42,15 @@ public class MixinLivingEntity { cir.setReturnValue(false); } } + + @Inject(method = "getEquipmentSlotForItem", at = @At("HEAD"), cancellable = true) + private static void getEquipmentSlotForItem(ItemStack stack, CallbackInfoReturnable cir) { + Item item = stack.getItem(); + if (item instanceof ItemExtension) { + EquipmentSlot slot = ((ItemExtension) item).getCustomEquipmentSlot(stack); + if (slot != null) { + cir.setReturnValue(slot); + } + } + } } diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinNaturalSpawner.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinNaturalSpawner.java index 5827b953..65977ee8 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinNaturalSpawner.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinNaturalSpawner.java @@ -38,7 +38,7 @@ public abstract class MixinNaturalSpawner { } @Redirect( - method = "spawnCategoryForPosition", + method = "spawnCategoryForPosition(Lnet/minecraft/world/entity/MobCategory;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ChunkAccess;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/NaturalSpawner$SpawnPredicate;Lnet/minecraft/world/level/NaturalSpawner$AfterSpawnCallback;)V", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/level/NaturalSpawner;isValidPositionForMob(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Mob;D)Z", diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPersistentEntitySectionManager.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPersistentEntitySectionManager.java index bb0cc63b..924f0aab 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPersistentEntitySectionManager.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPersistentEntitySectionManager.java @@ -1,6 +1,6 @@ /* * This file is part of architectury. - * Copyright (C) 2020, 2021 shedaniel + * Copyright (C) 2020, 2021 architectury * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/fabric/src/main/resources/architectury.mixins.json b/fabric/src/main/resources/architectury.mixins.json index 939bf5f8..59582603 100644 --- a/fabric/src/main/resources/architectury.mixins.json +++ b/fabric/src/main/resources/architectury.mixins.json @@ -28,14 +28,13 @@ "MixinCatSpawner", "MixinCommands", "MixinDedicatedServer", + "MixinEntity", "MixinExplosion", "MixinFarmBlock", "MixinFurnaceResultSlot", "MixinInventory", "MixinItemEntity", - "MixinLevelChunk", "MixinLivingEntity", - "MixinMob", "MixinNaturalSpawner", "MixinPatrolSpawner", "MixinPersistentEntitySectionManager", diff --git a/gradle.properties b/gradle.properties index 47ff23d4..b21100cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -minecraft_version=21w14a -supported_version=21w14a +minecraft_version=21w17a +supported_version=21w17a cf_type=beta @@ -12,8 +12,7 @@ base_version=2.0 maven_group=me.shedaniel fabric_loader_version=0.11.3 -fabric_api_version=0.32.7+1.17 -mod_menu_version=2.0.0-beta.3 +fabric_api_version=0.34.0+1.17 +mod_menu_version=2.0.0-beta.4 -#forge_version=36 -.0.42 +#forge_version=36.0.42 diff --git a/testmod-common/src/main/java/me/shedaniel/architectury/test/events/DebugEvents.java b/testmod-common/src/main/java/me/shedaniel/architectury/test/events/DebugEvents.java index 229041c0..3b8db67b 100644 --- a/testmod-common/src/main/java/me/shedaniel/architectury/test/events/DebugEvents.java +++ b/testmod-common/src/main/java/me/shedaniel/architectury/test/events/DebugEvents.java @@ -94,11 +94,11 @@ public class DebugEvents { } return InteractionResult.PASS; }); - EntityEvent.ENTER_CHUNK.register(((entity, nx, nz, ox, oz) -> { - if (entity instanceof Player && entity.inChunk) { + EntityEvent.ENTER_SECTION.register(((entity, nx, ny, nz, ox, oy, oz) -> { + if (entity instanceof Player) { Player player = (Player) entity; - SINK.accept("%s switched chunks: %s => %s", entity.getScoreboardName(), chunkPos(ox, oz), chunkPos(nx, nz)); - player.displayClientMessage(new TextComponent("Entering chunk: " + chunkPos(nx, nz)), true); + SINK.accept("%s switched section: %s => %s", entity.getScoreboardName(), sectionPos(ox, oy, oz), sectionPos(nx, oy, nz)); + player.displayClientMessage(new TextComponent("Entering chunk: " + sectionPos(nx, ny, nz)), true); } })); EntityEvent.LIVING_CHECK_SPAWN.register(((entity, level, x, y, z, type, spawner) -> { @@ -328,6 +328,10 @@ public class DebugEvents { return "[" + x + ", " + z + "]"; } + private static String sectionPos(int x, int y, int z) { + return "[" + x + ", " + y + ", " + z + "]"; + } + private static String toSimpleName(Object o) { return o == null ? "null" : o.getClass().getSimpleName() + "@" + Integer.toHexString(o.hashCode()); }