From c68da4946c0512103813ba2229bdc29492ab2034 Mon Sep 17 00:00:00 2001 From: Patbox <39821509+Patbox@users.noreply.github.com> Date: Sun, 28 Nov 2021 10:38:34 +0100 Subject: [PATCH] [1.2.0] Update to 1.18 - Ported to 1.18 - You can disable creation of graves in void or in case of death from /kill command, - You can now add your own enchantments that will get skipped from adding to grave, - You can disable default compatibility with soulbound enchantment, - You can now allow attackers to take items from graves (disabled by default), - Added option for replacing any block with grave (instead of only air/fluids) - Changed some default config values, - Graves will be waterlogged now if visual block supports it --- build.gradle | 19 ++-- gradle.properties | 12 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- src/main/java/eu/pb4/graves/GravesMod.java | 13 +-- .../pb4/graves/compat/InventorioCompat.java | 2 +- .../java/eu/pb4/graves/config/Config.java | 100 +++++++++--------- .../eu/pb4/graves/config/data/ConfigData.java | 23 ++-- .../graves/config/data/old/ConfigDataV1.java | 1 - .../event/PlayerGraveCreationEvent.java | 1 + .../java/eu/pb4/graves/grave/GraveBlock.java | 36 +++---- .../eu/pb4/graves/grave/GraveBlockEntity.java | 11 +- .../java/eu/pb4/graves/grave/GraveGui.java | 2 +- .../java/eu/pb4/graves/grave/GraveInfo.java | 49 ++++++--- .../eu/pb4/graves/grave/GravesLookType.java | 50 +++++---- .../pb4/graves/mixin/LivingEntityMixin.java | 55 +++++++--- .../eu/pb4/graves/other/GraveListGui.java | 2 +- .../java/eu/pb4/graves/other/GraveUtils.java | 31 +++--- .../data/universal_graves/lang/en_us.json | 2 + src/main/resources/fabric.mod.json | 6 +- 19 files changed, 244 insertions(+), 173 deletions(-) diff --git a/build.gradle b/build.gradle index 59fd833..a764ee6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,10 @@ plugins { - id 'fabric-loom' version '0.9-SNAPSHOT' + id 'fabric-loom' version '0.10-SNAPSHOT' id 'maven-publish' } -sourceCompatibility = JavaVersion.VERSION_16 -targetCompatibility = JavaVersion.VERSION_16 +sourceCompatibility = JavaVersion.VERSION_17 +targetCompatibility = JavaVersion.VERSION_17 archivesBaseName = project.archives_base_name version = project.mod_version @@ -39,7 +39,6 @@ repositories { name 'Gegy' url 'https://maven.gegy.dev' } - } dependencies { @@ -52,11 +51,11 @@ dependencies { modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modImplementation include("eu.pb4:sgui:1.0.0-rc5+1.17.1") - modImplementation include("eu.pb4:hologram-api:0.2.1+1.17.1") - modImplementation include("eu.pb4:placeholder-api:1.1.2+1.17.1") - modImplementation include("eu.pb4:polymer:0.1.8+1.17.1") - modImplementation include("fr.catcore:server-translations-api:1.4.8+1.17") + 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.4+1.18-rc3") + modImplementation include("fr.catcore:server-translations-api:1.4.8+1.18-pre1") modImplementation include("me.lucko:fabric-permissions-api:0.1-SNAPSHOT") modCompileOnly "dev.emi:trinkets:3.0.4" @@ -87,7 +86,7 @@ tasks.withType(JavaCompile).configureEach { it.options.encoding = "UTF-8" // Minecraft 1.17 (21w19a) upwards uses Java 16. - it.options.release = 16 + it.options.release = 17 } java { diff --git a/gradle.properties b/gradle.properties index 547290d..29ce8d3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,14 +3,16 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use - minecraft_version=1.17.1 - yarn_mappings=1.17.1+build.59 - loader_version=0.11.6 + minecraft_version=1.18-rc3 + yarn_mappings=1.18-rc3+build.1 + loader_version=0.12.5 + + #Fabric api + fabric_version=0.43.1+1.18 # Mod Properties - mod_version = 1.1.4+1.17.1 + mod_version = 1.2.0+1.18 maven_group = eu.pb4 archives_base_name = graves # Dependencies - fabric_version=0.40.1+1.17 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf..e750102 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/eu/pb4/graves/GravesMod.java b/src/main/java/eu/pb4/graves/GravesMod.java index cdaaf6c..7ecf944 100644 --- a/src/main/java/eu/pb4/graves/GravesMod.java +++ b/src/main/java/eu/pb4/graves/GravesMod.java @@ -8,23 +8,19 @@ import eu.pb4.graves.grave.GraveBlockEntity; import eu.pb4.graves.grave.GraveManager; import eu.pb4.graves.other.Commands; -import eu.pb4.polymer.PolymerMod; -import eu.pb4.polymer.block.BlockHelper; +import eu.pb4.polymer.api.block.PolymerBlockUtils; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; -import net.minecraft.world.WorldEvents; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; public class GravesMod implements ModInitializer { public static final Logger LOGGER = LogManager.getLogger("Universal Graves"); @@ -32,6 +28,11 @@ public class GravesMod implements ModInitializer { public static final List DO_ON_NEXT_TICK = new ArrayList<>(); + private static boolean runRunners(Runnable c) { + c.run(); + return true; + } + @Override public void onInitialize() { this.crabboardDetection(); @@ -40,7 +41,7 @@ public void onInitialize() { Registry.register(Registry.BLOCK, new Identifier("universal_graves", "grave"), GraveBlock.INSTANCE); GraveBlockEntity.BLOCK_ENTITY_TYPE = Registry.register(Registry.BLOCK_ENTITY_TYPE, "universal_graves:grave", FabricBlockEntityTypeBuilder.create(GraveBlockEntity::new, GraveBlock.INSTANCE).build(null)); Commands.register(); - BlockHelper.registerVirtualBlockEntity(GraveBlockEntity.BLOCK_ENTITY_TYPE); + PolymerBlockUtils.registerBlockEntity(GraveBlockEntity.BLOCK_ENTITY_TYPE); if (loader.isModLoaded("trinkets")) { TrinketsCompat.register(); diff --git a/src/main/java/eu/pb4/graves/compat/InventorioCompat.java b/src/main/java/eu/pb4/graves/compat/InventorioCompat.java index 71435b8..3c0bd39 100644 --- a/src/main/java/eu/pb4/graves/compat/InventorioCompat.java +++ b/src/main/java/eu/pb4/graves/compat/InventorioCompat.java @@ -16,7 +16,7 @@ public static void register() { var stack = inv.getStack(i); if (!stack.isEmpty() && PlayerGraveItemAddedEvent.EVENT.invoker().canAddItem(player, stack) != ActionResult.FAIL - && !GraveUtils.hasSoulboundEnchantment(stack) + && !GraveUtils.hasSkippedEnchantment(stack) && !EnchantmentHelper.hasVanishingCurse(stack) ) { items.add(inv.removeStack(i)); diff --git a/src/main/java/eu/pb4/graves/config/Config.java b/src/main/java/eu/pb4/graves/config/Config.java index 85bf439..ab73d30 100644 --- a/src/main/java/eu/pb4/graves/config/Config.java +++ b/src/main/java/eu/pb4/graves/config/Config.java @@ -11,11 +11,13 @@ import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.CropBlock; +import net.minecraft.block.entity.BlockEntityType; import net.minecraft.command.argument.BlockArgumentParser; import net.minecraft.command.argument.ItemStringReader; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; @@ -54,9 +56,11 @@ public final class Config { @Nullable public final Text creationFailedGraveMessage; @Nullable - public final Text creationFailedPvPGraveMessage; + public final Text creationFailedVoidMessage; @Nullable - public final Text creationFailedClaimGraveMessage; + public final Text creationFailedPvPMessage; + @Nullable + public final Text creationFailedClaimMessage; public final GravesXPCalculation xpCalc; public final BlockStyleEntry[] customBlockStateStylesLocked; @@ -78,13 +82,14 @@ public Config(ConfigData data) { this.guiProtectedText = parse(data.guiProtectedText); this.guiText = parse(data.guiText); - this.noLongerProtectedMessage = !data.messageProtectionEnded.isEmpty() ? TextParser.parse(data.messageProtectionEnded) : null; - this.graveExpiredMessage = !data.messageGraveExpired.isEmpty() ? TextParser.parse(data.messageGraveExpired) : null; - this.graveBrokenMessage = !data.messageGraveBroken.isEmpty() ? TextParser.parse(data.messageGraveBroken) : null; - this.createdGraveMessage = !data.messageGraveCreated.isEmpty() ? TextParser.parse(data.messageGraveCreated) : null; - this.creationFailedGraveMessage = !data.messageCreationFailed.isEmpty() ? TextParser.parse(data.messageCreationFailed) : null; - this.creationFailedPvPGraveMessage = !data.messageCreationFailedPvP.isEmpty() ? TextParser.parse(data.messageCreationFailedPvP) : null; - this.creationFailedClaimGraveMessage = !data.messageCreationFailedClaim.isEmpty() ? TextParser.parse(data.messageCreationFailedClaim) : null; + this.noLongerProtectedMessage = parse(data.messageProtectionEnded); + this.graveExpiredMessage = parse(data.messageGraveExpired); + this.graveBrokenMessage = parse(data.messageGraveBroken); + this.createdGraveMessage = parse(data.messageGraveCreated); + this.creationFailedGraveMessage = parse(data.messageCreationFailed); + this.creationFailedVoidMessage = parse(data.messageCreationFailedVoid); + this.creationFailedPvPMessage = parse(data.messageCreationFailedPvP); + this.creationFailedClaimMessage = parse(data.messageCreationFailedClaim); this.customBlockStateStylesLocked = parseBlockStyles(this.configData.customBlockStateLockedStyles); this.customBlockStateStylesUnlocked = parseBlockStyles(this.configData.customBlockStateUnlockedStyles); @@ -93,7 +98,12 @@ public Config(ConfigData data) { this.guiItem = parseItems(this.configData.guiItem); } - public static ItemStack[] parseItems(List stringList) { + @Nullable + private static Text parse(String string) { + return !string.isEmpty() ? TextParser.parse(string) : null; + } + + private static ItemStack[] parseItems(List stringList) { var items = new ArrayList(); for (var itemDef : stringList) { @@ -116,7 +126,7 @@ public static ItemStack[] parseItems(List stringList) { return items.toArray(new ItemStack[0]); } - public static BlockStyleEntry[] parseBlockStyles(List stringList) { + private static BlockStyleEntry[] parseBlockStyles(List stringList) { var blockStates = new ArrayList(); for (String stateName : stringList) { @@ -125,11 +135,11 @@ public static BlockStyleEntry[] parseBlockStyles(List stringList) { if (stateData.getBlockState().getBlock() != GraveBlock.INSTANCE && stateData.getBlockState() != null) { if (stateData.getBlockState().hasBlockEntity()) { var blockEntity = ((BlockEntityProvider) stateData.getBlockState().getBlock()).createBlockEntity(BlockPos.ORIGIN, stateData.getBlockState()); - int i = -1; + BlockEntityType i = null; var packet = blockEntity.toUpdatePacket(); - if (packet != null) { - i = packet.getBlockEntityType(); + if (packet instanceof BlockEntityUpdateS2CPacket bePacket) { + i = bePacket.getBlockEntityType(); } if (stateData.getNbtData() != null) { @@ -138,19 +148,19 @@ public static BlockStyleEntry[] parseBlockStyles(List stringList) { blockStates.add(new BlockStyleEntry(stateData.getBlockState(), i, blockEntity.toInitialChunkDataNbt())); } else { - blockStates.add(new BlockStyleEntry(stateData.getBlockState(), -1, null)); + blockStates.add(new BlockStyleEntry(stateData.getBlockState(), null, null)); } } else { - blockStates.add(new BlockStyleEntry(Blocks.POTATOES.getDefaultState().with(CropBlock.AGE, 7), -1, null)); + blockStates.add(new BlockStyleEntry(Blocks.POTATOES.getDefaultState().with(CropBlock.AGE, 7), null, null)); } } catch (Exception e) { e.printStackTrace(); - blockStates.add(new BlockStyleEntry(Blocks.SKELETON_SKULL.getDefaultState(), -1, null)); + blockStates.add(new BlockStyleEntry(Blocks.SKELETON_SKULL.getDefaultState(), null, null)); } } if (blockStates.size() == 0) { - blockStates.add(new BlockStyleEntry(Blocks.SKELETON_SKULL.getDefaultState(), -1, null)); + blockStates.add(new BlockStyleEntry(Blocks.SKELETON_SKULL.getDefaultState(), null, null)); } return blockStates.toArray(new BlockStyleEntry[0]); @@ -158,40 +168,33 @@ public static BlockStyleEntry[] parseBlockStyles(List stringList) { public String getFormattedTime(long time) { - if (time != Long.MAX_VALUE) { + long seconds = time % 60; + long minutes = (time / 60) % 60; + long hours = (time / (60 * 60)) % 24; + long days = time / (60 * 60 * 24) % 365; + long years = time / (60 * 60 * 24 * 365); - long seconds = time % 60; - long minutes = (time / 60) % 60; - long hours = (time / (60 * 60)) % 24; - long days = time / (60 * 60 * 24) % 365; - long years = time / (60 * 60 * 24 * 365); + StringBuilder builder = new StringBuilder(); - StringBuilder builder = new StringBuilder(); - - if (years > 0) { - builder.append(years).append(configData.yearsText); - } - if (days > 0) { - builder.append(days).append(configData.daysText); - } - if (hours > 0) { - builder.append(hours).append(configData.hoursText); - } - if (minutes > 0) { - builder.append(minutes).append(configData.minutesText); - } - if (seconds >= 0) { - builder.append(seconds).append(configData.secondsText); - } else { - builder.append(time).append(configData.secondsText); - } - return builder.toString(); - } else { - return configData.neverExpires; + if (years > 0) { + builder.append(years).append(configData.yearsText); + } + if (days > 0) { + builder.append(days).append(configData.daysText); + } + if (hours > 0) { + builder.append(hours).append(configData.hoursText); + } + if (minutes > 0) { + builder.append(minutes).append(configData.minutesText); + } + if (seconds > 0 || time <= 0) { + builder.append(seconds).append(configData.secondsText); } + return builder.toString(); } - public static Text[] parse(List strings) { + private static Text[] parse(List strings) { List texts = new ArrayList<>(); for (String line : strings) { @@ -204,7 +207,8 @@ public static Text[] parse(List strings) { return texts.toArray(new Text[0]); } - public static record BlockStyleEntry(BlockState state, int blockEntityId, NbtCompound blockEntityNbt) { + public static record BlockStyleEntry(BlockState state, BlockEntityType blockEntityType, + NbtCompound blockEntityNbt) { } } 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 2804c40..c16211f 100644 --- a/src/main/java/eu/pb4/graves/config/data/ConfigData.java +++ b/src/main/java/eu/pb4/graves/config/data/ConfigData.java @@ -3,9 +3,11 @@ import eu.pb4.graves.grave.GravesLookType; import eu.pb4.graves.grave.GravesXPCalculation; import eu.pb4.graves.other.GraveUtils; +import net.minecraft.block.Block; import net.minecraft.block.Blocks; import net.minecraft.block.WallBlock; import net.minecraft.block.enums.WallShape; +import net.minecraft.tag.Tag; import java.util.*; @@ -32,18 +34,24 @@ public class ConfigData extends VersionedConfigData implements Cloneable { public int customStyleUpdateRate = 20; public boolean isProtected = true; - public int protectionTime = 300; - public int breakingTime = 900; + public int protectionTime = 900; + public int breakingTime = 1800; public boolean breakEmptyGraves = true; - public String xpStorageType = GravesXPCalculation.VANILLA.name; + public String xpStorageType = GravesXPCalculation.PERCENT_POINTS.name; public double xpPercentTypeValue = 100; + public boolean replaceAnyBlock = false; + //public boolean useRealTime = true; + public boolean createFromPvP = true; + public boolean createFromVoid = true; + public boolean createFromCommandDeaths = true; public boolean createInClaims = true; public boolean dropItemsAfterExpiring = true; public boolean shiftClickTakesItems = true; + public boolean allowAttackersToTakeItems = false; public String graveTitle = ""; @@ -59,24 +67,27 @@ public class ConfigData extends VersionedConfigData implements Cloneable { public List guiProtectedItem = Collections.singletonList("chest"); public List guiItem = Collections.singletonList("trapped_chest"); - public String messageGraveCreated = "${position}':'${world}'>"; + public String messageGraveCreated = "${position}':'${world}':'${break_time}'>"; public String messageProtectionEnded = "${position}':'${world}':'${item_count}'>"; public String messageGraveExpired = "${position}':'${world}':'${item_count}'>"; public String messageGraveBroken = "${position}':'${world}':'${item_count}'>"; public String messageCreationFailed = "${position}':'${world}'>"; + public String messageCreationFailedVoid = "${position}':'${world}'>"; public String messageCreationFailedPvP = "${position}':'${world}'>"; public String messageCreationFailedClaim = "${position}':'${world}'>"; - public String neverExpires = "Never"; - public String yearsText = "y"; public String daysText = "d"; public String hoursText = "h"; public String minutesText = "m"; public String secondsText = "s"; + public String infinityText = "∞"; + public Map worldNameOverrides = new HashMap<>(); + public boolean tryDetectionSoulbound = true; + public List skippedEnchantments = new ArrayList<>(); private static List getDefaultProtectedHologram() { diff --git a/src/main/java/eu/pb4/graves/config/data/old/ConfigDataV1.java b/src/main/java/eu/pb4/graves/config/data/old/ConfigDataV1.java index 957e28f..aa32844 100644 --- a/src/main/java/eu/pb4/graves/config/data/old/ConfigDataV1.java +++ b/src/main/java/eu/pb4/graves/config/data/old/ConfigDataV1.java @@ -144,7 +144,6 @@ public ConfigData update() { config.messageCreationFailed = this.displayCreationFailedGraveMessage ? this.creationFailedGraveMessage : ""; config.messageCreationFailedPvP = this.displayCreationFailedPvPGraveMessage ? this.creationFailedPvPGraveMessage : ""; config.messageCreationFailedClaim = this.displayCreationFailedClaimGraveMessage ? this.creationFailedClaimMessage : ""; - config.neverExpires = this.neverExpires; config.yearsText = this.yearsText; config.daysText = this.daysText; config.hoursText = this.hoursText; diff --git a/src/main/java/eu/pb4/graves/event/PlayerGraveCreationEvent.java b/src/main/java/eu/pb4/graves/event/PlayerGraveCreationEvent.java index 95d3022..7fe0fcd 100644 --- a/src/main/java/eu/pb4/graves/event/PlayerGraveCreationEvent.java +++ b/src/main/java/eu/pb4/graves/event/PlayerGraveCreationEvent.java @@ -29,6 +29,7 @@ enum CreationResult { BLOCK(false), BLOCK_PVP(false), BLOCK_CLAIM(false), + BLOCK_VOID(false), BLOCK_SILENT(false); private final boolean allow; diff --git a/src/main/java/eu/pb4/graves/grave/GraveBlock.java b/src/main/java/eu/pb4/graves/grave/GraveBlock.java index 9db9a16..a648339 100644 --- a/src/main/java/eu/pb4/graves/grave/GraveBlock.java +++ b/src/main/java/eu/pb4/graves/grave/GraveBlock.java @@ -2,7 +2,7 @@ import eu.pb4.graves.config.ConfigManager; import eu.pb4.graves.mixin.PlayerInventoryAccessor; -import eu.pb4.polymer.block.VirtualBlock; +import eu.pb4.polymer.api.block.PolymerBlock; import net.minecraft.block.*; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityTicker; @@ -12,6 +12,8 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.fluid.FluidState; +import net.minecraft.fluid.Fluids; import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemStack; import net.minecraft.item.ShieldItem; @@ -28,13 +30,14 @@ import org.jetbrains.annotations.Nullable; @SuppressWarnings({"deprecation"}) -public class GraveBlock extends Block implements VirtualBlock, BlockEntityProvider { +public class GraveBlock extends Block implements PolymerBlock, BlockEntityProvider, Waterloggable { public static BooleanProperty IS_LOCKED = BooleanProperty.of("is_locked"); public static GraveBlock INSTANCE = new GraveBlock(); private GraveBlock() { super(AbstractBlock.Settings.of(Material.METAL).dropsNothing().strength(2, 999)); + this.setDefaultState(this.getStateManager().getDefaultState().with(Properties.WATERLOGGED, false)); } public static void insertStack(PlayerInventory inventory, ItemStack stack) { @@ -47,7 +50,6 @@ public static void insertStack(PlayerInventory inventory, ItemStack stack) { if (slot >= 0) { inventory.main.set(slot, stack.copy()); - inventory.main.get(slot).setCooldown(5); stack.setCount(0); } } else { @@ -65,7 +67,7 @@ public static void insertStack(PlayerInventory inventory, ItemStack stack) { @Override protected void appendProperties(StateManager.Builder builder) { - builder.add(Properties.ROTATION).add(IS_LOCKED); + builder.add(Properties.ROTATION, IS_LOCKED, Properties.WATERLOGGED); } @Override @@ -134,31 +136,27 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt } @Override - public Block getVirtualBlock() { - return ConfigManager.getConfig().style.converter.getBlock(false); + public Block getPolymerBlock(BlockState state) { + return ConfigManager.getConfig().style.converter.getBlock(state.get(IS_LOCKED)); } @Override - public Block getVirtualBlock(BlockPos pos, World world) { - return ConfigManager.getConfig().style.converter.getBlock(world.getBlockState(pos).get(IS_LOCKED)); + public BlockState getPolymerBlockState(BlockState state) { + return ConfigManager.getConfig().style.converter.getBlockState(state.get(Properties.ROTATION), state.get(IS_LOCKED), state.get(Properties.WATERLOGGED)); } - - public BlockState getDefaultVirtualBlockState() { - return ConfigManager.getConfig().style.converter.getBlockState(0, true); - } - - public BlockState getVirtualBlockState(BlockState state) { - return ConfigManager.getConfig().style.converter.getBlockState(state.get(Properties.ROTATION), state.get(IS_LOCKED)); - } - - public void sendPacketsAfterCreation(ServerPlayerEntity player, BlockPos pos, BlockState state) { + @Override + public void onPolymerBlockSend(ServerPlayerEntity player, BlockPos.Mutable pos, BlockState state) { BlockEntity blockEntity = player.world.getBlockEntity(pos); if (blockEntity instanceof GraveBlockEntity grave) { - ConfigManager.getConfig().style.converter.sendNbt(player, state, pos, state.get(Properties.ROTATION), state.get(IS_LOCKED), grave.info); + ConfigManager.getConfig().style.converter.sendNbt(player, state, pos.toImmutable(), state.get(Properties.ROTATION), state.get(IS_LOCKED), grave.info); } } + public FluidState getFluidState(BlockState state) { + return state.get(Properties.WATERLOGGED) ? Fluids.WATER.getStill(false) : super.getFluidState(state); + } + @Nullable @Override public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { diff --git a/src/main/java/eu/pb4/graves/grave/GraveBlockEntity.java b/src/main/java/eu/pb4/graves/grave/GraveBlockEntity.java index 93495bf..c73e9e3 100644 --- a/src/main/java/eu/pb4/graves/grave/GraveBlockEntity.java +++ b/src/main/java/eu/pb4/graves/grave/GraveBlockEntity.java @@ -55,7 +55,7 @@ public DefaultedList getItems() { return this.stacks; } - public void setGrave(GameProfile profile, Collection itemStacks, int experience, Text deathCause, BlockState blockState) { + public void setGrave(GameProfile profile, Collection itemStacks, int experience, Text deathCause, BlockState blockState, Collection allowedUUIDs) { if (this.world == null || !(this.world instanceof ServerWorld)) { return; } @@ -68,7 +68,7 @@ public void setGrave(GameProfile profile, Collection itemStacks, int } this.replacedBlockState = blockState; - this.info = new GraveInfo(profile, this.pos, Objects.requireNonNull(this.getWorld()).getRegistryKey().getValue(), System.currentTimeMillis() / 1000, experience, itemStacks.size(), deathCause); + this.info = new GraveInfo(profile, this.pos, Objects.requireNonNull(this.getWorld()).getRegistryKey().getValue(), System.currentTimeMillis() / 1000, experience, itemStacks.size(), deathCause, allowedUUIDs); GraveManager.INSTANCE.add(this.info); this.markDirty(); @@ -77,7 +77,7 @@ public void setGrave(GameProfile profile, Collection itemStacks, int } @Override - public NbtCompound writeNbt(NbtCompound nbt) { + protected void writeNbt(NbtCompound nbt) { super.writeNbt(nbt); NbtList nbtList = new NbtList(); @@ -96,7 +96,6 @@ public NbtCompound writeNbt(NbtCompound nbt) { nbt.put("GraveInfo", this.info.writeNbt(new NbtCompound())); nbt.put("BlockState", NbtHelper.fromBlockState(this.replacedBlockState)); - return nbt; } @@ -142,7 +141,7 @@ public void onBroken() { assert world != null; ServerPlayerEntity player = Objects.requireNonNull(world.getServer()).getPlayerManager().getPlayer(this.info.gameProfile.getId()); if (player != null) { - player.sendMessage(PlaceholderAPI.parsePredefinedText(text, PlaceholderAPI.PREDEFINED_PLACEHOLDER_PATTERN, this.info.getPlaceholders()), MessageType.SYSTEM, Util.NIL_UUID); + player.sendMessage(PlaceholderAPI.parsePredefinedText(text, PlaceholderAPI.PREDEFINED_PLACEHOLDER_PATTERN, this.info.getPlaceholders(this.world.getServer())), MessageType.SYSTEM, Util.NIL_UUID); } } @@ -211,7 +210,7 @@ public static void tick(World world, BlockPos pos, Block Config config = ConfigManager.getConfig(); - Map placeholders = self.info.getPlaceholders(); + Map placeholders = self.info.getPlaceholders(self.world.getServer()); if (config.configData.breakingTime > -1 && self.info.shouldBreak()) { world.setBlockState(pos, self.replacedBlockState, Block.NOTIFY_ALL); diff --git a/src/main/java/eu/pb4/graves/grave/GraveGui.java b/src/main/java/eu/pb4/graves/grave/GraveGui.java index 1b7c5b5..c25153a 100644 --- a/src/main/java/eu/pb4/graves/grave/GraveGui.java +++ b/src/main/java/eu/pb4/graves/grave/GraveGui.java @@ -22,7 +22,7 @@ public GraveGui(ServerPlayerEntity player, GraveBlockEntity grave) { super(getScreenHandlerType(grave.info.itemCount), player, false); this.grave = grave; GuiElementBuilder emptyPane = new GuiElementBuilder(Items.GRAY_STAINED_GLASS_PANE).hideFlags().setName(new LiteralText("")); - this.setTitle(PlaceholderAPI.parsePredefinedText(ConfigManager.getConfig().graveTitle, PlaceholderAPI.PREDEFINED_PLACEHOLDER_PATTERN, grave.info.getPlaceholders())); + this.setTitle(PlaceholderAPI.parsePredefinedText(ConfigManager.getConfig().graveTitle, PlaceholderAPI.PREDEFINED_PLACEHOLDER_PATTERN, grave.info.getPlaceholders(grave.getWorld().getServer()))); int x = 0; int skipped = 0; for (; x < this.grave.size(); x++) { diff --git a/src/main/java/eu/pb4/graves/grave/GraveInfo.java b/src/main/java/eu/pb4/graves/grave/GraveInfo.java index 0d0e347..b0f2c13 100644 --- a/src/main/java/eu/pb4/graves/grave/GraveInfo.java +++ b/src/main/java/eu/pb4/graves/grave/GraveInfo.java @@ -6,8 +6,8 @@ import eu.pb4.graves.other.GraveUtils; import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtHelper; +import net.minecraft.nbt.*; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; @@ -28,6 +28,7 @@ public final class GraveInfo { protected Text deathCause; protected BlockPos position; protected Identifier world; + protected Set allowedUUIDs; public GraveInfo() { this.gameProfile = DEFAULT_GAME_PROFILE; @@ -37,9 +38,10 @@ public GraveInfo() { this.deathCause = DEFAULT_DEATH_CAUSE; this.position = BlockPos.ORIGIN; this.world = ServerWorld.OVERWORLD.getValue(); + this.allowedUUIDs = new HashSet<>(); } - public GraveInfo(GameProfile profile, BlockPos position, Identifier world, long creationTime, int xp, int itemCount, Text deathCause) { + public GraveInfo(GameProfile profile, BlockPos position, Identifier world, long creationTime, int xp, int itemCount, Text deathCause, Collection allowedUUIDs) { this.gameProfile = profile; this.creationTime = creationTime; this.xp = xp; @@ -47,6 +49,7 @@ public GraveInfo(GameProfile profile, BlockPos position, Identifier world, long this.deathCause = deathCause; this.position = position; this.world = world; + this.allowedUUIDs = new HashSet<>(allowedUUIDs); } public NbtCompound writeNbt(NbtCompound nbt) { @@ -59,21 +62,37 @@ public NbtCompound writeNbt(NbtCompound nbt) { nbt.putString("DeathCause", Text.Serializer.toJson(this.deathCause)); nbt.putIntArray("Position", new int[] { position.getX(), position.getY(), position.getZ() }); nbt.putString("World", this.world.toString()); + + var list = new NbtList(); + for (var uuid : this.allowedUUIDs) { + list.add(NbtHelper.fromUuid(uuid)); + } + + nbt.put("AllowedUUIDs", list); return nbt; } public void readNbt(NbtCompound nbt) { - this.gameProfile = NbtHelper.toGameProfile(nbt.getCompound("GameProfile")); - this.xp = nbt.getInt("XP"); - this.creationTime = nbt.getLong("CreationTime"); - this.itemCount = nbt.getInt("ItemCount"); - this.deathCause = Text.Serializer.fromLenientJson(nbt.getString("DeathCause")); - int[] pos = nbt.getIntArray("Position"); - this.position = new BlockPos(pos[0], pos[1], pos[2]); - this.world = Identifier.tryParse(nbt.getString("World")); + try { + this.gameProfile = NbtHelper.toGameProfile(nbt.getCompound("GameProfile")); + this.xp = nbt.getInt("XP"); + this.creationTime = nbt.getLong("CreationTime"); + this.itemCount = nbt.getInt("ItemCount"); + this.deathCause = Text.Serializer.fromLenientJson(nbt.getString("DeathCause")); + int[] pos = nbt.getIntArray("Position"); + this.position = new BlockPos(pos[0], pos[1], pos[2]); + this.world = Identifier.tryParse(nbt.getString("World")); + this.allowedUUIDs.clear(); + + for (var nbtUUID : nbt.getList("AllowedUUIDs", NbtElement.INT_ARRAY_TYPE)) { + this.allowedUUIDs.add(NbtHelper.toUuid(nbtUUID)); + } + } catch (Exception e) { + e.printStackTrace(); + } } - public Map getPlaceholders() { + public Map getPlaceholders(MinecraftServer server) { Config config = ConfigManager.getConfig(); long currentTime = System.currentTimeMillis() / 1000; @@ -83,8 +102,8 @@ public Map getPlaceholders() { Map values = new HashMap<>(); values.put("player", new LiteralText(this.gameProfile != null ? this.gameProfile.getName() : "")); - values.put("protection_time", new LiteralText("" + (config.configData.protectionTime > -1 ? config.getFormattedTime(protectionTime) : "∞"))); - values.put("break_time", new LiteralText("" + (config.configData.breakingTime > -1 ? config.getFormattedTime(breakTime) : "∞"))); + values.put("protection_time", new LiteralText("" + (config.configData.protectionTime > -1 ? config.getFormattedTime(protectionTime) : config.configData.infinityText))); + values.put("break_time", new LiteralText("" + (config.configData.breakingTime > -1 ? config.getFormattedTime(breakTime) : config.configData.infinityText))); values.put("xp", new LiteralText("" + this.xp)); values.put("item_count", new LiteralText("" + this.itemCount)); values.put("position", new LiteralText("" + this.position.toShortString())); @@ -120,7 +139,7 @@ public boolean isProtected() { } public boolean canTakeFrom(PlayerEntity entity) { - return !this.isProtected() || this.gameProfile.getId().equals(entity.getUuid()) || Permissions.check(entity, "graves.can_open_others", 3); + return !this.isProtected() || this.gameProfile.getId().equals(entity.getUuid()) || this.allowedUUIDs.contains(entity.getUuid()) || Permissions.check(entity, "graves.can_open_others", 3); } public GameProfile getProfile() { diff --git a/src/main/java/eu/pb4/graves/grave/GravesLookType.java b/src/main/java/eu/pb4/graves/grave/GravesLookType.java index 4cb290f..28c557f 100644 --- a/src/main/java/eu/pb4/graves/grave/GravesLookType.java +++ b/src/main/java/eu/pb4/graves/grave/GravesLookType.java @@ -2,11 +2,14 @@ import eu.pb4.graves.config.ConfigManager; import eu.pb4.placeholders.PlaceholderAPI; +import eu.pb4.polymer.mixin.block.BlockEntityUpdateS2CPacketAccessor; +import fr.catcore.server.translations.api.LocalizationTarget; +import fr.catcore.server.translations.api.text.LocalizableText; import net.minecraft.block.*; +import net.minecraft.block.entity.BlockEntityType; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtHelper; import net.minecraft.nbt.NbtList; -import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.state.property.Properties; import net.minecraft.text.Text; @@ -32,7 +35,7 @@ public Block getBlock(boolean isLocked) { } @Override - public BlockState getBlockState(int direction, boolean isLocked) { + public BlockState getBlockState(int direction, boolean isLocked, boolean waterlogged) { return getBlock(isLocked).getDefaultState().with(PlayerSkullBlock.ROTATION, direction); } @@ -55,7 +58,7 @@ public Block getBlock(boolean isLocked) { } @Override - public BlockState getBlockState(int direction, boolean isLocked) { + public BlockState getBlockState(int direction, boolean isLocked, boolean waterlogged) { return getBlock(isLocked).getDefaultState().with(PlayerSkullBlock.ROTATION, direction); } @@ -89,10 +92,11 @@ public Block getBlock(boolean isLocked) { } @Override - public BlockState getBlockState(int direction, boolean isLocked) { + public BlockState getBlockState(int direction, boolean isLocked, boolean waterlogged) { var config = ConfigManager.getConfig(); var list = (isLocked ? config.customBlockStateStylesLocked : config.customBlockStateStylesUnlocked); - return list[direction % list.length].state(); + var state = list[direction % list.length].state(); + return state.getBlock() instanceof Waterloggable ? state.with(Properties.WATERLOGGED, waterlogged) : state; } @Override @@ -101,27 +105,28 @@ public void sendNbt(ServerPlayerEntity player, BlockState state, BlockPos pos, i var list = (isLocked ? config.customBlockStateStylesLocked : config.customBlockStateStylesUnlocked); var entry = list[direction % list.length]; - if (entry.blockEntityId() != -1 && entry.blockEntityNbt() != null) { + if (entry.blockEntityType() != null && entry.blockEntityNbt() != null) { var compound = entry.blockEntityNbt().copy(); - if (entry.blockEntityId() == BlockEntityUpdateS2CPacket.SIGN) { - var texts = isLocked ? config.signProtectedText : config.signText; - var placeholders = graveInfo.getPlaceholders(); - var size = Math.min(4, texts.length); - for (int i = 0; i < size; i++) { - compound.putString("Text" + (i + 1), - Text.Serializer.toJson( - PlaceholderAPI.parsePredefinedText(texts[i], PlaceholderAPI.PREDEFINED_PLACEHOLDER_PATTERN, placeholders) - ) - ); - } + var texts = isLocked ? config.signProtectedText : config.signText; + var placeholders = graveInfo.getPlaceholders(player.getServer()); + var size = Math.min(4, texts.length); + + var target = (LocalizationTarget) player; + + for (int i = 0; i < size; i++) { + compound.putString("Text" + (i + 1), + Text.Serializer.toJson( + LocalizableText.asLocalizedFor(PlaceholderAPI.parsePredefinedText(texts[i], PlaceholderAPI.PREDEFINED_PLACEHOLDER_PATTERN, placeholders), target) + ) + ); } compound.putInt("x", pos.getX()); compound.putInt("y", pos.getY()); compound.putInt("z", pos.getZ()); - player.networkHandler.sendPacket(new BlockEntityUpdateS2CPacket(pos, entry.blockEntityId(), compound)); + player.networkHandler.sendPacket(BlockEntityUpdateS2CPacketAccessor.createBlockEntityUpdateS2CPacket(pos, entry.blockEntityType(), compound)); } } @@ -161,12 +166,13 @@ public Block getBlock(boolean isLocked) { } @Override - public BlockState getBlockState(int rotation, boolean isLocked) { + public BlockState getBlockState(int rotation, boolean isLocked, boolean waterlogged) { boolean chest = this.getBlock(isLocked) instanceof ChestBlock; Direction direction = chest ? Direction.fromHorizontal(rotation / 4).getOpposite() : Direction.byId(rotation / 6); - return (isLocked ? locked : unlocked).with(chest ? ChestBlock.FACING : Properties.FACING, direction); + var state = (isLocked ? locked : unlocked).with(chest ? ChestBlock.FACING : Properties.FACING, direction); + return state.getBlock() instanceof Waterloggable ? state.with(Properties.WATERLOGGED, waterlogged) : state; } @Override @@ -181,14 +187,14 @@ public static void sendHeadToPlayer(ServerPlayerEntity player, BlockPos pos, Nbt compound.putInt("x", pos.getX()); compound.putInt("y", pos.getY()); compound.putInt("z", pos.getZ()); - player.networkHandler.sendPacket(new BlockEntityUpdateS2CPacket(pos, 4, compound)); + player.networkHandler.sendPacket(BlockEntityUpdateS2CPacketAccessor.createBlockEntityUpdateS2CPacket(pos, BlockEntityType.SKULL, compound)); } } public interface Converter { Block getBlock(boolean isLocked); - BlockState getBlockState(int direction, boolean isLocked); + BlockState getBlockState(int direction, boolean isLocked, boolean waterlogged); void sendNbt(ServerPlayerEntity player, BlockState state, BlockPos pos, int direction, boolean isLocked, GraveInfo graveInfo); diff --git a/src/main/java/eu/pb4/graves/mixin/LivingEntityMixin.java b/src/main/java/eu/pb4/graves/mixin/LivingEntityMixin.java index ad11a66..a8b5fbf 100644 --- a/src/main/java/eu/pb4/graves/mixin/LivingEntityMixin.java +++ b/src/main/java/eu/pb4/graves/mixin/LivingEntityMixin.java @@ -11,6 +11,7 @@ import eu.pb4.graves.grave.GravesXPCalculation; import eu.pb4.graves.other.GraveUtils; import eu.pb4.placeholders.PlaceholderAPI; +import net.fabricmc.fabric.api.tag.TagFactory; import net.fabricmc.fabric.api.tag.TagRegistry; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -22,7 +23,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.network.MessageType; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; import net.minecraft.state.property.Properties; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; @@ -34,21 +34,28 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.GameRules; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; @Mixin(LivingEntity.class) public abstract class LivingEntityMixin { + + @Unique + private boolean graves_commandKill = false; + + @Inject(method = "kill", at = @At("HEAD")) + private void graves_onKill(CallbackInfo ci) { + this.graves_commandKill = true; + } + @Inject(method = "drop", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;dropInventory()V", shift = At.Shift.BEFORE), cancellable = true) private void replaceWithGrave(DamageSource source, CallbackInfo ci) { if (((Object) this) instanceof ServerPlayerEntity player) { - if (player.getServerWorld().getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) { + if (player.getWorld().getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) { return; } @@ -57,17 +64,21 @@ private void replaceWithGrave(DamageSource source, CallbackInfo ci) { Text text = null; Map placeholders = Map.of( "position", new LiteralText("" + player.getBlockPos().toShortString()), - "world", new LiteralText(GraveUtils.toWorldName(player.getServerWorld().getRegistryKey().getValue())) + "world", new LiteralText(GraveUtils.toWorldName(player.getWorld().getRegistryKey().getValue())) ); if (!config.configData.createFromPvP && source.getAttacker() instanceof PlayerEntity) { - text = config.creationFailedPvPGraveMessage; + text = config.creationFailedPvPMessage; + } else if (!config.configData.createFromCommandDeaths && this.graves_commandKill) { + + } else if (!config.configData.createFromVoid && source == DamageSource.OUT_OF_WORLD && !this.graves_commandKill) { + text = config.creationFailedPvPMessage; } else { var eventResult = PlayerGraveCreationEvent.EVENT.invoker().shouldCreate(player); if (eventResult.canCreate()) { - var result = GraveUtils.findGravePosition(player, player.getServerWorld(), player.getBlockPos(), TagRegistry.block(GraveUtils.REPLACEABLE_TAG)); + var result = GraveUtils.findGravePosition(player, player.getWorld(), player.getBlockPos(), config.configData.replaceAnyBlock); if (result.result().canCreate()) { BlockPos gravePos = result.pos(); @@ -77,7 +88,7 @@ private void replaceWithGrave(DamageSource source, CallbackInfo ci) { ItemStack itemStack = player.getInventory().getStack(i); if (!itemStack.isEmpty() && PlayerGraveItemAddedEvent.EVENT.invoker().canAddItem(player, itemStack) != ActionResult.FAIL - && !GraveUtils.hasSoulboundEnchantment(itemStack) + && !GraveUtils.hasSkippedEnchantment(itemStack) && !EnchantmentHelper.hasVanishingCurse(itemStack) ) { items.add(player.getInventory().removeStack(i)); @@ -99,9 +110,20 @@ private void replaceWithGrave(DamageSource source, CallbackInfo ci) { } int finalI = i; - var world = player.getServerWorld(); + var world = player.getWorld(); var gameProfile = player.getGameProfile(); + var allowedUUID = new HashSet(); + + if (config.configData.allowAttackersToTakeItems) { + if (source.getAttacker() instanceof ServerPlayerEntity playerEntity) { + allowedUUID.add(playerEntity.getUuid()); + } + if (player.getAttacker() instanceof ServerPlayerEntity playerEntity) { + allowedUUID.add(playerEntity.getUuid()); + } + } + GravesMod.DO_ON_NEXT_TICK.add(() -> { Text text2 = null; Map placeholders2 = placeholders; @@ -110,9 +132,9 @@ private void replaceWithGrave(DamageSource source, CallbackInfo ci) { BlockEntity entity = world.getBlockEntity(gravePos); if (entity instanceof GraveBlockEntity grave) { - grave.setGrave(gameProfile, items, finalI, source.getDeathMessage(player), oldBlockState); + grave.setGrave(gameProfile, items, finalI, source.getDeathMessage(player), oldBlockState, allowedUUID); text2 = config.createdGraveMessage; - placeholders2 = grave.info.getPlaceholders(); + placeholders2 = grave.info.getPlaceholders(player.getServer()); } else { if (config.xpCalc != GravesXPCalculation.DROP) { ExperienceOrbEntity.spawn(world, Vec3d.ofCenter(gravePos), finalI); @@ -128,15 +150,16 @@ private void replaceWithGrave(DamageSource source, CallbackInfo ci) { } else { text = switch (result.result()) { case BLOCK -> config.creationFailedGraveMessage; - case BLOCK_CLAIM -> config.creationFailedClaimGraveMessage; + case BLOCK_CLAIM -> config.creationFailedClaimMessage; case ALLOW -> null; }; } } else { text = switch (eventResult) { case BLOCK -> config.creationFailedGraveMessage; - case BLOCK_CLAIM -> config.creationFailedClaimGraveMessage; - case BLOCK_PVP -> config.creationFailedPvPGraveMessage; + case BLOCK_CLAIM -> config.creationFailedClaimMessage; + case BLOCK_PVP -> config.creationFailedPvPMessage; + case BLOCK_VOID -> config.creationFailedVoidMessage; default -> null; }; } diff --git a/src/main/java/eu/pb4/graves/other/GraveListGui.java b/src/main/java/eu/pb4/graves/other/GraveListGui.java index c879fd7..a58ede0 100644 --- a/src/main/java/eu/pb4/graves/other/GraveListGui.java +++ b/src/main/java/eu/pb4/graves/other/GraveListGui.java @@ -54,7 +54,7 @@ private void updateIcons() { return; } - Map placeholders = graveInfo.getPlaceholders(); + Map placeholders = graveInfo.getPlaceholders(this.player.getServer()); List parsed = new ArrayList<>(); for (Text text : graveInfo.isProtected() ? ConfigManager.getConfig().guiProtectedText : ConfigManager.getConfig().guiText) { diff --git a/src/main/java/eu/pb4/graves/other/GraveUtils.java b/src/main/java/eu/pb4/graves/other/GraveUtils.java index a4af079..fbf01d7 100644 --- a/src/main/java/eu/pb4/graves/other/GraveUtils.java +++ b/src/main/java/eu/pb4/graves/other/GraveUtils.java @@ -3,10 +3,13 @@ import eu.pb4.graves.config.ConfigManager; import eu.pb4.graves.event.GraveValidPosCheckEvent; +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.item.ItemStack; +import net.minecraft.nbt.NbtCompound; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.state.property.Property; @@ -26,7 +29,8 @@ import java.util.stream.Collectors; public class GraveUtils { - public static final Identifier REPLACEABLE_TAG = new Identifier("universal_graves", "replaceable"); + public static final Identifier REPLACEABLE_ID = new Identifier("universal_graves", "replaceable"); + public static final Tag REPLACEABLE_TAG = TagFactory.BLOCK.create(GraveUtils.REPLACEABLE_ID); private static final Function, Comparable>, String> PROPERTY_MAP_PRINTER = new Function<>() { public String apply(@Nullable Map.Entry, Comparable> entry) { if (entry == null) { @@ -42,13 +46,13 @@ private > String nameValue(Property property, Compara } }; - public static BlockCheckResult findGravePosition(ServerPlayerEntity player, ServerWorld world, BlockPos blockPos, Tag replaceable) { + public static BlockCheckResult findGravePosition(ServerPlayerEntity player, ServerWorld world, BlockPos blockPos, boolean anyBlock) { int maxDistance = 8; int line = 1; var border = world.getWorldBorder(); - blockPos = new BlockPos(MathHelper.clamp(blockPos.getX(), border.getBoundWest() + 1, border.getBoundEast() - 1), MathHelper.clamp(blockPos.getY(), world.getBottomY(), world.getTopY() - 1), MathHelper.clamp(blockPos.getZ() + 1, border.getBoundNorth(), border.getBoundSouth() - 1)); - BlockResult result = isValidPos(player, world, border, blockPos, replaceable); + blockPos = new BlockPos(MathHelper.clamp(blockPos.getX(), border.getBoundWest() + 1, border.getBoundEast() - 1), MathHelper.clamp(blockPos.getY(), world.getBottomY(), world.getTopY() - 1), MathHelper.clamp(blockPos.getZ(), border.getBoundNorth() + 1, border.getBoundSouth() - 1)); + BlockResult result = isValidPos(player, world, border, blockPos, anyBlock); BlockResult tempResult; if (result.allow) { return new BlockCheckResult(blockPos, result); @@ -66,7 +70,7 @@ public static BlockCheckResult findGravePosition(ServerPlayerEntity player, Serv continue; } - tempResult = isValidPos(player, world, border, pos, replaceable); + tempResult = isValidPos(player, world, border, pos, anyBlock); if (tempResult.priority >= result.priority) { result = tempResult; } @@ -83,9 +87,9 @@ public static BlockCheckResult findGravePosition(ServerPlayerEntity player, Serv } - private static BlockResult isValidPos(ServerPlayerEntity player, ServerWorld world, WorldBorder border, BlockPos pos, Tag replaceable) { + 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() || replaceable.contains(state.getBlock()))) { + 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); } else { return BlockResult.BLOCK; @@ -122,11 +126,14 @@ public static String toWorldName(Identifier identifier) { return String.join(" ", parts); } - public static boolean hasSoulboundEnchantment(ItemStack stack) { - for (var enchant : EnchantmentHelper.get(stack).keySet()) { - var key = Registry.ENCHANTMENT.getId(enchant); - if (key.getPath().contains("soulbound") || key.getPath().contains("soul_bound")) { - return true; + public static boolean hasSkippedEnchantment(ItemStack stack) { + var config = ConfigManager.getConfig().configData; + for (var enchant : stack.getEnchantments()) { + if (enchant instanceof NbtCompound compound) { + var key = EnchantmentHelper.getIdFromNbt(compound); + if (key != null && config.skippedEnchantments.contains(key.toString()) || (config.tryDetectionSoulbound && (key.getPath().contains("soulbound") || key.getPath().contains("soul_bound")))) { + return true; + } } } return false; diff --git a/src/main/resources/data/universal_graves/lang/en_us.json b/src/main/resources/data/universal_graves/lang/en_us.json index cb4f683..6419ab0 100644 --- a/src/main/resources/data/universal_graves/lang/en_us.json +++ b/src/main/resources/data/universal_graves/lang/en_us.json @@ -11,7 +11,9 @@ "text.graves.expired": "Your grave at %s (%s) containing %s item(s) expired!", "text.graves.somebody_broke": "Your grave at %s (%s) containing %s item(s) has been broken!", "text.graves.created_at": "Created grave at %s (%s)", + "text.graves.created_at_expire": "Created grave at %s (%s). It will expire in %s", "text.graves.creation_failed": "Couldn't create grave! Your items were dropped at %s (%s)", + "text.graves.creation_failed_void": "Grave wasn't created, because you died in void!", "text.graves.creation_failed_pvp": "Grave wasn't created, because player killed you! Your items were dropped at %s (%s)", "text.graves.creation_failed_claim": "Grave wasn't created, because you were in a claim! Your items were dropped at %s (%s)", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 9a1154e..21a711a 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -26,9 +26,9 @@ ], "depends": { - "fabricloader": ">=0.11.3", + "fabricloader": ">=0.12.0", "fabric": "*", - "minecraft": ">=1.17.1", - "java": ">=16" + "minecraft": ">=1.18-rc.1", + "java": ">=17" } }