mirror of
https://github.com/architectury/architectury-api.git
synced 2026-03-28 03:56:59 -05:00
@@ -53,9 +53,9 @@ public interface EntityEvent {
|
||||
*/
|
||||
Event<Add> 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<EnterChunk> ENTER_CHUNK = EventFactory.createLoop();
|
||||
Event<EnterSection> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<InteractionResultHolder<ItemStack>> cir, ItemStack stack, HitResult target) {
|
||||
public void fillBucket(Level level, Player player, InteractionHand hand, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir, ItemStack stack, BlockHitResult target) {
|
||||
CompoundEventResult<ItemStack> result = PlayerEvent.FILL_BUCKET.invoker().fill(player, level, stack, target);
|
||||
if (result.interruptsFurtherEvaluation() && result.value() != null) {
|
||||
cir.setReturnValue(result.asMinecraft());
|
||||
|
||||
@@ -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<EquipmentSlot> 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);
|
||||
}
|
||||
}
|
||||
@@ -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;<init>(DDD)V", ordinal = 0),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
locals = LocalCapture.PRINT)
|
||||
private void explodePost(CallbackInfo ci, Set<BlockPos> set, float q, int r, int s, int t, int u, int v, int w, List<Entity> list) {
|
||||
ExplosionEvent.DETONATE.invoker().explode(level, (Explosion) (Object) this, list);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<EquipmentSlot> cir) {
|
||||
Item item = stack.getItem();
|
||||
if (item instanceof ItemExtension) {
|
||||
EquipmentSlot slot = ((ItemExtension) item).getCustomEquipmentSlot(stack);
|
||||
if (slot != null) {
|
||||
cir.setReturnValue(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,14 +28,13 @@
|
||||
"MixinCatSpawner",
|
||||
"MixinCommands",
|
||||
"MixinDedicatedServer",
|
||||
"MixinEntity",
|
||||
"MixinExplosion",
|
||||
"MixinFarmBlock",
|
||||
"MixinFurnaceResultSlot",
|
||||
"MixinInventory",
|
||||
"MixinItemEntity",
|
||||
"MixinLevelChunk",
|
||||
"MixinLivingEntity",
|
||||
"MixinMob",
|
||||
"MixinNaturalSpawner",
|
||||
"MixinPatrolSpawner",
|
||||
"MixinPersistentEntitySectionManager",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user