Skip to content

Commit

Permalink
Implement a few functions along with placeholders
Browse files Browse the repository at this point in the history
  • Loading branch information
GoldenStack committed Aug 29, 2024
1 parent c9fb10c commit eddf073
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 4 deletions.
153 changes: 149 additions & 4 deletions src/main/java/net/goldenstack/loot/LootFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
import net.minestom.server.MinecraftServer;
import net.minestom.server.ServerFlag;
import net.minestom.server.component.DataComponent;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.PlayerSkin;
import net.minestom.server.entity.*;
import net.minestom.server.entity.attribute.Attribute;
import net.minestom.server.entity.attribute.AttributeModifier;
import net.minestom.server.entity.attribute.AttributeOperation;
import net.minestom.server.instance.block.Block;
import net.minestom.server.item.ItemComponent;
import net.minestom.server.item.ItemStack;
Expand Down Expand Up @@ -70,7 +71,11 @@ public interface LootFunction {
Template.entry("set_book_cover", SetBookCover.class, SetBookCover.SERIALIZER),
Template.entry("fill_player_head", FillPlayerHead.class, FillPlayerHead.SERIALIZER),
Template.entry("enchant_randomly", EnchantRandomly.class, EnchantRandomly.SERIALIZER),
Template.entry("furnace_smelt", FurnaceSmelt.class, FurnaceSmelt.SERIALIZER)
Template.entry("furnace_smelt", FurnaceSmelt.class, FurnaceSmelt.SERIALIZER),
Template.entry("exploration_map", ExplorationMap.class, ExplorationMap.SERIALIZER),
Template.entry("set_name", SetName.class, SetName.SERIALIZER),
Template.entry("set_instrument", SetInstrument.class, SetInstrument.SERIALIZER),
Template.entry("set_attributes", SetAttributes.class, SetAttributes.SERIALIZER)
)
);

Expand Down Expand Up @@ -900,4 +905,144 @@ record FurnaceSmelt(@NotNull List<LootPredicate> predicates) implements LootFunc
}
}

record ExplorationMap(@NotNull List<LootPredicate> predicates) implements LootFunction {

public static final @NotNull BinaryTagSerializer<ExplorationMap> SERIALIZER = Template.template(
"conditions", Serial.lazy(() -> LootPredicate.SERIALIZER).list().optional(List.of()), ExplorationMap::predicates,
ExplorationMap::new
);

@Override
public @NotNull ItemStack apply(@NotNull ItemStack input, @NotNull LootContext context) {
if (!LootPredicate.all(predicates, context)) return input;

throw new UnsupportedOperationException("TODO: Implement ExplorationMap functionality and serialization");
}
}

record SetName(@NotNull List<LootPredicate> predicates, @Nullable Component name,
@Nullable RelevantEntity entity, @NotNull Target target) implements LootFunction {

public static final @NotNull BinaryTagSerializer<SetName> SERIALIZER = Template.template(
"conditions", Serial.lazy(() -> LootPredicate.SERIALIZER).list().optional(List.of()), SetName::predicates,
"name", BinaryTagSerializer.NBT_COMPONENT.optional(), SetName::name,
"entity", RelevantEntity.SERIALIZER.optional(), SetName::entity,
"target", Target.SERIALIZER.optional(Target.CUSTOM_NAME), SetName::target,
SetName::new
);

public enum Target {
ITEM_NAME("item_name", ItemComponent.ITEM_NAME),
CUSTOM_NAME("custom_name", ItemComponent.CUSTOM_NAME);

public static final @NotNull BinaryTagSerializer<Target> SERIALIZER = Template.constant(Target::id, Target.values());

private final String id;
private final DataComponent<Component> component;

Target(String id, DataComponent<Component> component) {
this.id = id;
this.component = component;
}

public String id() {
return id;
}

public DataComponent<Component> component() {
return component;
}
}

@Override
public @NotNull ItemStack apply(@NotNull ItemStack input, @NotNull LootContext context) {
if (!LootPredicate.all(predicates, context)) return input;

if (name == null) return input;

Component component = this.name;
// TODO: https://minecraft.wiki/w/Raw_JSON_text_format#Component_resolution
// This is not used in vanilla so it's fine for now.

return input.with(target.component(), component);
}
}

record SetInstrument(@NotNull List<LootPredicate> predicates) implements LootFunction {

public static final @NotNull BinaryTagSerializer<SetInstrument> SERIALIZER = Template.template(
"conditions", Serial.lazy(() -> LootPredicate.SERIALIZER).list().optional(List.of()), SetInstrument::predicates,
SetInstrument::new
);

@Override
public @NotNull ItemStack apply(@NotNull ItemStack input, @NotNull LootContext context) {
if (!LootPredicate.all(predicates, context)) return input;

throw new UnsupportedOperationException("TODO: Implement SetInstrument functionality and serialization");
}
}

record SetAttributes(@NotNull List<LootPredicate> predicates, @NotNull List<AttributeDirective> modifiers, boolean replace) implements LootFunction {

public static final @NotNull BinaryTagSerializer<SetAttributes> SERIALIZER = Template.template(
"conditions", Serial.lazy(() -> LootPredicate.SERIALIZER).list().optional(List.of()), SetAttributes::predicates,
"modifiers", AttributeDirective.SERIALIZER.list(), SetAttributes::modifiers,
"replace", BinaryTagSerializer.BOOLEAN.optional(true), SetAttributes::replace,
SetAttributes::new
);

public record AttributeDirective(@NotNull NamespaceID id, @NotNull Attribute attribute, @NotNull AttributeOperation operation,
@NotNull LootNumber amount, @NotNull List<EquipmentSlot> slots) {

public static final @NotNull BinaryTagSerializer<EquipmentSlot> CUSTOM_SLOT = Template.constant(
slot -> slot.name().toLowerCase(Locale.ROOT).replace("_", ""), EquipmentSlot.values()
);

public static final @NotNull BinaryTagSerializer<AttributeDirective> SERIALIZER = Template.template(
"id", Serial.KEY, AttributeDirective::id,
"attribute", Attribute.NBT_TYPE, AttributeDirective::attribute,
"operation", AttributeOperation.NBT_TYPE, AttributeDirective::operation,
"amount", LootNumber.SERIALIZER, AttributeDirective::amount,
"slot", Serial.coerceList(CUSTOM_SLOT), AttributeDirective::slots,
AttributeDirective::new
);

}

@Override
public @NotNull ItemStack apply(@NotNull ItemStack input, @NotNull LootContext context) {
if (!LootPredicate.all(predicates, context)) return input;

var component = input.get(ItemComponent.ATTRIBUTE_MODIFIERS, AttributeList.EMPTY);

List<AttributeList.Modifier> list = replace ? new ArrayList<>() : new ArrayList<>(component.modifiers());

for (var modifier : modifiers) {
if (modifier.slots().isEmpty()) continue;

AttributeModifier mod = new AttributeModifier(
modifier.id(),
modifier.amount().getDouble(context),
modifier.operation()
);

EquipmentSlot slot = modifier.slots().get(context.require(LootContext.RANDOM).nextInt(modifier.slots().size()));

EquipmentSlotGroup group = switch (slot) {
case MAIN_HAND -> EquipmentSlotGroup.MAIN_HAND;
case OFF_HAND -> EquipmentSlotGroup.OFF_HAND;
case BOOTS -> EquipmentSlotGroup.FEET;
case LEGGINGS -> EquipmentSlotGroup.LEGS;
case CHESTPLATE -> EquipmentSlotGroup.CHEST;
case HELMET -> EquipmentSlotGroup.HEAD;
};

list.add(new AttributeList.Modifier(modifier.attribute(), mod, group));
}

return input.with(ItemComponent.ATTRIBUTE_MODIFIERS, new AttributeList(list, component.showInTooltip()));
}
}

}
16 changes: 16 additions & 0 deletions src/main/java/net/goldenstack/loot/util/Serial.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
Expand Down Expand Up @@ -103,4 +104,19 @@ public class Serial {
};
}

public static <T> @NotNull BinaryTagSerializer<List<T>> coerceList(@NotNull BinaryTagSerializer<T> serializer) {
BinaryTagSerializer<List<T>> list = serializer.list();
return new BinaryTagSerializer<>() {
@Override
public @NotNull BinaryTag write(@NotNull Context context, @NotNull List<T> value) {
return value.size() == 1 ? serializer.write(value.getFirst()) : list.write(context, value);
}

@Override
public @NotNull List<T> read(@NotNull Context context, @NotNull BinaryTag tag) {
return tag instanceof ListBinaryTag ? list.read(context, tag) : List.of(serializer.read(context, tag));
}
};
}

}

0 comments on commit eddf073

Please sign in to comment.