diff --git a/build.gradle b/build.gradle index 75c009c..0919918 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ repositories { maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } maven { url 'https://api.modrinth.com/maven' } maven { url 'https://jitpack.io' } + maven { url "https://maven.shedaniel.me/" } maven { name = "TerraformersMC" url = "https://maven.terraformersmc.com/" @@ -60,7 +61,7 @@ dependencies { modImplementation include("eu.pb4:sgui:1.0.0-rc6+1.18-pre5") modImplementation include("eu.pb4:hologram-api:0.2.1+1.18-pre5") modImplementation include("eu.pb4:placeholder-api:1.1.3+1.17.1") - modImplementation include("eu.pb4:polymer:0.2.0-beta.20+1.18.1") + modImplementation include("eu.pb4:polymer:0.2.0-beta.21+1.18.1") modImplementation include("fr.catcore:server-translations-api:1.4.8+1.18-pre1") modImplementation include("me.lucko:fabric-permissions-api:0.1-SNAPSHOT") diff --git a/gradle.properties b/gradle.properties index 4850af4..b8efa45 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ org.gradle.jvmargs=-Xmx1G fabric_version=0.44.0+1.18 # Mod Properties - mod_version = 2.0.0-beta.4.2+1.18.1 + mod_version = 2.0.0-rc.1+1.18.1 maven_group = eu.pb4 archives_base_name = graves diff --git a/src/main/java/eu/pb4/graves/GravesMod.java b/src/main/java/eu/pb4/graves/GravesMod.java index 9147163..437a05c 100644 --- a/src/main/java/eu/pb4/graves/GravesMod.java +++ b/src/main/java/eu/pb4/graves/GravesMod.java @@ -10,6 +10,7 @@ import eu.pb4.graves.other.Commands; import eu.pb4.graves.other.VanillaInventoryMask; import eu.pb4.polymer.api.block.PolymerBlockUtils; +import eu.pb4.polymer.api.entity.PolymerEntityUtils; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; @@ -43,6 +44,8 @@ public void onInitialize() { Registry.register(Registry.ITEM, new Identifier("universal_graves", "icon"), IconItem.INSTANCE); Registry.register(Registry.BLOCK, new Identifier("universal_graves", "grave"), GraveBlock.INSTANCE); Registry.register(Registry.BLOCK, new Identifier("universal_graves", "visual_grave"), VisualGraveBlock.INSTANCE); + Registry.register(Registry.ENTITY_TYPE, new Identifier("universal_graves", "xp"), SafeXPEntity.TYPE); + PolymerEntityUtils.registerType(SafeXPEntity.TYPE); GraveBlockEntity.BLOCK_ENTITY_TYPE = Registry.register(Registry.BLOCK_ENTITY_TYPE, "universal_graves:grave", FabricBlockEntityTypeBuilder.create(GraveBlockEntity::new, GraveBlock.INSTANCE).build(null)); VisualGraveBlockEntity.BLOCK_ENTITY_TYPE = Registry.register(Registry.BLOCK_ENTITY_TYPE, "universal_graves:visual_grave", FabricBlockEntityTypeBuilder.create(VisualGraveBlockEntity::new, VisualGraveBlock.INSTANCE).build(null)); Commands.register(); diff --git a/src/main/java/eu/pb4/graves/config/data/ConfigData.java b/src/main/java/eu/pb4/graves/config/data/ConfigData.java index 1af28e9..9595835 100644 --- a/src/main/java/eu/pb4/graves/config/data/ConfigData.java +++ b/src/main/java/eu/pb4/graves/config/data/ConfigData.java @@ -48,6 +48,8 @@ public class ConfigData extends VersionedConfigData implements Cloneable { public boolean replaceAnyBlock = false; public int maxPlacementDistance = 8; public boolean useRealTime = false; + public boolean useAlternativeXPEntity = FabricLoader.getInstance().isModLoaded("origins") + || FabricLoader.getInstance().isModLoaded("bewitchment"); public boolean createFromPvP = true; public boolean createFromVoid = true; diff --git a/src/main/java/eu/pb4/graves/grave/Grave.java b/src/main/java/eu/pb4/graves/grave/Grave.java index 444ea6c..4bad229 100644 --- a/src/main/java/eu/pb4/graves/grave/Grave.java +++ b/src/main/java/eu/pb4/graves/grave/Grave.java @@ -4,6 +4,7 @@ import eu.pb4.graves.config.Config; import eu.pb4.graves.config.ConfigManager; import eu.pb4.graves.other.*; +import eu.pb4.graves.registry.SafeXPEntity; import eu.pb4.graves.ui.GraveGui; import eu.pb4.placeholders.PlaceholderAPI; import me.lucko.fabric.api.permissions.v0.Permissions; @@ -430,7 +431,7 @@ public void dropContent(MinecraftServer server) { var chunk = world.getChunk(ChunkSectionPos.getSectionCoord(this.location.x()), ChunkSectionPos.getSectionCoord(this.location.z())); ItemScatterer.spawn(world, this.location.blockPos(), this.asInventory()); - ExperienceOrbEntity.spawn(world, Vec3d.ofCenter(this.location.blockPos()), this.xp); + GraveUtils.spawnExp(world, Vec3d.ofCenter(this.location.blockPos()), this.xp); } @Override diff --git a/src/main/java/eu/pb4/graves/mixin/ExperienceOrbEntityAccessor.java b/src/main/java/eu/pb4/graves/mixin/ExperienceOrbEntityAccessor.java new file mode 100644 index 0000000..f133132 --- /dev/null +++ b/src/main/java/eu/pb4/graves/mixin/ExperienceOrbEntityAccessor.java @@ -0,0 +1,11 @@ +package eu.pb4.graves.mixin; + +import net.minecraft.entity.ExperienceOrbEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ExperienceOrbEntity.class) +public interface ExperienceOrbEntityAccessor { + @Accessor + void setAmount(int amount); +} diff --git a/src/main/java/eu/pb4/graves/mixin/LivingEntityMixin.java b/src/main/java/eu/pb4/graves/mixin/LivingEntityMixin.java index 152edae..bc78a03 100644 --- a/src/main/java/eu/pb4/graves/mixin/LivingEntityMixin.java +++ b/src/main/java/eu/pb4/graves/mixin/LivingEntityMixin.java @@ -130,10 +130,15 @@ private void replaceWithGrave(DamageSource source, CallbackInfo ci) { placeholders2 = grave.getPlaceholders(player.getServer()); } else { if (config.xpCalc != GravesXPCalculation.DROP) { - ExperienceOrbEntity.spawn(world, Vec3d.ofCenter(gravePos), finalExperience); + GraveUtils.spawnExp(world, Vec3d.ofCenter(gravePos), finalExperience); } text2 = config.creationFailedGraveMessage; - ItemScatterer.spawn(world, gravePos, DefaultedList.copyOf(ItemStack.EMPTY, items.toArray(new ItemStack[0]))); + var droppedItems = DefaultedList.ofSize(0, ItemStack.EMPTY); + for (var item : items) { + droppedItems.add(item.stack()); + } + + ItemScatterer.spawn(world, gravePos, droppedItems); ((PlayerAdditions) player).graves_setLastGrave(-1); } if (text2 != null) { diff --git a/src/main/java/eu/pb4/graves/other/GraveUtils.java b/src/main/java/eu/pb4/graves/other/GraveUtils.java index 0b32c4a..d14aedd 100644 --- a/src/main/java/eu/pb4/graves/other/GraveUtils.java +++ b/src/main/java/eu/pb4/graves/other/GraveUtils.java @@ -3,11 +3,13 @@ import eu.pb4.graves.config.ConfigManager; import eu.pb4.graves.event.GraveValidPosCheckEvent; +import eu.pb4.graves.registry.SafeXPEntity; import net.fabricmc.fabric.api.tag.TagFactory; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.ExperienceOrbEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.server.network.ServerPlayerEntity; @@ -19,6 +21,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; import net.minecraft.world.border.WorldBorder; import org.jetbrains.annotations.Nullable; @@ -104,8 +107,16 @@ private static BlockCheckResult findPos(ServerPlayerEntity player, ServerWorld w return new BlockCheckResult(null, result); } + public static void spawnExp(ServerWorld world, Vec3d pos, int amount) { + if (ConfigManager.getConfig().configData.useAlternativeXPEntity) { + SafeXPEntity.spawn(world, pos, amount); + } else { + ExperienceOrbEntity.spawn(world, pos, amount); + } + } + - private static BlockResult isValidPos(ServerPlayerEntity player, ServerWorld world, WorldBorder border, BlockPos pos, boolean anyBlock) { + private static BlockResult isValidPos(ServerPlayerEntity player, ServerWorld world, WorldBorder border, BlockPos pos, boolean anyBlock) { BlockState state = world.getBlockState(pos); if (border.contains(pos) && pos.getY() >= world.getBottomY() && pos.getY() < world.getTopY() && !state.hasBlockEntity() && (state.isAir() || anyBlock || REPLACEABLE_TAG.contains(state.getBlock()))) { return GraveValidPosCheckEvent.EVENT.invoker().isValid(player, world, pos); diff --git a/src/main/java/eu/pb4/graves/registry/SafeXPEntity.java b/src/main/java/eu/pb4/graves/registry/SafeXPEntity.java new file mode 100644 index 0000000..9a62890 --- /dev/null +++ b/src/main/java/eu/pb4/graves/registry/SafeXPEntity.java @@ -0,0 +1,49 @@ +package eu.pb4.graves.registry; + +import eu.pb4.graves.mixin.ExperienceOrbEntityAccessor; +import eu.pb4.polymer.api.entity.PolymerEntity; +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityDimensions; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.ExperienceOrbEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class SafeXPEntity extends ExperienceOrbEntity implements PolymerEntity { + public static EntityType TYPE = FabricEntityTypeBuilder.create().entityFactory(SafeXPEntity::new).fireImmune().disableSummon().dimensions(EntityDimensions.fixed(0.5F, 0.5F)).trackRangeChunks(6).trackedUpdateRate(20).build(); + public SafeXPEntity(World world, double x, double y, double z, int amount) { + this(TYPE, world); + this.setPosition(x, y, z); + this.setYaw((float)(this.random.nextDouble() * 360.0D)); + this.setVelocity((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); + ((ExperienceOrbEntityAccessor) this).setAmount(amount); + } + + public SafeXPEntity(EntityType entityType, World world) { + super((EntityType) (Object) entityType, world); + } + + public static void spawn(ServerWorld world, Vec3d pos, int amount) { + world.spawnEntity(new SafeXPEntity(world, pos.getX(), pos.getY(), pos.getZ(), amount)); + } + + @Override + public void onPlayerCollision(PlayerEntity player) { + if (!this.world.isClient) { + if (player.experiencePickUpDelay == 0) { + player.experiencePickUpDelay = 2; + player.sendPickup(this, 1); + player.addExperience(this.getExperienceAmount()); + this.discard(); + } + } + } + + @Override + public EntityType getPolymerEntityType() { + return EntityType.EXPERIENCE_BOTTLE; + } +} diff --git a/src/main/resources/universal-graves.mixins.json b/src/main/resources/universal-graves.mixins.json index b5e1925..b3a6844 100644 --- a/src/main/resources/universal-graves.mixins.json +++ b/src/main/resources/universal-graves.mixins.json @@ -4,6 +4,7 @@ "package": "eu.pb4.graves.mixin", "compatibilityLevel": "JAVA_16", "mixins": [ + "ExperienceOrbEntityAccessor", "LivingEntityMixin", "PlayerInventoryAccessor", "ServerPlayerEntityMixin",