diff --git a/common/build.gradle b/common/build.gradle index 0e8b0587..b26fac24 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -2,6 +2,10 @@ plugins { id "fabric-loom" } +loom { + accessWidener = file("src/main/resources/architectury-common.accessWidener") +} + dependencies { minecraft "com.mojang:minecraft:${rootProject.architect.minecraft}" mappings minecraft.officialMojangMappings() diff --git a/common/src/main/java/me/shedaniel/architectury/ArchitecturyPopulator.java b/common/src/main/java/me/shedaniel/architectury/ArchitecturyPopulator.java index d0508a23..669859b1 100644 --- a/common/src/main/java/me/shedaniel/architectury/ArchitecturyPopulator.java +++ b/common/src/main/java/me/shedaniel/architectury/ArchitecturyPopulator.java @@ -24,6 +24,14 @@ import java.lang.reflect.Modifier; public final class ArchitecturyPopulator { private ArchitecturyPopulator() {} + public static void populate() { + try { + populate(Class.forName(Thread.currentThread().getStackTrace()[2].getClassName())); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + public static void populate(Object o) { try { if (o instanceof Class) { 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 910dabee..9538ab67 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 @@ -20,15 +20,33 @@ import me.shedaniel.architectury.event.Event; import me.shedaniel.architectury.event.EventFactory; import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; public interface EntityEvent { /** * Invoked before LivingEntity#die, equivalent to forge's {@code LivingDeathEvent}. */ Event LIVING_DEATH = EventFactory.createInteractionResult(LivingDeath.class); + /** + * Invoked before LivingEntity#hurt, equivalent to forge's {@code LivingAttackEvent}. + */ + Event LIVING_ATTACK = EventFactory.createInteractionResult(LivingAttack.class); + /** + * Invoked before entity is added to a world, equivalent to forge's {@code EntityJoinWorldEvent}. + */ + Event ADD = EventFactory.createInteractionResult(Add.class); interface LivingDeath { InteractionResult die(LivingEntity entity, DamageSource source); } + + interface LivingAttack { + InteractionResult attack(LivingEntity entity, DamageSource source, float amount); + } + + interface Add { + InteractionResult add(Entity entity, Level world); + } } diff --git a/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java b/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java index c9f5f5a3..0929ba5c 100644 --- a/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java +++ b/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java @@ -23,6 +23,10 @@ import net.fabricmc.api.Environment; import net.minecraft.advancements.Advancement; import net.minecraft.client.player.LocalPlayer; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; public interface PlayerEvent { Event PLAYER_JOIN = EventFactory.createLoop(PlayerJoin.class); @@ -33,6 +37,9 @@ public interface PlayerEvent { @Environment(EnvType.CLIENT) Event CLIENT_PLAYER_RESPAWN = EventFactory.createLoop(ClientPlayerRespawn.class); Event PLAYER_ADVANCEMENT = EventFactory.createLoop(PlayerAdvancement.class); Event PLAYER_CLONE = EventFactory.createLoop(PlayerClone.class); + Event SMELT_ITEM = EventFactory.createLoop(SmeltItem.class); + Event PICKUP_ITEM_PRE = EventFactory.createInteractionResult(PickupItemPredicate.class); + Event PICKUP_ITEM_POST = EventFactory.createLoop(PickupItem.class); interface PlayerJoin { void join(ServerPlayer player); @@ -54,6 +61,18 @@ public interface PlayerEvent { void award(ServerPlayer player, Advancement advancement); } + interface SmeltItem { + void smelt(Player player, ItemStack smelted); + } + + interface PickupItemPredicate { + InteractionResult canPickup(Player player, ItemEntity entity, ItemStack smelted); + } + + interface PickupItem { + void pickup(Player player, ItemEntity entity, ItemStack smelted); + } + @Environment(EnvType.CLIENT) interface ClientPlayerJoin { void join(LocalPlayer player); diff --git a/common/src/main/java/me/shedaniel/architectury/registry/BlockProperties.java b/common/src/main/java/me/shedaniel/architectury/registry/BlockProperties.java new file mode 100644 index 00000000..55403c80 --- /dev/null +++ b/common/src/main/java/me/shedaniel/architectury/registry/BlockProperties.java @@ -0,0 +1,58 @@ +package me.shedaniel.architectury.registry; + +import me.shedaniel.architectury.ArchitecturyPopulator; +import me.shedaniel.architectury.Populatable; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; + +import java.util.function.Function; + +public abstract class BlockProperties extends BlockBehaviour.Properties implements BlockPropertiesExtension { + @Populatable + private static final Impl IMPL = null; + + public BlockProperties(Material material, Function function) { + super(material, function); + } + + public static BlockProperties of(Material material) { + return of(material, material.getColor()); + } + + public static BlockProperties of(Material material, DyeColor color) { + return of(material, color.getMaterialColor()); + } + + public static BlockProperties of(Material material, MaterialColor color) { + return IMPL.of(material, color); + } + + public static BlockProperties of(Material material, Function color) { + return IMPL.of(material, color); + } + + public static BlockProperties copy(BlockBehaviour block) { + return IMPL.copy(block); + } + + public static BlockProperties copy(BlockBehaviour.Properties properties) { + return IMPL.copy(properties); + } + + public interface Impl { + BlockProperties of(Material material, MaterialColor color); + + BlockProperties of(Material material, Function color); + + BlockProperties copy(BlockBehaviour block); + + BlockProperties copy(BlockBehaviour.Properties properties); + } + + static { + ArchitecturyPopulator.populate(); + } +} diff --git a/common/src/main/java/me/shedaniel/architectury/registry/BlockPropertiesExtension.java b/common/src/main/java/me/shedaniel/architectury/registry/BlockPropertiesExtension.java new file mode 100644 index 00000000..f2a49f0e --- /dev/null +++ b/common/src/main/java/me/shedaniel/architectury/registry/BlockPropertiesExtension.java @@ -0,0 +1,9 @@ +package me.shedaniel.architectury.registry; + +public interface BlockPropertiesExtension { + default BlockProperties tool(ToolType type) { + return tool(type, 0); + } + + BlockProperties tool(ToolType type, int level); +} \ No newline at end of file diff --git a/common/src/main/java/me/shedaniel/architectury/registry/ToolType.java b/common/src/main/java/me/shedaniel/architectury/registry/ToolType.java new file mode 100644 index 00000000..28c3f585 --- /dev/null +++ b/common/src/main/java/me/shedaniel/architectury/registry/ToolType.java @@ -0,0 +1,55 @@ +package me.shedaniel.architectury.registry; + +import me.shedaniel.architectury.Populatable; +import net.minecraft.tags.Tag; +import net.minecraft.world.item.Item; + +import java.util.function.Supplier; + +public final class ToolType { + public static final ToolType PICKAXE = create("pickaxe", ToolType::pickaxeTag); + public static final ToolType AXE = create("axe", ToolType::axeTag); + public static final ToolType HOE = create("hoe", ToolType::hoeTag); + public static final ToolType SHOVEL = create("shovel", ToolType::shovelTag); + @Populatable + private static final Impl IMPL = null; + + private static Tag pickaxeTag() { + return IMPL.pickaxeTag(); + } + + private static Tag axeTag() { + return IMPL.axeTag(); + } + + private static Tag hoeTag() { + return IMPL.hoeTag(); + } + + private static Tag shovelTag() { + return IMPL.shovelTag(); + } + + public final String forgeName; + public final Supplier> fabricTag; + private Object obj; + + private ToolType(String forgeName, Supplier> fabricTag) { + this.forgeName = forgeName; + this.fabricTag = fabricTag; + } + + public static ToolType create(String forgeName, Supplier> fabricTag) { + return new ToolType(forgeName, fabricTag); + } + + public interface Impl { + Tag pickaxeTag(); + + Tag axeTag(); + + Tag hoeTag(); + + Tag shovelTag(); + } +} diff --git a/common/src/main/resources/architectury-common.accessWidener b/common/src/main/resources/architectury-common.accessWidener new file mode 100644 index 00000000..26b38f61 --- /dev/null +++ b/common/src/main/resources/architectury-common.accessWidener @@ -0,0 +1,2 @@ +accessWidener v1 named +accessible method net/minecraft/world/level/block/state/BlockBehaviour$Properties (Lnet/minecraft/world/level/material/Material;Ljava/util/function/Function;)V \ No newline at end of file diff --git a/common/src/main/resources/fabric.mod.json b/common/src/main/resources/fabric.mod.json index 135630f5..9d8f1e2f 100644 --- a/common/src/main/resources/fabric.mod.json +++ b/common/src/main/resources/fabric.mod.json @@ -2,5 +2,6 @@ "_comment": "This file is here to make fabric loader load this on the Knot classloader.", "schemaVersion": 1, "id": "architectury-common", - "version": "0.0.1" + "version": "0.0.1", + "accessWidener": "architectury-common.accessWidener" } \ No newline at end of file diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinFurnaceResultSlot.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinFurnaceResultSlot.java new file mode 100644 index 00000000..50c6cc6d --- /dev/null +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinFurnaceResultSlot.java @@ -0,0 +1,22 @@ +package me.shedaniel.architectury.mixin.fabric; + +import me.shedaniel.architectury.event.events.PlayerEvent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.FurnaceResultSlot; +import net.minecraft.world.item.ItemStack; +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(FurnaceResultSlot.class) +public class MixinFurnaceResultSlot { + @Shadow @Final private Player player; + + @Inject(method = "checkTakeAchievements", at = @At("RETURN")) + private void checkTakeAchievements(ItemStack itemStack, CallbackInfo ci) { + PlayerEvent.SMELT_ITEM.invoker().smelt(player, itemStack); + } +} diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinItemEntity.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinItemEntity.java new file mode 100644 index 00000000..7464cab7 --- /dev/null +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinItemEntity.java @@ -0,0 +1,33 @@ +package me.shedaniel.architectury.mixin.fabric; + +import me.shedaniel.architectury.event.events.PlayerEvent; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +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(ItemEntity.class) +public abstract class MixinItemEntity { + @Shadow + public abstract ItemStack getItem(); + + @Inject(method = "playerTouch", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getCount()I"), cancellable = true) + private void prePickup(Player player, CallbackInfo ci) { + InteractionResult canPickUp = PlayerEvent.PICKUP_ITEM_PRE.invoker().canPickup(player, (ItemEntity) (Object) this, getItem()); + if (canPickUp == InteractionResult.FAIL) { + ci.cancel(); + } + } + + @Inject(method = "playerTouch", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;take(Lnet/minecraft/world/entity/Entity;I)V")) + private void pickup(Player player, CallbackInfo ci) { + PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(player, (ItemEntity) (Object) this, getItem()); + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..88fff6f4 --- /dev/null +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinLivingEntity.java @@ -0,0 +1,22 @@ +package me.shedaniel.architectury.mixin.fabric; + +import me.shedaniel.architectury.event.events.EntityEvent; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +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(LivingEntity.class) +public class MixinLivingEntity { + @Inject(method = "hurt", at = @At("HEAD"), cancellable = true) + private void hurt(DamageSource damageSource, float f, CallbackInfoReturnable cir) { + if ((Object) this instanceof Player) return; + if (EntityEvent.LIVING_ATTACK.invoker().attack((LivingEntity) (Object) this, damageSource, f) == InteractionResult.FAIL) { + cir.setReturnValue(false); + } + } +} diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerLevel.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerLevel.java index fa2dac60..4b7fd29f 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerLevel.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerLevel.java @@ -16,13 +16,18 @@ package me.shedaniel.architectury.mixin.fabric; +import me.shedaniel.architectury.event.events.EntityEvent; import me.shedaniel.architectury.event.events.LifecycleEvent; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.ProgressListener; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; 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.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ServerLevel.class) public class MixinServerLevel { @@ -30,4 +35,28 @@ public class MixinServerLevel { private void save(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) { LifecycleEvent.SERVER_WORLD_SAVE.invoker().act((ServerLevel) (Object) this); } + + @Inject(method = "addEntity", at = @At(value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerLevel;getChunk(IILnet/minecraft/world/level/chunk/ChunkStatus;Z)Lnet/minecraft/world/level/chunk/ChunkAccess;"), + cancellable = true) + private void addEntity(Entity entity, CallbackInfoReturnable cir) { + if (EntityEvent.ADD.invoker().add(entity, (ServerLevel) (Object) this) == InteractionResult.FAIL) { + cir.setReturnValue(false); + } + } + + @Inject(method = "addPlayer", at = @At("HEAD"), cancellable = true) + private void addPlayer(ServerPlayer serverPlayer, CallbackInfo ci) { + if (EntityEvent.ADD.invoker().add(serverPlayer, (ServerLevel) (Object) this) == InteractionResult.FAIL) { + ci.cancel(); + } + } + + @Inject(method = "loadFromChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;add(Lnet/minecraft/world/entity/Entity;)V"), + cancellable = true) + private void loadFromChunk(Entity entity, CallbackInfoReturnable cir) { + if (EntityEvent.ADD.invoker().add(entity, (ServerLevel) (Object) this) == InteractionResult.FAIL) { + cir.setReturnValue(false); + } + } } diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/PlayerAttackInvoker.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/PlayerAttackInvoker.java new file mode 100644 index 00000000..b7257d52 --- /dev/null +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/PlayerAttackInvoker.java @@ -0,0 +1,23 @@ +package me.shedaniel.architectury.mixin.fabric; + +import me.shedaniel.architectury.event.events.EntityEvent; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.player.RemotePlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +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(value = {LocalPlayer.class, Player.class, RemotePlayer.class}) +public class PlayerAttackInvoker { + @Inject(method = "hurt", at = @At("HEAD"), cancellable = true) + private void hurt(DamageSource damageSource, float f, CallbackInfoReturnable cir) { + if (EntityEvent.LIVING_ATTACK.invoker().attack((LivingEntity) (Object) this, damageSource, f) == InteractionResult.FAIL && (Object) this instanceof Player) { + cir.setReturnValue(false); + } + } +} diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinClientLevel.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinClientLevel.java index bd1c0f8f..6ee2586c 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinClientLevel.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinClientLevel.java @@ -16,12 +16,15 @@ package me.shedaniel.architectury.mixin.fabric.client; +import me.shedaniel.architectury.event.events.EntityEvent; import me.shedaniel.architectury.event.events.LifecycleEvent; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.resources.ResourceKey; import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.DimensionType; import org.spongepowered.asm.mixin.Mixin; @@ -37,4 +40,11 @@ public class MixinClientLevel { private void construct(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey resourceKey, DimensionType dimensionType, int i, Supplier supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) { LifecycleEvent.CLIENT_WORLD_LOAD.invoker().act((ClientLevel) (Object) this); } + + @Inject(method = "addEntity", at = @At("HEAD"), cancellable = true) + private void addEntity(int i, Entity entity, CallbackInfo ci) { + if (EntityEvent.ADD.invoker().add(entity, (ClientLevel) (Object) this) == InteractionResult.FAIL) { + ci.cancel(); + } + } } diff --git a/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/BlockPropertiesImpl.java b/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/BlockPropertiesImpl.java new file mode 100644 index 00000000..55e74a6d --- /dev/null +++ b/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/BlockPropertiesImpl.java @@ -0,0 +1,66 @@ +package me.shedaniel.architectury.registry.fabric; + +import me.shedaniel.architectury.registry.BlockProperties; +import me.shedaniel.architectury.registry.ToolType; +import net.fabricmc.fabric.impl.object.builder.BlockSettingsInternals; +import net.fabricmc.fabric.impl.object.builder.FabricBlockInternals; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; + +import java.util.function.Function; + +public class BlockPropertiesImpl implements BlockProperties.Impl { + @Override + public BlockProperties of(Material material, MaterialColor color) { + return new Impl(material, (state) -> color); + } + + @Override + public BlockProperties of(Material material, Function color) { + return new Impl(material, color); + } + + @Override + public BlockProperties copy(BlockBehaviour old) { + return copy(old.properties); + } + + @Override + public BlockProperties copy(BlockBehaviour.Properties old) { + BlockProperties properties = of(old.material, old.materialColor); + properties.material = old.material; + properties.destroyTime = old.destroyTime; + properties.explosionResistance = old.explosionResistance; + properties.hasCollision = old.hasCollision; + properties.isRandomlyTicking = old.isRandomlyTicking; + properties.lightEmission = old.lightEmission; + properties.materialColor = old.materialColor; + properties.soundType = old.soundType; + properties.friction = old.friction; + properties.speedFactor = old.speedFactor; + properties.dynamicShape = old.dynamicShape; + properties.canOcclude = old.canOcclude; + properties.isAir = old.isAir; + properties.requiresCorrectToolForDrops = old.requiresCorrectToolForDrops; + BlockSettingsInternals otherInternals = (BlockSettingsInternals) old; + FabricBlockInternals.ExtraData extraData = otherInternals.getExtraData(); + if (extraData != null) { + ((BlockSettingsInternals) this).setExtraData(extraData); + } + return properties; + } + + private static final class Impl extends BlockProperties { + public Impl(Material material, Function function) { + super(material, function); + } + + @Override + public BlockProperties tool(ToolType type, int level) { + FabricBlockInternals.computeExtraData(this).addMiningLevel(type.fabricTag.get(), level); + return this; + } + } +} diff --git a/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/ToolTypeImpl.java b/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/ToolTypeImpl.java new file mode 100644 index 00000000..147c9bec --- /dev/null +++ b/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/ToolTypeImpl.java @@ -0,0 +1,28 @@ +package me.shedaniel.architectury.registry.fabric; + +import me.shedaniel.architectury.registry.ToolType; +import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; +import net.minecraft.tags.Tag; +import net.minecraft.world.item.Item; + +public class ToolTypeImpl implements ToolType.Impl { + @Override + public Tag pickaxeTag() { + return FabricToolTags.PICKAXES; + } + + @Override + public Tag axeTag() { + return FabricToolTags.AXES; + } + + @Override + public Tag hoeTag() { + return FabricToolTags.HOES; + } + + @Override + public Tag shovelTag() { + return FabricToolTags.SHOVELS; + } +} diff --git a/fabric/src/main/resources/architectury.accessWidener b/fabric/src/main/resources/architectury.accessWidener index 70498058..c8ea1d44 100644 --- a/fabric/src/main/resources/architectury.accessWidener +++ b/fabric/src/main/resources/architectury.accessWidener @@ -1,4 +1,49 @@ accessWidener v1 named accessible method net/minecraft/client/gui/screens/Screen addButton (Lnet/minecraft/client/gui/components/AbstractWidget;)Lnet/minecraft/client/gui/components/AbstractWidget; accessible method net/minecraft/client/gui/screens/Screen addWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener; -accessible field net/minecraft/client/gui/screens/Screen buttons Ljava/util/List; \ No newline at end of file +accessible field net/minecraft/client/gui/screens/Screen buttons Ljava/util/List; +accessible field net/minecraft/world/level/block/state/BlockBehaviour properties Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties material Lnet/minecraft/world/level/material/Material; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties material Lnet/minecraft/world/level/material/Material; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties materialColor Ljava/util/function/Function; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties materialColor Ljava/util/function/Function; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties hasCollision Z +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties hasCollision Z +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties soundType Lnet/minecraft/world/level/block/SoundType; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties soundType Lnet/minecraft/world/level/block/SoundType; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties lightEmission Ljava/util/function/ToIntFunction; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties lightEmission Ljava/util/function/ToIntFunction; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties explosionResistance F +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties explosionResistance F +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties destroyTime F +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties destroyTime F +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties requiresCorrectToolForDrops Z +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties requiresCorrectToolForDrops Z +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isRandomlyTicking Z +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties isRandomlyTicking Z +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties friction F +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties friction F +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties speedFactor F +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties speedFactor F +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties jumpFactor F +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties jumpFactor F +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties drops Lnet/minecraft/resources/ResourceLocation; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties drops Lnet/minecraft/resources/ResourceLocation; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties canOcclude Z +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties canOcclude Z +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isAir Z +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties isAir Z +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isValidSpawn Lnet/minecraft/world/level/block/state/BlockBehaviour$StateArgumentPredicate; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties isValidSpawn Lnet/minecraft/world/level/block/state/BlockBehaviour$StateArgumentPredicate; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isRedstoneConductor Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties isRedstoneConductor Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isSuffocating Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties isSuffocating Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties isViewBlocking Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties isViewBlocking Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties hasPostProcess Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties hasPostProcess Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties emissiveRendering Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties emissiveRendering Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate; +accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties dynamicShape Z +mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties dynamicShape Z \ No newline at end of file diff --git a/fabric/src/main/resources/architectury.mixins.json b/fabric/src/main/resources/architectury.mixins.json index 1baef9e7..cdf91db9 100644 --- a/fabric/src/main/resources/architectury.mixins.json +++ b/fabric/src/main/resources/architectury.mixins.json @@ -12,8 +12,9 @@ "client.MixinScreen" ], "mixins": [ - "ExplosionPreInvoker", "LivingDeathInvoker", "MixinCommands", "MixinExplosion", "MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList", - "MixinServerGamePacketListenerImpl", "MixinServerLevel", "MixinServerPlayer" + "ExplosionPreInvoker", "LivingDeathInvoker", "MixinCommands", "MixinExplosion", "MixinFurnaceResultSlot", "MixinItemEntity", "MixinLivingEntity", + "MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList", "MixinServerGamePacketListenerImpl", "MixinServerLevel", "MixinServerPlayer", + "PlayerAttackInvoker" ], "injectors": { "defaultRequire": 1 diff --git a/forge/build.gradle b/forge/build.gradle index 091a78f3..7bcf073f 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -23,7 +23,7 @@ minecraft { client { workingDirectory project.file("run") mods { - examplemod { + architectury { source sourceSets.main } } @@ -31,7 +31,7 @@ minecraft { server { workingDirectory project.file("run") mods { - examplemod { + architectury { source sourceSets.main } } diff --git a/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImpl.java b/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImpl.java index d14bbbfb..eaf39d7a 100644 --- a/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImpl.java +++ b/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImpl.java @@ -34,13 +34,13 @@ import net.minecraftforge.event.CommandEvent; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.ServerChatEvent; import net.minecraftforge.event.TickEvent.*; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; import net.minecraftforge.event.entity.player.AdvancementEvent; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; import net.minecraftforge.event.entity.player.ItemTooltipEvent; -import net.minecraftforge.event.entity.player.PlayerEvent.Clone; -import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; -import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent; -import net.minecraftforge.event.entity.player.PlayerEvent.PlayerRespawnEvent; +import net.minecraftforge.event.entity.player.PlayerEvent.*; import net.minecraftforge.event.world.ExplosionEvent.Detonate; import net.minecraftforge.event.world.ExplosionEvent.Start; import net.minecraftforge.event.world.WorldEvent; @@ -306,6 +306,35 @@ public class EventHandlerImpl implements EventHandler.Impl { public static void event(Detonate event) { ExplosionEvent.DETONATE.invoker().explode(event.getWorld(), event.getExplosion(), event.getAffectedEntities()); } + + @SubscribeEvent + public static void event(LivingAttackEvent event) { + if (EntityEvent.LIVING_ATTACK.invoker().attack(event.getEntityLiving(), event.getSource(), event.getAmount()) == ActionResultType.FAIL) { + event.setCanceled(true); + } + } + + @SubscribeEvent + public static void event(EntityJoinWorldEvent event) { + if (EntityEvent.ADD.invoker().add(event.getEntity(), event.getWorld()) == ActionResultType.FAIL) { + event.setCanceled(true); + } + } + + @SubscribeEvent + public static void event(ItemSmeltedEvent event) { + PlayerEvent.SMELT_ITEM.invoker().smelt(event.getPlayer(), event.getSmelting()); + } + + @SubscribeEvent + public static void event(EntityItemPickupEvent event) { + PlayerEvent.PICKUP_ITEM_PRE.invoker().canPickup(event.getPlayer(), event.getItem(), event.getItem().getItem()); + } + + @SubscribeEvent + public static void event(ItemPickupEvent event) { + PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(event.getPlayer(), event.getOriginalEntity(), event.getStack()); + } } @OnlyIn(Dist.DEDICATED_SERVER) diff --git a/forge/src/main/java/me/shedaniel/architectury/forge/ArchitecturyForge.java b/forge/src/main/java/me/shedaniel/architectury/forge/ArchitecturyForge.java new file mode 100644 index 00000000..a59013dd --- /dev/null +++ b/forge/src/main/java/me/shedaniel/architectury/forge/ArchitecturyForge.java @@ -0,0 +1,7 @@ +package me.shedaniel.architectury.forge; + +import net.minecraftforge.fml.common.Mod; + +@Mod("architectury") +public class ArchitecturyForge { +} diff --git a/forge/src/main/java/me/shedaniel/architectury/hooks/forge/ExplosionHooksImpl.java b/forge/src/main/java/me/shedaniel/architectury/hooks/forge/ExplosionHooksImpl.java index a7efc941..445b1bae 100644 --- a/forge/src/main/java/me/shedaniel/architectury/hooks/forge/ExplosionHooksImpl.java +++ b/forge/src/main/java/me/shedaniel/architectury/hooks/forge/ExplosionHooksImpl.java @@ -20,7 +20,6 @@ import me.shedaniel.architectury.hooks.ExplosionHooks; import net.minecraft.entity.Entity; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.Explosion; -import net.minecraftforge.fml.common.ObfuscationReflectionHelper; public class ExplosionHooksImpl implements ExplosionHooks.Impl { @Override @@ -35,19 +34,11 @@ public class ExplosionHooksImpl implements ExplosionHooks.Impl { @Override public float getRadius(Explosion explosion) { - try { - return (float) ObfuscationReflectionHelper.findField(Explosion.class, "field_77280_f").get(explosion); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } + return explosion.radius; } @Override public void setRadius(Explosion explosion, float v) { - try { - ObfuscationReflectionHelper.findField(Explosion.class, "field_77280_f").set(explosion, v); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } + explosion.radius = v; } } diff --git a/forge/src/main/java/me/shedaniel/architectury/hooks/forge/ScreenHooksImpl.java b/forge/src/main/java/me/shedaniel/architectury/hooks/forge/ScreenHooksImpl.java index ea43d496..96bbeefb 100644 --- a/forge/src/main/java/me/shedaniel/architectury/hooks/forge/ScreenHooksImpl.java +++ b/forge/src/main/java/me/shedaniel/architectury/hooks/forge/ScreenHooksImpl.java @@ -28,11 +28,7 @@ import java.util.List; public class ScreenHooksImpl implements ScreenHooks.Impl { @Override public List getButtons(Screen screen) { - try { - return (List) ObfuscationReflectionHelper.findField(Screen.class, "field_230710_m_").get(screen); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } + return screen.buttons; } @Override diff --git a/forge/src/main/java/me/shedaniel/architectury/registry/forge/BlockPropertiesImpl.java b/forge/src/main/java/me/shedaniel/architectury/registry/forge/BlockPropertiesImpl.java new file mode 100644 index 00000000..342354c1 --- /dev/null +++ b/forge/src/main/java/me/shedaniel/architectury/registry/forge/BlockPropertiesImpl.java @@ -0,0 +1,60 @@ +package me.shedaniel.architectury.registry.forge; + +import me.shedaniel.architectury.registry.BlockProperties; +import me.shedaniel.architectury.registry.ToolType; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.BlockState; +import net.minecraft.block.material.Material; +import net.minecraft.block.material.MaterialColor; + +import java.util.function.Function; + +public class BlockPropertiesImpl implements BlockProperties.Impl { + @Override + public BlockProperties of(Material material, MaterialColor materialColor) { + return new Impl(material, (state) -> materialColor); + } + + @Override + public BlockProperties of(Material material, Function function) { + return new Impl(material, function); + } + + @Override + public BlockProperties copy(AbstractBlock abstractBlock) { + return copy(abstractBlock.properties); + } + + @Override + public BlockProperties copy(AbstractBlock.Properties old) { + BlockProperties properties = of(old.material, old.materialColor); + properties.material = old.material; + properties.destroyTime = old.destroyTime; + properties.explosionResistance = old.explosionResistance; + properties.hasCollision = old.hasCollision; + properties.isRandomlyTicking = old.isRandomlyTicking; + properties.lightEmission = old.lightEmission; + properties.materialColor = old.materialColor; + properties.soundType = old.soundType; + properties.friction = old.friction; + properties.speedFactor = old.speedFactor; + properties.dynamicShape = old.dynamicShape; + properties.canOcclude = old.canOcclude; + properties.isAir = old.isAir; + properties.requiresCorrectToolForDrops = old.requiresCorrectToolForDrops; + return properties; + } + + private static final class Impl extends BlockProperties { + public Impl(Material material, Function function) { + super(material, function); + } + + @Override + public BlockProperties tool(ToolType type, int level) { + harvestTool(net.minecraftforge.common.ToolType.get(type.forgeName)); + harvestLevel(level); + return this; + } + } +} diff --git a/forge/src/main/java/me/shedaniel/architectury/registry/forge/ToolTypeImpl.java b/forge/src/main/java/me/shedaniel/architectury/registry/forge/ToolTypeImpl.java new file mode 100644 index 00000000..7f6f29ea --- /dev/null +++ b/forge/src/main/java/me/shedaniel/architectury/registry/forge/ToolTypeImpl.java @@ -0,0 +1,28 @@ +package me.shedaniel.architectury.registry.forge; + + +import me.shedaniel.architectury.registry.ToolType; +import net.minecraft.item.Item; +import net.minecraft.tags.ITag; + +public class ToolTypeImpl implements ToolType.Impl { + @Override + public ITag pickaxeTag() { + return null; + } + + @Override + public ITag axeTag() { + return null; + } + + @Override + public ITag hoeTag() { + return null; + } + + @Override + public ITag shovelTag() { + return null; + } +} diff --git a/forge/src/main/resources/META-INF/accesstransformer.cfg b/forge/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..419bbdb2 --- /dev/null +++ b/forge/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1,18 @@ +public net.minecraft.block.AbstractBlock field_235684_aB_ #properties +public net.minecraft.block.AbstractBlock$Properties (Lnet/minecraft/block/material/Material;Ljava/util/function/Function;)V +public net.minecraft.block.AbstractBlock$Properties field_200953_a #material +public net.minecraft.block.AbstractBlock$Properties field_200959_g #destroyTime +public net.minecraft.block.AbstractBlock$Properties field_200958_f #explosionResistance +public net.minecraft.block.AbstractBlock$Properties field_200955_c #hasCollision +public net.minecraft.block.AbstractBlock$Properties field_200960_h #isRandomlyTicking +public net.minecraft.block.AbstractBlock$Properties field_235803_e_ #lightEmission +public net.minecraft.block.AbstractBlock$Properties field_235800_b_ #materialColor +public net.minecraft.block.AbstractBlock$Properties field_200956_d #soundType +public net.minecraft.block.AbstractBlock$Properties field_200961_i #friction +public net.minecraft.block.AbstractBlock$Properties field_226893_j_ #speedFactor +public net.minecraft.block.AbstractBlock$Properties field_208772_j #dynamicShape +public net.minecraft.block.AbstractBlock$Properties field_226895_m_ #canOcclude +public net.minecraft.block.AbstractBlock$Properties field_235813_o_ #isAir +public net.minecraft.block.AbstractBlock$Properties field_235806_h_ #requiresCorrectToolForDrops +public-f net.minecraft.world.Explosion field_77280_f #radius +public net.minecraft.client.gui.screen.Screen field_230710_m_ #buttons \ No newline at end of file