Skip to content

Commit

Permalink
Implement necessary data components
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexProgrammerDE committed May 17, 2024
1 parent b96cf99 commit 195635d
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 20 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ flatlaf-fonts-inter = { module = "com.formdev:flatlaf-fonts-inter", version.ref
flatlaf-fonts-jetbrains-mono = { module = "com.formdev:flatlaf-fonts-jetbrains-mono", version.ref = "flatlaf-jetbrains-mono-version" }
xchart = "org.knowm.xchart:xchart:3.8.8"
miglayout-swing = "com.miglayout:miglayout-swing:11.3"
mcprotocollib = "com.github.GeyserMC:MCProtocolLib:42ea4a4"
mcprotocollib = "com.github.GeyserMC:MCProtocolLib:1b80c1b"
velocity-native = "com.velocitypowered:velocity-native:3.1.2-SNAPSHOT"
netty-raknet = "org.cloudburstmc.netty:netty-transport-raknet:1.0.0.CR1-SNAPSHOT"
via-version = { module = "com.viaversion:viaversion-common", version.ref = "via-version" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,52 +22,121 @@
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.soulfiremc.server.protocol.codecs.ExtraCodecs;
import com.soulfiremc.util.GsonInstance;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.tools.Tool;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.key.Key;
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.FoodProperties;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemAttributeModifiers;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.MobEffectDetails;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ToolData;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.MobEffectInstance;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.type.IntDataComponent;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.type.ObjectDataComponent;

@Slf4j
public record JsonDataComponents(Map<DataComponentType<?>, DataComponent<?, ?>> components) {
public static final Codec<ToolData.Rule> TOOL_RULE_CODEC = RecordCodecBuilder.create(
public static UUID uuidFromIntArray(int[] bits) {
return new UUID((long) bits[0] << 32 | (long) bits[1] & 4294967295L, (long) bits[2] << 32 | (long) bits[3] & 4294967295L);
}

public static int[] uuidToIntArray(UUID uuid) {
var l = uuid.getMostSignificantBits();
var m = uuid.getLeastSignificantBits();
return leastMostToIntArray(l, m);
}

private static int[] leastMostToIntArray(long most, long least) {
return new int[] {(int) (most >> 32), (int) most, (int) (least >> 32), (int) least};
}

public static DataResult<int[]> fixedSize(IntStream stream, int size) {
var is = stream.limit(size + 1).toArray();
if (is.length != size) {
Supplier<String> supplier = () -> "Input is not a list of " + size + " ints";
return is.length >= size ? DataResult.error(supplier, Arrays.copyOf(is, size)) : DataResult.error(supplier);
} else {
return DataResult.success(is);
}
}

public static final Codec<UUID> UUID_CODEC = Codec.INT_STREAM
.comapFlatMap(uuids -> fixedSize(uuids, 4).map(JsonDataComponents::uuidFromIntArray), uuid -> Arrays.stream(uuidToIntArray(uuid)));
@SuppressWarnings("PatternValidation")
private static final Codec<Effect> MCPL_EFFECT_CODEC = Codec.STRING.xmap(s -> Effect.valueOf(Key.key(s).value().toUpperCase(Locale.ROOT)), e -> Key.key(e.name().toLowerCase(Locale.ROOT)).toString());
@SuppressWarnings("PatternValidation")
private static final Codec<AttributeType> ATTRIBUTE_TYPE_CODEC = Codec.STRING.xmap(s -> AttributeType.getByKey(Key.key(s)), a -> a.key().toString());
private static final Codec<ItemAttributeModifiers.EquipmentSlotGroup> MCPL_EQUIPMENT_SLOT_GROUP_CODEC = Codec.STRING.xmap(
s -> ItemAttributeModifiers.EquipmentSlotGroup.valueOf(s.toUpperCase(Locale.ROOT)), g -> g.name().toLowerCase(Locale.ROOT));
private static final Codec<ModifierOperation> MCPL_MODIFIER_OPERATION_CODEC = Codec.STRING.xmap(
s -> ModifierOperation.valueOf(s.toUpperCase(Locale.ROOT)), g -> g.name().toLowerCase(Locale.ROOT));
public static final MapCodec<ItemAttributeModifiers.AttributeModifier> ATTRIBUTE_MODIFIER_MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
RegistryCodecs.homogeneousList(Registries.BLOCK).fieldOf("blocks").forGetter(ToolData.Rule::getHolders),
ExtraCodecs.POSITIVE_FLOAT.optionalFieldOf("speed").forGetter(ToolData.Rule::getSpeed),
Codec.BOOL.optionalFieldOf("correct_for_drops").forGetter(ToolData.Rule::getCorrectForDrops)
UUID_CODEC.fieldOf("uuid").forGetter(ItemAttributeModifiers.AttributeModifier::getId),
Codec.STRING.fieldOf("name").forGetter(ItemAttributeModifiers.AttributeModifier::getName),
Codec.DOUBLE.fieldOf("amount").forGetter(ItemAttributeModifiers.AttributeModifier::getAmount),
MCPL_MODIFIER_OPERATION_CODEC.fieldOf("operation").forGetter(ItemAttributeModifiers.AttributeModifier::getOperation)
)
.apply(instance, ToolData.Rule::new)
.apply(instance, ItemAttributeModifiers.AttributeModifier::new)
);
public static final Codec<ToolData> TOOL_CODEC = RecordCodecBuilder.create(
public static final Codec<ItemAttributeModifiers.Entry> Item_ATTRIBUTE_MODIFIERS_ENTRY_CODEC = RecordCodecBuilder.create(
instance -> instance.group(
ToolData.Rule.CODEC.listOf().fieldOf("rules").forGetter(ToolData::getRules),
Codec.FLOAT.optionalFieldOf("default_mining_speed", 1.0F).forGetter(ToolData::getDefaultMiningSpeed),
ExtraCodecs.NON_NEGATIVE_INT.optionalFieldOf("damage_per_block", 1).forGetter(ToolData::getDamagePerBlock)
ATTRIBUTE_TYPE_CODEC.fieldOf("type").forGetter(a -> AttributeType.getById(a.getAttribute())),
ATTRIBUTE_MODIFIER_MAP_CODEC.forGetter(ItemAttributeModifiers.Entry::getModifier),
MCPL_EQUIPMENT_SLOT_GROUP_CODEC.optionalFieldOf("slot", ItemAttributeModifiers.EquipmentSlotGroup.ANY).forGetter(ItemAttributeModifiers.Entry::getSlot)
)
.apply(instance, Tool::new)
.apply(instance, (a, b, c) -> new ItemAttributeModifiers.Entry(a.id(), b, c))
);
public static final Codec<MobEffectDetails> MOB_EFFECT_DETAILS_CODEC = RecordCodecBuilder.create(
private static final Codec<ItemAttributeModifiers> ITEM_ATTRIBUTE_MODIFIERS_FULL_CODEC = RecordCodecBuilder.create(
instance -> instance.group(
BuiltInRegistries.MOB_EFFECT.holderByNameCodec().fieldOf("id").forGetter(MobEffectDetails::getEffect),
MobEffectDetails.Details.MAP_CODEC.forGetter(MobEffectDetails::asDetails)
Item_ATTRIBUTE_MODIFIERS_ENTRY_CODEC.listOf().fieldOf("modifiers").forGetter(ItemAttributeModifiers::getModifiers),
Codec.BOOL.optionalFieldOf("show_in_tooltip", true).forGetter(ItemAttributeModifiers::isShowInTooltip)
)
.apply(instance, MobEffectDetails::new)
.apply(instance, ItemAttributeModifiers::new)
);
public static final Codec<ItemAttributeModifiers> ITEM_ATTRIBUTE_MODIFIERS_CODEC = Codec.withAlternative(
ITEM_ATTRIBUTE_MODIFIERS_FULL_CODEC, Item_ATTRIBUTE_MODIFIERS_ENTRY_CODEC.listOf(), list -> new ItemAttributeModifiers(list, true)
);
public static final MapCodec<MobEffectDetails> MOB_EFFECT_DETAILS_MAP_CODEC = MapCodec.recursive(
"MobEffectInstance.Details",
codec -> RecordCodecBuilder.mapCodec(
instance -> instance.group(
ExtraCodecs.UNSIGNED_BYTE.optionalFieldOf("amplifier", 0).forGetter(MobEffectDetails::getAmplifier),
Codec.INT.optionalFieldOf("duration", 0).forGetter(MobEffectDetails::getDuration),
Codec.BOOL.optionalFieldOf("ambient", false).forGetter(MobEffectDetails::isAmbient),
Codec.BOOL.optionalFieldOf("show_particles", true).forGetter(MobEffectDetails::isShowParticles),
Codec.BOOL.optionalFieldOf("show_icon").forGetter(arg -> Optional.of(arg.isShowIcon())),
codec.optionalFieldOf("hidden_effect").forGetter(d -> Optional.ofNullable(d.getHiddenEffect()))
)
.apply(instance, (a, b, c, d, e, f) -> new MobEffectDetails(a, b, c, d, e.orElse(d), f.orElse(null)))
)
);
public static final Codec<MobEffectInstance> MOB_EFFECT_INSTANCE_CODEC = RecordCodecBuilder.create(
instance -> instance.group(
MCPL_EFFECT_CODEC.fieldOf("id").forGetter(MobEffectInstance::getEffect),
MOB_EFFECT_DETAILS_MAP_CODEC.forGetter(MobEffectInstance::getDetails)
)
.apply(instance, MobEffectInstance::new)
);
public static final Codec<FoodProperties.PossibleEffect> POSSIBLE_EFFECT_CODEC = RecordCodecBuilder.create(
instance -> instance.group(
MOB_EFFECT_DETAILS_CODEC.fieldOf("effect").forGetter(FoodProperties.PossibleEffect::getEffect),
MOB_EFFECT_INSTANCE_CODEC.fieldOf("effect").forGetter(FoodProperties.PossibleEffect::getEffect),
Codec.floatRange(0.0F, 1.0F).optionalFieldOf("probability", 1.0F).forGetter(FoodProperties.PossibleEffect::getProbability)
)
.apply(instance, FoodProperties.PossibleEffect::new)
Expand Down Expand Up @@ -104,10 +173,10 @@ public JsonDataComponents read(JsonReader in) {
map.put(DataComponentType.RARITY, new IntDataComponent(DataComponentType.RARITY, Rarity.valueOf(rarity.toUpperCase(Locale.ROOT)).ordinal()));
}
case "minecraft:attribute_modifiers" -> {

map.put(DataComponentType.ATTRIBUTE_MODIFIERS, new ObjectDataComponent<>(DataComponentType.ATTRIBUTE_MODIFIERS, ITEM_ATTRIBUTE_MODIFIERS_CODEC.decode(JsonOps.INSTANCE, value).result().orElseThrow().getFirst()));
}
case "minecraft:tool" -> {
map.put(DataComponentType.TOOL, new ObjectDataComponent<>(DataComponentType.TOOL, TOOL_CODEC.decode(JsonOps.INSTANCE, value).result().orElseThrow().getFirst()));
// TODO: Implement
}
case "minecraft:food" -> {
map.put(DataComponentType.FOOD, new ObjectDataComponent<>(DataComponentType.FOOD, FOOD_PROPERTIES_CODEC.decode(JsonOps.INSTANCE, value).result().orElseThrow().getFirst()));
Expand Down

0 comments on commit 195635d

Please sign in to comment.