diff --git a/src/main/java/twilightforest/util/BoundingBoxUtils.java b/src/main/java/twilightforest/util/BoundingBoxUtils.java index 865f92d992..a072e8e22f 100644 --- a/src/main/java/twilightforest/util/BoundingBoxUtils.java +++ b/src/main/java/twilightforest/util/BoundingBoxUtils.java @@ -51,12 +51,12 @@ public static CompoundTag boundingBoxToExistingNBT(BoundingBox box, CompoundTag public static BoundingBox NBTToBoundingBox(CompoundTag nbt) { return new BoundingBox( - nbt.getInt("minX"), - nbt.getInt("minY"), - nbt.getInt("minZ"), - nbt.getInt("maxX"), - nbt.getInt("maxY"), - nbt.getInt("maxZ") + nbt.getIntOr("minX", 0), + nbt.getIntOr("minY", 0), + nbt.getIntOr("minZ", 0), + nbt.getIntOr("maxX", 0), + nbt.getIntOr("maxY", 0), + nbt.getIntOr("maxZ", 0) ); } @@ -92,7 +92,7 @@ public static BoundingBox getComponentToAddBoundingBox(int x, int y, int z, int public static AABB vectorsMinMax(List vec3List, double expand) { if (vec3List.isEmpty()) return null; - Vec3 first = vec3List.get(0); + Vec3 first = vec3List.getFirst(); return new AABB( vec3List.stream().mapToDouble(Vec3::x).reduce(first.x, Math::min) - expand, diff --git a/src/main/java/twilightforest/util/DisplayUtil.java b/src/main/java/twilightforest/util/DisplayUtil.java index 03effac1b8..4443847f2c 100644 --- a/src/main/java/twilightforest/util/DisplayUtil.java +++ b/src/main/java/twilightforest/util/DisplayUtil.java @@ -2,14 +2,21 @@ import com.mojang.math.Transformation; import com.mojang.serialization.DataResult; +import com.mojang.serialization.JsonOps; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.*; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.resources.RegistryOps; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.ValueInput; import org.joml.Matrix4f; import tamaized.beanification.Component; @@ -43,7 +50,9 @@ public boolean spawnBlockDisplay(Level level, BoundingBox box, BlockState displa entityNBT.putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(EntityType.BLOCK_DISPLAY).toString()); - Optional spawned = EntityType.create(entityNBT, level); + ProblemReporter.Collector entitySpawnReporter = new ProblemReporter.Collector(); + ValueInput valueInput = TagValueInput.create(entitySpawnReporter, level.registryAccess(), entityNBT); + Optional spawned = EntityType.create(valueInput, level, EntitySpawnReason.LOAD); if (spawned.isEmpty()) return false; Entity entity = spawned.get(); @@ -65,7 +74,9 @@ public void setTextEntity(Level level, double x, double y, double z, Display.Bil CompoundTag entityNBT = new CompoundTag(); entityNBT.put("Pos", this.newDoubleList(x, y, z)); - entityNBT.putString("text", net.minecraft.network.chat.Component.Serializer.toJson(name, level.registryAccess())); + var registryOps = RegistryOps.create(JsonOps.INSTANCE, level.registryAccess()); + String jsonText = ComponentSerialization.CODEC.encodeStart(registryOps, name).getOrThrow().toString(); + entityNBT.putString("text", jsonText); DataResult serializedAlignment = Display.TextDisplay.Align.CODEC.encodeStart(NbtOps.INSTANCE, Display.TextDisplay.Align.CENTER); if (serializedAlignment.isSuccess()) { @@ -83,7 +94,9 @@ public void setTextEntity(Level level, double x, double y, double z, Display.Bil entityNBT.putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(EntityType.TEXT_DISPLAY).toString()); - Optional spawned = EntityType.create(entityNBT, level); + ProblemReporter.Collector entitySpawnReporter = new ProblemReporter.Collector(); + ValueInput valueInput = TagValueInput.create(entitySpawnReporter, level.registryAccess(), entityNBT); + Optional spawned = EntityType.create(valueInput, level, EntitySpawnReason.LOAD); if (spawned.isEmpty()) return; Entity entity = spawned.get(); diff --git a/src/main/java/twilightforest/util/PlayerHelper.java b/src/main/java/twilightforest/util/PlayerHelper.java index 0a362ed5d0..3264e04d22 100644 --- a/src/main/java/twilightforest/util/PlayerHelper.java +++ b/src/main/java/twilightforest/util/PlayerHelper.java @@ -21,7 +21,7 @@ public class PlayerHelper { @Deprecated public static void grantAdvancement(ServerPlayer player, Identifier id) { PlayerAdvancements advancements = player.getAdvancements(); - AdvancementHolder holder = player.getServer().getAdvancements().get(id); + AdvancementHolder holder = player.level().getServer().getAdvancements().get(id); if (holder != null) { for (String criterion : advancements.getOrStartProgress(holder).getRemainingCriteria()) { advancements.award(holder, criterion); @@ -33,7 +33,7 @@ public static void grantAdvancement(ServerPlayer player, Identifier id) { @Deprecated public static void grantCriterion(ServerPlayer player, Identifier id, String criterion) { PlayerAdvancements advancements = player.getAdvancements(); - AdvancementHolder holder = player.getAdvancements().get(id); + AdvancementHolder holder = player.level().getServer().getAdvancements().get(id); if (holder != null) { advancements.award(holder, criterion); } @@ -46,7 +46,7 @@ public static AdvancementHolder getAdvancement(Player player, Identifier advance ClientAdvancements manager = localPlayer.connection.getAdvancements(); return manager.get(advancementLocation); } else if (player instanceof ServerPlayer serverPlayer) { - ServerLevel world = (ServerLevel) serverPlayer.level(); + ServerLevel world = serverPlayer.level(); return world.getServer().getAdvancements().get(advancementLocation); } @@ -62,13 +62,12 @@ public static boolean doesPlayerHaveRequiredAdvancement(Player player, @Nullable AdvancementProgress progress = manager.progress.get(holder); return progress != null && progress.isDone(); } - return false; } else { if (player instanceof ServerPlayer) { return holder != null && ((ServerPlayer) player).getAdvancements().getOrStartProgress(holder).isDone(); } - return false; } + return false; } public static boolean doesPlayerHaveRequiredAdvancements(Player player, List requiredAdvancements) { diff --git a/src/main/java/twilightforest/util/Restriction.java b/src/main/java/twilightforest/util/Restriction.java index 2761c314b1..39325a96a9 100644 --- a/src/main/java/twilightforest/util/Restriction.java +++ b/src/main/java/twilightforest/util/Restriction.java @@ -27,6 +27,7 @@ * @param lockedBiomeToast Item that is used as an icon for the notification that tells the player that the area is locked * @param advancements List of advancements that are required to make a biome no longer restricted */ +public record Restriction(@Nullable ResourceKey hintStructureKey, ResourceKey enforcement, float multiplier, @Nullable ItemStackTemplate lockedBiomeToast, List advancements) { public record Restriction(@Nullable ResourceKey hintStructureKey, ResourceKey enforcement, float multiplier, @Nullable ItemStackTemplate lockedBiomeToast, List advancements) { @@ -62,7 +63,12 @@ public static Optional getRestrictionForBiome(Biome biome, Entity e return Optional.empty(); } - return Optional.of(restrictions); + return Optional.empty(); + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static Restriction create(Optional> hintStructureKey, ResourceKey enforcer, float multiplier, Optional lockedBiomeToast, List advancements) { + return new Restriction(hintStructureKey.orElse(null), enforcer, multiplier, lockedBiomeToast.orElse(null), advancements); } public static boolean isBiomeSafeFor(Biome biome, Entity entity) { diff --git a/src/main/java/twilightforest/util/TFItemStackUtils.java b/src/main/java/twilightforest/util/TFItemStackUtils.java index 31407d0785..7c5b8448b1 100644 --- a/src/main/java/twilightforest/util/TFItemStackUtils.java +++ b/src/main/java/twilightforest/util/TFItemStackUtils.java @@ -3,10 +3,11 @@ import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvents; @@ -21,6 +22,7 @@ import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.ItemLike; import org.codehaus.plexus.util.StringUtils; +import twilightforest.TwilightForestMod; import twilightforest.block.KeepsakeCasketBlock; import twilightforest.events.CharmEvents; import twilightforest.init.TFDataComponents; @@ -29,44 +31,55 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.function.Consumer; +import java.util.Optional; public class TFItemStackUtils { public static boolean consumeInventoryItem(final Player player, final ItemLike item, CompoundTag persistentTag, boolean saveItemToTag) { - return consumeInventoryItem(player.getInventory().armor, item, persistentTag, saveItemToTag, player.registryAccess()) - || consumeInventoryItem(player.getInventory().items, item, persistentTag, saveItemToTag, player.registryAccess()) - || consumeInventoryItem(player.getInventory().offhand, item, persistentTag, saveItemToTag, player.registryAccess()); + for (int i = 0; i < player.getInventory().getContainerSize(); i++) { + ItemStack stack = player.getInventory().getItem(i); + if (consumeInventoryItem(stack, item, persistentTag, saveItemToTag, player.registryAccess())) { + return true; + } + } + return false; } - public static boolean consumeInventoryItem(final NonNullList stacks, final ItemLike item, CompoundTag persistentTag, boolean saveItemToTag, HolderLookup.Provider provider) { - for (ItemStack stack : stacks) { - if (stack.is(item.asItem())) { - if (saveItemToTag) persistentTag.put(CharmEvents.CONSUMED_CHARM_TAG, stack.save(provider)); - BlockItemStateProperties blockItemStateProperties = stack.get(DataComponents.BLOCK_STATE); - if (blockItemStateProperties != null && blockItemStateProperties.properties().containsKey(KeepsakeCasketBlock.BREAKAGE.getName())) { - String propertyValueString = blockItemStateProperties.properties().get(KeepsakeCasketBlock.BREAKAGE.getName()); - - persistentTag.putInt(CharmEvents.CASKET_DAMAGE_TAG, StringUtils.isNumeric(propertyValueString) ? Integer.parseInt(propertyValueString) : 0); - } else if (stack.has(TFDataComponents.CASKET_DAMAGE)) { - persistentTag.putInt(CharmEvents.CASKET_DAMAGE_TAG, stack.getOrDefault(TFDataComponents.CASKET_DAMAGE, 0)); - } - stack.shrink(1); - return true; + public static boolean consumeInventoryItem(final ItemStack stack, final ItemLike item, CompoundTag persistentTag, boolean saveItemToTag, HolderLookup.Provider provider) { + if (stack.is(item.asItem())) { + Optional tag = ItemStack.CODEC.encodeStart(provider.createSerializationContext(NbtOps.INSTANCE), stack).resultOrPartial(TwilightForestMod.LOGGER::error); + if (tag.isPresent()) { + persistentTag.put(CharmEvents.CONSUMED_CHARM_TAG, tag.get()); + } + BlockItemStateProperties blockItemStateProperties = stack.get(DataComponents.BLOCK_STATE); + if (blockItemStateProperties != null && blockItemStateProperties.properties().containsKey(KeepsakeCasketBlock.BREAKAGE.getName())) { + String propertyValueString = blockItemStateProperties.properties().get(KeepsakeCasketBlock.BREAKAGE.getName()); + + persistentTag.putInt(CharmEvents.CASKET_DAMAGE_TAG, StringUtils.isNumeric(propertyValueString) ? Integer.parseInt(propertyValueString) : 0); + } else if (stack.has(TFDataComponents.CASKET_DAMAGE)) { + persistentTag.putInt(CharmEvents.CASKET_DAMAGE_TAG, stack.getOrDefault(TFDataComponents.CASKET_DAMAGE, 0)); } + stack.shrink(1); + return true; } return false; } public static NonNullList sortArmorForCasket(Player player) { - NonNullList armor = player.getInventory().armor; + NonNullList armor = NonNullList.create(); + for (int i = Inventory.INVENTORY_SIZE; i < Inventory.SLOT_BODY_ARMOR; i++) { + armor.add(player.getInventory().getItem(i)); + } Collections.reverse(armor); return armor; } public static NonNullList sortInvForCasket(Player player) { - NonNullList inv = player.getInventory().items; + NonNullList inv = NonNullList.create(); + for (int i = 0; i < 36; i++) { + inv.add(player.getInventory().getItem(i)); + } NonNullList sorted = NonNullList.create(); //hotbar at the bottom sorted.addAll(inv.subList(9, 36)); @@ -88,21 +101,6 @@ public static NonNullList splitToSize(ItemStack stack) { return result; } - public static boolean hasToolMaterial(ItemStack stack, Tier tier) { - - Item item = stack.getItem(); - - // see TileEntityFurnace.getItemBurnTime - if (item instanceof TieredItem tieredItem && tier.equals(tieredItem.getTier())) { - return true; - } - if (item instanceof SwordItem sword && tier.equals(sword.getTier())) { - return true; - } - return item instanceof HoeItem hoe && tier.equals(hoe.getTier()); - } - - public static boolean hasInfoTag(ItemStack stack, String key) { CustomData customData = stack.get(DataComponents.CUSTOM_DATA); return customData != null && customData.contains(key); @@ -126,43 +124,46 @@ public static void clearInfoTag(ItemStack stack, String key) { //[VanillaCopy] of Inventory.load, but removed clearing all slots //also add a handler to move items to the next available slot if the slot they want to go to isnt available - public static void loadNoClear(RegistryAccess registryAccess, ListTag tag, Inventory inventory) { - + public static void loadNoClear(HolderLookup.Provider registryAccess, ListTag tag, Inventory inventory) { List blockedItems = new ArrayList<>(); for (int i = 0; i < tag.size(); ++i) { - CompoundTag compoundtag = tag.getCompound(i); - int j = compoundtag.getByte("Slot") & 255; - ItemStack itemstack = ItemStack.parseOptional(registryAccess, compoundtag); + CompoundTag compoundtag = tag.getCompoundOrEmpty(i); + int j = compoundtag.getByteOr("Slot", (byte) 0) & 255; + ItemStack itemstack = ItemStack.OPTIONAL_CODEC.parse(NbtOps.INSTANCE, compoundtag).resultOrPartial(_ -> {}).orElse(ItemStack.EMPTY); + if (!itemstack.isEmpty()) { - if (j < inventory.items.size()) { - if (inventory.items.get(j).isEmpty()) { - inventory.items.set(j, itemstack); - } else { - blockedItems.add(itemstack); - } - } else if (j >= 100 && j < inventory.armor.size() + 100) { - if (inventory.armor.get(j - 100).isEmpty()) { - inventory.armor.set(j - 100, itemstack); - } else { - blockedItems.add(itemstack); - } - } else if (j >= 150 && j < inventory.offhand.size() + 150) { - if (inventory.offhand.get(j - 150).isEmpty()) { - inventory.offhand.set(j - 150, itemstack); + int targetSlot = -1; + + if (j < Inventory.INVENTORY_SIZE) { + targetSlot = j; + } else if (j >= 100 && j < 104) { + targetSlot = Inventory.INVENTORY_SIZE + (j - 100); + } else if (j == 150) { + targetSlot = Inventory.SLOT_OFFHAND; + } + + if (targetSlot >= 0) { + if (inventory.getItem(targetSlot).isEmpty()) { + inventory.setItem(targetSlot, itemstack); } else { blockedItems.add(itemstack); } + } else { + blockedItems.add(itemstack); } } } - if (!blockedItems.isEmpty()) blockedItems.forEach(inventory::add); + if (!blockedItems.isEmpty()) { + blockedItems.forEach(inventory::add); + } } + public static void hurtButDontBreak(ItemStack stack, int amount, ServerLevel level, @Nullable LivingEntity entity) { if (stack.isDamageableItem()) { - amount = stack.getItem().damageItem(stack, amount, entity, item -> {}); + amount = stack.getItem().damageItem(stack, amount, entity, _ -> {}); if (entity == null || !entity.hasInfiniteMaterials()) { if (amount > 0) { amount = EnchantmentHelper.processDurabilityChange(level, stack, amount); diff --git a/src/main/java/twilightforest/util/WorldUtil.java b/src/main/java/twilightforest/util/WorldUtil.java index 555cdda088..d1a0abc7b9 100644 --- a/src/main/java/twilightforest/util/WorldUtil.java +++ b/src/main/java/twilightforest/util/WorldUtil.java @@ -43,7 +43,7 @@ private WorldUtil() { } public static long getOverworldSeed() { - return Objects.requireNonNull(ServerLifecycleHooks.getCurrentServer()).getWorldData().worldGenOptions().seed(); + return Objects.requireNonNull(ServerLifecycleHooks.getCurrentServer()).overworld().getSeed(); } public static RegistryAccess getRegistryAccess() { diff --git a/src/main/java/twilightforest/util/entities/EntityUtil.java b/src/main/java/twilightforest/util/entities/EntityUtil.java index 31e520b377..73f32e92a4 100644 --- a/src/main/java/twilightforest/util/entities/EntityUtil.java +++ b/src/main/java/twilightforest/util/entities/EntityUtil.java @@ -4,20 +4,23 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Holder; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; import net.minecraft.tags.TagKey; import net.minecraft.util.Mth; +import net.minecraft.util.ProblemReporter; import net.minecraft.util.RandomSource; import net.minecraft.world.Container; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.decoration.HangingEntity; -import net.minecraft.world.entity.decoration.Painting; -import net.minecraft.world.entity.decoration.PaintingVariant; +import net.minecraft.world.entity.decoration.painting.Painting; +import net.minecraft.world.entity.decoration.painting.PaintingVariant; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -31,6 +34,9 @@ import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; @@ -41,6 +47,7 @@ import twilightforest.entity.EnforcedHomePoint; import twilightforest.init.TFSounds; +import java.awt.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; @@ -136,13 +143,11 @@ public static void killLavaAround(Entity entity) { } //copy of Mob.doHurtTarget, allows for using a custom DamageSource instead of the generic Mob Attack one - public static boolean properlyApplyCustomDamageSource(Mob entity, Entity victim, DamageSource source, @Nullable SoundEvent flingSound) { + public static boolean properlyApplyCustomDamageSource(ServerLevel serverLevel, Mob entity, Entity victim, DamageSource source, @Nullable SoundEvent flingSound) { float f = (float) entity.getAttributeValue(Attributes.ATTACK_DAMAGE); - if (entity.level() instanceof ServerLevel serverlevel) { - f = EnchantmentHelper.modifyDamage(serverlevel, entity.getWeaponItem(), entity, source, f); - } + f = EnchantmentHelper.modifyDamage(serverLevel, entity.getWeaponItem(), entity, source, f); - boolean flag = victim.hurt(source, f); + boolean flag = victim.hurtServer(serverLevel, source, f); if (flag) { float f1 = getKnockback(entity, victim, source); if (f1 > 0.0F && victim instanceof LivingEntity livingentity) { @@ -172,7 +177,7 @@ protected static float getKnockback(Mob entity, Entity victim, DamageSource sour @Nullable private static T createEntityIgnoreException(EntityType type, ServerLevelAccessor levelAccessor) { try { - return type.create(levelAccessor.getLevel()); + return type.create(levelAccessor.getLevel(), EntitySpawnReason.NATURAL); } catch (Exception exception) { return null; } @@ -191,7 +196,7 @@ public static boolean tryHangPainting(WorldGenLevel world, BlockPos pos, Directi return false; } - painting.setVariant(chosenPainting); + painting.setComponent(DataComponents.PAINTING_VARIANT, chosenPainting); if (checkValidPaintingPosition(world, painting)) { world.addFreshEntity(painting); @@ -210,7 +215,7 @@ public static Holder getPaintingOfSize(WorldGenLevel level, Ran public static Holder getPaintingOfSize(WorldGenLevel level, RandomSource rand, int width, int height, boolean exactMeasurements) { List> valid = new ArrayList<>(); - for (Holder art : level.registryAccess().registryOrThrow(Registries.PAINTING_VARIANT).holders().toList()) { + for (Holder.Reference art : level.registryAccess().lookupOrThrow(Registries.PAINTING_VARIANT).listElements().toList()) { if (exactMeasurements) { if (art.value().width() == width && art.value().height() == height) { valid.add(art); @@ -232,7 +237,7 @@ public static Holder getPaintingOfSize(WorldGenLevel level, Ran public static List> getPaintingsOfSizeOrSmaller(WorldGenLevel level, TagKey lichTowerPaintings, int width, int height) { List> valid = new ArrayList<>(); - for (Holder art : level.registryAccess().registryOrThrow(Registries.PAINTING_VARIANT).getTagOrEmpty(lichTowerPaintings)) { + for (Holder art : level.registryAccess().lookupOrThrow(Registries.PAINTING_VARIANT).getTagOrEmpty(lichTowerPaintings)) { if (art.value().width() <= width && art.value().height() <= height) { valid.add(art); } @@ -275,7 +280,7 @@ public static List getEntitiesInAABB(WorldGenLevel world, AABB boundingB ChunkAccess chunk = world.getChunk(i1, j1, ChunkStatus.STRUCTURE_STARTS); if (chunk instanceof ProtoChunk proto) { proto.getEntities().forEach(nbt -> { - Entity entity = EntityType.loadEntityRecursive(nbt, world.getLevel(), e -> e); + Entity entity = EntityType.loadEntityRecursive(nbt, world.getLevel(), EntitySpawnReason.NATURAL, e -> e); if (entity != null && boundingBox.intersects(entity.getBoundingBox())) { list.add(entity); } @@ -290,12 +295,12 @@ public static List getEntitiesInAABB(WorldGenLevel world, AABB boundingB @SuppressWarnings("unchecked") public static boolean convertEntity(LivingEntity oldEntity, EntityType newType) { if (!(oldEntity.level() instanceof ServerLevel level)) return false; - var newEntity = newType.create(level); + var newEntity = newType.create(level, EntitySpawnReason.CONVERSION); if (newEntity == null) return false; if (!(newEntity instanceof LivingEntity living) || EventHooks.canLivingConvert(oldEntity, (EntityType) living.getType(), timer -> {})) { var passengerSave = oldEntity.getPassengers(); if (oldEntity instanceof Mob mob && newEntity instanceof Mob newMob) { - newEntity = mob.convertTo((EntityType) newMob.getType(), true); + newEntity = mob.convertTo((EntityType) newMob.getType(), ConversionParams.single(newMob, true, true), (ConversionParams.AfterConversion) _ -> {}); } else { newEntity.copyPosition(oldEntity); @@ -305,7 +310,7 @@ public static boolean convertEntity(LivingEntity oldEntity, EntityType newTyp ItemStack itemstack = oldEntity.getItemBySlot(equipmentslot).copyAndClear(); if (!itemstack.isEmpty()) { mob.setItemSlot(equipmentslot, itemstack.copyAndClear()); - mob.setDropChance(equipmentslot, oldMob.getEquipmentDropChance(equipmentslot)); + mob.setDropChance(equipmentslot, oldMob.getDropChances().byEquipment(equipmentslot)); } } } @@ -316,10 +321,20 @@ public static boolean convertEntity(LivingEntity oldEntity, EntityType newTyp oldEntity.level().addFreshEntity(newEntity); oldEntity.discard(); } - try { // try copying what can be copied + try { UUID uuid = newEntity.getUUID(); - newEntity.load(oldEntity.saveWithoutId(newEntity.saveWithoutId(new CompoundTag()))); + ProblemReporter reporter = ProblemReporter.DISCARDING; + RegistryAccess provider = level.registryAccess(); + TagValueOutput outputFactory = TagValueOutput.createWithContext(reporter, provider); + + oldEntity.saveWithoutId(outputFactory); + + CompoundTag copiedData = outputFactory.buildResult(); + ValueInput inputFactory = TagValueInput.create(reporter, provider, copiedData); + + newEntity.load(inputFactory); newEntity.setUUID(uuid); + if (newEntity instanceof LivingEntity living) { living.setHealth(living.getMaxHealth()); } @@ -327,8 +342,13 @@ public static boolean convertEntity(LivingEntity oldEntity, EntityType newTyp TwilightForestMod.LOGGER.warn("Couldn't transform entity NBT data", e); } - if (oldEntity instanceof Saddleable saddleable && saddleable.isSaddled() && !(newEntity instanceof Saddleable)) { - newEntity.spawnAtLocation(Items.SADDLE); + ItemStack saddleStack = oldEntity.getItemBySlot(EquipmentSlot.SADDLE); + if (!saddleStack.isEmpty() && saddleStack.is(Items.SADDLE)) { + if (!(newEntity instanceof LivingEntity newLiving) || !newLiving.canUseSlot(EquipmentSlot.SADDLE)) { + newEntity.spawnAtLocation(level, Items.SADDLE); + } else { + newLiving.setItemSlot(EquipmentSlot.SADDLE, saddleStack.copy()); + } } if (newEntity instanceof Mob mob) { @@ -337,13 +357,13 @@ public static boolean convertEntity(LivingEntity oldEntity, EntityType newTyp for (EquipmentSlot equipmentslot : EquipmentSlot.values()) { ItemStack itemstack = mob.getItemBySlot(equipmentslot).copyAndClear(); - mob.spawnAtLocation(itemstack); + mob.spawnAtLocation(level, itemstack); } } if (!passengerSave.isEmpty()) { for (var entity : passengerSave) { - entity.startRiding(newEntity, true); + entity.startRiding(newEntity, true, false); } } @@ -357,7 +377,7 @@ public static boolean convertEntity(LivingEntity oldEntity, EntityType newTyp @Nullable public static T createEntityIgnoreException(ServerLevelAccessor level, EntityType type) { try { - return type.create(level.getLevel()); + return type.create(level.getLevel(), EntitySpawnReason.NATURAL); } catch (Exception exception) { return null; } diff --git a/src/main/java/twilightforest/util/entities/OminousFireDamageSource.java b/src/main/java/twilightforest/util/entities/OminousFireDamageSource.java index 5ffa51cf64..782399dc16 100644 --- a/src/main/java/twilightforest/util/entities/OminousFireDamageSource.java +++ b/src/main/java/twilightforest/util/entities/OminousFireDamageSource.java @@ -3,7 +3,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.monster.Zombie; +import net.minecraft.world.entity.monster.zombie.Zombie; import net.minecraft.world.entity.player.Player; import twilightforest.init.TFDataAttachments; @@ -15,10 +15,10 @@ public OminousFireDamageSource(DamageSource wrappedSource) { @Override public Component getLocalizedDeathMessage(LivingEntity living) { if (living.getKillCredit() instanceof Zombie zombie && zombie.hasData(TFDataAttachments.ZOMBIFIED_PLAYER)) { - if (living instanceof Player player && player.getGameProfile().getName().equals(zombie.getData(TFDataAttachments.ZOMBIFIED_PLAYER).getName())) { + if (living instanceof Player player && player.getGameProfile().name().equals(zombie.getData(TFDataAttachments.ZOMBIFIED_PLAYER).name())) { return Component.translatable("death.attack.twilightforest.ominousFire.zombified_player.self", living.getDisplayName()); } - return Component.translatable("death.attack.twilightforest.ominousFire.zombified_player", living.getDisplayName(), zombie.getData(TFDataAttachments.ZOMBIFIED_PLAYER).getName()); + return Component.translatable("death.attack.twilightforest.ominousFire.zombified_player", living.getDisplayName(), zombie.getData(TFDataAttachments.ZOMBIFIED_PLAYER).name()); } return super.getLocalizedDeathMessage(living); } diff --git a/src/main/java/twilightforest/util/iterators/RectangleLatticeIterator.java b/src/main/java/twilightforest/util/iterators/RectangleLatticeIterator.java index 8c2e29534e..6b7baf8136 100644 --- a/src/main/java/twilightforest/util/iterators/RectangleLatticeIterator.java +++ b/src/main/java/twilightforest/util/iterators/RectangleLatticeIterator.java @@ -7,15 +7,14 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; import net.minecraft.world.level.levelgen.structure.BoundingBox; -import org.jetbrains.annotations.NotNull; import java.util.Iterator; -import java.util.Optional; // For making rectangular grids that are approximately-evenly spaced (floating-point -> integer rounding), even if re-sampled for a different chunk or general region // Making a hexagonal pattern will require using two of these // Positions are lazily generated, meaning no excess of positions are produced if terminated early public class RectangleLatticeIterator implements Iterator, Iterable { + private final int yLevel, latticeStartX, latticeStartZ, latticeCountX, latticeCountZ; private final float xSpacing, zSpacing, xOffset, zOffset; private final TernaryIntegerFunction converter; @@ -71,7 +70,6 @@ public boolean hasNext() { return this.latticeX < this.latticeCountX; } - @NotNull @Override public Iterator iterator() { return this; @@ -121,14 +119,11 @@ public static TriangularLatticeConfig fromNBT(CompoundTag tag) { float spacing = tag.getFloatOr("spacing", 0f); if (spacing <= 0.0000001) spacing = 3.5f; - float xOffset = tag.getFloat("x_offset").orElse(Mth.cos(Mth.PI / 6f) * spacing); - float zOffset = tag.getFloat("z_offset").orElse(Mth.sin(Mth.PI / 6f) * spacing); - - float xSpacing = tag.getFloatOr("x_spacing", 0f); - float zSpacing = tag.getFloatOr("z_spacing", 0f); + float xOffset = tag.getFloatOr("x_offset", Mth.cos(Mth.PI / 6f) * spacing); + float zOffset = tag.getFloatOr("z_offset", Mth.sin(Mth.PI / 6f) * spacing); - if (xSpacing != 0 || zSpacing != 0) { - return new TriangularLatticeConfig(spacing, xOffset, zOffset, xSpacing, zSpacing); + if (tag.contains("x_spacing") || tag.contains("z_spacing")) { + return new TriangularLatticeConfig(spacing, xOffset, zOffset, tag.getFloatOr("x_spacing", 0.0F), tag.getFloatOr("z_spacing", 0.0F)); } else { return new TriangularLatticeConfig(spacing, xOffset, zOffset); } diff --git a/src/main/java/twilightforest/util/jigsaw/JigsawRecord.java b/src/main/java/twilightforest/util/jigsaw/JigsawRecord.java index 554c3fecec..2d6426eaaa 100644 --- a/src/main/java/twilightforest/util/jigsaw/JigsawRecord.java +++ b/src/main/java/twilightforest/util/jigsaw/JigsawRecord.java @@ -1,6 +1,5 @@ package twilightforest.util.jigsaw; -import net.minecraft.Optionull; import net.minecraft.core.BlockPos; import net.minecraft.core.FrontAndTop; import net.minecraft.nbt.CompoundTag; @@ -45,34 +44,34 @@ public static List fromUnprocessedInfos(List tag.getInt("selection_priority"), 0), + info.nbt().getIntOr("selection_priority", 0), JigsawUtil.process(info.state().getValue(JigsawBlock.ORIENTATION), settings), StructureTemplate.calculateRelativePosition(settings, info.pos()), - Optionull.mapOrDefault(info.nbt(), tag -> tag.getString("pool"), "minecraft:empty"), - Optionull.mapOrDefault(info.nbt(), tag -> tag.getString("name"), ""), - Optionull.mapOrDefault(info.nbt(), tag -> tag.getString("target"), "") + info.nbt().getStringOr("pool", "minecraft:empty"), + info.nbt().getStringOr("name", ""), + info.nbt().getStringOr("target", "") ); } public static JigsawRecord fromJigsawBlock(StructureTemplate.StructureBlockInfo info) { return new JigsawRecord( - Optionull.mapOrDefault(info.nbt(), tag -> tag.getInt("selection_priority"), 0), + info.nbt().getIntOr("selection_priority", 0), info.state().getValue(JigsawBlock.ORIENTATION), info.pos(), - Optionull.mapOrDefault(info.nbt(), tag -> tag.getString("pool"), "minecraft:empty"), - Optionull.mapOrDefault(info.nbt(), tag -> tag.getString("name"), ""), - Optionull.mapOrDefault(info.nbt(), tag -> tag.getString("target"), "") + info.nbt().getStringOr("pool", "minecraft:empty"), + info.nbt().getStringOr("name", ""), + info.nbt().getStringOr("target", "") ); } public static JigsawRecord fromTag(CompoundTag tag) { return new JigsawRecord( - tag.getInt("priority"), - FrontAndTop.values()[tag.getInt("facing")], - new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")), - tag.getString("pool"), - tag.getString("name"), - tag.getString("target") + tag.getIntOr("priority", 0), + FrontAndTop.values()[tag.getIntOr("facing", 0)], + new BlockPos(tag.getIntOr("x", 0), tag.getIntOr("y", 0), tag.getIntOr("z", 0)), + tag.getStringOr("pool", ""), + tag.getStringOr("name", ""), + tag.getStringOr("target", "") ); } diff --git a/src/main/java/twilightforest/util/jigsaw/JigsawUtil.java b/src/main/java/twilightforest/util/jigsaw/JigsawUtil.java index 7f8942afd6..10dce19fd5 100644 --- a/src/main/java/twilightforest/util/jigsaw/JigsawUtil.java +++ b/src/main/java/twilightforest/util/jigsaw/JigsawUtil.java @@ -8,12 +8,12 @@ import net.minecraft.util.Util; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.JigsawBlock; -import net.minecraft.world.level.levelgen.structure.pools.SinglePoolElement; import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; import org.jetbrains.annotations.Nullable; +import java.util.Comparator; import java.util.List; public class JigsawUtil { @@ -64,7 +64,7 @@ public static List readConnectableJigsaws( if (random != null) { Util.shuffle(returnables, random); // "Stable" sorting - preserves order of "equal" priorities, as arranged by prior shuffling. - SinglePoolElement.sortBySelectionPriority(returnables); + returnables.sort(Comparator.comparingInt(info -> info.nbt() == null ? 0 : info.nbt().getIntOr("selection_priority", 0)).reversed()); } return returnables; diff --git a/src/main/java/twilightforest/util/landmarks/LandmarkUtil.java b/src/main/java/twilightforest/util/landmarks/LandmarkUtil.java index f96960b236..a5f367b08c 100644 --- a/src/main/java/twilightforest/util/landmarks/LandmarkUtil.java +++ b/src/main/java/twilightforest/util/landmarks/LandmarkUtil.java @@ -16,10 +16,10 @@ import net.minecraft.world.level.levelgen.structure.StructureStart; import net.minecraft.world.phys.AABB; import org.jetbrains.annotations.Nullable; -import twilightforest.tags.TFStructureTags; import twilightforest.entity.EnforcedHomePoint; import twilightforest.init.TFAdvancements; import twilightforest.init.TFGameRules; +import twilightforest.tags.TFStructureTags; import twilightforest.world.components.structures.start.TFStructureStart; import twilightforest.world.components.structures.util.CustomStructureData; @@ -28,7 +28,6 @@ import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.StreamSupport; @SuppressWarnings("OptionalIsPresent") public final class LandmarkUtil { @@ -37,14 +36,12 @@ public static Optional locateNearestLandmarkStart(LevelAccessor } public static Optional locateNearestMatchingLandmark(LevelAccessor level, TagKey matching, int chunkX, int chunkZ) { - var structureRegistry = level.registryAccess().lookupOrThrow(Registries.STRUCTURE); - if (structureRegistry.size() == 0) return Optional.empty(); - var holders = structureRegistry.getTagOrEmpty(matching); - if (!holders.iterator().hasNext()) return Optional.empty(); - - HolderSet holderSet = HolderSet.direct(StreamSupport.stream(holders.spliterator(), false).toList()); + var structureRegistry = level.registryAccess().lookup(Registries.STRUCTURE); + if (structureRegistry.isEmpty()) return Optional.empty(); + Optional> holders = structureRegistry.get().get(matching); + if (holders.isEmpty()) return Optional.empty(); - return locateNearestMatchingLandmark(level, holderSet, chunkX, chunkZ); + return locateNearestMatchingLandmark(level, holders.get(), chunkX, chunkZ); } public static Optional locateNearestMatchingLandmark(LevelAccessor level, HolderSet matching, int chunkX, int chunkZ) { @@ -94,7 +91,7 @@ public static void markStructureConquered(Level level, @Nullable GlobalPos pos, public static Structure structureForKey(LevelReader level, ResourceKey structureKey) { Optional> registry = level.registryAccess().lookup(Registries.STRUCTURE); - return registry.isPresent() ? registry.get().get(structureKey).orElseThrow().value() : null; + return registry.isPresent() ? registry.get().get(structureKey).get().value() : null; } public static Optional locateNearestLandmarkStart(LevelAccessor level, ResourceKey structureKey, BlockPos pos) {