Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/main/java/twilightforest/util/BoundingBoxUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ public static CompoundTag boundingBoxToExistingNBT(BoundingBox box, CompoundTag

public static BoundingBox NBTToBoundingBox(CompoundTag nbt) {
return new BoundingBox(
nbt.getInt("minX"),
Comment thread
albazavr-alba marked this conversation as resolved.
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)
);
}

Expand Down Expand Up @@ -92,7 +92,7 @@ public static BoundingBox getComponentToAddBoundingBox(int x, int y, int z, int
public static AABB vectorsMinMax(List<Vec3> 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,
Expand Down
19 changes: 16 additions & 3 deletions src/main/java/twilightforest/util/DisplayUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<Entity> spawned = EntityType.create(entityNBT, level);
ProblemReporter.Collector entitySpawnReporter = new ProblemReporter.Collector();
ValueInput valueInput = TagValueInput.create(entitySpawnReporter, level.registryAccess(), entityNBT);
Optional<Entity> spawned = EntityType.create(valueInput, level, EntitySpawnReason.LOAD);

if (spawned.isEmpty()) return false;
Entity entity = spawned.get();
Expand All @@ -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<Tag> serializedAlignment = Display.TextDisplay.Align.CODEC.encodeStart(NbtOps.INSTANCE, Display.TextDisplay.Align.CENTER);
if (serializedAlignment.isSuccess()) {
Expand All @@ -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<Entity> spawned = EntityType.create(entityNBT, level);
ProblemReporter.Collector entitySpawnReporter = new ProblemReporter.Collector();
ValueInput valueInput = TagValueInput.create(entitySpawnReporter, level.registryAccess(), entityNBT);
Optional<Entity> spawned = EntityType.create(valueInput, level, EntitySpawnReason.LOAD);

if (spawned.isEmpty()) return;
Entity entity = spawned.get();
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/twilightforest/util/PlayerHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}
Expand All @@ -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);
}

Expand All @@ -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<Identifier> requiredAdvancements) {
Expand Down
31 changes: 17 additions & 14 deletions src/main/java/twilightforest/util/Restriction.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import net.minecraft.util.ExtraCodecs;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ItemStackTemplate;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.structure.Structure;
import twilightforest.TFRegistries;
Expand All @@ -26,23 +26,17 @@
* @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
*/
Comment thread
albazavr-alba marked this conversation as resolved.
public record Restriction(@Nullable ResourceKey<Structure> hintStructureKey, ResourceKey<Enforcement> enforcement, float multiplier, @Nullable ItemStackTemplate lockedBiomeToast, List<Identifier> advancements) {

public record Restriction(@Nullable ResourceKey<Structure> hintStructureKey, ResourceKey<Enforcement> enforcement,
float multiplier, @Nullable ItemStack lockedBiomeToast, List<Identifier> advancements) {

//TODO: test that the itemstacktemplate works in datagen
public static final Codec<Restriction> CODEC = RecordCodecBuilder.create((recordCodecBuilder) -> recordCodecBuilder.group(
ResourceKey.codec(Registries.STRUCTURE).optionalFieldOf("structure_key").forGetter((restriction) -> Optional.ofNullable(restriction.hintStructureKey())),
ResourceKey.codec(TFRegistries.Keys.ENFORCEMENT).fieldOf("enforcement").forGetter(Restriction::enforcement),
Codec.FLOAT.fieldOf("multiplier").forGetter(Restriction::multiplier),
ItemStack.CODEC.optionalFieldOf("locked_biome_toast").forGetter((restriction) -> Optional.ofNullable(restriction.lockedBiomeToast())),
Comment thread
albazavr-alba marked this conversation as resolved.
Outdated
ItemStackTemplate.CODEC.optionalFieldOf("locked_biome_toast").forGetter(restriction -> Optional.ofNullable(restriction.lockedBiomeToast())),
ExtraCodecs.nonEmptyList(Identifier.CODEC.listOf()).fieldOf("advancements").forGetter(Restriction::advancements)
).apply(recordCodecBuilder, Restriction::create));

@SuppressWarnings("OptionalUsedAsFieldOrParameterType") // Vanilla does this too
private static Restriction create(Optional<ResourceKey<Structure>> hintStructureKey, ResourceKey<Enforcement> enforcer, float multiplier, Optional<ItemStack> lockedBiomeToast, List<Identifier> advancements) {
return new Restriction(hintStructureKey.orElse(null), enforcer, multiplier, lockedBiomeToast.orElse(null), advancements);
}

public static Optional<Restriction> getRestrictionForBiome(Biome biome, Entity entity) {
if (!(entity instanceof Player player))
return Optional.empty();
Expand All @@ -56,12 +50,21 @@ public static Optional<Restriction> getRestrictionForBiome(Biome biome, Entity e
if (restrictionsRegistry.isEmpty())
return Optional.empty();

Restriction restrictions = restrictionsRegistry.get().get(biomeLocation);
if (restrictions == null || PlayerHelper.doesPlayerHaveRequiredAdvancements(player, restrictions.advancements())) {
return Optional.empty();
if (restrictionsRegistry.get().get(biomeLocation).isPresent()) {
Restriction restrictions = restrictionsRegistry.get().get(biomeLocation).get().value();
if (PlayerHelper.doesPlayerHaveRequiredAdvancements(player, restrictions.advancements())) {
return Optional.empty();
}

return Optional.of(restrictions);
}

return Optional.of(restrictions);
return Optional.empty();
}

@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private static Restriction create(Optional<ResourceKey<Structure>> hintStructureKey, ResourceKey<Enforcement> enforcer, float multiplier, Optional<ItemStackTemplate> lockedBiomeToast, List<Identifier> advancements) {
return new Restriction(hintStructureKey.orElse(null), enforcer, multiplier, lockedBiomeToast.orElse(null), advancements);
}

public static boolean isBiomeSafeFor(Biome biome, Entity entity) {
Expand Down
119 changes: 61 additions & 58 deletions src/main/java/twilightforest/util/TFItemStackUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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())
Comment thread
albazavr-alba marked this conversation as resolved.
|| 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<ItemStack> 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> 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<ItemStack> sortArmorForCasket(Player player) {
NonNullList<ItemStack> armor = player.getInventory().armor;
NonNullList<ItemStack> armor = NonNullList.create();
for (int i = 36; i < 41; i++) {
armor.add(player.getInventory().getItem(i));
}
Collections.reverse(armor);
return armor;
}

public static NonNullList<ItemStack> sortInvForCasket(Player player) {
NonNullList<ItemStack> inv = player.getInventory().items;
NonNullList<ItemStack> inv = NonNullList.create();
for (int i = 0; i < 36; i++) {
Comment thread
albazavr-alba marked this conversation as resolved.
Outdated
inv.add(player.getInventory().getItem(i));
}
NonNullList<ItemStack> sorted = NonNullList.create();
//hotbar at the bottom
sorted.addAll(inv.subList(9, 36));
Expand All @@ -88,21 +101,6 @@ public static NonNullList<ItemStack> 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);
Expand All @@ -126,43 +124,48 @@ 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<ItemStack> 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 < 36) {
targetSlot = j;
}
else if (j >= 100 && j < 104) {
targetSlot = 36 + (j - 100);
}
else if (j == 150) {
targetSlot = 40;
Comment thread
albazavr-alba marked this conversation as resolved.
Outdated
}

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);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/twilightforest/util/WorldUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Loading
Loading