From 4e6504dede4421d16dd46aca9db08afc91bc6719 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 13 Jun 2022 23:32:33 +0300 Subject: [PATCH 01/70] Implemented the core Component API --- library/data/component/build.gradle | 17 +++ .../quiltmc/qsl/component/api/Component.java | 4 + .../api/ComponentInjectionPredicate.java | 7 ++ .../qsl/component/api/ComponentProvider.java | 14 +++ .../quiltmc/qsl/component/api/Components.java | 32 ++++++ .../api/components/IntegerComponent.java | 41 +++++++ .../api/components/InventoryComponent.java | 105 ++++++++++++++++++ .../api/components/NbtComponent.java | 71 ++++++++++++ .../api/identifier/ComponentIdentifier.java | 17 +++ .../qsl/component/impl/ComponentsImpl.java | 38 +++++++ .../defaults/DefaultIntegerComponent.java | 35 ++++++ .../defaults/DefaultInventoryComponent.java | 30 +++++ .../predicates/ClassInjectionPredicate.java | 42 +++++++ .../InheritedInjectionPredicate.java | 30 +++++ .../component/impl/util/StringConstants.java | 5 + .../qsl/component/mixin/MixinEntity.java | 82 ++++++++++++++ .../resources/assets/quilt_recipe/icon.png | Bin 0 -> 261 bytes .../resources/quilt_component.mixins.json | 11 ++ .../qsl/component/test/ComponentTestMod.java | 83 ++++++++++++++ .../src/testmod/resources/quilt.mod.json | 23 ++++ 20 files changed, 687 insertions(+) create mode 100644 library/data/component/build.gradle create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java create mode 100644 library/data/component/src/main/resources/assets/quilt_recipe/icon.png create mode 100644 library/data/component/src/main/resources/quilt_component.mixins.json create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java create mode 100644 library/data/component/src/testmod/resources/quilt.mod.json diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle new file mode 100644 index 0000000000..aff1229c2d --- /dev/null +++ b/library/data/component/build.gradle @@ -0,0 +1,17 @@ +plugins { + id("qsl.module") +} + +qslModule { + name = "Quilt Component Attachment API" + moduleName = "component" + id = "quilt_component" + description = "API allowing attachment and querying of an ECS-like interface for entities, block-entities, chunks, etc." + library = "data" + moduleDependencies { + core { + api("qsl_base") + testmodOnly("lifecycle_events") + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java new file mode 100644 index 0000000000..5a27d8c281 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java @@ -0,0 +1,4 @@ +package org.quiltmc.qsl.component.api; + +public interface Component { +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java new file mode 100644 index 0000000000..f661a63dd3 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java @@ -0,0 +1,7 @@ +package org.quiltmc.qsl.component.api; + +public interface ComponentInjectionPredicate { + + boolean canInject(ComponentProvider provider); + +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java new file mode 100644 index 0000000000..ef05809088 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -0,0 +1,14 @@ +package org.quiltmc.qsl.component.api; + +import com.google.common.collect.ImmutableCollection; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; + +import java.util.Optional; + +public interface ComponentProvider { + + Optional expose(ComponentIdentifier id); + + ImmutableCollection exposeAll(); + +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java new file mode 100644 index 0000000000..298d127d3c --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -0,0 +1,32 @@ +package org.quiltmc.qsl.component.api; + +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.predicates.ClassInjectionPredicate; +import org.quiltmc.qsl.component.impl.predicates.InheritedInjectionPredicate; + +import java.util.Optional; + +public final class Components { + public static void inject(Class clazz, ComponentIdentifier component) { + ComponentsImpl.inject(new ClassInjectionPredicate(clazz), component); + } + + public static void injectInheritage(Class clazz, ComponentIdentifier component) { + ComponentsImpl.inject(new InheritedInjectionPredicate(clazz), component); + } + + public static Optional expose(ComponentIdentifier id, S obj) { + if (obj instanceof ComponentProvider provider) { + return provider.expose(id); + } + + return Optional.empty(); + } + + public static ImmutableCollection exposeAll(S obj) { + return obj instanceof ComponentProvider provider ? provider.exposeAll() : ImmutableList.of(); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java new file mode 100644 index 0000000000..45e1b453fd --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java @@ -0,0 +1,41 @@ +package org.quiltmc.qsl.component.api.components; + +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtInt; +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.defaults.DefaultIntegerComponent; + +import java.util.function.Supplier; + +public interface IntegerComponent extends NbtComponent { + static ComponentIdentifier create(int initialValue, Identifier id) { + Supplier supplier = () -> new DefaultIntegerComponent(initialValue); + return ComponentsImpl.register(id, supplier); + } + + static ComponentIdentifier create(Identifier id) { + return ComponentsImpl.register(id, DefaultIntegerComponent::new); + } + + int get(); + + void set(int value); + + void increment(); + + void decrement(); + + default NbtInt write() { + return NbtInt.of(this.get()); + } + + default void read(NbtInt nbt) { + this.set(nbt.intValue()); + } + + default byte nbtType() { + return NbtElement.INT_TYPE; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java new file mode 100644 index 0000000000..303d32768f --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -0,0 +1,105 @@ +package org.quiltmc.qsl.component.api.components; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventories; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.DefaultedList; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.defaults.DefaultInventoryComponent; + +import java.util.function.Supplier; + +public interface InventoryComponent extends NbtComponent, Inventory { + static ComponentIdentifier ofSize(int size, Identifier id) { + Supplier component = () -> new DefaultInventoryComponent(size); + return ComponentsImpl.register(id, component); + } + + static ComponentIdentifier of(Supplier> items, Identifier id) { + Supplier component = () -> new DefaultInventoryComponent(items); + return ComponentsImpl.register(id, component); + } + + DefaultedList getStacks(); + + @Override + default int size() { + return this.getStacks().size(); + } + + @Override + default boolean isEmpty() { + for (ItemStack stack : this.getStacks()) { + if (!stack.isEmpty()) { + return false; + } + } + + return true; + } + + @Override + default ItemStack getStack(int slot) { + return this.getStacks().get(slot); + } + + @Override + default ItemStack removeStack(int slot, int amount) { + var result = Inventories.splitStack(this.getStacks(), slot, amount); + this.markDirty(); + + return result; + } + + @Override + default ItemStack removeStack(int slot) { + var result = Inventories.removeStack(this.getStacks(), slot); + this.markDirty(); + + return result; + } + + @Override + default void setStack(int slot, ItemStack stack) { + this.getStacks().set(slot, stack); + if (stack.getCount() > getMaxCountPerStack()) { + stack.setCount(getMaxCountPerStack()); + } + + this.markDirty(); + } + + @Override + default boolean canPlayerUse(PlayerEntity player) { + return true; + } + + @Override + default NbtCompound write() { + return Inventories.writeNbt(new NbtCompound(), this.getStacks()); + } + + @Override + default void read(NbtCompound nbt) { + Inventories.readNbt(nbt, this.getStacks()); + } + + @Override + default byte nbtType() { + return NbtElement.COMPOUND_TYPE; + } + + @Override + void markDirty(); + + @Override + default void clear() { + this.getStacks().clear(); + this.markDirty(); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java new file mode 100644 index 0000000000..34e3fc6f0f --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -0,0 +1,71 @@ +package org.quiltmc.qsl.component.api.components; + +import net.minecraft.nbt.*; +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.api.Component; + +public interface NbtComponent extends Component { + + T write(); + + void read(T nbt); + + byte nbtType(); + + @SuppressWarnings("unchecked") // Suppressing because we know those values are hardcoded either way. + static void forward(NbtComponent nbtComponent, Identifier id, NbtCompound nbt) { + switch (nbtComponent.nbtType()){ + case NbtElement.BYTE_TYPE -> { + NbtByte nbtTarget = (NbtByte) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.SHORT_TYPE -> { + NbtShort nbtTarget = (NbtShort) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.INT_TYPE -> { + NbtInt nbtTarget = (NbtInt) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.LONG_TYPE -> { + NbtLong nbtTarget = (NbtLong) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.FLOAT_TYPE -> { + NbtFloat nbtTarget = (NbtFloat) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.DOUBLE_TYPE -> { + NbtDouble nbtTarget = (NbtDouble) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.BYTE_ARRAY_TYPE -> { + NbtByteArray nbtTarget = (NbtByteArray) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.STRING_TYPE -> { + NbtString nbtTarget = (NbtString) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.LIST_TYPE -> { + NbtList nbtTarget = (NbtList) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.COMPOUND_TYPE -> { + NbtCompound nbtTarget = (NbtCompound) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.INT_ARRAY_TYPE -> { + NbtIntArray nbtTarget = (NbtIntArray) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + case NbtElement.LONG_ARRAY_TYPE -> { + NbtLongArray nbtTarget = (NbtLongArray) nbt.get(id.toString()); + ((NbtComponent) nbtComponent).read(nbtTarget); + } + default -> // TODO: Handle non-vanilla nbt types. + throw new RuntimeException("The nbt data type with id %d is not handled at the moment!".formatted(nbtComponent.nbtType())); + } + } + +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java new file mode 100644 index 0000000000..63d3e67882 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java @@ -0,0 +1,17 @@ +package org.quiltmc.qsl.component.api.identifier; + +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.api.Component; + +import java.util.Optional; + +public record ComponentIdentifier(Identifier id){ + + public Optional cast(Component component) { + try { + return Optional.of((T)component); + } catch (ClassCastException ignored) { + return Optional.empty(); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java new file mode 100644 index 0000000000..d65a729a29 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -0,0 +1,38 @@ +package org.quiltmc.qsl.component.impl; + +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; + +import java.util.*; +import java.util.function.Supplier; + +public class ComponentsImpl { + private static final Map>> INJECTION_REGISTRY = new HashMap<>(); + private static final Map> REGISTRY = new HashMap<>(); + + public static void inject(ComponentInjectionPredicate predicate, ComponentIdentifier id) { + Map> currentInjections = INJECTION_REGISTRY.getOrDefault(predicate, new HashMap<>()); + Supplier supplier = REGISTRY.get(id.id()); + if (supplier == null) { + throw new IllegalArgumentException("The target id %s does not match any registered component!".formatted(id.toString())); + } + + currentInjections.put(id.id(), supplier); + + INJECTION_REGISTRY.put(predicate, currentInjections); + } + + public static ComponentIdentifier register(Identifier id, Supplier component) { + REGISTRY.put(id, component); + return new ComponentIdentifier<>(id); + } + + public static Map> get(ComponentProvider provider) { + return INJECTION_REGISTRY.entrySet().stream() + .filter(it -> it.getKey().canInject(provider)) + .collect(HashMap::new, (map, entry) -> map.putAll(entry.getValue()), HashMap::putAll); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java new file mode 100644 index 0000000000..e41d1c1329 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java @@ -0,0 +1,35 @@ +package org.quiltmc.qsl.component.impl.defaults; + +import org.quiltmc.qsl.component.api.components.IntegerComponent; + +public class DefaultIntegerComponent implements IntegerComponent { + private int value; + + public DefaultIntegerComponent(int defaultValue) { + this.value = defaultValue; + } + + public DefaultIntegerComponent() { + this(0); + } + + @Override + public int get() { + return this.value; + } + + @Override + public void set(int value) { + this.value = value; + } + + @Override + public void increment() { + this.value++; + } + + @Override + public void decrement() { + this.value--; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java new file mode 100644 index 0000000000..bbb91f9728 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java @@ -0,0 +1,30 @@ +package org.quiltmc.qsl.component.impl.defaults; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.collection.DefaultedList; +import org.quiltmc.qsl.component.api.components.InventoryComponent; + +import java.util.function.Supplier; + +public class DefaultInventoryComponent implements InventoryComponent { + private final DefaultedList stacks; + private final Runnable dirtyOperation = () -> {}; + + public DefaultInventoryComponent(int size){ + this.stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); + } + + public DefaultInventoryComponent(Supplier> stacks){ + this.stacks = stacks.get(); + } + + @Override + public DefaultedList getStacks() { + return this.stacks; + } + + @Override + public void markDirty() { + this.dirtyOperation.run(); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java new file mode 100644 index 0000000000..62443c83e3 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java @@ -0,0 +1,42 @@ +package org.quiltmc.qsl.component.impl.predicates; + +import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; +import org.quiltmc.qsl.component.api.ComponentProvider; + +import java.util.Arrays; +import java.util.Objects; + +public class ClassInjectionPredicate implements ComponentInjectionPredicate { + protected final Class clazz; + + public ClassInjectionPredicate(Class clazz){ + if (implementsComponentProvider(clazz)) { + this.clazz = clazz; + } else { + throw new IllegalArgumentException("Cannot create an injection predicate for a class that isn't a ComponentProvider"); + } + } + + private static boolean implementsComponentProvider(Class clazz) { + return Arrays.stream(clazz.getInterfaces()).anyMatch(it -> it == ComponentProvider.class) || (clazz.getSuperclass() != null && implementsComponentProvider(clazz.getSuperclass())); + } + + @Override + public boolean canInject(ComponentProvider provider) { + return provider.getClass() == clazz; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o instanceof ClassInjectionPredicate that) { + return clazz.equals(that.clazz); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(clazz); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java new file mode 100644 index 0000000000..07be0b2020 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java @@ -0,0 +1,30 @@ +package org.quiltmc.qsl.component.impl.predicates; + +import org.quiltmc.qsl.component.api.ComponentProvider; + +import java.util.Objects; + +public class InheritedInjectionPredicate extends ClassInjectionPredicate { + public InheritedInjectionPredicate(Class clazz) { + super(clazz); + } + + @Override + public boolean canInject(ComponentProvider provider) { + return canInject(this.clazz, provider.getClass()); + } + + public static boolean canInject(Class target, Class current) { + return target == current || (current != null && canInject(target, current.getSuperclass())); + } + + @Override + public int hashCode() { + return super.hashCode() + Objects.hash(this.getClass()); + } + + @Override + public boolean equals(Object o) { + return o.getClass() == InheritedInjectionPredicate.class && super.equals(o); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java new file mode 100644 index 0000000000..833a46dfc0 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java @@ -0,0 +1,5 @@ +package org.quiltmc.qsl.component.impl.util; + +public final class StringConstants { + public static final String COMPONENT_ROOT = "qsl_component_root"; +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java new file mode 100644 index 0000000000..1c9dd4a559 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -0,0 +1,82 @@ +package org.quiltmc.qsl.component.mixin; + +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableMap; +import it.unimi.dsi.fastutil.Pair; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.nbt.*; +import net.minecraft.util.Identifier; +import net.minecraft.world.World; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.util.StringConstants; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +@Mixin(Entity.class) +@Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) +public abstract class MixinEntity { + + private ImmutableMap qsl$components; + + @Inject(method = "", at = @At("RETURN")) + private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { + if (!world.isClient) { + var this$ = (Entity) (Object) this; + System.out.println(this.getClass()); + var builder = ImmutableMap.builder(); + + // TODO: Caching + Map> injections = + ComponentsImpl.get((ComponentProvider) this$); + injections.forEach((id, supplier) -> builder.put(id, supplier.get())); + this.qsl$components = builder.build(); + } + } + + public Optional comp$expose(ComponentIdentifier id) { + return Optional.ofNullable(this.qsl$components.get(id.id())) + .map(id::cast) + .map(Optional::orElseThrow); + } + + public ImmutableCollection comp$exposeAll() { + return this.qsl$components.values(); + } + + @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) + private void onSerialize(NbtCompound nbt, CallbackInfoReturnable cir) { + var componentNbt = new NbtCompound(); + + this.qsl$applyActionToSerializable((id, nbtComponent) -> componentNbt.put(id.toString(), nbtComponent.write())); + + nbt.put(StringConstants.COMPONENT_ROOT, componentNbt); + } + + @Inject(method = "readNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;readCustomDataFromNbt(Lnet/minecraft/nbt/NbtCompound;)V")) + private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { + var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); + + this.qsl$applyActionToSerializable((id, nbtComponent) -> NbtComponent.forward(nbtComponent, id, rootQslNbt)); + } + + private void qsl$applyActionToSerializable(BiConsumer> action) { + this.qsl$components.entrySet().stream() + .filter(it -> it.getValue() instanceof NbtComponent) + .map(it -> Pair.of(it.getKey(), ((NbtComponent) it.getValue()))) + .forEach(pair -> action.accept(pair.key(), pair.value())); + } +} diff --git a/library/data/component/src/main/resources/assets/quilt_recipe/icon.png b/library/data/component/src/main/resources/assets/quilt_recipe/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8d54ad0021bbf0258acfe2ba452ccc0e6f36f566 GIT binary patch literal 261 zcmV+g0s8)lP)O|2F_@TM=AcYyV#WxOBw)fQtW(8;_SF|EJmfx^Vx~qyO1! z+uE1g+$r5#A>8-?004nWL_t(I%jJ{V3V COW_INVENTORY = InventoryComponent.of( + () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64)), + new Identifier("quilt_component_test", "cow_inventory") + ); + public static final ComponentIdentifier CREEPER_DYED_TIME = + IntegerComponent.create(new Identifier(MODID, "creeper_dye_time")); + + @Override + public void onInitialize(ModContainer mod) { + // Application Code + Components.inject(CreeperEntity.class, CREEPER_DYED_TIME); + Components.injectInheritage(CowEntity.class, COW_INVENTORY); + + // Testing Code + ServerTickEvents.START.register(server -> { + ServerWorld world = server.getWorld(World.OVERWORLD); + assert world != null; + world.iterateEntities().forEach(entity -> { + if (entity instanceof CowEntity) { + Components.expose(COW_INVENTORY, entity) + .ifPresent(inventoryComponent -> { + if (inventoryComponent.isEmpty()) { + entity.discard(); + world.createExplosion( + entity, + entity.getX(), entity.getY(), entity.getZ(), + 4.0f, Explosion.DestructionType.NONE + ); + } else { + inventoryComponent.removeStack(0, 1); + } + }); + } else if (entity instanceof CreeperEntity creeper) { + Optional exposed = Components.expose(CREEPER_DYED_TIME, creeper); + exposed.ifPresent(IntegerComponent::increment); + exposed.filter(it -> it.get() >= 200).ifPresent(integerComponent -> creeper.ignite()); + } + }); + }); + } + +} diff --git a/library/data/component/src/testmod/resources/quilt.mod.json b/library/data/component/src/testmod/resources/quilt.mod.json new file mode 100644 index 0000000000..521a57b6d2 --- /dev/null +++ b/library/data/component/src/testmod/resources/quilt.mod.json @@ -0,0 +1,23 @@ +{ + "schema_version": 1, + "quilt_loader": { + "group": "org.quiltmc.qsl.data", + "id": "quilt_component_test", + "version": "1.0.0", + "metadata": { + "name": "Quilt Component API Test mod.", + "license": "Apache-2.0" + }, + "intermediate_mappings": "net.fabricmc:intermediary", + "load_type": "always", + "entrypoints": { + "init": [ + "org.quiltmc.qsl.component.test.ComponentTestMod" + ] + }, + "depends": [ + "quilt_loader", + "quilt_component" + ] + } +} From a400da6761bbb5c983eaea085ae5a9725c76ad88 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 14 Jun 2022 00:02:14 +0300 Subject: [PATCH 02/70] Modified creeper testing a bit --- .../org/quiltmc/qsl/component/test/ComponentTestMod.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 01e6cd1655..7fe4eb9b9f 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -44,7 +44,7 @@ public class ComponentTestMod implements ModInitializer { new Identifier("quilt_component_test", "cow_inventory") ); public static final ComponentIdentifier CREEPER_DYED_TIME = - IntegerComponent.create(new Identifier(MODID, "creeper_dye_time")); + IntegerComponent.create(200, new Identifier(MODID, "creeper_dye_time")); @Override public void onInitialize(ModContainer mod) { @@ -73,8 +73,8 @@ public void onInitialize(ModContainer mod) { }); } else if (entity instanceof CreeperEntity creeper) { Optional exposed = Components.expose(CREEPER_DYED_TIME, creeper); - exposed.ifPresent(IntegerComponent::increment); - exposed.filter(it -> it.get() >= 200).ifPresent(integerComponent -> creeper.ignite()); + exposed.ifPresent(IntegerComponent::decrement); + exposed.filter(it -> it.get() <= 0).ifPresent(ignored -> creeper.ignite()); } }); }); From d3ddc7b25408c652e77d193196aa4cbceb38fa37 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 14 Jun 2022 12:15:28 +0300 Subject: [PATCH 03/70] Implemented caching for injection targets. --- .../qsl/component/impl/ComponentCache.java | 41 +++++++++++++++++++ .../qsl/component/impl/ComponentsImpl.java | 40 ++++++++++++++---- .../predicates/ClassInjectionPredicate.java | 5 +++ .../InheritedInjectionPredicate.java | 5 +++ .../qsl/component/mixin/MixinEntity.java | 3 -- .../qsl/component/test/ComponentTestMod.java | 8 ++-- 6 files changed, 86 insertions(+), 16 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java new file mode 100644 index 0000000000..7ac863a736 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java @@ -0,0 +1,41 @@ +package org.quiltmc.qsl.component.impl; + +import net.minecraft.util.Identifier; +import net.minecraft.util.Util; +import org.quiltmc.qsl.component.api.Component; + +import java.util.*; +import java.util.function.Supplier; + +public class ComponentCache { + + private static ComponentCache INSTANCE; + + private final Map, Map>> injectionCache = new HashMap<>(); + + private ComponentCache() { + + } + + public static ComponentCache getInstance(){ + if (INSTANCE == null) { + INSTANCE = new ComponentCache(); + } + + return INSTANCE; + } + + public Optional>> getCache(Class clazz) { + if (!this.injectionCache.containsKey(clazz)) { + return Optional.empty(); + } + + return Optional.of(this.injectionCache.get(clazz)); + } + + public void record(Class clazz, Collection components) { + if (this.injectionCache.put(clazz, Util.make(new HashMap<>(), map -> components.forEach(id -> map.put(id, ComponentsImpl.getEntry(id))))) != null) { + throw new IllegalStateException("Cannot register cache twice for class %s".formatted(clazz)); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index d65a729a29..3e89f9b027 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -1,6 +1,7 @@ package org.quiltmc.qsl.component.impl; import net.minecraft.util.Identifier; +import net.minecraft.util.Util; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; @@ -10,19 +11,27 @@ import java.util.function.Supplier; public class ComponentsImpl { - private static final Map>> INJECTION_REGISTRY = new HashMap<>(); - private static final Map> REGISTRY = new HashMap<>(); + private static final Map> INJECTION_REGISTRY = new HashMap<>(); + private static final Map> REGISTRY = new HashMap<>(); public static void inject(ComponentInjectionPredicate predicate, ComponentIdentifier id) { - Map> currentInjections = INJECTION_REGISTRY.getOrDefault(predicate, new HashMap<>()); Supplier supplier = REGISTRY.get(id.id()); if (supplier == null) { - throw new IllegalArgumentException("The target id %s does not match any registered component!".formatted(id.toString())); + throw new IllegalArgumentException( + "The target id %s does not match any registered component!".formatted(id.toString()) + ); } - currentInjections.put(id.id(), supplier); - - INJECTION_REGISTRY.put(predicate, currentInjections); + if (INJECTION_REGISTRY.containsKey(predicate)) { + if (!INJECTION_REGISTRY.get(predicate).add(id.id())) { + throw new IllegalStateException( + "Cannot inject the predicate %s with %s more than once! Consider creating a new component!" + .formatted(predicate.toString(), id.id().toString()) + ); + } + } else { + INJECTION_REGISTRY.put(predicate, Util.make(new HashSet<>(), set -> set.add(id.id()))); + } } public static ComponentIdentifier register(Identifier id, Supplier component) { @@ -31,8 +40,21 @@ public static ComponentIdentifier register(Identifier i } public static Map> get(ComponentProvider provider) { - return INJECTION_REGISTRY.entrySet().stream() + Optional>> cache = ComponentCache.getInstance().getCache(provider.getClass()); + + return cache.orElseGet(() -> { + Map> returnMap = INJECTION_REGISTRY.entrySet().stream() .filter(it -> it.getKey().canInject(provider)) - .collect(HashMap::new, (map, entry) -> map.putAll(entry.getValue()), HashMap::putAll); + .map(Map.Entry::getValue) + .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, REGISTRY.get(id))), HashMap::putAll); + + ComponentCache.getInstance().record(provider.getClass(), returnMap.keySet()); + + return returnMap; + }); + } + + public static Supplier getEntry(Identifier id) { + return REGISTRY.get(id); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java index 62443c83e3..a1cec337f2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java @@ -39,4 +39,9 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(clazz); } + + @Override + public String toString() { + return "ClassInjectionPredicate{clazz=" + clazz + '}'; + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java index 07be0b2020..ff54ee2c1e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java @@ -27,4 +27,9 @@ public int hashCode() { public boolean equals(Object o) { return o.getClass() == InheritedInjectionPredicate.class && super.equals(o); } + + @Override + public String toString() { + return "InheritedInjectionPredicate{clazz=" + this.clazz + '}'; + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 1c9dd4a559..6802f65b97 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -39,7 +39,6 @@ private void onEntityInit(EntityType entityType, World world, CallbackInfo ci System.out.println(this.getClass()); var builder = ImmutableMap.builder(); - // TODO: Caching Map> injections = ComponentsImpl.get((ComponentProvider) this$); injections.forEach((id, supplier) -> builder.put(id, supplier.get())); @@ -60,7 +59,6 @@ private void onEntityInit(EntityType entityType, World world, CallbackInfo ci @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void onSerialize(NbtCompound nbt, CallbackInfoReturnable cir) { var componentNbt = new NbtCompound(); - this.qsl$applyActionToSerializable((id, nbtComponent) -> componentNbt.put(id.toString(), nbtComponent.write())); nbt.put(StringConstants.COMPONENT_ROOT, componentNbt); @@ -69,7 +67,6 @@ private void onSerialize(NbtCompound nbt, CallbackInfoReturnable ci @Inject(method = "readNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;readCustomDataFromNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - this.qsl$applyActionToSerializable((id, nbtComponent) -> NbtComponent.forward(nbtComponent, id, rootQslNbt)); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 7fe4eb9b9f..b08c2bc77a 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -43,13 +43,13 @@ public class ComponentTestMod implements ModInitializer { () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64)), new Identifier("quilt_component_test", "cow_inventory") ); - public static final ComponentIdentifier CREEPER_DYED_TIME = - IntegerComponent.create(200, new Identifier(MODID, "creeper_dye_time")); + public static final ComponentIdentifier CREEPER_EXPLODE_TIME = + IntegerComponent.create(200, new Identifier(MODID, "creeper_explode_time")); @Override public void onInitialize(ModContainer mod) { // Application Code - Components.inject(CreeperEntity.class, CREEPER_DYED_TIME); + Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); Components.injectInheritage(CowEntity.class, COW_INVENTORY); // Testing Code @@ -72,7 +72,7 @@ public void onInitialize(ModContainer mod) { } }); } else if (entity instanceof CreeperEntity creeper) { - Optional exposed = Components.expose(CREEPER_DYED_TIME, creeper); + Optional exposed = Components.expose(CREEPER_EXPLODE_TIME, creeper); exposed.ifPresent(IntegerComponent::decrement); exposed.filter(it -> it.get() <= 0).ifPresent(ignored -> creeper.ignite()); } From f2f6c512434e8c67b3bac4a471f489e210dcea81 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 14 Jun 2022 14:58:51 +0300 Subject: [PATCH 04/70] Reformat and better tests. --- .../qsl/component/api/ComponentProvider.java | 2 +- .../quiltmc/qsl/component/api/Components.java | 9 ++- .../qsl/component/impl/ComponentsImpl.java | 4 +- .../FilteredInheritedInjectionPredicate.java | 39 +++++++++++ .../InheritedInjectionPredicate.java | 8 +-- .../component/impl/util/StringConstants.java | 2 +- .../qsl/component/mixin/MixinEntity.java | 45 +++++++------ .../qsl/component/test/ComponentTestMod.java | 65 +++++++++++-------- 8 files changed, 114 insertions(+), 60 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index ef05809088..47cd04bf39 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -7,7 +7,7 @@ public interface ComponentProvider { - Optional expose(ComponentIdentifier id); + Optional expose(ComponentIdentifier id); ImmutableCollection exposeAll(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 298d127d3c..76d1fba2d4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -5,6 +5,7 @@ import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.predicates.ClassInjectionPredicate; +import org.quiltmc.qsl.component.impl.predicates.FilteredInheritedInjectionPredicate; import org.quiltmc.qsl.component.impl.predicates.InheritedInjectionPredicate; import java.util.Optional; @@ -18,9 +19,15 @@ public static void injectInheritage(Class clazz, Com ComponentsImpl.inject(new InheritedInjectionPredicate(clazz), component); } + public static void injectInheritanceExcept(Class clazz, ComponentIdentifier component, Class... exceptions) { + ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), component); + } + public static Optional expose(ComponentIdentifier id, S obj) { if (obj instanceof ComponentProvider provider) { - return provider.expose(id); + return provider.expose(id) + .map(id::cast) + .map(Optional::orElseThrow); } return Optional.empty(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 3e89f9b027..0aa33f905f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -40,9 +40,7 @@ public static ComponentIdentifier register(Identifier i } public static Map> get(ComponentProvider provider) { - Optional>> cache = ComponentCache.getInstance().getCache(provider.getClass()); - - return cache.orElseGet(() -> { + return ComponentCache.getInstance().getCache(provider.getClass()).orElseGet(() -> { Map> returnMap = INJECTION_REGISTRY.entrySet().stream() .filter(it -> it.getKey().canInject(provider)) .map(Map.Entry::getValue) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java new file mode 100644 index 0000000000..f7848b14d7 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java @@ -0,0 +1,39 @@ +package org.quiltmc.qsl.component.impl.predicates; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public class FilteredInheritedInjectionPredicate extends InheritedInjectionPredicate { + private final List> exceptions; + + public FilteredInheritedInjectionPredicate(Class clazz, Class[] exceptions) { + super(clazz); + this.exceptions = new ArrayList<>(Arrays.asList(exceptions)); + } + + @Override + public boolean canInject(Class current) { + return !this.exceptions.contains(current) && super.canInject(current); + } + + @Override + public int hashCode() { + return super.hashCode() + 37 * Objects.hash(this.exceptions); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof FilteredInheritedInjectionPredicate)) return false; + if (!super.equals(o)) return false; + FilteredInheritedInjectionPredicate that = (FilteredInheritedInjectionPredicate) o; + return exceptions.equals(that.exceptions); + } + + @Override + public String toString() { + return "FilteredInheritedInjectionPredicate{clazz=" + clazz + ", exceptions=" + exceptions + '}'; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java index ff54ee2c1e..d918e8a543 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java @@ -11,11 +11,11 @@ public InheritedInjectionPredicate(Class clazz) { @Override public boolean canInject(ComponentProvider provider) { - return canInject(this.clazz, provider.getClass()); + return this.canInject(provider.getClass()); } - public static boolean canInject(Class target, Class current) { - return target == current || (current != null && canInject(target, current.getSuperclass())); + public boolean canInject(Class current) { + return this.clazz == current || (current != null && canInject(current.getSuperclass())); } @Override @@ -25,7 +25,7 @@ public int hashCode() { @Override public boolean equals(Object o) { - return o.getClass() == InheritedInjectionPredicate.class && super.equals(o); + return o instanceof InheritedInjectionPredicate && super.equals(o); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java index 833a46dfc0..62ffec9044 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java @@ -1,5 +1,5 @@ package org.quiltmc.qsl.component.impl.util; public final class StringConstants { - public static final String COMPONENT_ROOT = "qsl_component_root"; + public static final String COMPONENT_ROOT = "QslComponentRoot"; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 6802f65b97..58ada62427 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -2,10 +2,9 @@ import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMap; -import it.unimi.dsi.fastutil.Pair; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.nbt.*; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; import net.minecraft.world.World; import org.quiltmc.qsl.component.api.Component; @@ -22,8 +21,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.*; -import java.util.function.BiConsumer; +import java.util.Map; +import java.util.Optional; import java.util.function.Supplier; @Mixin(Entity.class) @@ -31,25 +30,32 @@ public abstract class MixinEntity { private ImmutableMap qsl$components; + private ImmutableMap> qsl$nbtComponents; @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { if (!world.isClient) { - var this$ = (Entity) (Object) this; - System.out.println(this.getClass()); + System.out.println(this.getClass()); // TODO: Remove this var builder = ImmutableMap.builder(); - Map> injections = - ComponentsImpl.get((ComponentProvider) this$); + Map> injections = ComponentsImpl.get((ComponentProvider) this); injections.forEach((id, supplier) -> builder.put(id, supplier.get())); this.qsl$components = builder.build(); + this.qsl$nbtComponents = this.qsl$components.entrySet().stream() + .filter(it -> it.getValue() instanceof NbtComponent) + .collect( + ImmutableMap::>builder, + (map, entry) -> map.put(entry.getKey(), ((NbtComponent) entry.getValue())), + (builder1, builder2) -> builder1.putAll(builder2.build()) + ).build(); + } else { + this.qsl$components = ImmutableMap.of(); + this.qsl$nbtComponents = ImmutableMap.of(); } } - public Optional comp$expose(ComponentIdentifier id) { - return Optional.ofNullable(this.qsl$components.get(id.id())) - .map(id::cast) - .map(Optional::orElseThrow); + public Optional comp$expose(ComponentIdentifier id) { + return Optional.ofNullable(this.qsl$components.get(id.id())); } public ImmutableCollection comp$exposeAll() { @@ -58,22 +64,15 @@ private void onEntityInit(EntityType entityType, World world, CallbackInfo ci @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void onSerialize(NbtCompound nbt, CallbackInfoReturnable cir) { - var componentNbt = new NbtCompound(); - this.qsl$applyActionToSerializable((id, nbtComponent) -> componentNbt.put(id.toString(), nbtComponent.write())); + var rootQslNbt = new NbtCompound(); + this.qsl$nbtComponents.forEach((id, nbtComponent) -> rootQslNbt.put(id.toString(), nbtComponent.write())); - nbt.put(StringConstants.COMPONENT_ROOT, componentNbt); + nbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); } @Inject(method = "readNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;readCustomDataFromNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - this.qsl$applyActionToSerializable((id, nbtComponent) -> NbtComponent.forward(nbtComponent, id, rootQslNbt)); - } - - private void qsl$applyActionToSerializable(BiConsumer> action) { - this.qsl$components.entrySet().stream() - .filter(it -> it.getValue() instanceof NbtComponent) - .map(it -> Pair.of(it.getKey(), ((NbtComponent) it.getValue()))) - .forEach(pair -> action.accept(pair.key(), pair.value())); + this.qsl$nbtComponents.forEach((id, nbtComponent) -> NbtComponent.forward(nbtComponent, id, rootQslNbt)); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index b08c2bc77a..52c9c8f98f 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -17,6 +17,7 @@ package org.quiltmc.qsl.component.test; import net.minecraft.entity.mob.CreeperEntity; +import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -32,8 +33,7 @@ import org.quiltmc.qsl.component.api.components.InventoryComponent; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.lifecycle.api.event.ServerTickEvents; - -import java.util.Optional; +import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; public class ComponentTestMod implements ModInitializer { public static final String MODID = "quilt_component_test"; @@ -45,39 +45,50 @@ public class ComponentTestMod implements ModInitializer { ); public static final ComponentIdentifier CREEPER_EXPLODE_TIME = IntegerComponent.create(200, new Identifier(MODID, "creeper_explode_time")); + public static final ComponentIdentifier HOSTILE_EXPLODE_TIME = + IntegerComponent.create(new Identifier(MODID, "hostile_explode_time")); @Override public void onInitialize(ModContainer mod) { // Application Code Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); Components.injectInheritage(CowEntity.class, COW_INVENTORY); + Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); // Testing Code - ServerTickEvents.START.register(server -> { - ServerWorld world = server.getWorld(World.OVERWORLD); - assert world != null; - world.iterateEntities().forEach(entity -> { - if (entity instanceof CowEntity) { - Components.expose(COW_INVENTORY, entity) - .ifPresent(inventoryComponent -> { - if (inventoryComponent.isEmpty()) { - entity.discard(); - world.createExplosion( - entity, - entity.getX(), entity.getY(), entity.getZ(), - 4.0f, Explosion.DestructionType.NONE - ); - } else { - inventoryComponent.removeStack(0, 1); - } - }); - } else if (entity instanceof CreeperEntity creeper) { - Optional exposed = Components.expose(CREEPER_EXPLODE_TIME, creeper); - exposed.ifPresent(IntegerComponent::decrement); - exposed.filter(it -> it.get() <= 0).ifPresent(ignored -> creeper.ignite()); - } - }); - }); + ServerWorldTickEvents.START.register((ignored, world) -> world.iterateEntities().forEach(entity -> { + if (entity instanceof CowEntity) { + Components.expose(COW_INVENTORY, entity).ifPresent(inventoryComponent -> { + if (inventoryComponent.isEmpty()) { + entity.discard(); + world.createExplosion( + entity, + entity.getX(), entity.getY(), entity.getZ(), + 4.0f, Explosion.DestructionType.NONE + ); + } else { + inventoryComponent.removeStack(0, 1); + } + }); + } else if (entity instanceof CreeperEntity creeper) { + Components.expose(CREEPER_EXPLODE_TIME, creeper).ifPresent(explodeTime -> { + if (explodeTime.get() > 0) { + explodeTime.decrement(); + } else { + creeper.ignite(); + } + }); + } else if (entity instanceof HostileEntity hostile) { + Components.expose(HOSTILE_EXPLODE_TIME, hostile).ifPresent(explodeTime -> { + if (explodeTime.get() <= 200) { + explodeTime.increment(); + } else { + hostile.discard(); + hostile.getWorld().createExplosion(null, hostile.getX(), hostile.getY(), hostile.getZ(), 1.0f, Explosion.DestructionType.NONE); + } + }); + } + })); } } From 20a75cbefd0a40575943b6d0e1c6b4fa21b5ee1f Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 14 Jun 2022 16:23:15 +0300 Subject: [PATCH 05/70] Implemented ComponentProvider for Block Entities. --- .../qsl/component/api/ComponentProvider.java | 15 ++++ .../api/components/NbtComponent.java | 75 +++++++------------ .../impl/util/duck/NbtComponentProvider.java | 9 +++ .../qsl/component/mixin/MixinBlockEntity.java | 71 ++++++++++++++++++ .../qsl/component/mixin/MixinEntity.java | 18 +---- .../resources/quilt_component.mixins.json | 1 + .../qsl/component/test/ComponentTestMod.java | 27 ++++++- 7 files changed, 149 insertions(+), 67 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 47cd04bf39..db6006843b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -1,9 +1,14 @@ package org.quiltmc.qsl.component.api; import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableMap; +import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import java.util.Map; import java.util.Optional; +import java.util.function.Supplier; public interface ComponentProvider { @@ -11,4 +16,14 @@ public interface ComponentProvider { ImmutableCollection exposeAll(); + static ImmutableMap createComponents(ComponentProvider provider) { + System.out.println(provider.getClass()); // TODO: Remove this + var builder = ImmutableMap.builder(); + + Map> injections = ComponentsImpl.get(provider); + injections.forEach((id, supplier) -> builder.put(id, supplier.get())); + + return builder.build(); + } + } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index 34e3fc6f0f..20785d20df 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -1,9 +1,12 @@ package org.quiltmc.qsl.component.api.components; +import com.google.common.collect.ImmutableMap; import net.minecraft.nbt.*; import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.Component; +import java.util.Map; + public interface NbtComponent extends Component { T write(); @@ -14,58 +17,34 @@ public interface NbtComponent extends Component { @SuppressWarnings("unchecked") // Suppressing because we know those values are hardcoded either way. static void forward(NbtComponent nbtComponent, Identifier id, NbtCompound nbt) { + NbtElement nbtTarget = nbt.get(id.toString()); switch (nbtComponent.nbtType()){ - case NbtElement.BYTE_TYPE -> { - NbtByte nbtTarget = (NbtByte) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.SHORT_TYPE -> { - NbtShort nbtTarget = (NbtShort) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.INT_TYPE -> { - NbtInt nbtTarget = (NbtInt) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.LONG_TYPE -> { - NbtLong nbtTarget = (NbtLong) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.FLOAT_TYPE -> { - NbtFloat nbtTarget = (NbtFloat) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.DOUBLE_TYPE -> { - NbtDouble nbtTarget = (NbtDouble) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.BYTE_ARRAY_TYPE -> { - NbtByteArray nbtTarget = (NbtByteArray) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.STRING_TYPE -> { - NbtString nbtTarget = (NbtString) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.LIST_TYPE -> { - NbtList nbtTarget = (NbtList) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.COMPOUND_TYPE -> { - NbtCompound nbtTarget = (NbtCompound) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.INT_ARRAY_TYPE -> { - NbtIntArray nbtTarget = (NbtIntArray) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } - case NbtElement.LONG_ARRAY_TYPE -> { - NbtLongArray nbtTarget = (NbtLongArray) nbt.get(id.toString()); - ((NbtComponent) nbtComponent).read(nbtTarget); - } + case NbtElement.BYTE_TYPE -> ((NbtComponent) nbtComponent).read((NbtByte) nbtTarget); + case NbtElement.SHORT_TYPE -> ((NbtComponent) nbtComponent).read((NbtShort) nbtTarget); + case NbtElement.INT_TYPE -> ((NbtComponent) nbtComponent).read((NbtInt) nbtTarget); + case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); + case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); + case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); + case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); + case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); + case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); + case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); + case NbtElement.INT_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtIntArray) nbtTarget); + case NbtElement.LONG_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtLongArray) nbtTarget); default -> // TODO: Handle non-vanilla nbt types. throw new RuntimeException("The nbt data type with id %d is not handled at the moment!".formatted(nbtComponent.nbtType())); } } + static ImmutableMap> getNbtSerializable(ImmutableMap components) { + var builder = ImmutableMap.>builder(); + + for (var entry : components.entrySet()) { + if (entry.getValue() instanceof NbtComponent nbtComponent) { + builder.put(entry.getKey(), nbtComponent); + } + } + + return builder.build(); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java new file mode 100644 index 0000000000..fd4132b3e5 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java @@ -0,0 +1,9 @@ +package org.quiltmc.qsl.component.impl.util.duck; + +import com.google.common.collect.ImmutableMap; +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.api.components.NbtComponent; + +public interface NbtComponentProvider { + ImmutableMap> get(); +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java new file mode 100644 index 0000000000..20804ace54 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -0,0 +1,71 @@ +package org.quiltmc.qsl.component.mixin; + +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableMap; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.util.StringConstants; +import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Optional; + +@Implements({ + @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$"), + @Interface(iface = ComponentProvider.class, prefix = "comp$") +}) +@Mixin(BlockEntity.class) +public class MixinBlockEntity { + + private ImmutableMap qsl$components; + private ImmutableMap> qsl$nbtComponents; + + @Inject( + method = "m_qgnqsprj", // The lambda used in second map operation. + at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V") + ) + private static void onReadNbt(NbtCompound nbt, String string, BlockEntity blockEntity, CallbackInfoReturnable cir) { + var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); + ((NbtComponentProvider) blockEntity).get().forEach((id, nbtComponent) -> NbtComponent.forward(nbtComponent, id, rootQslNbt)); + } + + @Inject(method = "", at = @At("RETURN")) + private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { + this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); + this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); + } + + @Inject(method = "toNbt", at = @At("RETURN")) + private void onWriteNbt(CallbackInfoReturnable cir) { + var rootQslNbt = new NbtCompound(); + this.qsl$nbtComponents.forEach((id, nbtComponent) -> rootQslNbt.put(id.toString(), nbtComponent.write())); + + cir.getReturnValue().put(StringConstants.COMPONENT_ROOT, rootQslNbt); + } + + public ImmutableMap> nbtExp$get() { + return this.qsl$nbtComponents; + } + + public Optional comp$expose(ComponentIdentifier id) { + return Optional.ofNullable(this.qsl$components.get(id.id())); + } + + public ImmutableCollection comp$exposeAll() { + return this.qsl$components.values(); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 58ada62427..848017a37b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -11,7 +11,6 @@ import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.components.NbtComponent; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.util.StringConstants; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -21,9 +20,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; @Mixin(Entity.class) @Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) @@ -35,19 +32,8 @@ public abstract class MixinEntity { @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { if (!world.isClient) { - System.out.println(this.getClass()); // TODO: Remove this - var builder = ImmutableMap.builder(); - - Map> injections = ComponentsImpl.get((ComponentProvider) this); - injections.forEach((id, supplier) -> builder.put(id, supplier.get())); - this.qsl$components = builder.build(); - this.qsl$nbtComponents = this.qsl$components.entrySet().stream() - .filter(it -> it.getValue() instanceof NbtComponent) - .collect( - ImmutableMap::>builder, - (map, entry) -> map.put(entry.getKey(), ((NbtComponent) entry.getValue())), - (builder1, builder2) -> builder1.putAll(builder2.build()) - ).build(); + this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); + this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); } else { this.qsl$components = ImmutableMap.of(); this.qsl$nbtComponents = ImmutableMap.of(); diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index 3a60ddc9dc..a35ef27760 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -3,6 +3,7 @@ "package": "org.quiltmc.qsl.component.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "MixinBlockEntity", "MixinEntity" ], "injectors": { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 52c9c8f98f..47593c9654 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -16,15 +16,17 @@ package org.quiltmc.qsl.component.test; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.ChestBlockEntity; import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; -import net.minecraft.world.World; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.explosion.Explosion; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; @@ -32,7 +34,6 @@ import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.InventoryComponent; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import org.quiltmc.qsl.lifecycle.api.event.ServerTickEvents; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; public class ComponentTestMod implements ModInitializer { @@ -47,6 +48,8 @@ public class ComponentTestMod implements ModInitializer { IntegerComponent.create(200, new Identifier(MODID, "creeper_explode_time")); public static final ComponentIdentifier HOSTILE_EXPLODE_TIME = IntegerComponent.create(new Identifier(MODID, "hostile_explode_time")); + public static final ComponentIdentifier CHEST_NUMBER = + IntegerComponent.create(new Identifier(MODID, "chest_number")); @Override public void onInitialize(ModContainer mod) { @@ -54,6 +57,7 @@ public void onInitialize(ModContainer mod) { Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); Components.injectInheritage(CowEntity.class, COW_INVENTORY); Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); + Components.inject(ChestBlockEntity.class, CHEST_NUMBER); // Testing Code ServerWorldTickEvents.START.register((ignored, world) -> world.iterateEntities().forEach(entity -> { @@ -89,6 +93,23 @@ public void onInitialize(ModContainer mod) { }); } })); + + + ServerWorldTickEvents.START.register((server, world) -> + BlockPos.streamOutwards(new BlockPos(0, 0, 0), 5, 5, 5).forEach(pos -> { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof ChestBlockEntity chest) { + Components.expose(CHEST_NUMBER, chest) + .ifPresent(integerComponent -> { + if (integerComponent.get() == 0) { + integerComponent.set(world.random.nextInt(10)); + } else if (integerComponent.get() == 6) { + world.setBlockState(pos, Blocks.DIAMOND_BLOCK.getDefaultState()); + } + }); + } + }) + ); } } From febe5a8e22416afc3cc828fa58f97d26d85cc74f Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 20 Jun 2022 10:38:55 +0300 Subject: [PATCH 06/70] Added Chunks are Component Providers(serialization does not work yet). --- .../qsl/component/api/ComponentProvider.java | 17 +-- .../quiltmc/qsl/component/api/Components.java | 17 +-- .../api/components/NbtComponent.java | 10 +- .../component/impl/util/duck/CustomChunk.java | 10 ++ .../impl/util/duck/NbtComponentProvider.java | 5 +- .../qsl/component/mixin/MixinBlockEntity.java | 33 ++--- .../qsl/component/mixin/MixinChunk.java | 59 +++++++++ .../component/mixin/MixinChunkSerializer.java | 40 ++++++ .../qsl/component/mixin/MixinEntity.java | 19 +-- .../qsl/component/mixin/MixinItemStack.java | 8 ++ .../resources/quilt_component.mixins.json | 5 +- .../qsl/component/test/ComponentTestMod.java | 120 ++++++++++-------- 12 files changed, 238 insertions(+), 105 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/CustomChunk.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index db6006843b..42cbfd10a3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -1,29 +1,26 @@ package org.quiltmc.qsl.component.api; -import com.google.common.collect.ImmutableCollection; -import com.google.common.collect.ImmutableMap; import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.ComponentsImpl; +import java.util.HashMap; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; public interface ComponentProvider { Optional expose(ComponentIdentifier id); - ImmutableCollection exposeAll(); + Map exposeAll(); - static ImmutableMap createComponents(ComponentProvider provider) { + static @NotNull Map createComponents(@NotNull ComponentProvider provider) { System.out.println(provider.getClass()); // TODO: Remove this - var builder = ImmutableMap.builder(); + var map = new HashMap(); + ComponentsImpl.get(provider).forEach((identifier, supplier) -> map.put(identifier, supplier.get())); - Map> injections = ComponentsImpl.get(provider); - injections.forEach((id, supplier) -> builder.put(id, supplier.get())); - - return builder.build(); + return map; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 76d1fba2d4..fe05e43d85 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -1,25 +1,26 @@ package org.quiltmc.qsl.component.api; -import com.google.common.collect.ImmutableCollection; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.predicates.ClassInjectionPredicate; import org.quiltmc.qsl.component.impl.predicates.FilteredInheritedInjectionPredicate; import org.quiltmc.qsl.component.impl.predicates.InheritedInjectionPredicate; +import java.util.Map; import java.util.Optional; public final class Components { - public static void inject(Class clazz, ComponentIdentifier component) { + public static void inject(Class clazz, ComponentIdentifier component) { ComponentsImpl.inject(new ClassInjectionPredicate(clazz), component); } - public static void injectInheritage(Class clazz, ComponentIdentifier component) { + public static void injectInheritage(Class clazz, ComponentIdentifier component) { ComponentsImpl.inject(new InheritedInjectionPredicate(clazz), component); } - public static void injectInheritanceExcept(Class clazz, ComponentIdentifier component, Class... exceptions) { + public static void injectInheritanceExcept(Class clazz, ComponentIdentifier component, Class... exceptions) { ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), component); } @@ -27,13 +28,13 @@ public static Optional expose(ComponentIdentifier if (obj instanceof ComponentProvider provider) { return provider.expose(id) .map(id::cast) - .map(Optional::orElseThrow); + .map(Optional::orElseThrow); // If the casting fails something is wrong with the provided ComponentIdentifier. In that case we just throw. } return Optional.empty(); } - public static ImmutableCollection exposeAll(S obj) { - return obj instanceof ComponentProvider provider ? provider.exposeAll() : ImmutableList.of(); + public static Map exposeAll(S obj) { + return obj instanceof ComponentProvider provider ? provider.exposeAll() : ImmutableMap.of(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index 20785d20df..4ae0c34c92 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -1,10 +1,10 @@ package org.quiltmc.qsl.component.api.components; -import com.google.common.collect.ImmutableMap; import net.minecraft.nbt.*; import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.Component; +import java.util.HashMap; import java.util.Map; public interface NbtComponent extends Component { @@ -36,15 +36,15 @@ static void forward(NbtComponent nbtComponent, Identifier id, NbtCompound nbt } } - static ImmutableMap> getNbtSerializable(ImmutableMap components) { - var builder = ImmutableMap.>builder(); + static Map> getNbtSerializable(Map components) { + var map = new HashMap>(); for (var entry : components.entrySet()) { if (entry.getValue() instanceof NbtComponent nbtComponent) { - builder.put(entry.getKey(), nbtComponent); + map.put(entry.getKey(), nbtComponent); } } - return builder.build(); + return map; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/CustomChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/CustomChunk.java new file mode 100644 index 0000000000..c64760b67c --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/CustomChunk.java @@ -0,0 +1,10 @@ +package org.quiltmc.qsl.component.impl.util.duck; + +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.api.Component; + +import java.util.Map; + +public interface CustomChunk { + void setComponents(Map components); +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java index fd4132b3e5..4dc8ee40e9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java @@ -1,9 +1,10 @@ package org.quiltmc.qsl.component.impl.util.duck; -import com.google.common.collect.ImmutableMap; import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.components.NbtComponent; +import java.util.Map; + public interface NbtComponentProvider { - ImmutableMap> get(); + Map> get(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 20804ace54..a58159ac78 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -1,6 +1,5 @@ package org.quiltmc.qsl.component.mixin; -import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMap; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -22,6 +21,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Map; import java.util.Optional; @Implements({ @@ -31,22 +31,14 @@ @Mixin(BlockEntity.class) public class MixinBlockEntity { - private ImmutableMap qsl$components; - private ImmutableMap> qsl$nbtComponents; + private Map qsl$components; + private Map> qsl$nbtComponents; - @Inject( - method = "m_qgnqsprj", // The lambda used in second map operation. - at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V") - ) - private static void onReadNbt(NbtCompound nbt, String string, BlockEntity blockEntity, CallbackInfoReturnable cir) { - var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - ((NbtComponentProvider) blockEntity).get().forEach((id, nbtComponent) -> NbtComponent.forward(nbtComponent, id, rootQslNbt)); - } @Inject(method = "", at = @At("RETURN")) private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { - this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); - this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); + this.qsl$components = ImmutableMap.copyOf(ComponentProvider.createComponents((ComponentProvider) this)); + this.qsl$nbtComponents = ImmutableMap.copyOf(NbtComponent.getNbtSerializable(this.qsl$components)); } @Inject(method = "toNbt", at = @At("RETURN")) @@ -57,7 +49,16 @@ private void onWriteNbt(CallbackInfoReturnable cir) { cir.getReturnValue().put(StringConstants.COMPONENT_ROOT, rootQslNbt); } - public ImmutableMap> nbtExp$get() { + @Inject( + method = "m_qgnqsprj", // The lambda used in second map operation. + at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V") + ) + private static void onReadNbt(NbtCompound nbt, String string, BlockEntity blockEntity, CallbackInfoReturnable cir) { + var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); + ((NbtComponentProvider) blockEntity).get().forEach((id, nbtComponent) -> NbtComponent.forward(nbtComponent, id, rootQslNbt)); + } + + public Map> nbtExp$get() { return this.qsl$nbtComponents; } @@ -65,7 +66,7 @@ private void onWriteNbt(CallbackInfoReturnable cir) { return Optional.ofNullable(this.qsl$components.get(id.id())); } - public ImmutableCollection comp$exposeAll() { - return this.qsl$components.values(); + public Map comp$exposeAll() { + return this.qsl$components; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java new file mode 100644 index 0000000000..5c053ac427 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -0,0 +1,59 @@ +package org.quiltmc.qsl.component.mixin; + +import net.minecraft.util.Identifier; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.HeightLimitView; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraft.world.chunk.UpgradeData; +import net.minecraft.world.gen.chunk.BlendingData; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.util.duck.CustomChunk; +import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +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.Map; +import java.util.Optional; + +@Implements({ + @Interface(iface = ComponentProvider.class, prefix = "comp$"), + @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$"), + @Interface(iface = CustomChunk.class, prefix = "chunk$") +}) +@Mixin(Chunk.class) +public class MixinChunk { + + private Map qsl$components; + private Map> qsl$nbtComponents; + + @Inject(method = "", at = @At("RETURN")) + private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { + this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); + this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); + } + + public Map> nbtExp$get() { + return this.qsl$nbtComponents; + } + + public Optional comp$expose(ComponentIdentifier id) { + return Optional.ofNullable(this.qsl$components.get(id.id())); + } + + public Map comp$exposeAll() { + return this.qsl$components; + } + + public void chunk$setComponents(Map components) { + this.qsl$components = components; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java new file mode 100644 index 0000000000..0fb246b0d2 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java @@ -0,0 +1,40 @@ +package org.quiltmc.qsl.component.mixin; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.ChunkSerializer; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ProtoChunk; +import net.minecraft.world.chunk.ReadOnlyChunk; +import net.minecraft.world.poi.PointOfInterestStorage; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.impl.util.StringConstants; +import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ChunkSerializer.class) +public class MixinChunkSerializer { + @Inject(method = "deserialize", at = @At("RETURN"), cancellable = true) + private static void deserializeComponents(ServerWorld world, PointOfInterestStorage poiStorage, ChunkPos pos, NbtCompound nbt, CallbackInfoReturnable cir) { + Chunk ret = cir.getReturnValue(); + + if (ret instanceof ReadOnlyChunk readOnly) { + NbtCompound rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); + ((NbtComponentProvider) readOnly.getWrappedChunk()).get().forEach((id, component) -> NbtComponent.forward(component, id, rootQslNbt)); + cir.setReturnValue(readOnly); + } + } + + @Inject(method = "serialize", at = @At("RETURN"), cancellable = true) + private static void serializeComponents(ServerWorld world, Chunk chunk, CallbackInfoReturnable cir) { + var rootQslNbt = new NbtCompound(); + ((NbtComponentProvider) chunk).get().forEach((id, component) -> rootQslNbt.put(id.toString(), component.write())); + NbtCompound ret = cir.getReturnValue(); + ret.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + cir.setReturnValue(ret); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 848017a37b..2f8923c4f0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -1,6 +1,5 @@ package org.quiltmc.qsl.component.mixin; -import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMap; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -20,32 +19,28 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Map; import java.util.Optional; @Mixin(Entity.class) @Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) public abstract class MixinEntity { - private ImmutableMap qsl$components; - private ImmutableMap> qsl$nbtComponents; + private Map qsl$components; + private Map> qsl$nbtComponents; @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { - if (!world.isClient) { - this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); - this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); - } else { - this.qsl$components = ImmutableMap.of(); - this.qsl$nbtComponents = ImmutableMap.of(); - } + this.qsl$components = ImmutableMap.copyOf(ComponentProvider.createComponents((ComponentProvider) this)); + this.qsl$nbtComponents = ImmutableMap.copyOf(NbtComponent.getNbtSerializable(this.qsl$components)); } public Optional comp$expose(ComponentIdentifier id) { return Optional.ofNullable(this.qsl$components.get(id.id())); } - public ImmutableCollection comp$exposeAll() { - return this.qsl$components.values(); + public Map comp$exposeAll() { + return this.qsl$components; } @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java new file mode 100644 index 0000000000..c9f83e6300 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -0,0 +1,8 @@ +package org.quiltmc.qsl.component.mixin; + +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ItemStack.class) +public class MixinItemStack { +} diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index a35ef27760..c50a84001c 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -4,7 +4,10 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "MixinBlockEntity", - "MixinEntity" + "MixinChunk", + "MixinChunkSerializer", + "MixinEntity", + "MixinItemStack" ], "injectors": { "defaultRequire": 1 diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 47593c9654..0753870277 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -16,18 +16,22 @@ package org.quiltmc.qsl.component.test; -import net.minecraft.block.Blocks; -import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.ChestBlockEntity; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import net.minecraft.util.TypeFilter; import net.minecraft.util.collection.DefaultedList; -import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.Chunk; import net.minecraft.world.explosion.Explosion; +import org.jetbrains.annotations.Nullable; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.api.Components; @@ -50,66 +54,80 @@ public class ComponentTestMod implements ModInitializer { IntegerComponent.create(new Identifier(MODID, "hostile_explode_time")); public static final ComponentIdentifier CHEST_NUMBER = IntegerComponent.create(new Identifier(MODID, "chest_number")); + public static final ComponentIdentifier CHUNK_INVENTORY = InventoryComponent.ofSize(1, + new Identifier(MODID, "chunk_inventory") + ); @Override public void onInitialize(ModContainer mod) { // Application Code + Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); Components.injectInheritage(CowEntity.class, COW_INVENTORY); Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); Components.inject(ChestBlockEntity.class, CHEST_NUMBER); // Testing Code - ServerWorldTickEvents.START.register((ignored, world) -> world.iterateEntities().forEach(entity -> { - if (entity instanceof CowEntity) { - Components.expose(COW_INVENTORY, entity).ifPresent(inventoryComponent -> { - if (inventoryComponent.isEmpty()) { - entity.discard(); - world.createExplosion( - entity, - entity.getX(), entity.getY(), entity.getZ(), - 4.0f, Explosion.DestructionType.NONE - ); - } else { - inventoryComponent.removeStack(0, 1); - } - }); - } else if (entity instanceof CreeperEntity creeper) { - Components.expose(CREEPER_EXPLODE_TIME, creeper).ifPresent(explodeTime -> { - if (explodeTime.get() > 0) { - explodeTime.decrement(); - } else { - creeper.ignite(); - } - }); - } else if (entity instanceof HostileEntity hostile) { - Components.expose(HOSTILE_EXPLODE_TIME, hostile).ifPresent(explodeTime -> { - if (explodeTime.get() <= 200) { - explodeTime.increment(); - } else { - hostile.discard(); - hostile.getWorld().createExplosion(null, hostile.getX(), hostile.getY(), hostile.getZ(), 1.0f, Explosion.DestructionType.NONE); - } - }); - } - })); + ServerWorldTickEvents.START.register((ignored, world) -> { + world.getEntitiesByType(TypeFilter.instanceOf(CowEntity.class), cowEntity -> true).forEach(entity -> + Components.expose(COW_INVENTORY, entity).ifPresent(inventoryComponent -> { + if (inventoryComponent.isEmpty()) { + world.createExplosion( + entity, + entity.getX(), entity.getY(), entity.getZ(), + 4.0f, Explosion.DestructionType.NONE + ); + entity.discard(); + } else { + inventoryComponent.removeStack(0, 1); + } + })); + + world.getEntitiesByType(new TypeFilter() { + @Nullable + @Override + public CreeperEntity downcast(Entity obj) { + return obj.getType() == EntityType.CREEPER ? (CreeperEntity) obj : null; + } + + @Override + public Class getBaseClass() { + return CreeperEntity.class; + } + }, creeper -> true).forEach(creeper -> Components.expose(CREEPER_EXPLODE_TIME, creeper).ifPresent(explodeTime -> { + if (explodeTime.get() > 0) { + explodeTime.decrement(); + } else { + creeper.ignite(); + } + })); + world.getEntitiesByType(TypeFilter.instanceOf(HostileEntity.class), hostile -> true).forEach(hostile -> Components.expose(HOSTILE_EXPLODE_TIME, hostile).ifPresent(explodeTime -> { + if (explodeTime.get() <= 200) { + explodeTime.increment(); + } else { + hostile.getWorld().createExplosion(null, hostile.getX(), hostile.getY(), hostile.getZ(), 1.0f, Explosion.DestructionType.NONE); + hostile.discard(); + } + })); - ServerWorldTickEvents.START.register((server, world) -> - BlockPos.streamOutwards(new BlockPos(0, 0, 0), 5, 5, 5).forEach(pos -> { - BlockEntity blockEntity = world.getBlockEntity(pos); - if (blockEntity instanceof ChestBlockEntity chest) { - Components.expose(CHEST_NUMBER, chest) - .ifPresent(integerComponent -> { - if (integerComponent.get() == 0) { - integerComponent.set(world.random.nextInt(10)); - } else if (integerComponent.get() == 6) { - world.setBlockState(pos, Blocks.DIAMOND_BLOCK.getDefaultState()); - } - }); + ServerPlayerEntity player = world.getRandomAlivePlayer(); + if (player == null) { + return; + } + Chunk chunk = world.getChunk(player.getBlockPos()); + Components.expose(CHUNK_INVENTORY, chunk).ifPresent(inventory -> { + if (player.getInventory().getStack(9).isOf(Items.DIRT)) { + player.getInventory().getStack(9).decrement(1); + ItemStack stack = inventory.getStack(0); + if (stack.isEmpty()) { + inventory.setStack(0, Items.DIRT.getDefaultStack()); + } else { + stack.increment(1); } - }) - ); + } + player.sendMessage(Text.literal(inventory.getStack(0).toString()), false); + }); + }); } - } From 7c30217ef94e83ef897ff7f3174b98e3946638a2 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 20 Jun 2022 17:03:06 +0300 Subject: [PATCH 07/70] Fully implemented chunk component providers and some itemstack implementation. --- .../qsl/component/api/ComponentProvider.java | 2 +- .../api/components/InventoryComponent.java | 11 +-- .../api/components/NbtComponent.java | 43 ++++++--- .../api/identifier/ComponentIdentifier.java | 1 + .../qsl/component/impl/ComponentCache.java | 9 +- .../qsl/component/impl/ComponentsImpl.java | 7 +- .../defaults/DefaultIntegerComponent.java | 14 +++ .../defaults/DefaultInventoryComponent.java | 29 +++++- .../component/impl/util/duck/CustomChunk.java | 10 --- .../impl/util/duck/NbtComponentProvider.java | 2 +- .../qsl/component/mixin/MixinBlockEntity.java | 4 +- .../qsl/component/mixin/MixinChunk.java | 17 ++-- .../component/mixin/MixinChunkSerializer.java | 13 +-- .../qsl/component/mixin/MixinEntity.java | 2 +- .../qsl/component/mixin/MixinItemEntity.java | 25 ++++++ .../qsl/component/mixin/MixinItemStack.java | 89 ++++++++++++++++++- .../component/mixin/MixinPacketByteBuf.java | 33 +++++++ .../qsl/component/mixin/MixinWorldChunk.java | 33 +++++++ .../resources/quilt_component.mixins.json | 5 +- .../qsl/component/test/ComponentTestMod.java | 14 ++- .../src/testmod/resources/quilt.mod.json | 3 +- 21 files changed, 302 insertions(+), 64 deletions(-) delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/CustomChunk.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemEntity.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 42cbfd10a3..4979466117 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -16,7 +16,7 @@ public interface ComponentProvider { Map exposeAll(); static @NotNull Map createComponents(@NotNull ComponentProvider provider) { - System.out.println(provider.getClass()); // TODO: Remove this + // System.out.println(provider.getClass()); // TODO: Remove this var map = new HashMap(); ComponentsImpl.get(provider).forEach((identifier, supplier) -> map.put(identifier, supplier.get())); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index 303d32768f..780182b531 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -51,7 +51,7 @@ default ItemStack getStack(int slot) { @Override default ItemStack removeStack(int slot, int amount) { var result = Inventories.splitStack(this.getStacks(), slot, amount); - this.markDirty(); + this.saveNeeded(); return result; } @@ -59,7 +59,7 @@ default ItemStack removeStack(int slot, int amount) { @Override default ItemStack removeStack(int slot) { var result = Inventories.removeStack(this.getStacks(), slot); - this.markDirty(); + this.saveNeeded(); return result; } @@ -71,7 +71,7 @@ default void setStack(int slot, ItemStack stack) { stack.setCount(getMaxCountPerStack()); } - this.markDirty(); + this.saveNeeded(); } @Override @@ -94,12 +94,9 @@ default byte nbtType() { return NbtElement.COMPOUND_TYPE; } - @Override - void markDirty(); - @Override default void clear() { this.getStacks().clear(); - this.markDirty(); + this.saveNeeded(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index 4ae0c34c92..21e8ff04fb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -2,10 +2,12 @@ import net.minecraft.nbt.*; import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.Component; import java.util.HashMap; import java.util.Map; +import java.util.Optional; public interface NbtComponent extends Component { @@ -15,22 +17,35 @@ public interface NbtComponent extends Component { byte nbtType(); - @SuppressWarnings("unchecked") // Suppressing because we know those values are hardcoded either way. - static void forward(NbtComponent nbtComponent, Identifier id, NbtCompound nbt) { + void saveNeeded(); + + void setSaveOperation(Runnable runnable); + + static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier id, @NotNull NbtCompound nbt) { NbtElement nbtTarget = nbt.get(id.toString()); + read(nbtComponent, nbtTarget); + } + + static void writeTo(@NotNull NbtCompound root, @NotNull NbtComponent nbtComponent, @NotNull Identifier id) { + root.put(id.toString(), nbtComponent.write()); + } + + @SuppressWarnings("unchecked") + // Suppressing because we know those values are hardcoded either way. + static void read(@NotNull NbtComponent nbtComponent, NbtElement nbt) { switch (nbtComponent.nbtType()){ - case NbtElement.BYTE_TYPE -> ((NbtComponent) nbtComponent).read((NbtByte) nbtTarget); - case NbtElement.SHORT_TYPE -> ((NbtComponent) nbtComponent).read((NbtShort) nbtTarget); - case NbtElement.INT_TYPE -> ((NbtComponent) nbtComponent).read((NbtInt) nbtTarget); - case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); - case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); - case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); - case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); - case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); - case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); - case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); - case NbtElement.INT_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtIntArray) nbtTarget); - case NbtElement.LONG_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtLongArray) nbtTarget); + case NbtElement.BYTE_TYPE -> ((NbtComponent) nbtComponent).read((NbtByte) nbt); + case NbtElement.SHORT_TYPE -> ((NbtComponent) nbtComponent).read((NbtShort) nbt); + case NbtElement.INT_TYPE -> ((NbtComponent) nbtComponent).read((NbtInt) nbt); + case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbt); + case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbt); + case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbt); + case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbt); + case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbt); + case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbt); + case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbt); + case NbtElement.INT_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtIntArray) nbt); + case NbtElement.LONG_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtLongArray) nbt); default -> // TODO: Handle non-vanilla nbt types. throw new RuntimeException("The nbt data type with id %d is not handled at the moment!".formatted(nbtComponent.nbtType())); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java index 63d3e67882..7336d4993b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java @@ -7,6 +7,7 @@ public record ComponentIdentifier(Identifier id){ + @SuppressWarnings("unchecked") public Optional cast(Component component) { try { return Optional.of((T)component); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java index 7ac863a736..3aef9dec01 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java @@ -33,8 +33,13 @@ public Optional>> getCache(Class clazz, Collection components) { - if (this.injectionCache.put(clazz, Util.make(new HashMap<>(), map -> components.forEach(id -> map.put(id, ComponentsImpl.getEntry(id))))) != null) { + public void clear() { + this.injectionCache.clear(); + } + + public void record(Class clazz, Map> components) { + if (this.injectionCache.put(clazz, Util.make(new HashMap<>(), map -> map.putAll(components))) != null) { + // If there was a value there, it means we attempted an override, and so we throw. throw new IllegalStateException("Cannot register cache twice for class %s".formatted(clazz)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 0aa33f905f..f5e86a6f55 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -32,6 +32,7 @@ public static void inject(ComponentInjectionPredicate pred } else { INJECTION_REGISTRY.put(predicate, Util.make(new HashSet<>(), set -> set.add(id.id()))); } + ComponentCache.getInstance().clear(); // Always clear the cache after an injection is registered. } public static ComponentIdentifier register(Identifier id, Supplier component) { @@ -46,13 +47,9 @@ public static Map> get(ComponentProvid .map(Map.Entry::getValue) .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, REGISTRY.get(id))), HashMap::putAll); - ComponentCache.getInstance().record(provider.getClass(), returnMap.keySet()); + ComponentCache.getInstance().record(provider.getClass(), returnMap); return returnMap; }); } - - public static Supplier getEntry(Identifier id) { - return REGISTRY.get(id); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java index e41d1c1329..5f090f03af 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java @@ -2,6 +2,8 @@ import org.quiltmc.qsl.component.api.components.IntegerComponent; +import java.util.Objects; + public class DefaultIntegerComponent implements IntegerComponent { private int value; @@ -32,4 +34,16 @@ public void increment() { public void decrement() { this.value--; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DefaultIntegerComponent that)) return false; + return value == that.value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java index bbb91f9728..6f11a4c643 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java @@ -4,11 +4,12 @@ import net.minecraft.util.collection.DefaultedList; import org.quiltmc.qsl.component.api.components.InventoryComponent; +import java.util.Objects; import java.util.function.Supplier; public class DefaultInventoryComponent implements InventoryComponent { private final DefaultedList stacks; - private final Runnable dirtyOperation = () -> {}; + private Runnable dirtyOperation; public DefaultInventoryComponent(int size){ this.stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); @@ -23,8 +24,32 @@ public DefaultedList getStacks() { return this.stacks; } + @Override + public void saveNeeded() { + if (this.dirtyOperation != null) { + this.dirtyOperation.run(); + } + } + + @Override + public void setSaveOperation(Runnable runnable) { + this.dirtyOperation = runnable; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DefaultInventoryComponent that)) return false; + return stacks.equals(that.stacks); + } + + @Override + public int hashCode() { + return Objects.hash(stacks); + } + @Override public void markDirty() { - this.dirtyOperation.run(); + this.saveNeeded(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/CustomChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/CustomChunk.java deleted file mode 100644 index c64760b67c..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/CustomChunk.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.quiltmc.qsl.component.impl.util.duck; - -import net.minecraft.util.Identifier; -import org.quiltmc.qsl.component.api.Component; - -import java.util.Map; - -public interface CustomChunk { - void setComponents(Map components); -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java index 4dc8ee40e9..ea708a291b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java @@ -6,5 +6,5 @@ import java.util.Map; public interface NbtComponentProvider { - Map> get(); + Map> getNbtComponents(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index a58159ac78..55b1420a61 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -55,10 +55,10 @@ private void onWriteNbt(CallbackInfoReturnable cir) { ) private static void onReadNbt(NbtCompound nbt, String string, BlockEntity blockEntity, CallbackInfoReturnable cir) { var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - ((NbtComponentProvider) blockEntity).get().forEach((id, nbtComponent) -> NbtComponent.forward(nbtComponent, id, rootQslNbt)); + ((NbtComponentProvider) blockEntity).getNbtComponents().forEach((id, nbtComponent) -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)); } - public Map> nbtExp$get() { + public Map> nbtExp$getNbtComponents() { return this.qsl$nbtComponents; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 5c053ac427..6df1c6aa9b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -12,11 +12,11 @@ import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.components.NbtComponent; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import org.quiltmc.qsl.component.impl.util.duck.CustomChunk; import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -26,11 +26,13 @@ @Implements({ @Interface(iface = ComponentProvider.class, prefix = "comp$"), - @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$"), - @Interface(iface = CustomChunk.class, prefix = "chunk$") + @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$") }) @Mixin(Chunk.class) -public class MixinChunk { +public abstract class MixinChunk { + + @Shadow + public abstract void setNeedsSaving(boolean needsSaving); private Map qsl$components; private Map> qsl$nbtComponents; @@ -39,9 +41,10 @@ public class MixinChunk { private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); + this.qsl$nbtComponents.forEach((ignored, nbtComponent) -> nbtComponent.setSaveOperation(() -> this.setNeedsSaving(true))); } - public Map> nbtExp$get() { + public Map> nbtExp$getNbtComponents() { return this.qsl$nbtComponents; } @@ -52,8 +55,4 @@ private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView public Map comp$exposeAll() { return this.qsl$components; } - - public void chunk$setComponents(Map components) { - this.qsl$components = components; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java index 0fb246b0d2..9e263f395d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java @@ -20,19 +20,22 @@ public class MixinChunkSerializer { @Inject(method = "deserialize", at = @At("RETURN"), cancellable = true) private static void deserializeComponents(ServerWorld world, PointOfInterestStorage poiStorage, ChunkPos pos, NbtCompound nbt, CallbackInfoReturnable cir) { - Chunk ret = cir.getReturnValue(); + ProtoChunk ret = cir.getReturnValue(); + NbtCompound rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); if (ret instanceof ReadOnlyChunk readOnly) { - NbtCompound rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - ((NbtComponentProvider) readOnly.getWrappedChunk()).get().forEach((id, component) -> NbtComponent.forward(component, id, rootQslNbt)); - cir.setReturnValue(readOnly); + ((NbtComponentProvider) readOnly.getWrappedChunk()).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); + } else { + ((NbtComponentProvider) ret).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); } + + cir.setReturnValue(ret); } @Inject(method = "serialize", at = @At("RETURN"), cancellable = true) private static void serializeComponents(ServerWorld world, Chunk chunk, CallbackInfoReturnable cir) { var rootQslNbt = new NbtCompound(); - ((NbtComponentProvider) chunk).get().forEach((id, component) -> rootQslNbt.put(id.toString(), component.write())); + ((NbtComponentProvider) chunk).getNbtComponents().forEach((id, component) -> NbtComponent.writeTo(rootQslNbt, component, id)); NbtCompound ret = cir.getReturnValue(); ret.put(StringConstants.COMPONENT_ROOT, rootQslNbt); cir.setReturnValue(ret); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 2f8923c4f0..9432cc4a45 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -54,6 +54,6 @@ private void onSerialize(NbtCompound nbt, CallbackInfoReturnable ci @Inject(method = "readNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;readCustomDataFromNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - this.qsl$nbtComponents.forEach((id, nbtComponent) -> NbtComponent.forward(nbtComponent, id, rootQslNbt)); + this.qsl$nbtComponents.forEach((id, nbtComponent) -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemEntity.java new file mode 100644 index 0000000000..57199c48eb --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemEntity.java @@ -0,0 +1,25 @@ +package org.quiltmc.qsl.component.mixin; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.ItemEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ItemEntity.class) +public abstract class MixinItemEntity extends Entity { + public MixinItemEntity(EntityType entityType, World world) { + super(entityType, world); + } + + @Inject(method = "canMerge(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemStack;)Z", at = @At("HEAD"), cancellable = true) + private static void properCanMerge(ItemStack stack1, ItemStack stack2, CallbackInfoReturnable cir) { + // data get entity @e[type=item, limit=1] + cir.setReturnValue(ItemStack.canCombine(stack1, stack2) && stack1.getCount() + stack2.getCount() <= stack1.getMaxCount()); + } + +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index c9f83e6300..3cf47d6761 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -1,8 +1,95 @@ package org.quiltmc.qsl.component.mixin; +import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.util.StringConstants; +import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Map; +import java.util.Optional; + +@Implements({ + @Interface(iface = ComponentProvider.class, prefix = "comp$"), + @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$") +}) @Mixin(ItemStack.class) -public class MixinItemStack { +public abstract class MixinItemStack { // FIXME: Figure out why ItemEntities erase the Qsl Component data once they get picked up??!! + + private Map qsl$components; + private Map> qsl$nbtComponents; + + @Inject(method = "canCombine", at = @At("RETURN"), cancellable = true) + private static void checkForComponents(ItemStack stack, ItemStack otherStack, CallbackInfoReturnable cir) { + var otherMap = ((ComponentProvider) (Object) otherStack).exposeAll(); + cir.setReturnValue(cir.getReturnValue() && ((ComponentProvider) (Object) stack).exposeAll().entrySet().stream() + .allMatch(entry -> otherMap.get(entry.getKey()).equals(entry.getValue())) + ); + } + + @Inject(method = "isEqual", at = @At("RETURN"), cancellable = true) + private void checkForComponentsClient(ItemStack stack, CallbackInfoReturnable cir) { + var otherMap = ((ComponentProvider) (Object) stack).exposeAll(); + cir.setReturnValue(cir.getReturnValue() && ((ComponentProvider) this).exposeAll().entrySet().stream() + .allMatch(entry -> otherMap.get(entry.getKey()).equals(entry.getValue())) + ); + } + + @Inject(method = "(Lnet/minecraft/item/ItemConvertible;I)V", at = @At("RETURN")) + private void onItemInit(ItemConvertible itemConvertible, int i, CallbackInfo ci) { + this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); + this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); + } + + @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;)V", at = @At("RETURN")) + private void deserializeComponentsFromNbt(NbtCompound nbtCompound, CallbackInfo ci) { + this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); + this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); + var rootQslNbt = nbtCompound.getCompound(StringConstants.COMPONENT_ROOT); + this.qsl$nbtComponents.forEach((id, nbtComponent) -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)); + } + + @Inject(method = "writeNbt", at = @At("RETURN")) + private void onWrite(NbtCompound nbt, CallbackInfoReturnable cir) { + var rootQslNbt = new NbtCompound(); + this.qsl$nbtComponents.forEach((id, nbtComponent) -> rootQslNbt.put(id.toString(), nbtComponent.write())); + nbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + } + + @Inject(method = "copy", at = @At(value = "RETURN", ordinal = 1)) + private void recordComponentNbt(CallbackInfoReturnable cir) { + ItemStack stack = cir.getReturnValue(); + Map> stackMap = ((NbtComponentProvider) (Object) stack).getNbtComponents(); + for (var entry : this.qsl$nbtComponents.entrySet()) { + NbtElement nbt = entry.getValue().write(); + Identifier id = entry.getKey(); + + NbtComponent.read(stackMap.get(id), nbt); + } + } + + public Optional comp$expose(ComponentIdentifier id) { + return Optional.ofNullable(this.qsl$components.get(id.id())); + } + + public Map comp$exposeAll() { + return this.qsl$components; + } + + public Map> nbtExp$getNbtComponents() { + return this.qsl$nbtComponents; + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java new file mode 100644 index 0000000000..236ff19034 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java @@ -0,0 +1,33 @@ +package org.quiltmc.qsl.component.mixin; + +import io.netty.buffer.ByteBuf; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.impl.util.StringConstants; +import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PacketByteBuf.class) +public abstract class MixinPacketByteBuf extends ByteBuf { + @Inject(method = "readItemStack", at = @At(value = "RETURN", ordinal = 1), cancellable = true) + private void readComponentData(CallbackInfoReturnable cir) { + ItemStack ret = cir.getReturnValue(); + var this$ = (PacketByteBuf) (Object) this; + NbtCompound rootQslNbt = this$.readNbt(); + if (rootQslNbt != null) { + ((NbtComponentProvider) (Object)ret).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); + cir.setReturnValue(ret); + } + } + + @Inject(method = "writeItemStack", at = @At("RETURN")) + private void writeComponentData(ItemStack stack, CallbackInfoReturnable cir) { + var this$ = (PacketByteBuf) (Object) this; + this$.writeNbt(stack.writeNbt(new NbtCompound()).getCompound(StringConstants.COMPONENT_ROOT)); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java new file mode 100644 index 0000000000..82964bd9cd --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -0,0 +1,33 @@ +package org.quiltmc.qsl.component.mixin; + +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.HeightLimitView; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.*; +import net.minecraft.world.gen.chunk.BlendingData; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.spongepowered.asm.mixin.Mixin; +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.Map; + +@Mixin(WorldChunk.class) +public abstract class MixinWorldChunk extends Chunk { + public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, @Nullable ChunkSection[] chunkSections, @Nullable BlendingData blendingData) { + super(chunkPos, upgradeData, heightLimitView, registry, l, chunkSections, blendingData); + } + + @Inject(method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/ProtoChunk;Lnet/minecraft/world/chunk/WorldChunk$PostLoadProcessor;)V", at = @At("TAIL")) + private void copyComponentData(ServerWorld serverWorld, ProtoChunk protoChunk, WorldChunk.PostLoadProcessor postLoadProcessor, CallbackInfo ci) { + var this$ = (ComponentProvider) this; + Map componentMap = this$.exposeAll(); + componentMap.putAll(((ComponentProvider) protoChunk).exposeAll()); + } +} diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index c50a84001c..3da89047cc 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -7,7 +7,10 @@ "MixinChunk", "MixinChunkSerializer", "MixinEntity", - "MixinItemStack" + "MixinItemEntity", + "MixinItemStack", + "MixinPacketByteBuf", + "MixinWorldChunk" ], "injectors": { "defaultRequire": 1 diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 0753870277..2421ecdc10 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -22,6 +22,7 @@ import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; +import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.server.network.ServerPlayerEntity; @@ -57,15 +58,18 @@ public class ComponentTestMod implements ModInitializer { public static final ComponentIdentifier CHUNK_INVENTORY = InventoryComponent.ofSize(1, new Identifier(MODID, "chunk_inventory") ); + public static final ComponentIdentifier ITEMSTACK_NOMBER = + IntegerComponent.create(new Identifier(MODID, "itemstack_nomber")); @Override public void onInitialize(ModContainer mod) { // Application Code - Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); Components.injectInheritage(CowEntity.class, COW_INVENTORY); Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); Components.inject(ChestBlockEntity.class, CHEST_NUMBER); + Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); + Components.inject(ItemStack.class, ITEMSTACK_NOMBER); // Testing Code ServerWorldTickEvents.START.register((ignored, world) -> { @@ -126,8 +130,14 @@ public Class getBaseClass() { stack.increment(1); } } - player.sendMessage(Text.literal(inventory.getStack(0).toString()), false); + player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); }); + + Inventory inventory = player.getInventory(); + ItemStack stack = inventory.getStack(9); + if (!stack.isEmpty()) { + Components.expose(ITEMSTACK_NOMBER, stack).ifPresent(IntegerComponent::increment); + } }); } } diff --git a/library/data/component/src/testmod/resources/quilt.mod.json b/library/data/component/src/testmod/resources/quilt.mod.json index 521a57b6d2..57d5b84106 100644 --- a/library/data/component/src/testmod/resources/quilt.mod.json +++ b/library/data/component/src/testmod/resources/quilt.mod.json @@ -17,7 +17,8 @@ }, "depends": [ "quilt_loader", - "quilt_component" + "quilt_component", + "quilt_lifecycle_events" ] } } From 4ad221361bd50f13ef1db86f07c5cfbaeb7f647b Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 21 Jun 2022 12:05:49 +0300 Subject: [PATCH 08/70] Added marking dirty to other providers that require it --- .../defaults/DefaultIntegerComponent.java | 13 ++++ .../quiltmc/qsl/component/impl/util/Lazy.java | 59 +++++++++++++++++++ .../qsl/component/mixin/MixinBlockEntity.java | 24 ++++---- .../qsl/component/mixin/MixinWorldChunk.java | 4 ++ 4 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java index 5f090f03af..d1b04b0f6b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java @@ -6,6 +6,7 @@ public class DefaultIntegerComponent implements IntegerComponent { private int value; + private Runnable saveOperation; public DefaultIntegerComponent(int defaultValue) { this.value = defaultValue; @@ -46,4 +47,16 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(value); } + + @Override + public void saveNeeded() { + if (this.saveOperation != null) { + this.saveOperation.run(); + } + } + + @Override + public void setSaveOperation(Runnable runnable) { + this.saveOperation = runnable; + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java new file mode 100644 index 0000000000..61b733e0b7 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java @@ -0,0 +1,59 @@ +package org.quiltmc.qsl.component.impl.util; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class Lazy { + + @NotNull + private final Supplier sup; + @Nullable + private T value; + + @NotNull + public static Lazy of(@NotNull Supplier sup) { + return new Lazy<>(sup); + } + + private Lazy(@NotNull Supplier sup) { + this.sup = sup; + this.value = null; + } + + @NotNull + public T get() { + if (value == null) { + this.value = sup.get(); + } + + return value; + } + + @NotNull + public Supplier getSupplier() { + return sup; + } + + public boolean isEmpty() { + return this.value == null; + } + + @NotNull + public Lazy map(@NotNull Function func) { + return Lazy.of(() -> func.apply(this.get())); + } + + public void computeIfPresent(@NotNull Consumer action) { + if (!this.isEmpty()) { + action.accept(this.get()); + } + } + + public void compute(@NotNull Consumer action) { + action.accept(this.get()); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 55b1420a61..a01edb5c8a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -16,6 +16,7 @@ import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -29,16 +30,28 @@ @Interface(iface = ComponentProvider.class, prefix = "comp$") }) @Mixin(BlockEntity.class) -public class MixinBlockEntity { +public abstract class MixinBlockEntity { private Map qsl$components; private Map> qsl$nbtComponents; + @Inject( + method = "m_qgnqsprj", // The lambda used in second map operation. + at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V") + ) + private static void onReadNbt(NbtCompound nbt, String string, BlockEntity blockEntity, CallbackInfoReturnable cir) { + var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); + ((NbtComponentProvider) blockEntity).getNbtComponents().forEach((id, nbtComponent) -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)); + } + + @Shadow + public abstract void markDirty(); @Inject(method = "", at = @At("RETURN")) private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { this.qsl$components = ImmutableMap.copyOf(ComponentProvider.createComponents((ComponentProvider) this)); this.qsl$nbtComponents = ImmutableMap.copyOf(NbtComponent.getNbtSerializable(this.qsl$components)); + this.qsl$nbtComponents.forEach((id, component) -> component.setSaveOperation(this::markDirty)); } @Inject(method = "toNbt", at = @At("RETURN")) @@ -49,15 +62,6 @@ private void onWriteNbt(CallbackInfoReturnable cir) { cir.getReturnValue().put(StringConstants.COMPONENT_ROOT, rootQslNbt); } - @Inject( - method = "m_qgnqsprj", // The lambda used in second map operation. - at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V") - ) - private static void onReadNbt(NbtCompound nbt, String string, BlockEntity blockEntity, CallbackInfoReturnable cir) { - var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - ((NbtComponentProvider) blockEntity).getNbtComponents().forEach((id, nbtComponent) -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)); - } - public Map> nbtExp$getNbtComponents() { return this.qsl$nbtComponents; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java index 82964bd9cd..41a853ef0b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -29,5 +30,8 @@ private void copyComponentData(ServerWorld serverWorld, ProtoChunk protoChunk, W var this$ = (ComponentProvider) this; Map componentMap = this$.exposeAll(); componentMap.putAll(((ComponentProvider) protoChunk).exposeAll()); + ((NbtComponentProvider) this$).getNbtComponents().forEach((id, component) -> + component.setSaveOperation(() -> this.setNeedsSaving(true)) + ); } } From dd6837df1bdda8bc5bdc15aea37a7ed073835c87 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 21 Jun 2022 12:47:17 +0300 Subject: [PATCH 09/70] Fixed a minor issue with chunks not saving qsl data when generated. --- .../api/components/InventoryComponent.java | 5 +++-- .../qsl/component/api/components/NbtComponent.java | 1 - .../qsl/component/mixin/MixinChunkSerializer.java | 8 ++------ .../quiltmc/qsl/component/mixin/MixinItemStack.java | 1 + .../qsl/component/mixin/MixinWorldChunk.java | 3 ++- .../{quilt_recipe => quilt_component}/icon.png | Bin .../qsl/component/test/ComponentTestMod.java | 7 ++++--- 7 files changed, 12 insertions(+), 13 deletions(-) rename library/data/component/src/main/resources/assets/{quilt_recipe => quilt_component}/icon.png (100%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index 780182b531..c76a039517 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -67,8 +67,9 @@ default ItemStack removeStack(int slot) { @Override default void setStack(int slot, ItemStack stack) { this.getStacks().set(slot, stack); - if (stack.getCount() > getMaxCountPerStack()) { - stack.setCount(getMaxCountPerStack()); + ItemStack slotStack = this.getStack(slot); + if (slotStack.getCount() > this.getMaxCountPerStack()) { + slotStack.setCount(this.getMaxCountPerStack()); } this.saveNeeded(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index 21e8ff04fb..83ed3b246d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -7,7 +7,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.Optional; public interface NbtComponent extends Component { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java index 9e263f395d..79b15bfdfa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java @@ -22,13 +22,9 @@ public class MixinChunkSerializer { private static void deserializeComponents(ServerWorld world, PointOfInterestStorage poiStorage, ChunkPos pos, NbtCompound nbt, CallbackInfoReturnable cir) { ProtoChunk ret = cir.getReturnValue(); NbtCompound rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); + var target = ret instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : ret; - if (ret instanceof ReadOnlyChunk readOnly) { - ((NbtComponentProvider) readOnly.getWrappedChunk()).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); - } else { - ((NbtComponentProvider) ret).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); - } - + ((NbtComponentProvider) target).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); cir.setReturnValue(ret); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index 3cf47d6761..b57628cc27 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Optional; +@SuppressWarnings("ConstantConditions") @Implements({ @Interface(iface = ComponentProvider.class, prefix = "comp$"), @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$") diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java index 41a853ef0b..d0b0b2464d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -27,9 +27,10 @@ public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitVi @Inject(method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/ProtoChunk;Lnet/minecraft/world/chunk/WorldChunk$PostLoadProcessor;)V", at = @At("TAIL")) private void copyComponentData(ServerWorld serverWorld, ProtoChunk protoChunk, WorldChunk.PostLoadProcessor postLoadProcessor, CallbackInfo ci) { + var target = protoChunk instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : protoChunk; var this$ = (ComponentProvider) this; Map componentMap = this$.exposeAll(); - componentMap.putAll(((ComponentProvider) protoChunk).exposeAll()); + componentMap.putAll(((ComponentProvider) target).exposeAll()); ((NbtComponentProvider) this$).getNbtComponents().forEach((id, component) -> component.setSaveOperation(() -> this.setNeedsSaving(true)) ); diff --git a/library/data/component/src/main/resources/assets/quilt_recipe/icon.png b/library/data/component/src/main/resources/assets/quilt_component/icon.png similarity index 100% rename from library/data/component/src/main/resources/assets/quilt_recipe/icon.png rename to library/data/component/src/main/resources/assets/quilt_component/icon.png diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 2421ecdc10..6597b5f5fb 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -69,7 +69,7 @@ public void onInitialize(ModContainer mod) { Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); - Components.inject(ItemStack.class, ITEMSTACK_NOMBER); +// Components.inject(ItemStack.class, ITEMSTACK_NOMBER); // Testing Code ServerWorldTickEvents.START.register((ignored, world) -> { @@ -121,8 +121,9 @@ public Class getBaseClass() { } Chunk chunk = world.getChunk(player.getBlockPos()); Components.expose(CHUNK_INVENTORY, chunk).ifPresent(inventory -> { - if (player.getInventory().getStack(9).isOf(Items.DIRT)) { - player.getInventory().getStack(9).decrement(1); + ItemStack playerStack = player.getInventory().getStack(9); + if (playerStack.isOf(Items.DIRT)) { + playerStack.decrement(1); ItemStack stack = inventory.getStack(0); if (stack.isEmpty()) { inventory.setStack(0, Items.DIRT.getDefaultStack()); From dc72de3f85d890985827841470328823c99bcff4 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 21 Jun 2022 15:56:42 +0300 Subject: [PATCH 10/70] Made LevelProperties a ComponentProvider allowing you to attach components to saves. --- .../api/components/FloatComponent.java | 39 +++++++++ .../qsl/component/impl/ComponentsImpl.java | 14 +-- .../impl/defaults/DefaultFloatComponent.java | 38 +++++++++ .../qsl/component/mixin/MixinEntity.java | 5 +- .../component/mixin/MixinLevelProperties.java | 85 +++++++++++++++++++ .../resources/quilt_component.mixins.json | 1 + .../qsl/component/test/ComponentTestMod.java | 15 +++- 7 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java new file mode 100644 index 0000000000..efdc60701e --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java @@ -0,0 +1,39 @@ +package org.quiltmc.qsl.component.api.components; + +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtFloat; +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.defaults.DefaultFloatComponent; + + +public interface FloatComponent extends Component, NbtComponent { + static ComponentIdentifier create(Identifier id) { + return ComponentsImpl.register(id, DefaultFloatComponent::new); + } + + static ComponentIdentifier create(float initialValue, Identifier id) { + return ComponentsImpl.register(id, () -> new DefaultFloatComponent(initialValue)); + } + + float get(); + + void set(float value); + + @Override + default NbtFloat write() { + return NbtFloat.of(this.get()); + } + + @Override + default void read(NbtFloat nbt) { + this.set(nbt.floatValue()); + } + + @Override + default byte nbtType() { + return NbtElement.FLOAT_TYPE; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index f5e86a6f55..772b4881cf 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -7,12 +7,15 @@ import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.function.Supplier; public class ComponentsImpl { private static final Map> INJECTION_REGISTRY = new HashMap<>(); - private static final Map> REGISTRY = new HashMap<>(); + private static final Map> REGISTRY = new HashMap<>(); // Look into using a Minecraft Registry for this. public static void inject(ComponentInjectionPredicate predicate, ComponentIdentifier id) { Supplier supplier = REGISTRY.get(id.id()); @@ -32,6 +35,7 @@ public static void inject(ComponentInjectionPredicate pred } else { INJECTION_REGISTRY.put(predicate, Util.make(new HashSet<>(), set -> set.add(id.id()))); } + ComponentCache.getInstance().clear(); // Always clear the cache after an injection is registered. } @@ -43,9 +47,9 @@ public static ComponentIdentifier register(Identifier i public static Map> get(ComponentProvider provider) { return ComponentCache.getInstance().getCache(provider.getClass()).orElseGet(() -> { Map> returnMap = INJECTION_REGISTRY.entrySet().stream() - .filter(it -> it.getKey().canInject(provider)) - .map(Map.Entry::getValue) - .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, REGISTRY.get(id))), HashMap::putAll); + .filter(it -> it.getKey().canInject(provider)) + .map(Map.Entry::getValue) + .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, REGISTRY.get(id))), HashMap::putAll); ComponentCache.getInstance().record(provider.getClass(), returnMap); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java new file mode 100644 index 0000000000..99039a37cc --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java @@ -0,0 +1,38 @@ +package org.quiltmc.qsl.component.impl.defaults; + +import org.quiltmc.qsl.component.api.components.FloatComponent; + +public class DefaultFloatComponent implements FloatComponent { + private float value; + private Runnable saveOperation; + + public DefaultFloatComponent() { + this(0); + } + + public DefaultFloatComponent(float initialValue) { + this.value = initialValue; + } + + @Override + public float get() { + return this.value; + } + + @Override + public void set(float value) { + this.value = value; + } + + @Override + public void saveNeeded() { + if (this.saveOperation != null) { + this.saveOperation.run(); + } + } + + @Override + public void setSaveOperation(Runnable runnable) { + this.saveOperation = runnable; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 9432cc4a45..106e307761 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -1,6 +1,5 @@ package org.quiltmc.qsl.component.mixin; -import com.google.common.collect.ImmutableMap; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.nbt.NbtCompound; @@ -31,8 +30,8 @@ public abstract class MixinEntity { @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { - this.qsl$components = ImmutableMap.copyOf(ComponentProvider.createComponents((ComponentProvider) this)); - this.qsl$nbtComponents = ImmutableMap.copyOf(NbtComponent.getNbtSerializable(this.qsl$components)); + this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); + this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); } public Optional comp$expose(ComponentIdentifier id) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java new file mode 100644 index 0000000000..236f213041 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -0,0 +1,85 @@ +package org.quiltmc.qsl.component.mixin; + +import com.mojang.datafixers.DataFixer; +import com.mojang.serialization.Dynamic; +import com.mojang.serialization.Lifecycle; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.DynamicRegistryManager; +import net.minecraft.world.SaveProperties; +import net.minecraft.world.border.WorldBorder; +import net.minecraft.world.gen.GeneratorOptions; +import net.minecraft.world.level.LevelInfo; +import net.minecraft.world.level.LevelProperties; +import net.minecraft.world.level.ServerWorldProperties; +import net.minecraft.world.level.storage.SaveVersionInfo; +import net.minecraft.world.timer.Timer; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.util.StringConstants; +import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +@Implements({ + @Interface(iface = ComponentProvider.class, prefix = "comp$"), + @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$") +}) +@Mixin(LevelProperties.class) +public abstract class MixinLevelProperties implements ServerWorldProperties, SaveProperties { + private Map qsl$components; + private Map> qsl$nbtComponents; + + @Inject(method = "readProperties", at = @At("RETURN")) + private static void readComponentData(Dynamic dynamic, DataFixer dataFixer, int dataVersion, @Nullable NbtCompound playerData, LevelInfo levelInfo, SaveVersionInfo saveVersionInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfoReturnable cir) { + LevelProperties retProperties = cir.getReturnValue(); + + dynamic.get(StringConstants.COMPONENT_ROOT) + .result() + .map(Dynamic::getValue) + .map(it -> (NbtCompound) it) // Casting here since we know it *cannot* be anything *but* NbtCompound. + .ifPresent(rootQslNbt -> ((NbtComponentProvider) retProperties).getNbtComponents().forEach( + (identifier, nbtComponent) -> NbtComponent.readFrom(nbtComponent, identifier, rootQslNbt) + )); + } + + @Inject(method = "updateProperties", at = @At("TAIL")) + private void writeComponentData(DynamicRegistryManager registryManager, NbtCompound levelNbt, NbtCompound playerNbt, CallbackInfo ci) { + var rootQslNbt = new NbtCompound(); + this.qsl$nbtComponents.forEach((identifier, nbtComponent) -> rootQslNbt.put(identifier.toString(), nbtComponent.write())); + levelNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + } + + @Inject(method = "(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/NbtCompound;ZIIIFJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lcom/mojang/serialization/Lifecycle;)V", at = @At("TAIL")) + private void onInit(DataFixer dataFixer, int i, NbtCompound nbtCompound, boolean bl, int j, int k, int l, float f, long m, long n, int o, int p, int q, boolean bl2, int r, boolean bl3, boolean bl4, boolean bl5, WorldBorder.Properties properties, int s, int t, UUID uUID, Set set, Timer timer, NbtCompound nbtCompound2, NbtCompound nbtCompound3, LevelInfo levelInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfo ci) { + this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); + this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); + } + + public Optional comp$expose(ComponentIdentifier id) { + return Optional.ofNullable(this.qsl$components.get(id.id())); + } + + public Map comp$exposeAll() { + return this.qsl$components; + } + + public Map> nbtExp$getNbtComponents() { + return this.qsl$nbtComponents; + } +} diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index 3da89047cc..cf1086677b 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -9,6 +9,7 @@ "MixinEntity", "MixinItemEntity", "MixinItemStack", + "MixinLevelProperties", "MixinPacketByteBuf", "MixinWorldChunk" ], diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 6597b5f5fb..e4f2194472 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -30,12 +30,15 @@ import net.minecraft.util.Identifier; import net.minecraft.util.TypeFilter; import net.minecraft.util.collection.DefaultedList; +import net.minecraft.world.SaveProperties; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.explosion.Explosion; +import net.minecraft.world.level.LevelProperties; import org.jetbrains.annotations.Nullable; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.components.FloatComponent; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.InventoryComponent; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; @@ -60,6 +63,8 @@ public class ComponentTestMod implements ModInitializer { ); public static final ComponentIdentifier ITEMSTACK_NOMBER = IntegerComponent.create(new Identifier(MODID, "itemstack_nomber")); + public static final ComponentIdentifier SAVE_FLOAT = + FloatComponent.create(new Identifier(MODID, "save_float")); @Override public void onInitialize(ModContainer mod) { @@ -69,10 +74,11 @@ public void onInitialize(ModContainer mod) { Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); + Components.inject(LevelProperties.class, SAVE_FLOAT); // Components.inject(ItemStack.class, ITEMSTACK_NOMBER); // Testing Code - ServerWorldTickEvents.START.register((ignored, world) -> { + ServerWorldTickEvents.START.register((server, world) -> { world.getEntitiesByType(TypeFilter.instanceOf(CowEntity.class), cowEntity -> true).forEach(entity -> Components.expose(COW_INVENTORY, entity).ifPresent(inventoryComponent -> { if (inventoryComponent.isEmpty()) { @@ -139,6 +145,13 @@ public Class getBaseClass() { if (!stack.isEmpty()) { Components.expose(ITEMSTACK_NOMBER, stack).ifPresent(IntegerComponent::increment); } + + SaveProperties props = server.getSaveProperties(); + Components.expose(SAVE_FLOAT, props) + .ifPresent(floatComponent -> { + floatComponent.set(floatComponent.get() + 0.5f); + player.sendMessage(Text.literal("%.3f".formatted(floatComponent.get())), false); + }); }); } } From f70624e33ed71d4e09dde802b5c0772b3555424f Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 21 Jun 2022 16:01:06 +0300 Subject: [PATCH 11/70] Reformatted code. --- .../qsl/component/api/ComponentProvider.java | 8 +++---- .../api/components/NbtComponent.java | 22 +++++++++---------- .../api/identifier/ComponentIdentifier.java | 4 ++-- .../qsl/component/impl/ComponentCache.java | 6 +++-- .../defaults/DefaultInventoryComponent.java | 4 ++-- .../predicates/ClassInjectionPredicate.java | 2 +- .../quiltmc/qsl/component/impl/util/Lazy.java | 10 ++++----- .../qsl/component/mixin/MixinChunk.java | 6 ++--- .../component/mixin/MixinPacketByteBuf.java | 2 +- 9 files changed, 33 insertions(+), 31 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 4979466117..e663c2105c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -11,10 +11,6 @@ public interface ComponentProvider { - Optional expose(ComponentIdentifier id); - - Map exposeAll(); - static @NotNull Map createComponents(@NotNull ComponentProvider provider) { // System.out.println(provider.getClass()); // TODO: Remove this var map = new HashMap(); @@ -23,4 +19,8 @@ public interface ComponentProvider { return map; } + Optional expose(ComponentIdentifier id); + + Map exposeAll(); + } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index 83ed3b246d..ba12f34d5b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -10,16 +10,6 @@ public interface NbtComponent extends Component { - T write(); - - void read(T nbt); - - byte nbtType(); - - void saveNeeded(); - - void setSaveOperation(Runnable runnable); - static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier id, @NotNull NbtCompound nbt) { NbtElement nbtTarget = nbt.get(id.toString()); read(nbtComponent, nbtTarget); @@ -32,7 +22,7 @@ static void writeTo(@NotNull NbtCompound root, @NotNull NbtComponent nbtCompo @SuppressWarnings("unchecked") // Suppressing because we know those values are hardcoded either way. static void read(@NotNull NbtComponent nbtComponent, NbtElement nbt) { - switch (nbtComponent.nbtType()){ + switch (nbtComponent.nbtType()) { case NbtElement.BYTE_TYPE -> ((NbtComponent) nbtComponent).read((NbtByte) nbt); case NbtElement.SHORT_TYPE -> ((NbtComponent) nbtComponent).read((NbtShort) nbt); case NbtElement.INT_TYPE -> ((NbtComponent) nbtComponent).read((NbtInt) nbt); @@ -61,4 +51,14 @@ static Map> getNbtSerializable(Map(Identifier id){ +public record ComponentIdentifier(Identifier id) { @SuppressWarnings("unchecked") public Optional cast(Component component) { try { - return Optional.of((T)component); + return Optional.of((T) component); } catch (ClassCastException ignored) { return Optional.empty(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java index 3aef9dec01..8b5069e703 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java @@ -4,7 +4,9 @@ import net.minecraft.util.Util; import org.quiltmc.qsl.component.api.Component; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; import java.util.function.Supplier; public class ComponentCache { @@ -17,7 +19,7 @@ private ComponentCache() { } - public static ComponentCache getInstance(){ + public static ComponentCache getInstance() { if (INSTANCE == null) { INSTANCE = new ComponentCache(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java index 6f11a4c643..04979c239c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java @@ -11,11 +11,11 @@ public class DefaultInventoryComponent implements InventoryComponent { private final DefaultedList stacks; private Runnable dirtyOperation; - public DefaultInventoryComponent(int size){ + public DefaultInventoryComponent(int size) { this.stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); } - public DefaultInventoryComponent(Supplier> stacks){ + public DefaultInventoryComponent(Supplier> stacks) { this.stacks = stacks.get(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java index a1cec337f2..16386d8cba 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java @@ -9,7 +9,7 @@ public class ClassInjectionPredicate implements ComponentInjectionPredicate { protected final Class clazz; - public ClassInjectionPredicate(Class clazz){ + public ClassInjectionPredicate(Class clazz) { if (implementsComponentProvider(clazz)) { this.clazz = clazz; } else { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java index 61b733e0b7..9e883522ff 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java @@ -14,16 +14,16 @@ public class Lazy { @Nullable private T value; - @NotNull - public static Lazy of(@NotNull Supplier sup) { - return new Lazy<>(sup); - } - private Lazy(@NotNull Supplier sup) { this.sup = sup; this.value = null; } + @NotNull + public static Lazy of(@NotNull Supplier sup) { + return new Lazy<>(sup); + } + @NotNull public T get() { if (value == null) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 6df1c6aa9b..2bbaf2b473 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -31,12 +31,12 @@ @Mixin(Chunk.class) public abstract class MixinChunk { - @Shadow - public abstract void setNeedsSaving(boolean needsSaving); - private Map qsl$components; private Map> qsl$nbtComponents; + @Shadow + public abstract void setNeedsSaving(boolean needsSaving); + @Inject(method = "", at = @At("RETURN")) private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java index 236ff19034..004a136ef1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java @@ -20,7 +20,7 @@ private void readComponentData(CallbackInfoReturnable cir) { var this$ = (PacketByteBuf) (Object) this; NbtCompound rootQslNbt = this$.readNbt(); if (rootQslNbt != null) { - ((NbtComponentProvider) (Object)ret).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); + ((NbtComponentProvider) (Object) ret).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); cir.setReturnValue(ret); } } From 25bc9ce7792ec940fddaf8d1f05416b9f34d1c9f Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 21 Jun 2022 23:16:05 +0300 Subject: [PATCH 12/70] Added some todos. --- .../org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java | 2 +- .../main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java index 79b15bfdfa..3983d2ec60 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java @@ -18,7 +18,7 @@ @Mixin(ChunkSerializer.class) public class MixinChunkSerializer { - @Inject(method = "deserialize", at = @At("RETURN"), cancellable = true) + @Inject(method = "deserialize", at = @At("RETURN"), cancellable = true) // FIXME: More chunk issues private static void deserializeComponents(ServerWorld world, PointOfInterestStorage poiStorage, ChunkPos pos, NbtCompound nbt, CallbackInfoReturnable cir) { ProtoChunk ret = cir.getReturnValue(); NbtCompound rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 106e307761..c5f1a06577 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -23,7 +23,7 @@ @Mixin(Entity.class) @Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) -public abstract class MixinEntity { +public abstract class MixinEntity { //TODO: Consider creating a container-like class to handle this instead of doing it manually. private Map qsl$components; private Map> qsl$nbtComponents; From 60dfd4abc4cfc2a62e2d0f0c8d8e99fbf9943c4e Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 21 Jun 2022 23:51:27 +0300 Subject: [PATCH 13/70] Added container(WIP) --- .../qsl/component/api/ComponentContainer.java | 84 +++++++++++++++++++ .../qsl/component/api/ComponentProvider.java | 9 +- .../quiltmc/qsl/component/api/Components.java | 2 +- 3 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java new file mode 100644 index 0000000000..e418fcd72c --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -0,0 +1,84 @@ +package org.quiltmc.qsl.component.api; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.impl.util.Lazy; +import org.quiltmc.qsl.component.impl.util.StringConstants; +import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; + +import java.util.*; + +public class ComponentContainer implements ComponentProvider, NbtComponentProvider { + private final Map> components; + private final List nbtComponents; + + public static Optional create(T obj) { + if (!(obj instanceof ComponentProvider provider)) { + return Optional.empty(); + } + + return Optional.of(new ComponentContainer(provider)); + } + + private ComponentContainer(ComponentProvider provider) { + this.components = ComponentProvider.createComponents(provider); + this.nbtComponents = new ArrayList<>(components.size()); + } + + @Override + public Optional expose(Identifier id) { // TODO: Check for nbt component + return Optional.ofNullable(this.components.get(id)) + .map(componentLazy -> { + if (componentLazy.isEmpty()) { + this.nbtComponents.add(id); + return componentLazy.get(); + } + + return componentLazy.get(); + }); + } + + @Override + public Map exposeAll() { + return this.components.entrySet().stream() + .filter(entry -> !entry.getValue().isEmpty()) + .collect(HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue().get()), HashMap::putAll); + } + + public Optional writeNbt() { + if (this.nbtComponents.isEmpty()) { + return Optional.empty(); + } + + var rootQslNbt = new NbtCompound(); + this.nbtComponents.forEach(id -> this.components.get(id).computeIfPresent(component -> + NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, id) + )); + + return rootQslNbt.isEmpty() ? Optional.empty() : Optional.of(rootQslNbt); + } + + public void readNbt(NbtCompound nbt) { + var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); + + rootQslNbt.getKeys().stream() + .map(Identifier::tryParse) + .filter(Objects::nonNull) + .forEach(id -> this.expose(id).ifPresent(component -> { + if (component instanceof NbtComponent nbtComponent) { + NbtComponent.readFrom(nbtComponent, id, rootQslNbt); + } + })); + } + + @Override + public Map> getNbtComponents() { + return this.nbtComponents.stream() + .map(id -> new Pair<>(id, this.components.get(id))) + .filter(pair -> Objects.nonNull(pair.getRight())) + .filter(pair -> pair.getRight().isEmpty()) + .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight().get()), HashMap::putAll); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index e663c2105c..eda02368d6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.util.Lazy; import java.util.HashMap; import java.util.Map; @@ -11,15 +12,15 @@ public interface ComponentProvider { - static @NotNull Map createComponents(@NotNull ComponentProvider provider) { + static @NotNull Map> createComponents(@NotNull ComponentProvider provider) { // System.out.println(provider.getClass()); // TODO: Remove this - var map = new HashMap(); - ComponentsImpl.get(provider).forEach((identifier, supplier) -> map.put(identifier, supplier.get())); + var map = new HashMap>(); + ComponentsImpl.get(provider).forEach((identifier, supplier) -> map.put(identifier, Lazy.of(supplier::get))); return map; } - Optional expose(ComponentIdentifier id); + Optional expose(Identifier id); Map exposeAll(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index fe05e43d85..be7729732d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -26,7 +26,7 @@ public static void injectInheritanceExcept(Class clazz, public static Optional expose(ComponentIdentifier id, S obj) { if (obj instanceof ComponentProvider provider) { - return provider.expose(id) + return provider.expose(id.id()) .map(id::cast) .map(Optional::orElseThrow); // If the casting fails something is wrong with the provided ComponentIdentifier. In that case we just throw. } From cc36b93f91b9a419e49728bf70480237d499a78c Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 22 Jun 2022 16:15:51 +0300 Subject: [PATCH 14/70] Implemented containers fully and switched to using them --- .../qsl/component/api/ComponentContainer.java | 81 ++----------- .../qsl/component/api/ComponentProvider.java | 7 +- .../quiltmc/qsl/component/api/Components.java | 4 +- .../api/components/NbtComponent.java | 18 +-- .../impl/LazifiedComponentContainer.java | 111 ++++++++++++++++++ .../impl/defaults/DefaultFloatComponent.java | 4 +- .../defaults/DefaultIntegerComponent.java | 5 +- .../defaults/DefaultInventoryComponent.java | 13 +- .../quiltmc/qsl/component/impl/util/Lazy.java | 26 +++- .../impl/util/duck/NbtComponentProvider.java | 10 -- .../qsl/component/mixin/MixinBlockEntity.java | 47 ++------ .../qsl/component/mixin/MixinChunk.java | 37 ++---- .../component/mixin/MixinChunkSerializer.java | 16 +-- .../qsl/component/mixin/MixinEntity.java | 42 +++---- .../qsl/component/mixin/MixinItemEntity.java | 25 ---- .../qsl/component/mixin/MixinItemStack.java | 96 --------------- .../component/mixin/MixinLevelProperties.java | 53 +++------ .../component/mixin/MixinPacketByteBuf.java | 33 ------ .../qsl/component/mixin/MixinWorldChunk.java | 11 +- .../resources/quilt_component.mixins.json | 3 - .../qsl/component/test/ComponentTestMod.java | 15 +-- 21 files changed, 232 insertions(+), 425 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemEntity.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index e418fcd72c..fe4cf0d0ad 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -2,83 +2,24 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; -import net.minecraft.util.Pair; +import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.impl.util.Lazy; -import org.quiltmc.qsl.component.impl.util.StringConstants; -import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; -import java.util.*; +import java.util.Map; +import java.util.Optional; -public class ComponentContainer implements ComponentProvider, NbtComponentProvider { - private final Map> components; - private final List nbtComponents; +public interface ComponentContainer { + Optional expose(Identifier id); - public static Optional create(T obj) { - if (!(obj instanceof ComponentProvider provider)) { - return Optional.empty(); - } + Map exposeAll(); - return Optional.of(new ComponentContainer(provider)); - } + void moveComponents(ComponentContainer other); - private ComponentContainer(ComponentProvider provider) { - this.components = ComponentProvider.createComponents(provider); - this.nbtComponents = new ArrayList<>(components.size()); - } + void writeNbt(NbtCompound providerRootNbt); - @Override - public Optional expose(Identifier id) { // TODO: Check for nbt component - return Optional.ofNullable(this.components.get(id)) - .map(componentLazy -> { - if (componentLazy.isEmpty()) { - this.nbtComponents.add(id); - return componentLazy.get(); - } + void readNbt(NbtCompound providerRootNbt); - return componentLazy.get(); - }); - } + void setSaveOperation(@NotNull Runnable runnable); - @Override - public Map exposeAll() { - return this.components.entrySet().stream() - .filter(entry -> !entry.getValue().isEmpty()) - .collect(HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue().get()), HashMap::putAll); - } - - public Optional writeNbt() { - if (this.nbtComponents.isEmpty()) { - return Optional.empty(); - } - - var rootQslNbt = new NbtCompound(); - this.nbtComponents.forEach(id -> this.components.get(id).computeIfPresent(component -> - NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, id) - )); - - return rootQslNbt.isEmpty() ? Optional.empty() : Optional.of(rootQslNbt); - } - - public void readNbt(NbtCompound nbt) { - var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - - rootQslNbt.getKeys().stream() - .map(Identifier::tryParse) - .filter(Objects::nonNull) - .forEach(id -> this.expose(id).ifPresent(component -> { - if (component instanceof NbtComponent nbtComponent) { - NbtComponent.readFrom(nbtComponent, id, rootQslNbt); - } - })); - } - - @Override - public Map> getNbtComponents() { - return this.nbtComponents.stream() - .map(id -> new Pair<>(id, this.components.get(id))) - .filter(pair -> Objects.nonNull(pair.getRight())) - .filter(pair -> pair.getRight().isEmpty()) - .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight().get()), HashMap::putAll); - } + Map> getNbtComponents(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index eda02368d6..7b47a79f1c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -2,13 +2,11 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.util.Lazy; import java.util.HashMap; import java.util.Map; -import java.util.Optional; public interface ComponentProvider { @@ -20,8 +18,7 @@ public interface ComponentProvider { return map; } - Optional expose(Identifier id); - - Map exposeAll(); + @NotNull + ComponentContainer getContainer(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index be7729732d..793c3a7bbb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -26,7 +26,7 @@ public static void injectInheritanceExcept(Class clazz, public static Optional expose(ComponentIdentifier id, S obj) { if (obj instanceof ComponentProvider provider) { - return provider.expose(id.id()) + return provider.getContainer().expose(id.id()) .map(id::cast) .map(Optional::orElseThrow); // If the casting fails something is wrong with the provided ComponentIdentifier. In that case we just throw. } @@ -35,6 +35,6 @@ public static Optional expose(ComponentIdentifier } public static Map exposeAll(S obj) { - return obj instanceof ComponentProvider provider ? provider.exposeAll() : ImmutableMap.of(); + return obj instanceof ComponentProvider provider ? provider.getContainer().exposeAll() : ImmutableMap.of(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index ba12f34d5b..fed5fbb2d0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -3,11 +3,9 @@ import net.minecraft.nbt.*; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; -import java.util.HashMap; -import java.util.Map; - public interface NbtComponent extends Component { static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier id, @NotNull NbtCompound nbt) { @@ -40,18 +38,6 @@ static void read(@NotNull NbtComponent nbtComponent, NbtElement nbt) { } } - static Map> getNbtSerializable(Map components) { - var map = new HashMap>(); - - for (var entry : components.entrySet()) { - if (entry.getValue() instanceof NbtComponent nbtComponent) { - map.put(entry.getKey(), nbtComponent); - } - } - - return map; - } - T write(); void read(T nbt); @@ -60,5 +46,5 @@ static Map> getNbtSerializable(Map> components; + private final List nbtComponents; + @Nullable + private Runnable saveOperation = null; + + private LazifiedComponentContainer(ComponentProvider provider) { + this.components = ComponentProvider.createComponents(provider); + this.nbtComponents = new ArrayList<>(components.size()); + } + + public static Optional create(T obj) { + if (!(obj instanceof ComponentProvider provider)) { + return Optional.empty(); + } + + return Optional.of(new LazifiedComponentContainer(provider)); + } + + public Optional expose(Identifier id) { + return Optional.ofNullable(this.components.get(id)) + .map(componentLazy -> { + if (componentLazy.isEmpty() && componentLazy.get() instanceof NbtComponent nbtComponent) { + this.nbtComponents.add(id); + nbtComponent.setSaveOperation(this.saveOperation); + return nbtComponent; + } + + return componentLazy.get(); + }); + } + + public Map exposeAll() { + return this.components.entrySet().stream() + .filter(entry -> !entry.getValue().isEmpty()) + .collect(HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue().get()), HashMap::putAll); + } + + public Map> getNbtComponents() { + return this.nbtComponents.stream() + .map(id -> new Pair<>(id, this.components.get(id))) + .filter(pair -> Objects.nonNull(pair.getRight())) + .filter(pair -> pair.getRight().isEmpty()) + .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight().get()), HashMap::putAll); + } + + public void setSaveOperation(@NotNull Runnable runnable) { + this.saveOperation = runnable; + } + + public void writeNbt(@NotNull NbtCompound providerRootNbt) { + var rootQslNbt = new NbtCompound(); + this.nbtComponents.forEach(id -> this.components.get(id).ifPresent(component -> + NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, id) + )); + + if (!rootQslNbt.isEmpty()) { + providerRootNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + } + } + + public void readNbt(@NotNull NbtCompound providerRootNbt) { + var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); + + rootQslNbt.getKeys().stream() + .map(Identifier::tryParse) + .filter(Objects::nonNull) + .forEach(id -> this.expose(id).ifPresent(component -> { + if (component instanceof NbtComponent nbtComponent) { + NbtComponent.readFrom(nbtComponent, id, rootQslNbt); + } + })); + } + + public void moveComponents(ComponentContainer other) { + if (other instanceof LazifiedComponentContainer otherContainer) { + otherContainer.components.forEach((id, componentLazy) -> { + if (!componentLazy.isEmpty()) { + this.components.put(id, componentLazy); + + if (componentLazy.get() instanceof NbtComponent nbtComponent) { + this.nbtComponents.add(id); + nbtComponent.setSaveOperation(this.saveOperation); + } + } + }); + + otherContainer.components.clear(); + otherContainer.nbtComponents.clear(); + } else { + throw new IllegalArgumentException("Cannot move components from a non-lazified container to one that is!"); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java index 99039a37cc..1f2b46480d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java @@ -1,9 +1,11 @@ package org.quiltmc.qsl.component.impl.defaults; +import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.FloatComponent; public class DefaultFloatComponent implements FloatComponent { private float value; + @Nullable private Runnable saveOperation; public DefaultFloatComponent() { @@ -32,7 +34,7 @@ public void saveNeeded() { } @Override - public void setSaveOperation(Runnable runnable) { + public void setSaveOperation(@Nullable Runnable runnable) { this.saveOperation = runnable; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java index d1b04b0f6b..5744232e8a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java @@ -1,11 +1,14 @@ package org.quiltmc.qsl.component.impl.defaults; +import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.IntegerComponent; import java.util.Objects; public class DefaultIntegerComponent implements IntegerComponent { + private int value; + @Nullable private Runnable saveOperation; public DefaultIntegerComponent(int defaultValue) { @@ -56,7 +59,7 @@ public void saveNeeded() { } @Override - public void setSaveOperation(Runnable runnable) { + public void setSaveOperation(@Nullable Runnable runnable) { this.saveOperation = runnable; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java index 04979c239c..123d821a21 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java @@ -2,14 +2,17 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.collection.DefaultedList; +import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.InventoryComponent; import java.util.Objects; import java.util.function.Supplier; public class DefaultInventoryComponent implements InventoryComponent { + private final DefaultedList stacks; - private Runnable dirtyOperation; + @Nullable + private Runnable saveOperation; public DefaultInventoryComponent(int size) { this.stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); @@ -26,14 +29,14 @@ public DefaultedList getStacks() { @Override public void saveNeeded() { - if (this.dirtyOperation != null) { - this.dirtyOperation.run(); + if (this.saveOperation != null) { + this.saveOperation.run(); } } @Override - public void setSaveOperation(Runnable runnable) { - this.dirtyOperation = runnable; + public void setSaveOperation(@Nullable Runnable runnable) { + this.saveOperation = runnable; } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java index 9e883522ff..cf019aac58 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java @@ -3,6 +3,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -24,6 +25,11 @@ public static Lazy of(@NotNull Supplier sup) { return new Lazy<>(sup); } + @NotNull + public Lazy compose(Function transformer) { + return Lazy.of(() -> transformer.apply(this.sup.get())); + } + @NotNull public T get() { if (value == null) { @@ -47,7 +53,7 @@ public Lazy map(@NotNull Function func) { return Lazy.of(() -> func.apply(this.get())); } - public void computeIfPresent(@NotNull Consumer action) { + public void ifPresent(@NotNull Consumer action) { if (!this.isEmpty()) { action.accept(this.get()); } @@ -56,4 +62,22 @@ public void computeIfPresent(@NotNull Consumer action) { public void compute(@NotNull Consumer action) { action.accept(this.get()); } + + @Override + public boolean equals(Object o) { + if (o instanceof Lazy other) { + if (other.isEmpty() == this.isEmpty()) { + return this.sup == other.sup; + } else { + return this.value == other.value; + } + } + + return false; + } + + @Override + public int hashCode() { + return Objects.hash(sup, value); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java deleted file mode 100644 index ea708a291b..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/duck/NbtComponentProvider.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.quiltmc.qsl.component.impl.util.duck; - -import net.minecraft.util.Identifier; -import org.quiltmc.qsl.component.api.components.NbtComponent; - -import java.util.Map; - -public interface NbtComponentProvider { - Map> getNbtComponents(); -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index a01edb5c8a..66236190be 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -1,18 +1,14 @@ package org.quiltmc.qsl.component.mixin; -import com.google.common.collect.ImmutableMap; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; -import org.quiltmc.qsl.component.api.Component; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import org.quiltmc.qsl.component.impl.util.StringConstants; -import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; @@ -22,26 +18,18 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Map; -import java.util.Optional; - -@Implements({ - @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$"), - @Interface(iface = ComponentProvider.class, prefix = "comp$") -}) +@Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) @Mixin(BlockEntity.class) public abstract class MixinBlockEntity { - private Map qsl$components; - private Map> qsl$nbtComponents; + private ComponentContainer qsl$container; @Inject( method = "m_qgnqsprj", // The lambda used in second map operation. at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V") ) private static void onReadNbt(NbtCompound nbt, String string, BlockEntity blockEntity, CallbackInfoReturnable cir) { - var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - ((NbtComponentProvider) blockEntity).getNbtComponents().forEach((id, nbtComponent) -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)); + ((ComponentProvider) blockEntity).getContainer().readNbt(nbt); } @Shadow @@ -49,28 +37,17 @@ private static void onReadNbt(NbtCompound nbt, String string, BlockEntity blockE @Inject(method = "", at = @At("RETURN")) private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { - this.qsl$components = ImmutableMap.copyOf(ComponentProvider.createComponents((ComponentProvider) this)); - this.qsl$nbtComponents = ImmutableMap.copyOf(NbtComponent.getNbtSerializable(this.qsl$components)); - this.qsl$nbtComponents.forEach((id, component) -> component.setSaveOperation(this::markDirty)); + this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); + this.qsl$container.setSaveOperation(this::markDirty); } @Inject(method = "toNbt", at = @At("RETURN")) private void onWriteNbt(CallbackInfoReturnable cir) { - var rootQslNbt = new NbtCompound(); - this.qsl$nbtComponents.forEach((id, nbtComponent) -> rootQslNbt.put(id.toString(), nbtComponent.write())); - - cir.getReturnValue().put(StringConstants.COMPONENT_ROOT, rootQslNbt); - } - - public Map> nbtExp$getNbtComponents() { - return this.qsl$nbtComponents; - } - - public Optional comp$expose(ComponentIdentifier id) { - return Optional.ofNullable(this.qsl$components.get(id.id())); + this.qsl$container.writeNbt(cir.getReturnValue()); } - public Map comp$exposeAll() { - return this.qsl$components; + @NotNull + public ComponentContainer comp$getContainer() { + return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 2bbaf2b473..64a7db3321 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -1,6 +1,5 @@ package org.quiltmc.qsl.component.mixin; -import net.minecraft.util.Identifier; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.Registry; import net.minecraft.world.HeightLimitView; @@ -8,11 +7,10 @@ import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.chunk.UpgradeData; import net.minecraft.world.gen.chunk.BlendingData; -import org.quiltmc.qsl.component.api.Component; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; @@ -21,38 +19,23 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Map; -import java.util.Optional; - -@Implements({ - @Interface(iface = ComponentProvider.class, prefix = "comp$"), - @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$") -}) +@Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) @Mixin(Chunk.class) public abstract class MixinChunk { - private Map qsl$components; - private Map> qsl$nbtComponents; + private ComponentContainer qsl$container; @Shadow public abstract void setNeedsSaving(boolean needsSaving); @Inject(method = "", at = @At("RETURN")) private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { - this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); - this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); - this.qsl$nbtComponents.forEach((ignored, nbtComponent) -> nbtComponent.setSaveOperation(() -> this.setNeedsSaving(true))); - } - - public Map> nbtExp$getNbtComponents() { - return this.qsl$nbtComponents; - } - - public Optional comp$expose(ComponentIdentifier id) { - return Optional.ofNullable(this.qsl$components.get(id.id())); + this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); + this.qsl$container.setSaveOperation(() -> this.setNeedsSaving(true)); } - public Map comp$exposeAll() { - return this.qsl$components; + @NotNull + public ComponentContainer comp$getContainer() { + return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java index 3983d2ec60..1ae2568b37 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java @@ -8,9 +8,7 @@ import net.minecraft.world.chunk.ProtoChunk; import net.minecraft.world.chunk.ReadOnlyChunk; import net.minecraft.world.poi.PointOfInterestStorage; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.impl.util.StringConstants; -import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; +import org.quiltmc.qsl.component.api.ComponentProvider; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -20,20 +18,16 @@ public class MixinChunkSerializer { @Inject(method = "deserialize", at = @At("RETURN"), cancellable = true) // FIXME: More chunk issues private static void deserializeComponents(ServerWorld world, PointOfInterestStorage poiStorage, ChunkPos pos, NbtCompound nbt, CallbackInfoReturnable cir) { - ProtoChunk ret = cir.getReturnValue(); - NbtCompound rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); + var ret = cir.getReturnValue(); var target = ret instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : ret; - - ((NbtComponentProvider) target).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); + ((ComponentProvider) target).getContainer().readNbt(nbt); cir.setReturnValue(ret); } @Inject(method = "serialize", at = @At("RETURN"), cancellable = true) private static void serializeComponents(ServerWorld world, Chunk chunk, CallbackInfoReturnable cir) { - var rootQslNbt = new NbtCompound(); - ((NbtComponentProvider) chunk).getNbtComponents().forEach((id, component) -> NbtComponent.writeTo(rootQslNbt, component, id)); - NbtCompound ret = cir.getReturnValue(); - ret.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + var ret = cir.getReturnValue(); + ((ComponentProvider) chunk).getContainer().writeNbt(ret); cir.setReturnValue(ret); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index c5f1a06577..c3aecb47e0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -3,13 +3,11 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.Identifier; import net.minecraft.world.World; -import org.quiltmc.qsl.component.api.Component; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import org.quiltmc.qsl.component.impl.util.StringConstants; +import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; @@ -18,41 +16,29 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Map; -import java.util.Optional; - -@Mixin(Entity.class) @Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) -public abstract class MixinEntity { //TODO: Consider creating a container-like class to handle this instead of doing it manually. +@Mixin(Entity.class) +public abstract class MixinEntity { - private Map qsl$components; - private Map> qsl$nbtComponents; + private ComponentContainer qsl$container; @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { - this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); - this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); - } - - public Optional comp$expose(ComponentIdentifier id) { - return Optional.ofNullable(this.qsl$components.get(id.id())); - } - - public Map comp$exposeAll() { - return this.qsl$components; + this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); } @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void onSerialize(NbtCompound nbt, CallbackInfoReturnable cir) { - var rootQslNbt = new NbtCompound(); - this.qsl$nbtComponents.forEach((id, nbtComponent) -> rootQslNbt.put(id.toString(), nbtComponent.write())); - - nbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + this.qsl$container.writeNbt(nbt); } @Inject(method = "readNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;readCustomDataFromNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { - var rootQslNbt = nbt.getCompound(StringConstants.COMPONENT_ROOT); - this.qsl$nbtComponents.forEach((id, nbtComponent) -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)); + this.qsl$container.readNbt(nbt); + } + + @NotNull + public ComponentContainer comp$getContainer() { + return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemEntity.java deleted file mode 100644 index 57199c48eb..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemEntity.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.quiltmc.qsl.component.mixin; - -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.ItemEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(ItemEntity.class) -public abstract class MixinItemEntity extends Entity { - public MixinItemEntity(EntityType entityType, World world) { - super(entityType, world); - } - - @Inject(method = "canMerge(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemStack;)Z", at = @At("HEAD"), cancellable = true) - private static void properCanMerge(ItemStack stack1, ItemStack stack2, CallbackInfoReturnable cir) { - // data get entity @e[type=item, limit=1] - cir.setReturnValue(ItemStack.canCombine(stack1, stack2) && stack1.getCount() + stack2.getCount() <= stack1.getMaxCount()); - } - -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java deleted file mode 100644 index b57628cc27..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.quiltmc.qsl.component.mixin; - -import net.minecraft.item.ItemConvertible; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.util.Identifier; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import org.quiltmc.qsl.component.impl.util.StringConstants; -import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Map; -import java.util.Optional; - -@SuppressWarnings("ConstantConditions") -@Implements({ - @Interface(iface = ComponentProvider.class, prefix = "comp$"), - @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$") -}) -@Mixin(ItemStack.class) -public abstract class MixinItemStack { // FIXME: Figure out why ItemEntities erase the Qsl Component data once they get picked up??!! - - private Map qsl$components; - private Map> qsl$nbtComponents; - - @Inject(method = "canCombine", at = @At("RETURN"), cancellable = true) - private static void checkForComponents(ItemStack stack, ItemStack otherStack, CallbackInfoReturnable cir) { - var otherMap = ((ComponentProvider) (Object) otherStack).exposeAll(); - cir.setReturnValue(cir.getReturnValue() && ((ComponentProvider) (Object) stack).exposeAll().entrySet().stream() - .allMatch(entry -> otherMap.get(entry.getKey()).equals(entry.getValue())) - ); - } - - @Inject(method = "isEqual", at = @At("RETURN"), cancellable = true) - private void checkForComponentsClient(ItemStack stack, CallbackInfoReturnable cir) { - var otherMap = ((ComponentProvider) (Object) stack).exposeAll(); - cir.setReturnValue(cir.getReturnValue() && ((ComponentProvider) this).exposeAll().entrySet().stream() - .allMatch(entry -> otherMap.get(entry.getKey()).equals(entry.getValue())) - ); - } - - @Inject(method = "(Lnet/minecraft/item/ItemConvertible;I)V", at = @At("RETURN")) - private void onItemInit(ItemConvertible itemConvertible, int i, CallbackInfo ci) { - this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); - this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); - } - - @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;)V", at = @At("RETURN")) - private void deserializeComponentsFromNbt(NbtCompound nbtCompound, CallbackInfo ci) { - this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); - this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); - var rootQslNbt = nbtCompound.getCompound(StringConstants.COMPONENT_ROOT); - this.qsl$nbtComponents.forEach((id, nbtComponent) -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)); - } - - @Inject(method = "writeNbt", at = @At("RETURN")) - private void onWrite(NbtCompound nbt, CallbackInfoReturnable cir) { - var rootQslNbt = new NbtCompound(); - this.qsl$nbtComponents.forEach((id, nbtComponent) -> rootQslNbt.put(id.toString(), nbtComponent.write())); - nbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); - } - - @Inject(method = "copy", at = @At(value = "RETURN", ordinal = 1)) - private void recordComponentNbt(CallbackInfoReturnable cir) { - ItemStack stack = cir.getReturnValue(); - Map> stackMap = ((NbtComponentProvider) (Object) stack).getNbtComponents(); - for (var entry : this.qsl$nbtComponents.entrySet()) { - NbtElement nbt = entry.getValue().write(); - Identifier id = entry.getKey(); - - NbtComponent.read(stackMap.get(id), nbt); - } - } - - public Optional comp$expose(ComponentIdentifier id) { - return Optional.ofNullable(this.qsl$components.get(id.id())); - } - - public Map comp$exposeAll() { - return this.qsl$components; - } - - public Map> nbtExp$getNbtComponents() { - return this.qsl$nbtComponents; - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index 236f213041..f25251d222 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -6,7 +6,6 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Identifier; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.world.SaveProperties; import net.minecraft.world.border.WorldBorder; @@ -16,13 +15,11 @@ import net.minecraft.world.level.ServerWorldProperties; import net.minecraft.world.level.storage.SaveVersionInfo; import net.minecraft.world.timer.Timer; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import org.quiltmc.qsl.component.impl.util.StringConstants; -import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; @@ -31,55 +28,33 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.UUID; -@Implements({ - @Interface(iface = ComponentProvider.class, prefix = "comp$"), - @Interface(iface = NbtComponentProvider.class, prefix = "nbtExp$") -}) +@Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) @Mixin(LevelProperties.class) public abstract class MixinLevelProperties implements ServerWorldProperties, SaveProperties { - private Map qsl$components; - private Map> qsl$nbtComponents; + + private ComponentContainer qsl$container; @Inject(method = "readProperties", at = @At("RETURN")) private static void readComponentData(Dynamic dynamic, DataFixer dataFixer, int dataVersion, @Nullable NbtCompound playerData, LevelInfo levelInfo, SaveVersionInfo saveVersionInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfoReturnable cir) { LevelProperties retProperties = cir.getReturnValue(); - - dynamic.get(StringConstants.COMPONENT_ROOT) - .result() - .map(Dynamic::getValue) - .map(it -> (NbtCompound) it) // Casting here since we know it *cannot* be anything *but* NbtCompound. - .ifPresent(rootQslNbt -> ((NbtComponentProvider) retProperties).getNbtComponents().forEach( - (identifier, nbtComponent) -> NbtComponent.readFrom(nbtComponent, identifier, rootQslNbt) - )); - } - - @Inject(method = "updateProperties", at = @At("TAIL")) - private void writeComponentData(DynamicRegistryManager registryManager, NbtCompound levelNbt, NbtCompound playerNbt, CallbackInfo ci) { - var rootQslNbt = new NbtCompound(); - this.qsl$nbtComponents.forEach((identifier, nbtComponent) -> rootQslNbt.put(identifier.toString(), nbtComponent.write())); - levelNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + ((ComponentProvider) retProperties).getContainer().readNbt((NbtCompound) dynamic.getValue()); } @Inject(method = "(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/NbtCompound;ZIIIFJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lcom/mojang/serialization/Lifecycle;)V", at = @At("TAIL")) private void onInit(DataFixer dataFixer, int i, NbtCompound nbtCompound, boolean bl, int j, int k, int l, float f, long m, long n, int o, int p, int q, boolean bl2, int r, boolean bl3, boolean bl4, boolean bl5, WorldBorder.Properties properties, int s, int t, UUID uUID, Set set, Timer timer, NbtCompound nbtCompound2, NbtCompound nbtCompound3, LevelInfo levelInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfo ci) { - this.qsl$components = ComponentProvider.createComponents((ComponentProvider) this); - this.qsl$nbtComponents = NbtComponent.getNbtSerializable(this.qsl$components); - } - - public Optional comp$expose(ComponentIdentifier id) { - return Optional.ofNullable(this.qsl$components.get(id.id())); + this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); } - public Map comp$exposeAll() { - return this.qsl$components; + @Inject(method = "updateProperties", at = @At("TAIL")) + private void writeComponentData(DynamicRegistryManager registryManager, NbtCompound levelNbt, NbtCompound playerNbt, CallbackInfo ci) { + this.qsl$container.writeNbt(levelNbt); } - public Map> nbtExp$getNbtComponents() { - return this.qsl$nbtComponents; + @NotNull + public ComponentContainer comp$getContainer() { + return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java deleted file mode 100644 index 004a136ef1..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinPacketByteBuf.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.quiltmc.qsl.component.mixin; - -import io.netty.buffer.ByteBuf; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.impl.util.StringConstants; -import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(PacketByteBuf.class) -public abstract class MixinPacketByteBuf extends ByteBuf { - @Inject(method = "readItemStack", at = @At(value = "RETURN", ordinal = 1), cancellable = true) - private void readComponentData(CallbackInfoReturnable cir) { - ItemStack ret = cir.getReturnValue(); - var this$ = (PacketByteBuf) (Object) this; - NbtCompound rootQslNbt = this$.readNbt(); - if (rootQslNbt != null) { - ((NbtComponentProvider) (Object) ret).getNbtComponents().forEach((id, component) -> NbtComponent.readFrom(component, id, rootQslNbt)); - cir.setReturnValue(ret); - } - } - - @Inject(method = "writeItemStack", at = @At("RETURN")) - private void writeComponentData(ItemStack stack, CallbackInfoReturnable cir) { - var this$ = (PacketByteBuf) (Object) this; - this$.writeNbt(stack.writeNbt(new NbtCompound()).getCompound(StringConstants.COMPONENT_ROOT)); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java index d0b0b2464d..9b0b966ffc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -1,7 +1,6 @@ package org.quiltmc.qsl.component.mixin; import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.Identifier; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.Registry; import net.minecraft.world.HeightLimitView; @@ -9,15 +8,12 @@ import net.minecraft.world.chunk.*; import net.minecraft.world.gen.chunk.BlendingData; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.util.duck.NbtComponentProvider; import org.spongepowered.asm.mixin.Mixin; 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.Map; @Mixin(WorldChunk.class) public abstract class MixinWorldChunk extends Chunk { @@ -28,11 +24,6 @@ public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitVi @Inject(method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/ProtoChunk;Lnet/minecraft/world/chunk/WorldChunk$PostLoadProcessor;)V", at = @At("TAIL")) private void copyComponentData(ServerWorld serverWorld, ProtoChunk protoChunk, WorldChunk.PostLoadProcessor postLoadProcessor, CallbackInfo ci) { var target = protoChunk instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : protoChunk; - var this$ = (ComponentProvider) this; - Map componentMap = this$.exposeAll(); - componentMap.putAll(((ComponentProvider) target).exposeAll()); - ((NbtComponentProvider) this$).getNbtComponents().forEach((id, component) -> - component.setSaveOperation(() -> this.setNeedsSaving(true)) - ); + ((ComponentProvider) this).getContainer().moveComponents(((ComponentProvider) target).getContainer()); } } diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index cf1086677b..a3a30a847b 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -7,10 +7,7 @@ "MixinChunk", "MixinChunkSerializer", "MixinEntity", - "MixinItemEntity", - "MixinItemStack", "MixinLevelProperties", - "MixinPacketByteBuf", "MixinWorldChunk" ], "injectors": { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index e4f2194472..f06877f945 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -22,7 +22,6 @@ import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; -import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.server.network.ServerPlayerEntity; @@ -140,17 +139,19 @@ public Class getBaseClass() { player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); }); - Inventory inventory = player.getInventory(); - ItemStack stack = inventory.getStack(9); - if (!stack.isEmpty()) { - Components.expose(ITEMSTACK_NOMBER, stack).ifPresent(IntegerComponent::increment); - } +// Inventory inventory = player.getInventory(); // TODO: Put this back once ItemStack is fully implemented. +// ItemStack stack = inventory.getStack(9); +// if (!stack.isEmpty()) { +// Components.expose(ITEMSTACK_NOMBER, stack).ifPresent(IntegerComponent::increment); +// } SaveProperties props = server.getSaveProperties(); Components.expose(SAVE_FLOAT, props) .ifPresent(floatComponent -> { floatComponent.set(floatComponent.get() + 0.5f); - player.sendMessage(Text.literal("%.3f".formatted(floatComponent.get())), false); + if (world.getTime() % 20 * 5 == 0) { + player.sendMessage(Text.literal("%.3f".formatted(floatComponent.get())), false); + } }); }); } From 127f91da358a69eb3eff7b26ff34605aa2f375fb Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 22 Jun 2022 23:46:50 +0300 Subject: [PATCH 15/70] Added SimpleComponent for custom ComponentProvider implementations. --- library/data/component/build.gradle | 1 + .../qsl/component/api/ComponentProvider.java | 16 ---- .../qsl/component/impl/ComponentsImpl.java | 6 +- .../impl/LazifiedComponentContainer.java | 8 +- .../impl/SimpleComponentContainer.java | 90 +++++++++++++++++++ .../resources/quilt_component.accesswidener | 3 + .../qsl/component/test/ComponentTestMod.java | 30 ++++--- .../quiltmc/qsl/component/test/TestBlock.java | 32 +++++++ .../qsl/component/test/TestBlockEntity.java | 67 ++++++++++++++ 9 files changed, 222 insertions(+), 31 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java create mode 100644 library/data/component/src/main/resources/quilt_component.accesswidener create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index aff1229c2d..443481695b 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -14,4 +14,5 @@ qslModule { testmodOnly("lifecycle_events") } } + accessWidener() } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 7b47a79f1c..12ed72672a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -1,24 +1,8 @@ package org.quiltmc.qsl.component.api; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.util.Lazy; - -import java.util.HashMap; -import java.util.Map; public interface ComponentProvider { - - static @NotNull Map> createComponents(@NotNull ComponentProvider provider) { - // System.out.println(provider.getClass()); // TODO: Remove this - var map = new HashMap>(); - ComponentsImpl.get(provider).forEach((identifier, supplier) -> map.put(identifier, Lazy.of(supplier::get))); - - return map; - } - @NotNull ComponentContainer getContainer(); - } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 772b4881cf..2aa77a9a5c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -15,7 +15,7 @@ public class ComponentsImpl { private static final Map> INJECTION_REGISTRY = new HashMap<>(); - private static final Map> REGISTRY = new HashMap<>(); // Look into using a Minecraft Registry for this. + private static final Map> REGISTRY = new HashMap<>(); // TODO: Look into using a Minecraft Registry for this. public static void inject(ComponentInjectionPredicate predicate, ComponentIdentifier id) { Supplier supplier = REGISTRY.get(id.id()); @@ -56,4 +56,8 @@ public static Map> get(ComponentProvid return returnMap; }); } + + public static Supplier getEntry(Identifier id) { + return REGISTRY.get(id); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java index fb15cdd971..eb3a40a3ce 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java @@ -22,7 +22,7 @@ public class LazifiedComponentContainer implements ComponentContainer { private Runnable saveOperation = null; private LazifiedComponentContainer(ComponentProvider provider) { - this.components = ComponentProvider.createComponents(provider); + this.components = createComponents(provider); this.nbtComponents = new ArrayList<>(components.size()); } @@ -34,6 +34,12 @@ public static Optional create(T obj) { return Optional.of(new LazifiedComponentContainer(provider)); } + public static @NotNull Map> createComponents(@NotNull ComponentProvider provider) { + var map = new HashMap>(); + ComponentsImpl.get(provider).forEach((identifier, supplier) -> map.put(identifier, Lazy.of(supplier::get))); + return map; + } + public Optional expose(Identifier id) { return Optional.ofNullable(this.components.get(id)) .map(componentLazy -> { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java new file mode 100644 index 0000000000..ef77436624 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java @@ -0,0 +1,90 @@ +package org.quiltmc.qsl.component.impl; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.util.StringConstants; + +import java.util.*; +import java.util.stream.Stream; + +public class SimpleComponentContainer implements ComponentContainer { + private final Map components; + private final List nbtComponents; + + public static @NotNull SimpleComponentContainer create(@Nullable Runnable saveOperation, ComponentIdentifier... ids) { + return new SimpleComponentContainer(saveOperation, Stream.of(ids).map(ComponentIdentifier::id)); + } + + private SimpleComponentContainer(@Nullable Runnable saveOperation, Stream componentIds) { + this.components = new HashMap<>(); + this.nbtComponents = new ArrayList<>(); + + componentIds.forEach(id -> { + Component component = ComponentsImpl.getEntry(id).get(); + this.components.put(id, component); + + if (component instanceof NbtComponent nbtComponent) { + this.nbtComponents.add(id); + nbtComponent.setSaveOperation(saveOperation); + } + }); + + componentIds.close(); + } + + @Override + public Optional expose(Identifier id) { + return Optional.ofNullable(this.components.get(id)); + } + + @Override + public Map exposeAll() { + return this.components; + } + + @Override + public void moveComponents(ComponentContainer other) { + } + + @Override + public void writeNbt(NbtCompound providerRootNbt) { + var rootQslNbt = new NbtCompound(); + this.nbtComponents.forEach(id -> this.expose(id).ifPresent(component -> NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, id))); + if (!rootQslNbt.isEmpty()) { + providerRootNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + } + } + + @Override + public void readNbt(NbtCompound providerRootNbt) { + var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); + + if (rootQslNbt.isEmpty()) { + return; + } + + rootQslNbt.getKeys().stream() + .map(Identifier::tryParse) + .filter(Objects::nonNull) + .forEach(id -> this.expose(id).ifPresent(component -> NbtComponent.readFrom((NbtComponent) component, id, rootQslNbt))); + } + + @Override + public void setSaveOperation(@NotNull Runnable runnable) { + + } + + @Override + public Map> getNbtComponents() { + return this.nbtComponents.stream() + .map(id -> new Pair<>(id, this.components.get(id))) + .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight()), HashMap::putAll); + } +} diff --git a/library/data/component/src/main/resources/quilt_component.accesswidener b/library/data/component/src/main/resources/quilt_component.accesswidener new file mode 100644 index 0000000000..b689638b64 --- /dev/null +++ b/library/data/component/src/main/resources/quilt_component.accesswidener @@ -0,0 +1,3 @@ +accessWidener v2 named + +extendable class net/minecraft/block/entity/BlockEntityType$BlockEntityFactory diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index f06877f945..a1d66dfe55 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -16,6 +16,10 @@ package org.quiltmc.qsl.component.test; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.ChestBlockEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -29,6 +33,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.TypeFilter; import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.registry.Registry; import net.minecraft.world.SaveProperties; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.explosion.Explosion; @@ -60,13 +65,17 @@ public class ComponentTestMod implements ModInitializer { public static final ComponentIdentifier CHUNK_INVENTORY = InventoryComponent.ofSize(1, new Identifier(MODID, "chunk_inventory") ); - public static final ComponentIdentifier ITEMSTACK_NOMBER = - IntegerComponent.create(new Identifier(MODID, "itemstack_nomber")); public static final ComponentIdentifier SAVE_FLOAT = FloatComponent.create(new Identifier(MODID, "save_float")); + public static final Block TEST_BLOCK = new TestBlock(AbstractBlock.Settings.copy(Blocks.STONE)); + public static final BlockEntityType TEST_BE_TYPE = + BlockEntityType.Builder.create(TestBlockEntity::new, TEST_BLOCK).build(null); + @Override public void onInitialize(ModContainer mod) { + Registry.register(Registry.BLOCK, new Identifier(MODID, "test_block"), TEST_BLOCK); + Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(MODID, "block_entity"), TEST_BE_TYPE); // Application Code Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); Components.injectInheritage(CowEntity.class, COW_INVENTORY); @@ -74,7 +83,6 @@ public void onInitialize(ModContainer mod) { Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(LevelProperties.class, SAVE_FLOAT); -// Components.inject(ItemStack.class, ITEMSTACK_NOMBER); // Testing Code ServerWorldTickEvents.START.register((server, world) -> { @@ -127,24 +135,20 @@ public Class getBaseClass() { Chunk chunk = world.getChunk(player.getBlockPos()); Components.expose(CHUNK_INVENTORY, chunk).ifPresent(inventory -> { ItemStack playerStack = player.getInventory().getStack(9); - if (playerStack.isOf(Items.DIRT)) { - playerStack.decrement(1); - ItemStack stack = inventory.getStack(0); + ItemStack stack = inventory.getStack(0); + if (!playerStack.isEmpty()) { if (stack.isEmpty()) { - inventory.setStack(0, Items.DIRT.getDefaultStack()); + inventory.setStack(0, new ItemStack(playerStack.getItem())); + playerStack.decrement(1); } else { stack.increment(1); + playerStack.decrement(1); + inventory.saveNeeded(); } } player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); }); -// Inventory inventory = player.getInventory(); // TODO: Put this back once ItemStack is fully implemented. -// ItemStack stack = inventory.getStack(9); -// if (!stack.isEmpty()) { -// Components.expose(ITEMSTACK_NOMBER, stack).ifPresent(IntegerComponent::increment); -// } - SaveProperties props = server.getSaveProperties(); Components.expose(SAVE_FLOAT, props) .ifPresent(floatComponent -> { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java new file mode 100644 index 0000000000..e5b8bd327e --- /dev/null +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -0,0 +1,32 @@ +package org.quiltmc.qsl.component.test; + +import net.minecraft.block.*; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +public class TestBlock extends Block implements BlockEntityProvider { + public TestBlock(Settings settings) { + super(settings); + } + + @Nullable + @Override + public BlockEntityTicker getTicker(World world, BlockState state, BlockEntityType type) { + return TestBlockEntity::tick; + } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return ComponentTestMod.TEST_BE_TYPE.instantiate(pos, state); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } +} diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java new file mode 100644 index 0000000000..235355fc60 --- /dev/null +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -0,0 +1,67 @@ +package org.quiltmc.qsl.component.test; + +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.nbt.NbtCompound;; +import net.minecraft.network.Packet; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.components.IntegerComponent; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.SimpleComponentContainer; + +public class TestBlockEntity extends BlockEntity implements ComponentProvider { + public static final ComponentIdentifier TEST_BE_INT = + IntegerComponent.create(new Identifier("quilt_component_test", "test_be_int")); + + private final ComponentContainer container = + SimpleComponentContainer.create(this::markDirty, TEST_BE_INT); + + public TestBlockEntity(BlockPos blockPos, BlockState blockState) { + super(ComponentTestMod.TEST_BE_TYPE, blockPos, blockState); + } + + @Override + public @NotNull ComponentContainer getContainer() { + return this.container; + } + + @Override + protected void writeNbt(NbtCompound nbt) { + super.writeNbt(nbt); + this.container.writeNbt(nbt); + } + + @Override + public void readNbt(NbtCompound nbt) { + super.readNbt(nbt); + this.container.readNbt(nbt); + } + + public static void tick(World world, BlockPos ignoredPos, BlockState ignoredState, T blockEntity) { + if (world.isClient) { + return; + } + + Components.expose(TEST_BE_INT, blockEntity).ifPresent(IntegerComponent::increment); + } + + @Override + public NbtCompound toInitialChunkDataNbt() { + return this.toNbt(); + } + + @Nullable + @Override + public Packet toUpdatePacket() { + return BlockEntityUpdateS2CPacket.of(this); + } +} From e53f5e776223603a3d3ab133af4cf887fbbe61df Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 23 Jun 2022 11:39:21 +0300 Subject: [PATCH 16/70] Fixed testmod issue. --- .../qsl/component/test/ComponentTestMod.java | 16 +++++++++----- .../qsl/component/test/TestBlockEntity.java | 22 +++---------------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index a1d66dfe55..4b0944ef0a 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -68,14 +68,16 @@ public class ComponentTestMod implements ModInitializer { public static final ComponentIdentifier SAVE_FLOAT = FloatComponent.create(new Identifier(MODID, "save_float")); + // Attention do NOT place this block in any world because registry sync issues will make the game hung upon rejoining. public static final Block TEST_BLOCK = new TestBlock(AbstractBlock.Settings.copy(Blocks.STONE)); public static final BlockEntityType TEST_BE_TYPE = - BlockEntityType.Builder.create(TestBlockEntity::new, TEST_BLOCK).build(null); + BlockEntityType.Builder.create(TestBlockEntity::new, TEST_BLOCK, Blocks.NOTE_BLOCK).build(null); @Override public void onInitialize(ModContainer mod) { Registry.register(Registry.BLOCK, new Identifier(MODID, "test_block"), TEST_BLOCK); Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(MODID, "block_entity"), TEST_BE_TYPE); + Block.STATE_IDS.add(TEST_BLOCK.getDefaultState()); // Application Code Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); Components.injectInheritage(CowEntity.class, COW_INVENTORY); @@ -138,12 +140,16 @@ public Class getBaseClass() { ItemStack stack = inventory.getStack(0); if (!playerStack.isEmpty()) { if (stack.isEmpty()) { - inventory.setStack(0, new ItemStack(playerStack.getItem())); + var newStack = playerStack.copy(); + newStack.setCount(1); + inventory.setStack(0, newStack); playerStack.decrement(1); } else { - stack.increment(1); - playerStack.decrement(1); - inventory.saveNeeded(); + if (ItemStack.canCombine(stack, playerStack)) { + stack.increment(1); + playerStack.decrement(1); + inventory.saveNeeded(); + } } } player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 235355fc60..39f20dbc1e 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -2,28 +2,23 @@ import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; -import net.minecraft.nbt.NbtCompound;; -import net.minecraft.network.Packet; -import net.minecraft.network.listener.ClientPlayPacketListener; -import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.SimpleComponentContainer; -public class TestBlockEntity extends BlockEntity implements ComponentProvider { +public class TestBlockEntity extends BlockEntity { public static final ComponentIdentifier TEST_BE_INT = IntegerComponent.create(new Identifier("quilt_component_test", "test_be_int")); private final ComponentContainer container = - SimpleComponentContainer.create(this::markDirty, TEST_BE_INT); + SimpleComponentContainer.create(this::markDirty, TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY); public TestBlockEntity(BlockPos blockPos, BlockState blockState) { super(ComponentTestMod.TEST_BE_TYPE, blockPos, blockState); @@ -53,15 +48,4 @@ public static void tick(World world, BlockPos ignoredPos Components.expose(TEST_BE_INT, blockEntity).ifPresent(IntegerComponent::increment); } - - @Override - public NbtCompound toInitialChunkDataNbt() { - return this.toNbt(); - } - - @Nullable - @Override - public Packet toUpdatePacket() { - return BlockEntityUpdateS2CPacket.of(this); - } } From 737371b842dc95400f5054899d6915acb43fb814 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 23 Jun 2022 11:40:23 +0300 Subject: [PATCH 17/70] Added SimpleComponentContainer --- .../qsl/component/api/ComponentContainer.java | 2 -- .../impl/LazifiedComponentContainer.java | 20 ++++++++++++------- .../impl/SimpleComponentContainer.java | 13 +++--------- .../resources/quilt_component.accesswidener | 2 +- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index fe4cf0d0ad..c9e118dfcd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -20,6 +20,4 @@ public interface ComponentContainer { void readNbt(NbtCompound providerRootNbt); void setSaveOperation(@NotNull Runnable runnable); - - Map> getNbtComponents(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java index eb3a40a3ce..650d37bc95 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java @@ -40,6 +40,7 @@ public static Optional create(T obj) { return map; } + @Override public Optional expose(Identifier id) { return Optional.ofNullable(this.components.get(id)) .map(componentLazy -> { @@ -53,24 +54,27 @@ public Optional expose(Identifier id) { }); } + @Override public Map exposeAll() { return this.components.entrySet().stream() .filter(entry -> !entry.getValue().isEmpty()) .collect(HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue().get()), HashMap::putAll); } - public Map> getNbtComponents() { - return this.nbtComponents.stream() - .map(id -> new Pair<>(id, this.components.get(id))) - .filter(pair -> Objects.nonNull(pair.getRight())) - .filter(pair -> pair.getRight().isEmpty()) - .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight().get()), HashMap::putAll); - } +// public Map> getNbtComponents() { +// return this.nbtComponents.stream() +// .map(id -> new Pair<>(id, this.components.get(id))) +// .filter(pair -> Objects.nonNull(pair.getRight())) +// .filter(pair -> pair.getRight().isEmpty()) +// .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight().get()), HashMap::putAll); +// } + @Override public void setSaveOperation(@NotNull Runnable runnable) { this.saveOperation = runnable; } + @Override public void writeNbt(@NotNull NbtCompound providerRootNbt) { var rootQslNbt = new NbtCompound(); this.nbtComponents.forEach(id -> this.components.get(id).ifPresent(component -> @@ -82,6 +86,7 @@ public void writeNbt(@NotNull NbtCompound providerRootNbt) { } } + @Override public void readNbt(@NotNull NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); @@ -95,6 +100,7 @@ public void readNbt(@NotNull NbtCompound providerRootNbt) { })); } + @Override public void moveComponents(ComponentContainer other) { if (other instanceof LazifiedComponentContainer otherContainer) { otherContainer.components.forEach((id, componentLazy) -> { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java index ef77436624..b45b0d4f4b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java @@ -2,7 +2,6 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; -import net.minecraft.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; @@ -18,7 +17,7 @@ public class SimpleComponentContainer implements ComponentContainer { private final Map components; private final List nbtComponents; - public static @NotNull SimpleComponentContainer create(@Nullable Runnable saveOperation, ComponentIdentifier... ids) { + public static @NotNull SimpleComponentContainer create(Runnable saveOperation, ComponentIdentifier... ids) { return new SimpleComponentContainer(saveOperation, Stream.of(ids).map(ComponentIdentifier::id)); } @@ -51,6 +50,7 @@ public Map exposeAll() { @Override public void moveComponents(ComponentContainer other) { + throw new IllegalStateException("Cannot move components into a SimpleComponentContainer"); } @Override @@ -78,13 +78,6 @@ public void readNbt(NbtCompound providerRootNbt) { @Override public void setSaveOperation(@NotNull Runnable runnable) { - - } - - @Override - public Map> getNbtComponents() { - return this.nbtComponents.stream() - .map(id -> new Pair<>(id, this.components.get(id))) - .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight()), HashMap::putAll); + throw new IllegalStateException("Cannot change the save operation of a SimpleComponentContainer since it needs to be passed into the constructor"); } } diff --git a/library/data/component/src/main/resources/quilt_component.accesswidener b/library/data/component/src/main/resources/quilt_component.accesswidener index b689638b64..2c01e93157 100644 --- a/library/data/component/src/main/resources/quilt_component.accesswidener +++ b/library/data/component/src/main/resources/quilt_component.accesswidener @@ -1,3 +1,3 @@ accessWidener v2 named - +# TODO: Remove this once the Block Entity API is merged. extendable class net/minecraft/block/entity/BlockEntityType$BlockEntityFactory From b0bf069542f28e8c4f54e93394770543e0cdbc8e Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 23 Jun 2022 13:36:45 +0300 Subject: [PATCH 18/70] Turned ComponentProvider into an injected interface. --- library/data/component/build.gradle | 17 ++++ .../qsl/component/api/ComponentProvider.java | 18 ++++ .../quiltmc/qsl/component/api/Components.java | 2 +- .../impl/LazifiedComponentContainer.java | 35 ++++---- .../impl/defaults/DefaultFloatComponent.java | 1 + .../defaults/DefaultIntegerComponent.java | 4 + .../qsl/component/mixin/MixinBlockEntity.java | 20 ++--- .../qsl/component/mixin/MixinChunk.java | 9 +- .../component/mixin/MixinChunkSerializer.java | 5 +- .../qsl/component/mixin/MixinEntity.java | 9 +- .../component/mixin/MixinLevelProperties.java | 12 +-- .../qsl/component/mixin/MixinWorldChunk.java | 4 +- .../qsl/component/test/ComponentTestMod.java | 90 ++++++++++--------- .../quiltmc/qsl/component/test/TestBlock.java | 1 + .../qsl/component/test/TestBlockEntity.java | 48 +++++++++- 15 files changed, 172 insertions(+), 103 deletions(-) diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index 443481695b..b82b47f2c6 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -14,5 +14,22 @@ qslModule { testmodOnly("lifecycle_events") } } + accessWidener() + + injectedInterface("net/minecraft/class_2586") { + values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + } + + injectedInterface("net/minecraft/class_1297") { + values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + } + + injectedInterface("net/minecraft/class_2791") { + values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + } + + injectedInterface("net/minecraft/class_31") { + values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 12ed72672a..f8f47a48a9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -1,8 +1,26 @@ package org.quiltmc.qsl.component.api; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.Entity; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.level.LevelProperties; import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.base.api.util.InjectedInterface; +import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import java.util.Optional; + +@InjectedInterface({ + BlockEntity.class, + Entity.class, + Chunk.class, + LevelProperties.class +}) public interface ComponentProvider { @NotNull ComponentContainer getContainer(); + + default Optional expose(ComponentIdentifier id) { + return Components.expose(id, this); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 793c3a7bbb..55c0ce9c02 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -24,7 +24,7 @@ public static void injectInheritanceExcept(Class clazz, ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), component); } - public static Optional expose(ComponentIdentifier id, S obj) { + public static Optional expose(ComponentIdentifier id, S obj) { if (obj instanceof ComponentProvider provider) { return provider.getContainer().expose(id.id()) .map(id::cast) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java index 650d37bc95..ba74d1e9ad 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java @@ -2,7 +2,6 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; -import net.minecraft.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; @@ -17,13 +16,13 @@ public class LazifiedComponentContainer implements ComponentContainer { private final Map> components; - private final List nbtComponents; + private final Set nbtComponents; @Nullable private Runnable saveOperation = null; private LazifiedComponentContainer(ComponentProvider provider) { this.components = createComponents(provider); - this.nbtComponents = new ArrayList<>(components.size()); + this.nbtComponents = new HashSet<>(components.size()); } public static Optional create(T obj) { @@ -61,13 +60,15 @@ public Map exposeAll() { .collect(HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue().get()), HashMap::putAll); } -// public Map> getNbtComponents() { -// return this.nbtComponents.stream() -// .map(id -> new Pair<>(id, this.components.get(id))) -// .filter(pair -> Objects.nonNull(pair.getRight())) -// .filter(pair -> pair.getRight().isEmpty()) -// .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight().get()), HashMap::putAll); -// } + /* + public Map> getNbtComponents() { + return this.nbtComponents.stream() + .map(id -> new Pair<>(id, this.components.get(id))) + .filter(pair -> Objects.nonNull(pair.getRight())) + .filter(pair -> pair.getRight().isEmpty()) + .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight().get()), HashMap::putAll); + } + */ @Override public void setSaveOperation(@NotNull Runnable runnable) { @@ -103,16 +104,14 @@ public void readNbt(@NotNull NbtCompound providerRootNbt) { @Override public void moveComponents(ComponentContainer other) { if (other instanceof LazifiedComponentContainer otherContainer) { - otherContainer.components.forEach((id, componentLazy) -> { - if (!componentLazy.isEmpty()) { - this.components.put(id, componentLazy); + otherContainer.components.forEach((id, componentLazy) -> componentLazy.ifPresent(component -> { + this.components.put(id, componentLazy); // Directly overriding our value. - if (componentLazy.get() instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(id); - nbtComponent.setSaveOperation(this.saveOperation); - } + if (component instanceof NbtComponent nbtComponent) { + this.nbtComponents.add(id); + nbtComponent.setSaveOperation(this.saveOperation); } - }); + })); otherContainer.components.clear(); otherContainer.nbtComponents.clear(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java index 1f2b46480d..439bb2ee5d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java @@ -24,6 +24,7 @@ public float get() { @Override public void set(float value) { this.value = value; + this.saveNeeded(); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java index 5744232e8a..78ff711e24 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java @@ -27,18 +27,22 @@ public int get() { @Override public void set(int value) { this.value = value; + this.saveNeeded(); } @Override public void increment() { this.value++; + this.saveNeeded(); } @Override public void decrement() { this.value--; + this.saveNeeded(); } + // TODO: Fix hashing and equals @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 66236190be..2d2386bfc1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -9,8 +9,6 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -18,18 +16,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) @Mixin(BlockEntity.class) -public abstract class MixinBlockEntity { +public abstract class MixinBlockEntity implements ComponentProvider { private ComponentContainer qsl$container; - @Inject( - method = "m_qgnqsprj", // The lambda used in second map operation. - at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V") - ) - private static void onReadNbt(NbtCompound nbt, String string, BlockEntity blockEntity, CallbackInfoReturnable cir) { - ((ComponentProvider) blockEntity).getContainer().readNbt(nbt); + @Inject(method = "readNbt", at = @At("TAIL")) + private void onReadNbt(NbtCompound nbt, CallbackInfo ci) { + this.qsl$container.readNbt(nbt); } @Shadow @@ -41,13 +35,13 @@ private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, Block this.qsl$container.setSaveOperation(this::markDirty); } - @Inject(method = "toNbt", at = @At("RETURN")) + @Inject(method = "toNbt", at = @At("TAIL")) private void onWriteNbt(CallbackInfoReturnable cir) { this.qsl$container.writeNbt(cir.getReturnValue()); } - @NotNull - public ComponentContainer comp$getContainer() { + @Override + public @NotNull ComponentContainer getContainer() { return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 64a7db3321..523b5da387 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -11,17 +11,14 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) @Mixin(Chunk.class) -public abstract class MixinChunk { +public abstract class MixinChunk implements ComponentProvider { private ComponentContainer qsl$container; @@ -34,8 +31,8 @@ private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView this.qsl$container.setSaveOperation(() -> this.setNeedsSaving(true)); } - @NotNull - public ComponentContainer comp$getContainer() { + @Override + public @NotNull ComponentContainer getContainer() { return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java index 1ae2568b37..bd261247c2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java @@ -8,7 +8,6 @@ import net.minecraft.world.chunk.ProtoChunk; import net.minecraft.world.chunk.ReadOnlyChunk; import net.minecraft.world.poi.PointOfInterestStorage; -import org.quiltmc.qsl.component.api.ComponentProvider; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -20,14 +19,14 @@ public class MixinChunkSerializer { private static void deserializeComponents(ServerWorld world, PointOfInterestStorage poiStorage, ChunkPos pos, NbtCompound nbt, CallbackInfoReturnable cir) { var ret = cir.getReturnValue(); var target = ret instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : ret; - ((ComponentProvider) target).getContainer().readNbt(nbt); + target.getContainer().readNbt(nbt); cir.setReturnValue(ret); } @Inject(method = "serialize", at = @At("RETURN"), cancellable = true) private static void serializeComponents(ServerWorld world, Chunk chunk, CallbackInfoReturnable cir) { var ret = cir.getReturnValue(); - ((ComponentProvider) chunk).getContainer().writeNbt(ret); + chunk.getContainer().writeNbt(ret); cir.setReturnValue(ret); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index c3aecb47e0..ee1c87b7e9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -8,17 +8,14 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) @Mixin(Entity.class) -public abstract class MixinEntity { +public abstract class MixinEntity implements ComponentProvider { private ComponentContainer qsl$container; @@ -37,8 +34,8 @@ private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { this.qsl$container.readNbt(nbt); } - @NotNull - public ComponentContainer comp$getContainer() { + @Override + public @NotNull ComponentContainer getContainer() { return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index f25251d222..ca7c0bc2d5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -20,8 +20,6 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -31,16 +29,14 @@ import java.util.Set; import java.util.UUID; -@Implements(@Interface(iface = ComponentProvider.class, prefix = "comp$")) @Mixin(LevelProperties.class) -public abstract class MixinLevelProperties implements ServerWorldProperties, SaveProperties { +public abstract class MixinLevelProperties implements ServerWorldProperties, SaveProperties, ComponentProvider { private ComponentContainer qsl$container; @Inject(method = "readProperties", at = @At("RETURN")) private static void readComponentData(Dynamic dynamic, DataFixer dataFixer, int dataVersion, @Nullable NbtCompound playerData, LevelInfo levelInfo, SaveVersionInfo saveVersionInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfoReturnable cir) { - LevelProperties retProperties = cir.getReturnValue(); - ((ComponentProvider) retProperties).getContainer().readNbt((NbtCompound) dynamic.getValue()); + cir.getReturnValue().getContainer().readNbt((NbtCompound) dynamic.getValue()); } @Inject(method = "(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/NbtCompound;ZIIIFJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lcom/mojang/serialization/Lifecycle;)V", at = @At("TAIL")) @@ -53,8 +49,8 @@ private void writeComponentData(DynamicRegistryManager registryManager, NbtCompo this.qsl$container.writeNbt(levelNbt); } - @NotNull - public ComponentContainer comp$getContainer() { + @Override + public @NotNull ComponentContainer getContainer() { return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java index 9b0b966ffc..eaf88b76cf 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -8,13 +8,11 @@ import net.minecraft.world.chunk.*; import net.minecraft.world.gen.chunk.BlendingData; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.ComponentProvider; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - @Mixin(WorldChunk.class) public abstract class MixinWorldChunk extends Chunk { public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, @Nullable ChunkSection[] chunkSections, @Nullable BlendingData blendingData) { @@ -24,6 +22,6 @@ public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitVi @Inject(method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/ProtoChunk;Lnet/minecraft/world/chunk/WorldChunk$PostLoadProcessor;)V", at = @At("TAIL")) private void copyComponentData(ServerWorld serverWorld, ProtoChunk protoChunk, WorldChunk.PostLoadProcessor postLoadProcessor, CallbackInfo ci) { var target = protoChunk instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : protoChunk; - ((ComponentProvider) this).getContainer().moveComponents(((ComponentProvider) target).getContainer()); + this.getContainer().moveComponents(target.getContainer()); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 4b0944ef0a..5043063ada 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -21,7 +21,6 @@ import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.ChestBlockEntity; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; @@ -34,11 +33,9 @@ import net.minecraft.util.TypeFilter; import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.registry.Registry; -import net.minecraft.world.SaveProperties; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.explosion.Explosion; import net.minecraft.world.level.LevelProperties; -import org.jetbrains.annotations.Nullable; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.api.Components; @@ -48,6 +45,8 @@ import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; +import java.util.Objects; + public class ComponentTestMod implements ModInitializer { public static final String MODID = "quilt_component_test"; @@ -61,7 +60,7 @@ public class ComponentTestMod implements ModInitializer { public static final ComponentIdentifier HOSTILE_EXPLODE_TIME = IntegerComponent.create(new Identifier(MODID, "hostile_explode_time")); public static final ComponentIdentifier CHEST_NUMBER = - IntegerComponent.create(new Identifier(MODID, "chest_number")); + IntegerComponent.create(200, new Identifier(MODID, "chest_number")); public static final ComponentIdentifier CHUNK_INVENTORY = InventoryComponent.ofSize(1, new Identifier(MODID, "chunk_inventory") ); @@ -70,8 +69,6 @@ public class ComponentTestMod implements ModInitializer { // Attention do NOT place this block in any world because registry sync issues will make the game hung upon rejoining. public static final Block TEST_BLOCK = new TestBlock(AbstractBlock.Settings.copy(Blocks.STONE)); - public static final BlockEntityType TEST_BE_TYPE = - BlockEntityType.Builder.create(TestBlockEntity::new, TEST_BLOCK, Blocks.NOTE_BLOCK).build(null); @Override public void onInitialize(ModContainer mod) { @@ -89,7 +86,7 @@ public void onInitialize(ModContainer mod) { // Testing Code ServerWorldTickEvents.START.register((server, world) -> { world.getEntitiesByType(TypeFilter.instanceOf(CowEntity.class), cowEntity -> true).forEach(entity -> - Components.expose(COW_INVENTORY, entity).ifPresent(inventoryComponent -> { + entity.expose(COW_INVENTORY).ifPresent(inventoryComponent -> { if (inventoryComponent.isEmpty()) { world.createExplosion( entity, @@ -102,40 +99,45 @@ public void onInitialize(ModContainer mod) { } })); - world.getEntitiesByType(new TypeFilter() { - @Nullable - @Override - public CreeperEntity downcast(Entity obj) { - return obj.getType() == EntityType.CREEPER ? (CreeperEntity) obj : null; - } + world.getEntitiesByType(EntityType.CREEPER, creeper -> true) + .forEach(creeper -> Components.expose(CREEPER_EXPLODE_TIME, creeper).ifPresent(explodeTime -> { + if (explodeTime.get() > 0) { + explodeTime.decrement(); + } else { + creeper.ignite(); + } + })); - @Override - public Class getBaseClass() { - return CreeperEntity.class; - } - }, creeper -> true).forEach(creeper -> Components.expose(CREEPER_EXPLODE_TIME, creeper).ifPresent(explodeTime -> { - if (explodeTime.get() > 0) { - explodeTime.decrement(); - } else { - creeper.ignite(); - } - })); - - world.getEntitiesByType(TypeFilter.instanceOf(HostileEntity.class), hostile -> true).forEach(hostile -> Components.expose(HOSTILE_EXPLODE_TIME, hostile).ifPresent(explodeTime -> { - if (explodeTime.get() <= 200) { - explodeTime.increment(); - } else { - hostile.getWorld().createExplosion(null, hostile.getX(), hostile.getY(), hostile.getZ(), 1.0f, Explosion.DestructionType.NONE); - hostile.discard(); - } - })); + world.getEntitiesByType(TypeFilter.instanceOf(HostileEntity.class), hostile -> true) + .forEach(hostile -> hostile.expose(HOSTILE_EXPLODE_TIME).ifPresent(explodeTime -> { + if (explodeTime.get() <= 200) { + explodeTime.increment(); + } else { + hostile.getWorld().createExplosion( + null, + hostile.getX(), hostile.getY(), hostile.getZ(), + 1.0f, Explosion.DestructionType.NONE + ); + hostile.discard(); + } + })); ServerPlayerEntity player = world.getRandomAlivePlayer(); if (player == null) { return; } Chunk chunk = world.getChunk(player.getBlockPos()); - Components.expose(CHUNK_INVENTORY, chunk).ifPresent(inventory -> { + chunk.getBlockEntityPositions().stream() + .map(chunk::getBlockEntity) + .filter(Objects::nonNull) + .forEach(blockEntity -> blockEntity.expose(CHEST_NUMBER).ifPresent(integerComponent -> { + integerComponent.decrement(); + + if (integerComponent.get() <= 0) { + world.setBlockState(blockEntity.getPos(), Blocks.DIAMOND_BLOCK.getDefaultState()); + } + })); + chunk.expose(CHUNK_INVENTORY).ifPresent(inventory -> { ItemStack playerStack = player.getInventory().getStack(9); ItemStack stack = inventory.getStack(0); if (!playerStack.isEmpty()) { @@ -155,14 +157,18 @@ public Class getBaseClass() { player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); }); - SaveProperties props = server.getSaveProperties(); - Components.expose(SAVE_FLOAT, props) - .ifPresent(floatComponent -> { - floatComponent.set(floatComponent.get() + 0.5f); - if (world.getTime() % 20 * 5 == 0) { - player.sendMessage(Text.literal("%.3f".formatted(floatComponent.get())), false); - } - }); + LevelProperties props = ((LevelProperties) server.getSaveProperties()); + props.expose(SAVE_FLOAT).ifPresent(floatComponent -> { + floatComponent.set(floatComponent.get() + 0.5f); + if (world.getTime() % 100 == 0) { + player.sendMessage(Text.literal("%.3f".formatted(floatComponent.get())), false); + } + }); }); } + + public static final BlockEntityType TEST_BE_TYPE = + BlockEntityType.Builder.create(TestBlockEntity::new, TEST_BLOCK, Blocks.NOTE_BLOCK).build(null); + + } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index e5b8bd327e..fff1cd0dd8 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -25,6 +25,7 @@ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { return ComponentTestMod.TEST_BE_TYPE.instantiate(pos, state); } + @SuppressWarnings("deprecation") @Override public BlockRenderType getRenderType(BlockState state) { return BlockRenderType.MODEL; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 39f20dbc1e..a0ca7d6a8d 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -1,18 +1,28 @@ package org.quiltmc.qsl.component.test; import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntity; import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.Packet; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.SimpleComponentContainer; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + public class TestBlockEntity extends BlockEntity { public static final ComponentIdentifier TEST_BE_INT = IntegerComponent.create(new Identifier("quilt_component_test", "test_be_int")); @@ -41,11 +51,43 @@ public void readNbt(NbtCompound nbt) { this.container.readNbt(nbt); } - public static void tick(World world, BlockPos ignoredPos, BlockState ignoredState, T blockEntity) { + @Override + public NbtCompound toInitialChunkDataNbt() { + return this.toNbt(); + } + + @Nullable + @Override + public Packet toUpdatePacket() { + return BlockEntityUpdateS2CPacket.of(this); + } + + public static void tick(World world, BlockPos pos, BlockState ignoredState, T blockEntity) { if (world.isClient) { return; } - Components.expose(TEST_BE_INT, blockEntity).ifPresent(IntegerComponent::increment); + blockEntity.expose(TEST_BE_INT).ifPresent(integerComponent -> { + if (integerComponent.get() % 20 == 0) { + HashSet set = new HashSet<>(List.of(pos)); + expand(pos, pos, world, set); + } + + integerComponent.increment(); + }); + } + + private static void expand(BlockPos initialPos, BlockPos pos, World world, Set visited) { + Arrays.stream(Direction.values()) + .map(pos::offset) + .filter(visited::add) + .forEach(offsetPos -> { + BlockState stateAt = world.getBlockState(offsetPos); + if (stateAt.isAir()) { + world.setBlockState(offsetPos, Blocks.DIAMOND_BLOCK.getDefaultState()); + } else if (stateAt.isOf(Blocks.DIAMOND_BLOCK) && initialPos.isWithinDistance(offsetPos, 5)) { + expand(initialPos, offsetPos, world, visited); + } + }); } } From 789c339cd407dc3b51a3e74276e0617f43728ea9 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 23 Jun 2022 13:52:07 +0300 Subject: [PATCH 19/70] Reformat. --- .../qsl/component/api/ComponentContainer.java | 1 - .../impl/LazifiedComponentContainer.java | 2 +- .../impl/SimpleComponentContainer.java | 10 ++-- .../qsl/component/mixin/MixinBlockEntity.java | 2 +- .../qsl/component/mixin/MixinChunk.java | 2 +- .../component/mixin/MixinLevelProperties.java | 2 +- .../quiltmc/qsl/component/test/TestBlock.java | 5 +- .../qsl/component/test/TestBlockEntity.java | 56 +++++++++---------- .../src/testmod/resources/quilt.mod.json | 44 +++++++-------- 9 files changed, 63 insertions(+), 61 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index c9e118dfcd..62de535569 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -3,7 +3,6 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.components.NbtComponent; import java.util.Map; import java.util.Optional; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java index ba74d1e9ad..01d6c71c11 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java @@ -20,7 +20,7 @@ public class LazifiedComponentContainer implements ComponentContainer { @Nullable private Runnable saveOperation = null; - private LazifiedComponentContainer(ComponentProvider provider) { + protected LazifiedComponentContainer(ComponentProvider provider) { this.components = createComponents(provider); this.nbtComponents = new HashSet<>(components.size()); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java index b45b0d4f4b..9d8f8c3321 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java @@ -17,11 +17,7 @@ public class SimpleComponentContainer implements ComponentContainer { private final Map components; private final List nbtComponents; - public static @NotNull SimpleComponentContainer create(Runnable saveOperation, ComponentIdentifier... ids) { - return new SimpleComponentContainer(saveOperation, Stream.of(ids).map(ComponentIdentifier::id)); - } - - private SimpleComponentContainer(@Nullable Runnable saveOperation, Stream componentIds) { + protected SimpleComponentContainer(@Nullable Runnable saveOperation, Stream componentIds) { this.components = new HashMap<>(); this.nbtComponents = new ArrayList<>(); @@ -38,6 +34,10 @@ private SimpleComponentContainer(@Nullable Runnable saveOperation, Stream... ids) { + return new SimpleComponentContainer(saveOperation, Stream.of(ids).map(ComponentIdentifier::id)); + } + @Override public Optional expose(Identifier id) { return Optional.ofNullable(this.components.get(id)); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 2d2386bfc1..81920b4e10 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -7,8 +7,8 @@ import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 523b5da387..bd68d048d5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -9,8 +9,8 @@ import net.minecraft.world.gen.chunk.BlendingData; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index ca7c0bc2d5..2082fc9e1d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -18,8 +18,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index fff1cd0dd8..bbe4c9bd07 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -1,6 +1,9 @@ package org.quiltmc.qsl.component.test; -import net.minecraft.block.*; +import net.minecraft.block.Block; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityTicker; import net.minecraft.block.entity.BlockEntityType; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index a0ca7d6a8d..cd3545131e 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -34,34 +34,6 @@ public TestBlockEntity(BlockPos blockPos, BlockState blockState) { super(ComponentTestMod.TEST_BE_TYPE, blockPos, blockState); } - @Override - public @NotNull ComponentContainer getContainer() { - return this.container; - } - - @Override - protected void writeNbt(NbtCompound nbt) { - super.writeNbt(nbt); - this.container.writeNbt(nbt); - } - - @Override - public void readNbt(NbtCompound nbt) { - super.readNbt(nbt); - this.container.readNbt(nbt); - } - - @Override - public NbtCompound toInitialChunkDataNbt() { - return this.toNbt(); - } - - @Nullable - @Override - public Packet toUpdatePacket() { - return BlockEntityUpdateS2CPacket.of(this); - } - public static void tick(World world, BlockPos pos, BlockState ignoredState, T blockEntity) { if (world.isClient) { return; @@ -90,4 +62,32 @@ private static void expand(BlockPos initialPos, BlockPos pos, World world, Set toUpdatePacket() { + return BlockEntityUpdateS2CPacket.of(this); + } } diff --git a/library/data/component/src/testmod/resources/quilt.mod.json b/library/data/component/src/testmod/resources/quilt.mod.json index 57d5b84106..24b49c6738 100644 --- a/library/data/component/src/testmod/resources/quilt.mod.json +++ b/library/data/component/src/testmod/resources/quilt.mod.json @@ -1,24 +1,24 @@ { - "schema_version": 1, - "quilt_loader": { - "group": "org.quiltmc.qsl.data", - "id": "quilt_component_test", - "version": "1.0.0", - "metadata": { - "name": "Quilt Component API Test mod.", - "license": "Apache-2.0" - }, - "intermediate_mappings": "net.fabricmc:intermediary", - "load_type": "always", - "entrypoints": { - "init": [ - "org.quiltmc.qsl.component.test.ComponentTestMod" - ] - }, - "depends": [ - "quilt_loader", - "quilt_component", - "quilt_lifecycle_events" - ] - } + "schema_version": 1, + "quilt_loader": { + "group": "org.quiltmc.qsl.data", + "id": "quilt_component_test", + "version": "1.0.0", + "metadata": { + "name": "Quilt Component API Test mod.", + "license": "Apache-2.0" + }, + "intermediate_mappings": "net.fabricmc:intermediary", + "load_type": "always", + "entrypoints": { + "init": [ + "org.quiltmc.qsl.component.test.ComponentTestMod" + ] + }, + "depends": [ + "quilt_loader", + "quilt_component", + "quilt_lifecycle_events" + ] + } } From e4877675c78ad93fbb2604352f1d2355e784717b Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 23 Jun 2022 23:01:23 +0300 Subject: [PATCH 20/70] Run applyLicenses --- .../org/quiltmc/qsl/component/api/Component.java | 16 ++++++++++++++++ .../qsl/component/api/ComponentContainer.java | 16 ++++++++++++++++ .../api/ComponentInjectionPredicate.java | 16 ++++++++++++++++ .../qsl/component/api/ComponentProvider.java | 16 ++++++++++++++++ .../quiltmc/qsl/component/api/Components.java | 16 ++++++++++++++++ .../component/api/components/FloatComponent.java | 16 ++++++++++++++++ .../api/components/IntegerComponent.java | 16 ++++++++++++++++ .../api/components/InventoryComponent.java | 16 ++++++++++++++++ .../component/api/components/NbtComponent.java | 16 ++++++++++++++++ .../api/identifier/ComponentIdentifier.java | 16 ++++++++++++++++ .../qsl/component/impl/ComponentCache.java | 16 ++++++++++++++++ .../qsl/component/impl/ComponentsImpl.java | 16 ++++++++++++++++ .../impl/LazifiedComponentContainer.java | 16 ++++++++++++++++ .../component/impl/SimpleComponentContainer.java | 16 ++++++++++++++++ .../impl/defaults/DefaultFloatComponent.java | 16 ++++++++++++++++ .../impl/defaults/DefaultIntegerComponent.java | 16 ++++++++++++++++ .../impl/defaults/DefaultInventoryComponent.java | 16 ++++++++++++++++ .../impl/predicates/ClassInjectionPredicate.java | 16 ++++++++++++++++ .../FilteredInheritedInjectionPredicate.java | 16 ++++++++++++++++ .../predicates/InheritedInjectionPredicate.java | 16 ++++++++++++++++ .../quiltmc/qsl/component/impl/util/Lazy.java | 16 ++++++++++++++++ .../qsl/component/impl/util/StringConstants.java | 16 ++++++++++++++++ .../qsl/component/mixin/MixinBlockEntity.java | 16 ++++++++++++++++ .../quiltmc/qsl/component/mixin/MixinChunk.java | 16 ++++++++++++++++ .../component/mixin/MixinChunkSerializer.java | 16 ++++++++++++++++ .../quiltmc/qsl/component/mixin/MixinEntity.java | 16 ++++++++++++++++ .../component/mixin/MixinLevelProperties.java | 16 ++++++++++++++++ .../qsl/component/mixin/MixinWorldChunk.java | 16 ++++++++++++++++ .../qsl/component/test/ComponentTestMod.java | 5 ++--- .../quiltmc/qsl/component/test/TestBlock.java | 16 ++++++++++++++++ .../qsl/component/test/TestBlockEntity.java | 16 ++++++++++++++++ 31 files changed, 482 insertions(+), 3 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java index 5a27d8c281..2960a66a1f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api; public interface Component { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index 62de535569..3eb5e6556f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api; import net.minecraft.nbt.NbtCompound; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java index f661a63dd3..79f443d3bc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api; public interface ComponentInjectionPredicate { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index f8f47a48a9..933b8cd8cf 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api; import net.minecraft.block.entity.BlockEntity; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 55c0ce9c02..5fdff42159 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api; import com.google.common.collect.ImmutableMap; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java index efdc60701e..9a3f58b913 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.components; import net.minecraft.nbt.NbtElement; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java index 45e1b453fd..cea8b5e34d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.components; import net.minecraft.nbt.NbtElement; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index c76a039517..d115e814bb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.components; import net.minecraft.entity.player.PlayerEntity; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index fed5fbb2d0..ed7229fa37 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.components; import net.minecraft.nbt.*; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java index 1da706daa3..e1a0f4a679 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.identifier; import net.minecraft.util.Identifier; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java index 8b5069e703..32a87d6669 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl; import net.minecraft.util.Identifier; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 2aa77a9a5c..107c6abc03 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl; import net.minecraft.util.Identifier; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java index 01d6c71c11..71a8027aef 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl; import net.minecraft.nbt.NbtCompound; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java index 9d8f8c3321..930cfa99c7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl; import net.minecraft.nbt.NbtCompound; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java index 439bb2ee5d..30466bb3b5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.defaults; import org.jetbrains.annotations.Nullable; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java index 78ff711e24..34d092a448 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.defaults; import org.jetbrains.annotations.Nullable; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java index 123d821a21..f3162fef0b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.defaults; import net.minecraft.item.ItemStack; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java index 16386d8cba..667c505b34 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.predicates; import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java index f7848b14d7..c772f04027 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.predicates; import java.util.ArrayList; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java index d918e8a543..1dd218ca42 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.predicates; import org.quiltmc.qsl.component.api.ComponentProvider; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java index cf019aac58..1c77423d54 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.util; import org.jetbrains.annotations.NotNull; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java index 62ffec9044..3a5e1e17f4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.util; public final class StringConstants { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 81920b4e10..1957d6bb08 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import net.minecraft.block.BlockState; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index bd68d048d5..513f62777f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import net.minecraft.util.math.ChunkPos; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java index bd261247c2..6aa894c1e1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import net.minecraft.nbt.NbtCompound; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index ee1c87b7e9..4ba52c3d94 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import net.minecraft.entity.Entity; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index 2082fc9e1d..bdedeff81b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import com.mojang.datafixers.DataFixer; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java index eaf88b76cf..5a341812b3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import net.minecraft.server.world.ServerWorld; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 5043063ada..790a94a0af 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -32,7 +32,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.TypeFilter; import net.minecraft.util.collection.DefaultedList; -import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.*; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.explosion.Explosion; import net.minecraft.world.level.LevelProperties; @@ -53,7 +53,7 @@ public class ComponentTestMod implements ModInitializer { // Registration Code public static final ComponentIdentifier COW_INVENTORY = InventoryComponent.of( () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64)), - new Identifier("quilt_component_test", "cow_inventory") + new Identifier(MODID, "cow_inventory") ); public static final ComponentIdentifier CREEPER_EXPLODE_TIME = IntegerComponent.create(200, new Identifier(MODID, "creeper_explode_time")); @@ -170,5 +170,4 @@ public void onInitialize(ModContainer mod) { public static final BlockEntityType TEST_BE_TYPE = BlockEntityType.Builder.create(TestBlockEntity::new, TEST_BLOCK, Blocks.NOTE_BLOCK).build(null); - } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index bbe4c9bd07..8db0b48025 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.test; import net.minecraft.block.Block; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index cd3545131e..4f2e05fc6f 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.test; import net.minecraft.block.BlockState; From 32851c4e90e7873367fb4c727ac75328dac8f97a Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 24 Jun 2022 12:04:48 +0300 Subject: [PATCH 21/70] Added Component.Factory and restructured code. --- .../org/quiltmc/qsl/component/api/Component.java | 8 ++++++++ .../qsl/component/api/ComponentProvider.java | 2 +- .../quiltmc/qsl/component/api/Components.java | 8 ++++---- .../ComponentIdentifier.java | 2 +- .../component/api/components/FloatComponent.java | 3 +-- .../api/components/IntegerComponent.java | 8 ++------ .../api/components/InventoryComponent.java | 9 +++------ .../defaults/DefaultFloatComponent.java | 2 +- .../defaults/DefaultIntegerComponent.java | 2 +- .../defaults/DefaultInventoryComponent.java | 2 +- .../container}/LazifiedComponentContainer.java | 15 +++------------ .../container}/SimpleComponentContainer.java | 7 ++++--- .../predicates/ClassInjectionPredicate.java | 2 +- .../FilteredInheritedInjectionPredicate.java | 5 ++--- .../predicates/InheritedInjectionPredicate.java | 2 +- .../qsl/component/impl/ComponentCache.java | 7 +++---- .../qsl/component/impl/ComponentsImpl.java | 16 +++++++--------- .../qsl/component/mixin/MixinBlockEntity.java | 2 +- .../quiltmc/qsl/component/mixin/MixinChunk.java | 2 +- .../quiltmc/qsl/component/mixin/MixinEntity.java | 2 +- .../component/mixin/MixinLevelProperties.java | 2 +- .../qsl/component/test/ComponentTestMod.java | 2 +- .../qsl/component/test/TestBlockEntity.java | 4 ++-- 23 files changed, 51 insertions(+), 63 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{identifier => components}/ComponentIdentifier.java (95%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api/components}/defaults/DefaultFloatComponent.java (95%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api/components}/defaults/DefaultIntegerComponent.java (96%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api/components}/defaults/DefaultInventoryComponent.java (96%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api/container}/LazifiedComponentContainer.java (88%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api/container}/SimpleComponentContainer.java (93%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api}/predicates/ClassInjectionPredicate.java (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api}/predicates/FilteredInheritedInjectionPredicate.java (88%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api}/predicates/InheritedInjectionPredicate.java (96%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java index 2960a66a1f..207c21d371 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java @@ -16,5 +16,13 @@ package org.quiltmc.qsl.component.api; +import org.jetbrains.annotations.NotNull; + public interface Component { + + @FunctionalInterface + interface Factory { + @NotNull + T create(); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 933b8cd8cf..619bcb9863 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -22,7 +22,7 @@ import net.minecraft.world.level.LevelProperties; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.base.api.util.InjectedInterface; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.api.components.ComponentIdentifier; import java.util.Optional; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 5fdff42159..02445236bb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -18,11 +18,11 @@ import com.google.common.collect.ImmutableMap; import net.minecraft.util.Identifier; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.api.components.ComponentIdentifier; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.predicates.ClassInjectionPredicate; -import org.quiltmc.qsl.component.impl.predicates.FilteredInheritedInjectionPredicate; -import org.quiltmc.qsl.component.impl.predicates.InheritedInjectionPredicate; +import org.quiltmc.qsl.component.api.predicates.ClassInjectionPredicate; +import org.quiltmc.qsl.component.api.predicates.FilteredInheritedInjectionPredicate; +import org.quiltmc.qsl.component.api.predicates.InheritedInjectionPredicate; import java.util.Map; import java.util.Optional; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/ComponentIdentifier.java similarity index 95% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/ComponentIdentifier.java index e1a0f4a679..889394afc5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/identifier/ComponentIdentifier.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/ComponentIdentifier.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.identifier; +package org.quiltmc.qsl.component.api.components; import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.Component; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java index 9a3f58b913..ed82880355 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java @@ -20,9 +20,8 @@ import net.minecraft.nbt.NbtFloat; import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.defaults.DefaultFloatComponent; +import org.quiltmc.qsl.component.api.components.defaults.DefaultFloatComponent; public interface FloatComponent extends Component, NbtComponent { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java index cea8b5e34d..a0d34d725d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java @@ -19,16 +19,12 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtInt; import net.minecraft.util.Identifier; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.defaults.DefaultIntegerComponent; - -import java.util.function.Supplier; +import org.quiltmc.qsl.component.api.components.defaults.DefaultIntegerComponent; public interface IntegerComponent extends NbtComponent { static ComponentIdentifier create(int initialValue, Identifier id) { - Supplier supplier = () -> new DefaultIntegerComponent(initialValue); - return ComponentsImpl.register(id, supplier); + return ComponentsImpl.register(id, () -> new DefaultIntegerComponent(initialValue)); } static ComponentIdentifier create(Identifier id) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index d115e814bb..654d73457a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -24,21 +24,18 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.defaults.DefaultInventoryComponent; +import org.quiltmc.qsl.component.api.components.defaults.DefaultInventoryComponent; import java.util.function.Supplier; public interface InventoryComponent extends NbtComponent, Inventory { static ComponentIdentifier ofSize(int size, Identifier id) { - Supplier component = () -> new DefaultInventoryComponent(size); - return ComponentsImpl.register(id, component); + return ComponentsImpl.register(id, () -> new DefaultInventoryComponent(size)); } static ComponentIdentifier of(Supplier> items, Identifier id) { - Supplier component = () -> new DefaultInventoryComponent(items); - return ComponentsImpl.register(id, component); + return ComponentsImpl.register(id, () -> new DefaultInventoryComponent(items)); } DefaultedList getStacks(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultFloatComponent.java similarity index 95% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultFloatComponent.java index 30466bb3b5..ba84419442 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultFloatComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.defaults; +package org.quiltmc.qsl.component.api.components.defaults; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.FloatComponent; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java index 34d092a448..876ac1316f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.defaults; +package org.quiltmc.qsl.component.api.components.defaults; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.IntegerComponent; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultInventoryComponent.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultInventoryComponent.java index f3162fef0b..bbd0645e6c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/defaults/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultInventoryComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.defaults; +package org.quiltmc.qsl.component.api.components.defaults; import net.minecraft.item.ItemStack; import net.minecraft.util.collection.DefaultedList; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java similarity index 88% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java index 71a8027aef..8c15355d24 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl; +package org.quiltmc.qsl.component.api.container; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; @@ -24,6 +24,7 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.util.Lazy; import org.quiltmc.qsl.component.impl.util.StringConstants; @@ -51,7 +52,7 @@ public static Optional create(T obj) { public static @NotNull Map> createComponents(@NotNull ComponentProvider provider) { var map = new HashMap>(); - ComponentsImpl.get(provider).forEach((identifier, supplier) -> map.put(identifier, Lazy.of(supplier::get))); + ComponentsImpl.get(provider).forEach((identifier, factory) -> map.put(identifier, Lazy.of(factory::create))); return map; } @@ -76,16 +77,6 @@ public Map exposeAll() { .collect(HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue().get()), HashMap::putAll); } - /* - public Map> getNbtComponents() { - return this.nbtComponents.stream() - .map(id -> new Pair<>(id, this.components.get(id))) - .filter(pair -> Objects.nonNull(pair.getRight())) - .filter(pair -> pair.getRight().isEmpty()) - .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), (NbtComponent) pair.getRight().get()), HashMap::putAll); - } - */ - @Override public void setSaveOperation(@NotNull Runnable runnable) { this.saveOperation = runnable; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java similarity index 93% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java index 930cfa99c7..00bb58c7c7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl; +package org.quiltmc.qsl.component.api.container; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; @@ -23,7 +23,8 @@ import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.api.components.ComponentIdentifier; +import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.util.StringConstants; import java.util.*; @@ -38,7 +39,7 @@ protected SimpleComponentContainer(@Nullable Runnable saveOperation, Stream(); componentIds.forEach(id -> { - Component component = ComponentsImpl.getEntry(id).get(); + Component component = ComponentsImpl.getEntry(id).create(); this.components.put(id, component); if (component instanceof NbtComponent nbtComponent) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/ClassInjectionPredicate.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/ClassInjectionPredicate.java index 667c505b34..0f2193513f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/ClassInjectionPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.predicates; +package org.quiltmc.qsl.component.api.predicates; import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/FilteredInheritedInjectionPredicate.java similarity index 88% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/FilteredInheritedInjectionPredicate.java index c772f04027..c67fb4866f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/FilteredInheritedInjectionPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.predicates; +package org.quiltmc.qsl.component.api.predicates; import java.util.ArrayList; import java.util.Arrays; @@ -42,9 +42,8 @@ public int hashCode() { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof FilteredInheritedInjectionPredicate)) return false; + if (!(o instanceof FilteredInheritedInjectionPredicate that)) return false; if (!super.equals(o)) return false; - FilteredInheritedInjectionPredicate that = (FilteredInheritedInjectionPredicate) o; return exceptions.equals(that.exceptions); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/InheritedInjectionPredicate.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/InheritedInjectionPredicate.java index 1dd218ca42..19b3db66bf 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/InheritedInjectionPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.predicates; +package org.quiltmc.qsl.component.api.predicates; import org.quiltmc.qsl.component.api.ComponentProvider; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java index 32a87d6669..4b927faa92 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java @@ -23,13 +23,12 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; public class ComponentCache { private static ComponentCache INSTANCE; - private final Map, Map>> injectionCache = new HashMap<>(); + private final Map, Map>> injectionCache = new HashMap<>(); private ComponentCache() { @@ -43,7 +42,7 @@ public static ComponentCache getInstance() { return INSTANCE; } - public Optional>> getCache(Class clazz) { + public Optional>> getCache(Class clazz) { if (!this.injectionCache.containsKey(clazz)) { return Optional.empty(); } @@ -55,7 +54,7 @@ public void clear() { this.injectionCache.clear(); } - public void record(Class clazz, Map> components) { + public void record(Class clazz, Map> components) { if (this.injectionCache.put(clazz, Util.make(new HashMap<>(), map -> map.putAll(components))) != null) { // If there was a value there, it means we attempted an override, and so we throw. throw new IllegalStateException("Cannot register cache twice for class %s".formatted(clazz)); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 107c6abc03..56ece18296 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -21,21 +21,19 @@ import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.api.components.ComponentIdentifier; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.function.Supplier; public class ComponentsImpl { private static final Map> INJECTION_REGISTRY = new HashMap<>(); - private static final Map> REGISTRY = new HashMap<>(); // TODO: Look into using a Minecraft Registry for this. + private static final Map> REGISTRY = new HashMap<>(); // TODO: Look into using a Minecraft Registry for this. public static void inject(ComponentInjectionPredicate predicate, ComponentIdentifier id) { - Supplier supplier = REGISTRY.get(id.id()); - if (supplier == null) { + if (REGISTRY.get(id.id()) == null) { throw new IllegalArgumentException( "The target id %s does not match any registered component!".formatted(id.toString()) ); @@ -55,14 +53,14 @@ public static void inject(ComponentInjectionPredicate pred ComponentCache.getInstance().clear(); // Always clear the cache after an injection is registered. } - public static ComponentIdentifier register(Identifier id, Supplier component) { + public static ComponentIdentifier register(Identifier id, Component.Factory component) { REGISTRY.put(id, component); return new ComponentIdentifier<>(id); } - public static Map> get(ComponentProvider provider) { + public static Map> get(ComponentProvider provider) { return ComponentCache.getInstance().getCache(provider.getClass()).orElseGet(() -> { - Map> returnMap = INJECTION_REGISTRY.entrySet().stream() + Map> returnMap = INJECTION_REGISTRY.entrySet().stream() .filter(it -> it.getKey().canInject(provider)) .map(Map.Entry::getValue) .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, REGISTRY.get(id))), HashMap::putAll); @@ -73,7 +71,7 @@ public static Map> get(ComponentProvid }); } - public static Supplier getEntry(Identifier id) { + public static Component.Factory getEntry(Identifier id) { return REGISTRY.get(id); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 1957d6bb08..0b3c36c345 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; +import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 513f62777f..0f3f856cc3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; +import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 4ba52c3d94..c3bf69f2f5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; +import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index bdedeff81b..df6a040ddb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -35,7 +35,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.LazifiedComponentContainer; +import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 790a94a0af..29dcc5f94e 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -42,7 +42,7 @@ import org.quiltmc.qsl.component.api.components.FloatComponent; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.InventoryComponent; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; +import org.quiltmc.qsl.component.api.components.ComponentIdentifier; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; import java.util.Objects; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 4f2e05fc6f..f4a50f0635 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -31,8 +31,8 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.components.IntegerComponent; -import org.quiltmc.qsl.component.api.identifier.ComponentIdentifier; -import org.quiltmc.qsl.component.impl.SimpleComponentContainer; +import org.quiltmc.qsl.component.api.components.ComponentIdentifier; +import org.quiltmc.qsl.component.api.container.SimpleComponentContainer; import java.util.Arrays; import java.util.HashSet; From 35b62d16d3cceed3213a680b30dcefca86b095ab Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 24 Jun 2022 12:52:36 +0300 Subject: [PATCH 22/70] Switched to using vanilla registries to handle our registration process. --- .../qsl/component/api/ComponentProvider.java | 3 +- ...nentIdentifier.java => ComponentType.java} | 11 +++-- .../quiltmc/qsl/component/api/Components.java | 18 ++++++--- .../api/components/FloatComponent.java | 5 ++- .../api/components/IntegerComponent.java | 5 ++- .../api/components/InventoryComponent.java | 5 ++- .../defaults/DefaultIntegerComponent.java | 15 ------- .../container/SimpleComponentContainer.java | 6 +-- ...ache.java => ComponentInjectionCache.java} | 10 ++--- .../qsl/component/impl/ComponentsImpl.java | 40 ++++++++++++------- .../qsl/component/test/ComponentTestMod.java | 14 +++---- .../qsl/component/test/TestBlockEntity.java | 4 +- 12 files changed, 72 insertions(+), 64 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{components/ComponentIdentifier.java => ComponentType.java} (75%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/{ComponentCache.java => ComponentInjectionCache.java} (88%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 619bcb9863..9c82ae0dbe 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -22,7 +22,6 @@ import net.minecraft.world.level.LevelProperties; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.base.api.util.InjectedInterface; -import org.quiltmc.qsl.component.api.components.ComponentIdentifier; import java.util.Optional; @@ -36,7 +35,7 @@ public interface ComponentProvider { @NotNull ComponentContainer getContainer(); - default Optional expose(ComponentIdentifier id) { + default Optional expose(ComponentType id) { return Components.expose(id, this); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/ComponentIdentifier.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java similarity index 75% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/ComponentIdentifier.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 889394afc5..f52fcc97b8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/ComponentIdentifier.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components; +package org.quiltmc.qsl.component.api; import net.minecraft.util.Identifier; -import org.quiltmc.qsl.component.api.Component; +import org.jetbrains.annotations.NotNull; import java.util.Optional; -public record ComponentIdentifier(Identifier id) { +public record ComponentType(Identifier id, Component.Factory factory) implements Component.Factory { @SuppressWarnings("unchecked") public Optional cast(Component component) { @@ -31,4 +31,9 @@ public Optional cast(Component component) { return Optional.empty(); } } + + @Override + public @NotNull T create() { + return this.factory.create(); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 02445236bb..85e98a7086 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -18,7 +18,7 @@ import com.google.common.collect.ImmutableMap; import net.minecraft.util.Identifier; -import org.quiltmc.qsl.component.api.components.ComponentIdentifier; +import net.minecraft.util.registry.Registry; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.api.predicates.ClassInjectionPredicate; import org.quiltmc.qsl.component.api.predicates.FilteredInheritedInjectionPredicate; @@ -28,23 +28,29 @@ import java.util.Optional; public final class Components { - public static void inject(Class clazz, ComponentIdentifier component) { + public static final Registry> REGISTRY = ComponentsImpl.REGISTRY; + + public static void inject(ComponentInjectionPredicate predicate, ComponentType component) { + ComponentsImpl.inject(predicate, component); + } + + public static void inject(Class clazz, ComponentType component) { ComponentsImpl.inject(new ClassInjectionPredicate(clazz), component); } - public static void injectInheritage(Class clazz, ComponentIdentifier component) { + public static void injectInheritage(Class clazz, ComponentType component) { ComponentsImpl.inject(new InheritedInjectionPredicate(clazz), component); } - public static void injectInheritanceExcept(Class clazz, ComponentIdentifier component, Class... exceptions) { + public static void injectInheritanceExcept(Class clazz, ComponentType component, Class... exceptions) { ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), component); } - public static Optional expose(ComponentIdentifier id, S obj) { + public static Optional expose(ComponentType id, S obj) { if (obj instanceof ComponentProvider provider) { return provider.getContainer().expose(id.id()) .map(id::cast) - .map(Optional::orElseThrow); // If the casting fails something is wrong with the provided ComponentIdentifier. In that case we just throw. + .map(Optional::orElseThrow); // If the casting fails something is wrong with the provided ComponentType. In that case we just throw. } return Optional.empty(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java index ed82880355..0843931782 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java @@ -20,16 +20,17 @@ import net.minecraft.nbt.NbtFloat; import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.api.components.defaults.DefaultFloatComponent; public interface FloatComponent extends Component, NbtComponent { - static ComponentIdentifier create(Identifier id) { + static ComponentType create(Identifier id) { return ComponentsImpl.register(id, DefaultFloatComponent::new); } - static ComponentIdentifier create(float initialValue, Identifier id) { + static ComponentType create(float initialValue, Identifier id) { return ComponentsImpl.register(id, () -> new DefaultFloatComponent(initialValue)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java index a0d34d725d..b29f2b819f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java @@ -19,15 +19,16 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtInt; import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.api.components.defaults.DefaultIntegerComponent; public interface IntegerComponent extends NbtComponent { - static ComponentIdentifier create(int initialValue, Identifier id) { + static ComponentType create(int initialValue, Identifier id) { return ComponentsImpl.register(id, () -> new DefaultIntegerComponent(initialValue)); } - static ComponentIdentifier create(Identifier id) { + static ComponentType create(Identifier id) { return ComponentsImpl.register(id, DefaultIntegerComponent::new); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index 654d73457a..092b895fb3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -24,17 +24,18 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.api.components.defaults.DefaultInventoryComponent; import java.util.function.Supplier; public interface InventoryComponent extends NbtComponent, Inventory { - static ComponentIdentifier ofSize(int size, Identifier id) { + static ComponentType ofSize(int size, Identifier id) { return ComponentsImpl.register(id, () -> new DefaultInventoryComponent(size)); } - static ComponentIdentifier of(Supplier> items, Identifier id) { + static ComponentType of(Supplier> items, Identifier id) { return ComponentsImpl.register(id, () -> new DefaultInventoryComponent(items)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java index 876ac1316f..f21945f2aa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java @@ -19,8 +19,6 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.IntegerComponent; -import java.util.Objects; - public class DefaultIntegerComponent implements IntegerComponent { private int value; @@ -58,19 +56,6 @@ public void decrement() { this.saveNeeded(); } - // TODO: Fix hashing and equals - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof DefaultIntegerComponent that)) return false; - return value == that.value; - } - - @Override - public int hashCode() { - return Objects.hash(value); - } - @Override public void saveNeeded() { if (this.saveOperation != null) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java index 00bb58c7c7..e5a215f97e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java @@ -23,7 +23,7 @@ import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.components.ComponentIdentifier; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.util.StringConstants; @@ -51,8 +51,8 @@ protected SimpleComponentContainer(@Nullable Runnable saveOperation, Stream... ids) { - return new SimpleComponentContainer(saveOperation, Stream.of(ids).map(ComponentIdentifier::id)); + public static @NotNull SimpleComponentContainer create(Runnable saveOperation, ComponentType... ids) { + return new SimpleComponentContainer(saveOperation, Stream.of(ids).map(ComponentType::id)); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java similarity index 88% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java index 4b927faa92..a58aabd5d4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentCache.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java @@ -24,19 +24,19 @@ import java.util.Map; import java.util.Optional; -public class ComponentCache { +public class ComponentInjectionCache { - private static ComponentCache INSTANCE; + private static ComponentInjectionCache INSTANCE; private final Map, Map>> injectionCache = new HashMap<>(); - private ComponentCache() { + private ComponentInjectionCache() { } - public static ComponentCache getInstance() { + public static ComponentInjectionCache getInstance() { if (INSTANCE == null) { - INSTANCE = new ComponentCache(); + INSTANCE = new ComponentInjectionCache(); } return INSTANCE; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 56ece18296..4fdaae8e20 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -16,23 +16,29 @@ package org.quiltmc.qsl.component.impl; +import com.mojang.serialization.Lifecycle; import net.minecraft.util.Identifier; import net.minecraft.util.Util; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.util.registry.SimpleRegistry; +import org.jetbrains.annotations.ApiStatus; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.components.ComponentIdentifier; +import org.quiltmc.qsl.component.api.ComponentType; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; +@ApiStatus.Internal public class ComponentsImpl { private static final Map> INJECTION_REGISTRY = new HashMap<>(); - private static final Map> REGISTRY = new HashMap<>(); // TODO: Look into using a Minecraft Registry for this. + private static final RegistryKey>> REGISTRY_KEY = + RegistryKey.ofRegistry(new Identifier("quilt", "components")); + public static final Registry> REGISTRY = + new SimpleRegistry<>(REGISTRY_KEY, Lifecycle.experimental(), null); - public static void inject(ComponentInjectionPredicate predicate, ComponentIdentifier id) { + public static void inject(ComponentInjectionPredicate predicate, ComponentType id) { if (REGISTRY.get(id.id()) == null) { throw new IllegalArgumentException( "The target id %s does not match any registered component!".formatted(id.toString()) @@ -50,28 +56,32 @@ public static void inject(ComponentInjectionPredicate pred INJECTION_REGISTRY.put(predicate, Util.make(new HashSet<>(), set -> set.add(id.id()))); } - ComponentCache.getInstance().clear(); // Always clear the cache after an injection is registered. + ComponentInjectionCache.getInstance().clear(); // Always clear the cache after an injection is registered. } - public static ComponentIdentifier register(Identifier id, Component.Factory component) { - REGISTRY.put(id, component); - return new ComponentIdentifier<>(id); + public static ComponentType register(Identifier id, Component.Factory factory) { + var componentId = new ComponentType<>(id, factory); + return Registry.register(REGISTRY, id, componentId); } public static Map> get(ComponentProvider provider) { - return ComponentCache.getInstance().getCache(provider.getClass()).orElseGet(() -> { + return ComponentInjectionCache.getInstance().getCache(provider.getClass()).orElseGet(() -> { Map> returnMap = INJECTION_REGISTRY.entrySet().stream() .filter(it -> it.getKey().canInject(provider)) .map(Map.Entry::getValue) - .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, REGISTRY.get(id))), HashMap::putAll); + .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, getEntry(id))), HashMap::putAll); - ComponentCache.getInstance().record(provider.getClass(), returnMap); + ComponentInjectionCache.getInstance().record(provider.getClass(), returnMap); return returnMap; }); } public static Component.Factory getEntry(Identifier id) { - return REGISTRY.get(id); + return REGISTRY.getOrEmpty(id) + .orElseThrow(() -> + new IllegalArgumentException("Cannot access element with id %s in the component registry!" + .formatted(id.toString()) + )); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 29dcc5f94e..9f9a9d2ed0 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -42,7 +42,7 @@ import org.quiltmc.qsl.component.api.components.FloatComponent; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.InventoryComponent; -import org.quiltmc.qsl.component.api.components.ComponentIdentifier; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; import java.util.Objects; @@ -51,20 +51,20 @@ public class ComponentTestMod implements ModInitializer { public static final String MODID = "quilt_component_test"; // Registration Code - public static final ComponentIdentifier COW_INVENTORY = InventoryComponent.of( + public static final ComponentType COW_INVENTORY = InventoryComponent.of( () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64)), new Identifier(MODID, "cow_inventory") ); - public static final ComponentIdentifier CREEPER_EXPLODE_TIME = + public static final ComponentType CREEPER_EXPLODE_TIME = IntegerComponent.create(200, new Identifier(MODID, "creeper_explode_time")); - public static final ComponentIdentifier HOSTILE_EXPLODE_TIME = + public static final ComponentType HOSTILE_EXPLODE_TIME = IntegerComponent.create(new Identifier(MODID, "hostile_explode_time")); - public static final ComponentIdentifier CHEST_NUMBER = + public static final ComponentType CHEST_NUMBER = IntegerComponent.create(200, new Identifier(MODID, "chest_number")); - public static final ComponentIdentifier CHUNK_INVENTORY = InventoryComponent.ofSize(1, + public static final ComponentType CHUNK_INVENTORY = InventoryComponent.ofSize(1, new Identifier(MODID, "chunk_inventory") ); - public static final ComponentIdentifier SAVE_FLOAT = + public static final ComponentType SAVE_FLOAT = FloatComponent.create(new Identifier(MODID, "save_float")); // Attention do NOT place this block in any world because registry sync issues will make the game hung upon rejoining. diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index f4a50f0635..d187af5fe7 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.components.IntegerComponent; -import org.quiltmc.qsl.component.api.components.ComponentIdentifier; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.SimpleComponentContainer; import java.util.Arrays; @@ -40,7 +40,7 @@ import java.util.Set; public class TestBlockEntity extends BlockEntity { - public static final ComponentIdentifier TEST_BE_INT = + public static final ComponentType TEST_BE_INT = IntegerComponent.create(new Identifier("quilt_component_test", "test_be_int")); private final ComponentContainer container = From b8bba1138118ae0a2221ae1619d390aaa8debcaf Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 24 Jun 2022 12:58:08 +0300 Subject: [PATCH 23/70] Woops that went unnoticed. --- .../java/org/quiltmc/qsl/component/test/ComponentTestMod.java | 1 - 1 file changed, 1 deletion(-) diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 29dcc5f94e..7a0325a913 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -67,7 +67,6 @@ public class ComponentTestMod implements ModInitializer { public static final ComponentIdentifier SAVE_FLOAT = FloatComponent.create(new Identifier(MODID, "save_float")); - // Attention do NOT place this block in any world because registry sync issues will make the game hung upon rejoining. public static final Block TEST_BLOCK = new TestBlock(AbstractBlock.Settings.copy(Blocks.STONE)); @Override From 0bd3c480cb249d3cb1faaca7029b6d6e4e861248 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 24 Jun 2022 17:55:50 +0300 Subject: [PATCH 24/70] ItemStacks are now ComponentProviders. --- library/data/component/build.gradle | 4 + .../qsl/component/api/ComponentProvider.java | 6 +- .../qsl/component/mixin/MixinItemStack.java | 60 +++++++ .../resources/quilt_component.mixins.json | 1 + .../qsl/component/test/ComponentTestMod.java | 89 +---------- .../component/test/ServerTickListener.java | 148 ++++++++++++++++++ .../src/testmod/resources/quilt.mod.json | 3 + 7 files changed, 226 insertions(+), 85 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index b82b47f2c6..d3531b5e51 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -32,4 +32,8 @@ qslModule { injectedInterface("net/minecraft/class_31") { values = ["org/quiltmc/qsl/component/api/ComponentProvider"] } + + injectedInterface("net/minecraft/class_1799") { + values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 9c82ae0dbe..5ee61904ac 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -18,6 +18,7 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.level.LevelProperties; import org.jetbrains.annotations.NotNull; @@ -26,10 +27,11 @@ import java.util.Optional; @InjectedInterface({ - BlockEntity.class, Entity.class, + BlockEntity.class, Chunk.class, - LevelProperties.class + LevelProperties.class, + ItemStack.class }) public interface ComponentProvider { @NotNull diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java new file mode 100644 index 0000000000..bd58f287fb --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -0,0 +1,60 @@ +package org.quiltmc.qsl.component.mixin; + +import net.minecraft.item.ItemConvertible; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@SuppressWarnings("ConstantConditions") +@Mixin(ItemStack.class) +public abstract class MixinItemStack implements ComponentProvider { // TODO: Make sure nothing else may be broken before final PR. + + @Shadow + public abstract @Nullable NbtCompound getNbt(); + + @Shadow + public abstract NbtCompound getOrCreateNbt(); + + private LazifiedComponentContainer qsl$container; + + @Inject(method = "(Lnet/minecraft/item/ItemConvertible;I)V", at = @At("TAIL")) + private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo ci) { + this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); + this.qsl$container.setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())); + } + + @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;)V", at = @At("TAIL")) + private void readContainer(NbtCompound nbtCompound, CallbackInfo ci) { + this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); + this.qsl$container.setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())); + this.qsl$container.readNbt(this.getNbt()); + } + + @Inject(method = "setNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;postProcessNbt(Lnet/minecraft/nbt/NbtCompound;)V")) + private void readContainerAgain(NbtCompound nbt, CallbackInfo ci) { + if (this.qsl$container != null) { + this.qsl$container.readNbt(this.getNbt()); + } + } + + @Inject(method = "copy", at = @At(value = "RETURN", ordinal = 1)) + private void deserializeContainer(CallbackInfoReturnable cir) { + var container = cir.getReturnValue().getContainer(); + container.readNbt(this.getOrCreateNbt()); + } + + @Override + public @NotNull ComponentContainer getContainer() { + return this.qsl$container; + } +} diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index a3a30a847b..51c5e14d84 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -7,6 +7,7 @@ "MixinChunk", "MixinChunkSerializer", "MixinEntity", + "MixinItemStack", "MixinLevelProperties", "MixinWorldChunk" ], diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 9f9a9d2ed0..5548f5f0b4 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -29,6 +29,7 @@ import net.minecraft.item.Items; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; +import net.minecraft.util.Hand; import net.minecraft.util.Identifier; import net.minecraft.util.TypeFilter; import net.minecraft.util.collection.DefaultedList; @@ -69,12 +70,15 @@ public class ComponentTestMod implements ModInitializer { // Attention do NOT place this block in any world because registry sync issues will make the game hung upon rejoining. public static final Block TEST_BLOCK = new TestBlock(AbstractBlock.Settings.copy(Blocks.STONE)); + public static final ComponentType ITEMSTACK_INT = + IntegerComponent.create(new Identifier(MODID, "itemstack_int")); @Override public void onInitialize(ModContainer mod) { Registry.register(Registry.BLOCK, new Identifier(MODID, "test_block"), TEST_BLOCK); Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(MODID, "block_entity"), TEST_BE_TYPE); Block.STATE_IDS.add(TEST_BLOCK.getDefaultState()); + // Application Code Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); Components.injectInheritage(CowEntity.class, COW_INVENTORY); @@ -82,89 +86,8 @@ public void onInitialize(ModContainer mod) { Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(LevelProperties.class, SAVE_FLOAT); - - // Testing Code - ServerWorldTickEvents.START.register((server, world) -> { - world.getEntitiesByType(TypeFilter.instanceOf(CowEntity.class), cowEntity -> true).forEach(entity -> - entity.expose(COW_INVENTORY).ifPresent(inventoryComponent -> { - if (inventoryComponent.isEmpty()) { - world.createExplosion( - entity, - entity.getX(), entity.getY(), entity.getZ(), - 4.0f, Explosion.DestructionType.NONE - ); - entity.discard(); - } else { - inventoryComponent.removeStack(0, 1); - } - })); - - world.getEntitiesByType(EntityType.CREEPER, creeper -> true) - .forEach(creeper -> Components.expose(CREEPER_EXPLODE_TIME, creeper).ifPresent(explodeTime -> { - if (explodeTime.get() > 0) { - explodeTime.decrement(); - } else { - creeper.ignite(); - } - })); - - world.getEntitiesByType(TypeFilter.instanceOf(HostileEntity.class), hostile -> true) - .forEach(hostile -> hostile.expose(HOSTILE_EXPLODE_TIME).ifPresent(explodeTime -> { - if (explodeTime.get() <= 200) { - explodeTime.increment(); - } else { - hostile.getWorld().createExplosion( - null, - hostile.getX(), hostile.getY(), hostile.getZ(), - 1.0f, Explosion.DestructionType.NONE - ); - hostile.discard(); - } - })); - - ServerPlayerEntity player = world.getRandomAlivePlayer(); - if (player == null) { - return; - } - Chunk chunk = world.getChunk(player.getBlockPos()); - chunk.getBlockEntityPositions().stream() - .map(chunk::getBlockEntity) - .filter(Objects::nonNull) - .forEach(blockEntity -> blockEntity.expose(CHEST_NUMBER).ifPresent(integerComponent -> { - integerComponent.decrement(); - - if (integerComponent.get() <= 0) { - world.setBlockState(blockEntity.getPos(), Blocks.DIAMOND_BLOCK.getDefaultState()); - } - })); - chunk.expose(CHUNK_INVENTORY).ifPresent(inventory -> { - ItemStack playerStack = player.getInventory().getStack(9); - ItemStack stack = inventory.getStack(0); - if (!playerStack.isEmpty()) { - if (stack.isEmpty()) { - var newStack = playerStack.copy(); - newStack.setCount(1); - inventory.setStack(0, newStack); - playerStack.decrement(1); - } else { - if (ItemStack.canCombine(stack, playerStack)) { - stack.increment(1); - playerStack.decrement(1); - inventory.saveNeeded(); - } - } - } - player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); - }); - - LevelProperties props = ((LevelProperties) server.getSaveProperties()); - props.expose(SAVE_FLOAT).ifPresent(floatComponent -> { - floatComponent.set(floatComponent.get() + 0.5f); - if (world.getTime() % 100 == 0) { - player.sendMessage(Text.literal("%.3f".formatted(floatComponent.get())), false); - } - }); - }); + Components.inject(ItemStack.class, ITEMSTACK_INT); +// Components.inject(new ItemStackInjectionPredicate(Items.BOOKSHELF), ITEMSTACK_INT); } public static final BlockEntityType TEST_BE_TYPE = diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java new file mode 100644 index 0000000000..88850ee6ec --- /dev/null +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -0,0 +1,148 @@ +package org.quiltmc.qsl.component.test; + +import net.minecraft.block.Blocks; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.mob.HostileEntity; +import net.minecraft.entity.passive.CowEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.Hand; +import net.minecraft.util.TypeFilter; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.explosion.Explosion; +import net.minecraft.world.level.LevelProperties; +import org.quiltmc.qsl.base.api.event.ListenerPhase; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.components.IntegerComponent; +import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; + +import java.util.Objects; + +@ListenerPhase( + callbackTarget = ServerWorldTickEvents.End.class, + namespace = ComponentTestMod.MODID, path = "component_test_tick" +) +public class ServerTickListener implements ServerWorldTickEvents.End { + @Override + public void endWorldTick(MinecraftServer server, ServerWorld world) { + ServerPlayerEntity player = world.getRandomAlivePlayer(); + if (player == null) { + return; + } + Chunk chunk = world.getChunk(player.getBlockPos()); + LevelProperties props = ((LevelProperties) server.getSaveProperties()); + ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); + + cowTick(world); + creeperTick(world); + hostileTick(world); + currentChunkBETick(world, chunk); + currentChunkTick(player, chunk); + worldTick(world, player, props); + stackInHandTick(player, stackInHand); + } + + private void stackInHandTick(ServerPlayerEntity player, ItemStack stackInHand) { + if (!stackInHand.isEmpty() && stackInHand.isOf(Items.BOOKSHELF)) { + stackInHand.expose(ComponentTestMod.ITEMSTACK_INT).ifPresent(integerComponent -> { + integerComponent.increment(); + + if (integerComponent.get() >= 200) { + player.setStackInHand(Hand.MAIN_HAND, new ItemStack(Items.BOOK, 12)); + } + }); + } + } + + private void worldTick(ServerWorld world, ServerPlayerEntity player, LevelProperties props) { + props.expose(ComponentTestMod.SAVE_FLOAT).ifPresent(floatComponent -> { + floatComponent.set(floatComponent.get() + 0.5f); + if (world.getTime() % 100 == 0) { + player.sendMessage(Text.literal("%.3f".formatted(floatComponent.get())), false); + } + }); + } + + private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { + chunk.expose(ComponentTestMod.CHUNK_INVENTORY).ifPresent(inventory -> { + ItemStack playerStack = player.getInventory().getStack(9); + ItemStack stack = inventory.getStack(0); + if (!playerStack.isEmpty()) { + if (stack.isEmpty()) { + var newStack = playerStack.copy(); + newStack.setCount(1); + inventory.setStack(0, newStack); + playerStack.decrement(1); + } else { + if (ItemStack.canCombine(stack, playerStack)) { + stack.increment(1); + stack.expose(ComponentTestMod.ITEMSTACK_INT).ifPresent(IntegerComponent::increment); + playerStack.decrement(1); + inventory.saveNeeded(); + } + } + } + player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); + }); + } + + private void currentChunkBETick(ServerWorld world, Chunk chunk) { + chunk.getBlockEntityPositions().stream() + .map(chunk::getBlockEntity) + .filter(Objects::nonNull) + .forEach(blockEntity -> blockEntity.expose(ComponentTestMod.CHEST_NUMBER).ifPresent(integerComponent -> { + integerComponent.decrement(); + + if (integerComponent.get() <= 0) { + world.setBlockState(blockEntity.getPos(), Blocks.DIAMOND_BLOCK.getDefaultState()); + } + })); + } + + private void hostileTick(ServerWorld world) { + world.getEntitiesByType(TypeFilter.instanceOf(HostileEntity.class), hostile -> true) + .forEach(hostile -> hostile.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).ifPresent(explodeTime -> { + if (explodeTime.get() <= 200) { + explodeTime.increment(); + } else { + hostile.getWorld().createExplosion( + null, + hostile.getX(), hostile.getY(), hostile.getZ(), + 1.0f, Explosion.DestructionType.NONE + ); + hostile.discard(); + } + })); + } + + private void creeperTick(ServerWorld world) { + world.getEntitiesByType(EntityType.CREEPER, creeper -> true) + .forEach(creeper -> Components.expose(ComponentTestMod.CREEPER_EXPLODE_TIME, creeper).ifPresent(explodeTime -> { + if (explodeTime.get() > 0) { + explodeTime.decrement(); + } else { + creeper.ignite(); + } + })); + } + + private void cowTick(ServerWorld world) { + world.getEntitiesByType(TypeFilter.instanceOf(CowEntity.class), cowEntity -> true).forEach(entity -> + entity.expose(ComponentTestMod.COW_INVENTORY).ifPresent(inventoryComponent -> { + if (inventoryComponent.isEmpty()) { + world.createExplosion( + entity, + entity.getX(), entity.getY(), entity.getZ(), + 4.0f, Explosion.DestructionType.NONE + ); + entity.discard(); + } else { + inventoryComponent.removeStack(0, 1); + } + })); + } +} diff --git a/library/data/component/src/testmod/resources/quilt.mod.json b/library/data/component/src/testmod/resources/quilt.mod.json index 24b49c6738..5a0dc5db17 100644 --- a/library/data/component/src/testmod/resources/quilt.mod.json +++ b/library/data/component/src/testmod/resources/quilt.mod.json @@ -13,6 +13,9 @@ "entrypoints": { "init": [ "org.quiltmc.qsl.component.test.ComponentTestMod" + ], + "events": [ + "org.quiltmc.qsl.component.test.ServerTickListener" ] }, "depends": [ From 62fef93b90dd8b1b2850d81e4278945f627d4220 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 24 Jun 2022 18:14:03 +0300 Subject: [PATCH 25/70] Removed unneeded imports. --- .../qsl/component/test/ComponentTestMod.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 5548f5f0b4..28c8ddfd1d 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -21,32 +21,23 @@ import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.ChestBlockEntity; -import net.minecraft.entity.EntityType; import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; -import net.minecraft.util.Hand; import net.minecraft.util.Identifier; -import net.minecraft.util.TypeFilter; import net.minecraft.util.collection.DefaultedList; -import net.minecraft.util.registry.*; +import net.minecraft.util.registry.Registry; import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.explosion.Explosion; import net.minecraft.world.level.LevelProperties; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.components.FloatComponent; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.InventoryComponent; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; - -import java.util.Objects; public class ComponentTestMod implements ModInitializer { public static final String MODID = "quilt_component_test"; From 8c115242a6fa9c0e8360635790ece5e52eb75fe7 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 24 Jun 2022 19:07:51 +0300 Subject: [PATCH 26/70] Added component events. --- .../container/SimpleComponentContainer.java | 9 ++++--- .../component/api/event/ComponentEvents.java | 24 +++++++++++++++++++ .../qsl/component/impl/ComponentsImpl.java | 9 +++++++ .../qsl/component/impl/util/ErrorUtil.java | 13 ++++++++++ .../component/mixin/MixinChunkSerializer.java | 2 +- .../qsl/component/test/ComponentTestMod.java | 9 +++++-- 6 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java index e5a215f97e..8277d3489f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java @@ -22,9 +22,10 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.components.NbtComponent; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; import java.util.*; @@ -34,12 +35,14 @@ public class SimpleComponentContainer implements ComponentContainer { private final Map components; private final List nbtComponents; - protected SimpleComponentContainer(@Nullable Runnable saveOperation, Stream componentIds) { + public SimpleComponentContainer(@Nullable Runnable saveOperation, Stream componentIds) { this.components = new HashMap<>(); this.nbtComponents = new ArrayList<>(); componentIds.forEach(id -> { - Component component = ComponentsImpl.getEntry(id).create(); + Component component = Components.REGISTRY.getOrEmpty(id) + .orElseThrow(ErrorUtil.illegalArgument("Attempted to get invalid component with id %s".formatted(id.toString()))) + .create(); this.components.put(id, component); if (component instanceof NbtComponent nbtComponent) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java new file mode 100644 index 0000000000..0866087e4a --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java @@ -0,0 +1,24 @@ +package org.quiltmc.qsl.component.api.event; + +import org.quiltmc.qsl.base.api.event.Event; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.ComponentType; + +public class ComponentEvents { + + public static final Event INJECT = Event.create(Inject.class, listeners -> (provider, creator) -> { + for (Inject listener : listeners) { + listener.onInject(provider, creator); + } + }); + + @FunctionalInterface + public interface Inject { + void onInject(ComponentProvider provider, InjectionCreator creator); + } + + @FunctionalInterface + public interface InjectionCreator { + void inject(ComponentType type); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 4fdaae8e20..eca0ab7ea4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -27,6 +27,7 @@ import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.event.ComponentEvents; import java.util.*; @@ -64,6 +65,7 @@ public static ComponentType register(Identifier id, Com return Registry.register(REGISTRY, id, componentId); } + // TODO: Figure out to make caching work with provider specific injections. public static Map> get(ComponentProvider provider) { return ComponentInjectionCache.getInstance().getCache(provider.getClass()).orElseGet(() -> { Map> returnMap = INJECTION_REGISTRY.entrySet().stream() @@ -71,6 +73,13 @@ public static Map> get(ComponentProvider provid .map(Map.Entry::getValue) .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, getEntry(id))), HashMap::putAll); + ComponentEvents.INJECT.invoker().onInject(provider, type -> { + if (returnMap.containsKey(type.id())) { + throw new IllegalStateException("Cannot inject the same component twice on a provider!"); + } + + returnMap.putIfAbsent(type.id(), type.factory()); + }); ComponentInjectionCache.getInstance().record(provider.getClass(), returnMap); return returnMap; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java new file mode 100644 index 0000000000..8ff71004b6 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java @@ -0,0 +1,13 @@ +package org.quiltmc.qsl.component.impl.util; + +import java.util.function.Supplier; + +public class ErrorUtil { + public static Supplier illegalArgument(String message) { + return () -> new IllegalArgumentException(message); + } + + public static Supplier illegalState(String message) { + return () -> new IllegalStateException(message); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java index 6aa894c1e1..31b14a8f80 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java @@ -31,7 +31,7 @@ @Mixin(ChunkSerializer.class) public class MixinChunkSerializer { - @Inject(method = "deserialize", at = @At("RETURN"), cancellable = true) // FIXME: More chunk issues + @Inject(method = "deserialize", at = @At("RETURN"), cancellable = true) private static void deserializeComponents(ServerWorld world, PointOfInterestStorage poiStorage, ChunkPos pos, NbtCompound nbt, CallbackInfoReturnable cir) { var ret = cir.getReturnValue(); var target = ret instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : ret; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 364ae58d26..07b521d942 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -38,6 +38,7 @@ import org.quiltmc.qsl.component.api.components.FloatComponent; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.InventoryComponent; +import org.quiltmc.qsl.component.api.event.ComponentEvents; public class ComponentTestMod implements ModInitializer { public static final String MODID = "quilt_component_test"; @@ -76,8 +77,12 @@ public void onInitialize(ModContainer mod) { Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(LevelProperties.class, SAVE_FLOAT); - Components.inject(ItemStack.class, ITEMSTACK_INT); -// Components.inject(new ItemStackInjectionPredicate(Items.BOOKSHELF), ITEMSTACK_INT); +// Components.inject(new ItemStackInjectionPredicate(Items.BOOKSHELF), ITEMSTACK_INT); // TODO: Make this work at some point! + ComponentEvents.INJECT.register((provider, creator) -> { + if (provider instanceof ItemStack) { + creator.inject(ITEMSTACK_INT); + } + }); } public static final BlockEntityType TEST_BE_TYPE = From 21eed5155768849fe94a45d2d801db11293fd4e5 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 25 Jun 2022 21:58:03 +0300 Subject: [PATCH 27/70] Hooked the event for injections properly. --- .../api/container/LazifiedComponentContainer.java | 2 ++ .../quiltmc/qsl/component/api/event/ComponentEvents.java | 8 ++++---- .../org/quiltmc/qsl/component/impl/ComponentsImpl.java | 7 ------- .../org/quiltmc/qsl/component/test/ComponentTestMod.java | 8 ++++---- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java index 8c15355d24..7bdd7f5be6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java @@ -24,6 +24,7 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.event.ComponentEvents; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.util.Lazy; import org.quiltmc.qsl.component.impl.util.StringConstants; @@ -53,6 +54,7 @@ public static Optional create(T obj) { public static @NotNull Map> createComponents(@NotNull ComponentProvider provider) { var map = new HashMap>(); ComponentsImpl.get(provider).forEach((identifier, factory) -> map.put(identifier, Lazy.of(factory::create))); + ComponentEvents.INJECT.invoker().onInject(provider, type -> map.put(type.id(), Lazy.of(type::create))); return map; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java index 0866087e4a..fba7886f2f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java @@ -6,19 +6,19 @@ public class ComponentEvents { - public static final Event INJECT = Event.create(Inject.class, listeners -> (provider, creator) -> { + public static final Event INJECT = Event.create(Inject.class, listeners -> (provider, injector) -> { for (Inject listener : listeners) { - listener.onInject(provider, creator); + listener.onInject(provider, injector); } }); @FunctionalInterface public interface Inject { - void onInject(ComponentProvider provider, InjectionCreator creator); + void onInject(ComponentProvider provider, Injector injector); } @FunctionalInterface - public interface InjectionCreator { + public interface Injector { void inject(ComponentType type); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index eca0ab7ea4..22bcae7ec6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -27,7 +27,6 @@ import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.event.ComponentEvents; import java.util.*; @@ -73,13 +72,7 @@ public static Map> get(ComponentProvider provid .map(Map.Entry::getValue) .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, getEntry(id))), HashMap::putAll); - ComponentEvents.INJECT.invoker().onInject(provider, type -> { - if (returnMap.containsKey(type.id())) { - throw new IllegalStateException("Cannot inject the same component twice on a provider!"); - } - returnMap.putIfAbsent(type.id(), type.factory()); - }); ComponentInjectionCache.getInstance().record(provider.getClass(), returnMap); return returnMap; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 07b521d942..515fec30f3 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -77,10 +77,10 @@ public void onInitialize(ModContainer mod) { Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(LevelProperties.class, SAVE_FLOAT); -// Components.inject(new ItemStackInjectionPredicate(Items.BOOKSHELF), ITEMSTACK_INT); // TODO: Make this work at some point! - ComponentEvents.INJECT.register((provider, creator) -> { - if (provider instanceof ItemStack) { - creator.inject(ITEMSTACK_INT); + + ComponentEvents.INJECT.register((provider, injector) -> { + if (provider instanceof ItemStack stack && stack.isOf(Items.BOOKSHELF)) { + injector.inject(ITEMSTACK_INT); } }); } From dd8b4b3a2e4e4f68001468c3b0f0ac1d8262b388 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 27 Jun 2022 11:38:57 +0300 Subject: [PATCH 28/70] Improved API structure. --- .../api/components/FloatComponent.java | 2 +- .../api/components/IntegerComponent.java | 2 +- .../api/components/InventoryComponent.java | 7 ++++++- .../component/api/components/NbtComponent.java | 8 +++++++- .../defaults/DefaultFloatComponent.java | 12 +++++------- .../defaults/DefaultIntegerComponent.java | 12 +++++------- .../defaults/DefaultInventoryComponent.java | 17 +++++------------ .../container/LazifiedComponentContainer.java | 2 +- .../container/SimpleComponentContainer.java | 2 +- .../qsl/component/mixin/MixinBlockEntity.java | 2 +- .../quiltmc/qsl/component/mixin/MixinChunk.java | 2 +- .../qsl/component/mixin/MixinEntity.java | 2 +- .../qsl/component/mixin/MixinItemStack.java | 2 +- .../component/mixin/MixinLevelProperties.java | 2 +- .../qsl/component/test/TestBlockEntity.java | 2 +- 15 files changed, 38 insertions(+), 38 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{api => impl}/components/defaults/DefaultFloatComponent.java (88%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{api => impl}/components/defaults/DefaultIntegerComponent.java (89%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{api => impl}/components/defaults/DefaultInventoryComponent.java (88%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{api => impl}/container/LazifiedComponentContainer.java (98%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{api => impl}/container/SimpleComponentContainer.java (98%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java index 0843931782..545f2409aa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java @@ -22,7 +22,7 @@ import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.api.components.defaults.DefaultFloatComponent; +import org.quiltmc.qsl.component.impl.components.defaults.DefaultFloatComponent; public interface FloatComponent extends Component, NbtComponent { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java index b29f2b819f..6ad20ed5fa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java @@ -21,7 +21,7 @@ import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.api.components.defaults.DefaultIntegerComponent; +import org.quiltmc.qsl.component.impl.components.defaults.DefaultIntegerComponent; public interface IntegerComponent extends NbtComponent { static ComponentType create(int initialValue, Identifier id) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index 092b895fb3..45de6debb9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -26,7 +26,7 @@ import net.minecraft.util.collection.DefaultedList; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.api.components.defaults.DefaultInventoryComponent; +import org.quiltmc.qsl.component.impl.components.defaults.DefaultInventoryComponent; import java.util.function.Supplier; @@ -114,4 +114,9 @@ default void clear() { this.getStacks().clear(); this.saveNeeded(); } + + @Override + default void markDirty() { + this.saveNeeded(); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index ed7229fa37..5bf5f7055f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -60,7 +60,13 @@ static void read(@NotNull NbtComponent nbtComponent, NbtElement nbt) { byte nbtType(); - void saveNeeded(); + default void saveNeeded() { + if (this.getSaveOperation() != null) { + this.getSaveOperation().run(); + } + } void setSaveOperation(@Nullable Runnable runnable); + + @Nullable Runnable getSaveOperation(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultFloatComponent.java similarity index 88% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultFloatComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultFloatComponent.java index ba84419442..a4f267c356 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultFloatComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components.defaults; +package org.quiltmc.qsl.component.impl.components.defaults; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.FloatComponent; @@ -44,14 +44,12 @@ public void set(float value) { } @Override - public void saveNeeded() { - if (this.saveOperation != null) { - this.saveOperation.run(); - } + public void setSaveOperation(@Nullable Runnable runnable) { + this.saveOperation = runnable; } @Override - public void setSaveOperation(@Nullable Runnable runnable) { - this.saveOperation = runnable; + public @Nullable Runnable getSaveOperation() { + return this.saveOperation; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultIntegerComponent.java similarity index 89% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultIntegerComponent.java index f21945f2aa..b436e98454 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultIntegerComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components.defaults; +package org.quiltmc.qsl.component.impl.components.defaults; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.IntegerComponent; @@ -57,14 +57,12 @@ public void decrement() { } @Override - public void saveNeeded() { - if (this.saveOperation != null) { - this.saveOperation.run(); - } + public void setSaveOperation(@Nullable Runnable runnable) { + this.saveOperation = runnable; } @Override - public void setSaveOperation(@Nullable Runnable runnable) { - this.saveOperation = runnable; + public @Nullable Runnable getSaveOperation() { + return this.saveOperation; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultInventoryComponent.java similarity index 88% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultInventoryComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultInventoryComponent.java index bbd0645e6c..ef05eb5dbb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/defaults/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultInventoryComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components.defaults; +package org.quiltmc.qsl.component.impl.components.defaults; import net.minecraft.item.ItemStack; import net.minecraft.util.collection.DefaultedList; @@ -44,15 +44,13 @@ public DefaultedList getStacks() { } @Override - public void saveNeeded() { - if (this.saveOperation != null) { - this.saveOperation.run(); - } + public void setSaveOperation(@Nullable Runnable runnable) { + this.saveOperation = runnable; } @Override - public void setSaveOperation(@Nullable Runnable runnable) { - this.saveOperation = runnable; + public @Nullable Runnable getSaveOperation() { + return this.saveOperation; } @Override @@ -66,9 +64,4 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(stacks); } - - @Override - public void markDirty() { - this.saveNeeded(); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java similarity index 98% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java index 7bdd7f5be6..ce661f7610 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.container; +package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java similarity index 98% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 8277d3489f..43828342a4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.container; +package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 0b3c36c345..cbbaf82364 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 0f3f856cc3..1b3eb4c21b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index c3bf69f2f5..a08d833765 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index bd58f287fb..687f5903c2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index df6a040ddb..b2896d40f4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -35,7 +35,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index d187af5fe7..1197a42a0b 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -32,7 +32,7 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.container.SimpleComponentContainer; +import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; import java.util.Arrays; import java.util.HashSet; From 3902f9be73e3ff7d4e4b8fbf982e965d9756d1da Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 27 Jun 2022 13:21:29 +0300 Subject: [PATCH 29/70] More structure improvements. --- .../qsl/component/api/ComponentContainer.java | 6 +- .../impl/ComponentInjectionCache.java | 15 ++-- .../qsl/component/impl/ComponentsImpl.java | 25 +++--- .../container/LazifiedComponentContainer.java | 78 ++++++++++++------- .../container/SimpleComponentContainer.java | 9 +-- .../qsl/component/impl/util/ErrorUtil.java | 4 + .../qsl/component/mixin/MixinBlockEntity.java | 6 +- .../qsl/component/mixin/MixinChunk.java | 6 +- .../qsl/component/mixin/MixinEntity.java | 4 +- .../qsl/component/mixin/MixinItemStack.java | 31 +++++--- .../component/mixin/MixinLevelProperties.java | 4 +- .../component/test/ServerTickListener.java | 2 +- 12 files changed, 111 insertions(+), 79 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index 3eb5e6556f..af72120c7b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -30,9 +30,7 @@ public interface ComponentContainer { void moveComponents(ComponentContainer other); - void writeNbt(NbtCompound providerRootNbt); + void writeNbt(@NotNull NbtCompound providerRootNbt); - void readNbt(NbtCompound providerRootNbt); - - void setSaveOperation(@NotNull Runnable runnable); + void readNbt(@NotNull NbtCompound providerRootNbt); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java index a58aabd5d4..2cae52ac0b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java @@ -16,19 +16,16 @@ package org.quiltmc.qsl.component.impl; -import net.minecraft.util.Identifier; import net.minecraft.util.Util; -import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; public class ComponentInjectionCache { private static ComponentInjectionCache INSTANCE; - private final Map, Map>> injectionCache = new HashMap<>(); + private final Map, List>> injectionCache = new HashMap<>(); private ComponentInjectionCache() { @@ -42,7 +39,7 @@ public static ComponentInjectionCache getInstance() { return INSTANCE; } - public Optional>> getCache(Class clazz) { + public Optional>> getCache(Class clazz) { if (!this.injectionCache.containsKey(clazz)) { return Optional.empty(); } @@ -54,8 +51,8 @@ public void clear() { this.injectionCache.clear(); } - public void record(Class clazz, Map> components) { - if (this.injectionCache.put(clazz, Util.make(new HashMap<>(), map -> map.putAll(components))) != null) { + public void record(Class clazz, List> components) { + if (this.injectionCache.put(clazz, Util.make(new ArrayList<>(), list -> list.addAll(components))) != null) { // If there was a value there, it means we attempted an override, and so we throw. throw new IllegalStateException("Cannot register cache twice for class %s".formatted(clazz)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 22bcae7ec6..4ac7633875 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -27,8 +27,10 @@ import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; import java.util.*; +import java.util.stream.Collectors; @ApiStatus.Internal public class ComponentsImpl { @@ -65,25 +67,24 @@ public static ComponentType register(Identifier id, Com } // TODO: Figure out to make caching work with provider specific injections. - public static Map> get(ComponentProvider provider) { + public static List> get(ComponentProvider provider) { return ComponentInjectionCache.getInstance().getCache(provider.getClass()).orElseGet(() -> { - Map> returnMap = INJECTION_REGISTRY.entrySet().stream() + List> injectedTypes = INJECTION_REGISTRY.entrySet().stream() .filter(it -> it.getKey().canInject(provider)) .map(Map.Entry::getValue) - .collect(HashMap::new, (map, ids) -> ids.forEach(id -> map.put(id, getEntry(id))), HashMap::putAll); + .flatMap(Set::stream) + .map(ComponentsImpl::getEntry) + .collect(Collectors.toList()); + ComponentInjectionCache.getInstance().record(provider.getClass(), injectedTypes); - ComponentInjectionCache.getInstance().record(provider.getClass(), returnMap); - - return returnMap; + return injectedTypes; }); } - public static Component.Factory getEntry(Identifier id) { - return REGISTRY.getOrEmpty(id) - .orElseThrow(() -> - new IllegalArgumentException("Cannot access element with id %s in the component registry!" - .formatted(id.toString()) - )); + public static ComponentType getEntry(Identifier id) { + return REGISTRY.getOrEmpty(id).orElseThrow( + ErrorUtil.illegalArgument("Cannot access element with id %s in the component registry!".formatted(id)) + ); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java index ce661f7610..cc470dd22c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java @@ -23,9 +23,11 @@ import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.components.NbtComponent; import org.quiltmc.qsl.component.api.event.ComponentEvents; import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.Lazy; import org.quiltmc.qsl.component.impl.util.StringConstants; @@ -36,40 +38,44 @@ public class LazifiedComponentContainer implements ComponentContainer { private final Map> components; private final Set nbtComponents; @Nullable - private Runnable saveOperation = null; + private final Runnable saveOperation; - protected LazifiedComponentContainer(ComponentProvider provider) { - this.components = createComponents(provider); - this.nbtComponents = new HashSet<>(components.size()); + protected LazifiedComponentContainer(@NotNull ComponentProvider provider, @Nullable Runnable saveOperation) { + this.components = this.initializeComponents(provider); + this.nbtComponents = new HashSet<>(this.components.size()); + this.saveOperation = saveOperation; } - public static Optional create(T obj) { + private Map> initializeComponents(ComponentProvider provider) { + var map = new HashMap>(); + ComponentsImpl.get(provider).forEach(type -> map.put(type.id(), this.createLazy(type))); + ComponentEvents.INJECT.invoker().onInject(provider, type -> map.put(type.id(), this.createLazy(type))); + return map; + } + + private Lazy createLazy(ComponentType type) { + return Lazy.of(() -> { + Component component = type.create(); + if (component instanceof NbtComponent nbtComponent) { + this.nbtComponents.add(type.id()); + nbtComponent.setSaveOperation(this.saveOperation); + } + + return component; + }); + } + + public static Optional builder(T obj) { if (!(obj instanceof ComponentProvider provider)) { return Optional.empty(); } - return Optional.of(new LazifiedComponentContainer(provider)); - } - - public static @NotNull Map> createComponents(@NotNull ComponentProvider provider) { - var map = new HashMap>(); - ComponentsImpl.get(provider).forEach((identifier, factory) -> map.put(identifier, Lazy.of(factory::create))); - ComponentEvents.INJECT.invoker().onInject(provider, type -> map.put(type.id(), Lazy.of(type::create))); - return map; + return Optional.of(new Builder(provider)); } @Override public Optional expose(Identifier id) { - return Optional.ofNullable(this.components.get(id)) - .map(componentLazy -> { - if (componentLazy.isEmpty() && componentLazy.get() instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(id); - nbtComponent.setSaveOperation(this.saveOperation); - return nbtComponent; - } - - return componentLazy.get(); - }); + return Optional.ofNullable(this.components.get(id)).map(Lazy::get); } @Override @@ -79,11 +85,6 @@ public Map exposeAll() { .collect(HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue().get()), HashMap::putAll); } - @Override - public void setSaveOperation(@NotNull Runnable runnable) { - this.saveOperation = runnable; - } - @Override public void writeNbt(@NotNull NbtCompound providerRootNbt) { var rootQslNbt = new NbtCompound(); @@ -125,7 +126,26 @@ public void moveComponents(ComponentContainer other) { otherContainer.components.clear(); otherContainer.nbtComponents.clear(); } else { - throw new IllegalArgumentException("Cannot move components from a non-lazified container to one that is!"); + throw ErrorUtil.illegalArgument("Cannot move components from a non-lazified container to one that is!").get(); + } + } + + public static class Builder { + + private final ComponentProvider provider; + private Runnable saveOperation; + + private Builder(ComponentProvider provider) { + this.provider = provider; + } + + public Builder setSaveOperation(Runnable runnable) { + this.saveOperation = runnable; + return this; + } + + public LazifiedComponentContainer build() { + return new LazifiedComponentContainer(this.provider, this.saveOperation); } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 43828342a4..064f7a45aa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -74,7 +74,7 @@ public void moveComponents(ComponentContainer other) { } @Override - public void writeNbt(NbtCompound providerRootNbt) { + public void writeNbt(@NotNull NbtCompound providerRootNbt) { var rootQslNbt = new NbtCompound(); this.nbtComponents.forEach(id -> this.expose(id).ifPresent(component -> NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, id))); if (!rootQslNbt.isEmpty()) { @@ -83,7 +83,7 @@ public void writeNbt(NbtCompound providerRootNbt) { } @Override - public void readNbt(NbtCompound providerRootNbt) { + public void readNbt(@NotNull NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); if (rootQslNbt.isEmpty()) { @@ -95,9 +95,4 @@ public void readNbt(NbtCompound providerRootNbt) { .filter(Objects::nonNull) .forEach(id -> this.expose(id).ifPresent(component -> NbtComponent.readFrom((NbtComponent) component, id, rootQslNbt))); } - - @Override - public void setSaveOperation(@NotNull Runnable runnable) { - throw new IllegalStateException("Cannot change the save operation of a SimpleComponentContainer since it needs to be passed into the constructor"); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java index 8ff71004b6..9b1c628d0e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java @@ -10,4 +10,8 @@ public static Supplier illegalArgument(String message) public static Supplier illegalState(String message) { return () -> new IllegalStateException(message); } + + public static Supplier runtime(String msg) { + return () -> new RuntimeException(msg); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index cbbaf82364..a20027d2c4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -47,8 +47,10 @@ private void onReadNbt(NbtCompound nbt, CallbackInfo ci) { @Inject(method = "", at = @At("RETURN")) private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); - this.qsl$container.setSaveOperation(this::markDirty); + this.qsl$container = LazifiedComponentContainer.builder(this) + .orElseThrow() + .setSaveOperation(this::markDirty) + .build(); } @Inject(method = "toNbt", at = @At("TAIL")) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 1b3eb4c21b..0ed6dd20a8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -43,8 +43,10 @@ public abstract class MixinChunk implements ComponentProvider { @Inject(method = "", at = @At("RETURN")) private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); - this.qsl$container.setSaveOperation(() -> this.setNeedsSaving(true)); + this.qsl$container = LazifiedComponentContainer.builder(this) + .orElseThrow() + .setSaveOperation(() -> this.setNeedsSaving(true)) + .build(); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index a08d833765..d41ad2d3c2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -37,7 +37,9 @@ public abstract class MixinEntity implements ComponentProvider { @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); + this.qsl$container = LazifiedComponentContainer.builder(this) + .orElseThrow() + .build(); } @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index 687f5903c2..7ba955b1a2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -19,38 +19,47 @@ @Mixin(ItemStack.class) public abstract class MixinItemStack implements ComponentProvider { // TODO: Make sure nothing else may be broken before final PR. - @Shadow - public abstract @Nullable NbtCompound getNbt(); - @Shadow public abstract NbtCompound getOrCreateNbt(); + @Shadow + private @Nullable NbtCompound nbt; private LazifiedComponentContainer qsl$container; @Inject(method = "(Lnet/minecraft/item/ItemConvertible;I)V", at = @At("TAIL")) private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); - this.qsl$container.setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())); + this.qsl$container = LazifiedComponentContainer.builder(this) + .orElseThrow() + .setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) + .build(); } @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;)V", at = @At("TAIL")) private void readContainer(NbtCompound nbtCompound, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); - this.qsl$container.setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())); - this.qsl$container.readNbt(this.getNbt()); + this.qsl$container = LazifiedComponentContainer.builder(this) + .orElseThrow() + .setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) + .build(); + + if (this.nbt != null) { + this.qsl$container.readNbt(this.nbt); + } } @Inject(method = "setNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;postProcessNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void readContainerAgain(NbtCompound nbt, CallbackInfo ci) { if (this.qsl$container != null) { - this.qsl$container.readNbt(this.getNbt()); + this.qsl$container.readNbt(this.nbt); } } @Inject(method = "copy", at = @At(value = "RETURN", ordinal = 1)) private void deserializeContainer(CallbackInfoReturnable cir) { - var container = cir.getReturnValue().getContainer(); - container.readNbt(this.getOrCreateNbt()); + ItemStack copiedStack = cir.getReturnValue(); + NbtCompound nbt = copiedStack.getNbt(); + if (nbt != null) { + copiedStack.getContainer().readNbt(nbt); + } } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index b2896d40f4..f512cd00f1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -57,7 +57,9 @@ private static void readComponentData(Dynamic dynamic, DataFixer dat @Inject(method = "(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/NbtCompound;ZIIIFJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lcom/mojang/serialization/Lifecycle;)V", at = @At("TAIL")) private void onInit(DataFixer dataFixer, int i, NbtCompound nbtCompound, boolean bl, int j, int k, int l, float f, long m, long n, int o, int p, int q, boolean bl2, int r, boolean bl3, boolean bl4, boolean bl5, WorldBorder.Properties properties, int s, int t, UUID uUID, Set set, Timer timer, NbtCompound nbtCompound2, NbtCompound nbtCompound3, LevelInfo levelInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.create(this).orElseThrow(); + this.qsl$container = LazifiedComponentContainer.builder(this) + .orElseThrow() + .build(); } @Inject(method = "updateProperties", at = @At("TAIL")) diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 88850ee6ec..50212d9254 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -80,8 +80,8 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { } else { if (ItemStack.canCombine(stack, playerStack)) { stack.increment(1); - stack.expose(ComponentTestMod.ITEMSTACK_INT).ifPresent(IntegerComponent::increment); playerStack.decrement(1); + stack.expose(ComponentTestMod.ITEMSTACK_INT).ifPresent(IntegerComponent::increment); inventory.saveNeeded(); } } From a03dac835ac6d6159833c5267766a7ee9df67898 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 27 Jun 2022 15:16:30 +0300 Subject: [PATCH 30/70] SimpleComponentContainer builder. --- .../qsl/component/api/ComponentContainer.java | 3 - .../quiltmc/qsl/component/api/Components.java | 7 -- .../component/api/event/ComponentEvents.java | 15 ++++- .../qsl/component/api/wrapper/Wrapper.java | 17 +++++ .../qsl/component/impl/ComponentsImpl.java | 3 +- .../container/LazifiedComponentContainer.java | 11 +--- .../container/SimpleComponentContainer.java | 65 +++++++++++++------ .../qsl/component/test/ComponentTestMod.java | 6 +- .../quiltmc/qsl/component/test/TestBlock.java | 42 ++++++++++++ .../qsl/component/test/TestBlockEntity.java | 41 +++++++----- 10 files changed, 144 insertions(+), 66 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index af72120c7b..0dd16e0618 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -20,14 +20,11 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; -import java.util.Map; import java.util.Optional; public interface ComponentContainer { Optional expose(Identifier id); - Map exposeAll(); - void moveComponents(ComponentContainer other); void writeNbt(@NotNull NbtCompound providerRootNbt); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 85e98a7086..d1ab3e5c8b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -16,15 +16,12 @@ package org.quiltmc.qsl.component.api; -import com.google.common.collect.ImmutableMap; -import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.api.predicates.ClassInjectionPredicate; import org.quiltmc.qsl.component.api.predicates.FilteredInheritedInjectionPredicate; import org.quiltmc.qsl.component.api.predicates.InheritedInjectionPredicate; -import java.util.Map; import java.util.Optional; public final class Components { @@ -55,8 +52,4 @@ public static Optional expose(ComponentType id, S return Optional.empty(); } - - public static Map exposeAll(S obj) { - return obj instanceof ComponentProvider provider ? provider.getContainer().exposeAll() : ImmutableMap.of(); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java index fba7886f2f..246258c8aa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java @@ -3,22 +3,31 @@ import org.quiltmc.qsl.base.api.event.Event; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.components.IntegerComponent; + +import java.util.function.BooleanSupplier; public class ComponentEvents { - public static final Event INJECT = Event.create(Inject.class, listeners -> (provider, injector) -> { - for (Inject listener : listeners) { + public static final Event DYNAMIC_INJECT = Event.create(DynamicInject.class, listeners -> (provider, injector) -> { + for (DynamicInject listener : listeners) { listener.onInject(provider, injector); } }); @FunctionalInterface - public interface Inject { + public interface DynamicInject { void onInject(ComponentProvider provider, Injector injector); } @FunctionalInterface public interface Injector { void inject(ComponentType type); + + default void injectIf(boolean condition, ComponentType type) { + if (condition) { + this.inject(type); + } + } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java new file mode 100644 index 0000000000..bec895cbb9 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java @@ -0,0 +1,17 @@ +package org.quiltmc.qsl.component.api.wrapper; + +public class Wrapper { + private T value; + + public Wrapper(T value) { + this.value = value; + } + + public void set(T value) { + this.value = value; + } + + public T get() { + return this.value; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 4ac7633875..f2a6577e8f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -66,8 +66,7 @@ public static ComponentType register(Identifier id, Com return Registry.register(REGISTRY, id, componentId); } - // TODO: Figure out to make caching work with provider specific injections. - public static List> get(ComponentProvider provider) { + public static List> getInjections(ComponentProvider provider) { return ComponentInjectionCache.getInstance().getCache(provider.getClass()).orElseGet(() -> { List> injectedTypes = INJECTION_REGISTRY.entrySet().stream() .filter(it -> it.getKey().canInject(provider)) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java index cc470dd22c..57dfd22bfb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java @@ -48,8 +48,8 @@ protected LazifiedComponentContainer(@NotNull ComponentProvider provider, @Nulla private Map> initializeComponents(ComponentProvider provider) { var map = new HashMap>(); - ComponentsImpl.get(provider).forEach(type -> map.put(type.id(), this.createLazy(type))); - ComponentEvents.INJECT.invoker().onInject(provider, type -> map.put(type.id(), this.createLazy(type))); + ComponentsImpl.getInjections(provider).forEach(type -> map.put(type.id(), this.createLazy(type))); + ComponentEvents.DYNAMIC_INJECT.invoker().onInject(provider, type -> map.put(type.id(), this.createLazy(type))); return map; } @@ -78,13 +78,6 @@ public Optional expose(Identifier id) { return Optional.ofNullable(this.components.get(id)).map(Lazy::get); } - @Override - public Map exposeAll() { - return this.components.entrySet().stream() - .filter(entry -> !entry.getValue().isEmpty()) - .collect(HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue().get()), HashMap::putAll); - } - @Override public void writeNbt(@NotNull NbtCompound providerRootNbt) { var rootQslNbt = new NbtCompound(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 064f7a45aa..9fbc82780f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -18,14 +18,11 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.*; import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; import java.util.*; @@ -35,27 +32,27 @@ public class SimpleComponentContainer implements ComponentContainer { private final Map components; private final List nbtComponents; - public SimpleComponentContainer(@Nullable Runnable saveOperation, Stream componentIds) { + protected SimpleComponentContainer(@Nullable Runnable saveOperation, Stream> types) { this.components = new HashMap<>(); this.nbtComponents = new ArrayList<>(); - componentIds.forEach(id -> { - Component component = Components.REGISTRY.getOrEmpty(id) - .orElseThrow(ErrorUtil.illegalArgument("Attempted to get invalid component with id %s".formatted(id.toString()))) - .create(); - this.components.put(id, component); + types.forEach(type -> { + Component component = type.create(); + this.components.put(type.id(), component); if (component instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(id); + this.nbtComponents.add(type.id()); nbtComponent.setSaveOperation(saveOperation); } }); - componentIds.close(); + types.close(); } - public static @NotNull SimpleComponentContainer create(Runnable saveOperation, ComponentType... ids) { - return new SimpleComponentContainer(saveOperation, Stream.of(ids).map(ComponentType::id)); + @Contract("-> new") + @NotNull + public static Builder builder() { + return new Builder(); } @Override @@ -63,11 +60,6 @@ public Optional expose(Identifier id) { return Optional.ofNullable(this.components.get(id)); } - @Override - public Map exposeAll() { - return this.components; - } - @Override public void moveComponents(ComponentContainer other) { throw new IllegalStateException("Cannot move components into a SimpleComponentContainer"); @@ -95,4 +87,37 @@ public void readNbt(@NotNull NbtCompound providerRootNbt) { .filter(Objects::nonNull) .forEach(id -> this.expose(id).ifPresent(component -> NbtComponent.readFrom((NbtComponent) component, id, rootQslNbt))); } + + public static class Builder { + @Nullable + private Runnable saveOperation; + @NotNull + private final List> types; + + private Builder() { + this.types = new ArrayList<>(); + } + + @NotNull + public Builder setSaveOperation(@NotNull Runnable runnable) { + this.saveOperation = runnable; + return this; + } + + @NotNull + public Builder add(ComponentType type) { + this.types.add(type); + return this; + } + + @NotNull + public Builder add(ComponentType... types) { + this.types.addAll(Arrays.asList(types)); + return this; + } + + public SimpleComponentContainer build() { + return new SimpleComponentContainer(this.saveOperation, this.types.stream()); + } + } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 515fec30f3..846d8d457e 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -78,10 +78,8 @@ public void onInitialize(ModContainer mod) { Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(LevelProperties.class, SAVE_FLOAT); - ComponentEvents.INJECT.register((provider, injector) -> { - if (provider instanceof ItemStack stack && stack.isOf(Items.BOOKSHELF)) { - injector.inject(ITEMSTACK_INT); - } + ComponentEvents.DYNAMIC_INJECT.register((provider, injector) -> { + injector.injectIf(provider instanceof ItemStack stack && stack.isOf(Items.BOOKSHELF), ITEMSTACK_INT); }); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index 8db0b48025..c8a23842fb 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -23,9 +23,15 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityTicker; import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.wrapper.Wrapper; public class TestBlock extends Block implements BlockEntityProvider { public TestBlock(Settings settings) { @@ -44,6 +50,42 @@ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { return ComponentTestMod.TEST_BE_TYPE.instantiate(pos, state); } + @SuppressWarnings("deprecation") + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + BlockEntity be = world.getBlockEntity(pos); + if (world.isClient || be == null) { + return super.onUse(state, world, pos, player, hand, hit); + } + + ItemStack handStack = player.getStackInHand(hand); + + if (!handStack.isEmpty()) { + final Wrapper ret = new Wrapper<>(ActionResult.PASS); + + be.expose(ComponentTestMod.CHUNK_INVENTORY).ifPresent(inventoryComponent -> { + var stack = inventoryComponent.getStack(0); + + if (stack.isEmpty()) { + var copied = handStack.copy(); + copied.setCount(1); + inventoryComponent.setStack(0, copied); + ret.set(ActionResult.SUCCESS); + } else { + if (ItemStack.canCombine(stack, handStack)) { + stack.increment(1); + handStack.decrement(1); + inventoryComponent.saveNeeded(); + ret.set(ActionResult.SUCCESS); + } + } + }); + + return ret.get(); + } + return super.onUse(state, world, pos, player, hand, hit); + } + @SuppressWarnings("deprecation") @Override public BlockRenderType getRenderType(BlockState state) { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 1197a42a0b..a1124cb18d 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -30,8 +30,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.components.IntegerComponent; +import org.quiltmc.qsl.component.api.components.InventoryComponent; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; import java.util.Arrays; @@ -43,8 +44,10 @@ public class TestBlockEntity extends BlockEntity { public static final ComponentType TEST_BE_INT = IntegerComponent.create(new Identifier("quilt_component_test", "test_be_int")); - private final ComponentContainer container = - SimpleComponentContainer.create(this::markDirty, TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY); + private final ComponentContainer container = SimpleComponentContainer.builder() + .setSaveOperation(this::markDirty) + .add(TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) + .build(); public TestBlockEntity(BlockPos blockPos, BlockState blockState) { super(ComponentTestMod.TEST_BE_TYPE, blockPos, blockState); @@ -55,14 +58,16 @@ public static void tick(World world, BlockPos pos, Block return; } - blockEntity.expose(TEST_BE_INT).ifPresent(integerComponent -> { - if (integerComponent.get() % 20 == 0) { - HashSet set = new HashSet<>(List.of(pos)); - expand(pos, pos, world, set); - } + if (blockEntity.expose(ComponentTestMod.CHUNK_INVENTORY).map(InventoryComponent::isEmpty).orElse(true)) { + blockEntity.expose(TEST_BE_INT).ifPresent(integerComponent -> { + if (integerComponent.get() % 40 == 0) { + HashSet set = new HashSet<>(List.of(pos)); + expand(pos, pos, world, set); + } - integerComponent.increment(); - }); + integerComponent.increment(); + }); + } } private static void expand(BlockPos initialPos, BlockPos pos, World world, Set visited) { @@ -84,12 +89,6 @@ private static void expand(BlockPos initialPos, BlockPos pos, World world, Set toUpdatePacket() { return BlockEntityUpdateS2CPacket.of(this); } + + @Override + public NbtCompound toInitialChunkDataNbt() { + return this.toNbt(); + } } From 7df1c735fba41ec1f0561b37704e5e89e5a10a31 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 27 Jun 2022 18:02:02 +0300 Subject: [PATCH 31/70] Implemented the FunctionComponent library. * Function components can be called like normal functions provided you have access to the container. * Ticking components are called every tick if their container supports it. * Added builders to the two primary implementations of ComponentContainer. * Added static ComponentTypes. They are basically component singletons. * Moved some important API to Components.java --- library/data/component/build.gradle | 8 ++- .../qsl/component/api/ComponentContainer.java | 2 + .../qsl/component/api/ComponentProvider.java | 5 ++ .../qsl/component/api/ComponentType.java | 27 +++++++++- .../quiltmc/qsl/component/api/Components.java | 14 ++++++ .../api/components/FunctionComponent.java | 10 ++++ .../api/components/TickingComponent.java | 9 ++++ .../component/api/event/ComponentEvents.java | 3 -- .../qsl/component/impl/ComponentsImpl.java | 9 +++- .../container/LazifiedComponentContainer.java | 50 +++++++++++++++++-- .../container/SimpleComponentContainer.java | 15 ++++++ .../impl/event/ServerTickEventListener.java | 21 ++++++++ .../quiltmc/qsl/component/impl/util/Lazy.java | 10 ++++ .../qsl/component/mixin/MixinBlockEntity.java | 7 +-- .../MixinDirectBlockEntityTickInvoker.java | 26 ++++++++++ .../qsl/component/mixin/MixinEntity.java | 8 ++- .../qsl/component/mixin/MixinItemStack.java | 9 ++++ .../component/mixin/MixinLevelProperties.java | 1 + .../resources/quilt_component.accesswidener | 2 + .../resources/quilt_component.mixins.json | 1 + .../qsl/component/test/ComponentTestMod.java | 44 ++++++++++++++-- .../component/test/ServerTickListener.java | 12 ----- 22 files changed, 262 insertions(+), 31 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index d3531b5e51..721d4bc57a 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -11,7 +11,13 @@ qslModule { moduleDependencies { core { api("qsl_base") - testmodOnly("lifecycle_events") + api("lifecycle_events") + } + } + + entrypoints { + events { + values = ["org.quiltmc.qsl.component.impl.event.ServerTickEventListener"] } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index 0dd16e0618..7aa2759e3d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -30,4 +30,6 @@ public interface ComponentContainer { void writeNbt(@NotNull NbtCompound providerRootNbt); void readNbt(@NotNull NbtCompound providerRootNbt); + + void tick(@NotNull ComponentProvider provider); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 5ee61904ac..66ea056c40 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -23,6 +23,7 @@ import net.minecraft.world.level.LevelProperties; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.base.api.util.InjectedInterface; +import org.quiltmc.qsl.component.api.components.FunctionComponent; import java.util.Optional; @@ -40,4 +41,8 @@ public interface ComponentProvider { default Optional expose(ComponentType id) { return Components.expose(id, this); } + + default > Optional call(ComponentType type, T t) { + return this.expose(type).map(func -> func.call(this, t)); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index f52fcc97b8..2fd183adbc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -19,9 +19,12 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; -public record ComponentType(Identifier id, Component.Factory factory) implements Component.Factory { +public record ComponentType(Identifier id, Component.Factory factory, boolean isStatic) implements Component.Factory { + public static final Static STATIC_CACHE = new Static(); @SuppressWarnings("unchecked") public Optional cast(Component component) { @@ -34,6 +37,28 @@ public Optional cast(Component component) { @Override public @NotNull T create() { + if (this.isStatic) { + return STATIC_CACHE.getOrCreate(this); + } return this.factory.create(); } + + public static class Static { + private final Map staticInstances = new HashMap<>(); + + private Static() { + + } + + @SuppressWarnings("unchecked") + @NotNull C getOrCreate(ComponentType type) { + if (this.staticInstances.containsKey(type.id())) { + return (C) this.staticInstances.get(type.id()); + } else { + C singleton = type.factory.create(); + this.staticInstances.put(type.id(), singleton); + return singleton; + } + } + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index d1ab3e5c8b..0e27afa2aa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -16,7 +16,9 @@ package org.quiltmc.qsl.component.api; +import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; +import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.api.predicates.ClassInjectionPredicate; import org.quiltmc.qsl.component.api.predicates.FilteredInheritedInjectionPredicate; @@ -52,4 +54,16 @@ public static Optional expose(ComponentType id, S return Optional.empty(); } + + public static ComponentType register(Identifier id, Component.Factory factory) { + return ComponentsImpl.register(id, factory); + } + + public static ComponentType registerStatic(Identifier id, Component.Factory factory) { + return ComponentsImpl.registerStatic(id, factory); + } + + public static ComponentType registerTicking(Identifier id, C component) { + return ComponentsImpl.registerStatic(id, () -> component); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java new file mode 100644 index 0000000000..c185d7a97e --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java @@ -0,0 +1,10 @@ +package org.quiltmc.qsl.component.api.components; + +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentProvider; + +@FunctionalInterface +public interface FunctionComponent extends Component { + U call(@NotNull ComponentProvider provider, T t); +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java new file mode 100644 index 0000000000..a802f71b31 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java @@ -0,0 +1,9 @@ +package org.quiltmc.qsl.component.api.components; + +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentProvider; + +public interface TickingComponent extends Component { + void tick(@NotNull ComponentProvider provider); +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java index 246258c8aa..91a6d202f9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java @@ -3,9 +3,6 @@ import org.quiltmc.qsl.base.api.event.Event; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.components.IntegerComponent; - -import java.util.function.BooleanSupplier; public class ComponentEvents { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index f2a6577e8f..8f69614eba 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -62,8 +62,13 @@ public static void inject(ComponentInjectionPredicate pred } public static ComponentType register(Identifier id, Component.Factory factory) { - var componentId = new ComponentType<>(id, factory); - return Registry.register(REGISTRY, id, componentId); + var componentType = new ComponentType<>(id, factory, false); + return Registry.register(REGISTRY, id, componentType); + } + + public static ComponentType registerStatic(Identifier id, Component.Factory factory) { + var componentType = new ComponentType<>(id, factory, true); + return Registry.register(REGISTRY, id, componentType); } public static List> getInjections(ComponentProvider provider) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java index 57dfd22bfb..7dbef7caba 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java @@ -25,6 +25,7 @@ import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.api.event.ComponentEvents; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.util.ErrorUtil; @@ -36,14 +37,18 @@ public class LazifiedComponentContainer implements ComponentContainer { private final Map> components; - private final Set nbtComponents; + private final List nbtComponents; + private final List tickingComponents; @Nullable private final Runnable saveOperation; + private final boolean ticking; - protected LazifiedComponentContainer(@NotNull ComponentProvider provider, @Nullable Runnable saveOperation) { - this.components = this.initializeComponents(provider); - this.nbtComponents = new HashSet<>(this.components.size()); + protected LazifiedComponentContainer(@NotNull ComponentProvider provider, @Nullable Runnable saveOperation, boolean ticking) { this.saveOperation = saveOperation; + this.ticking = ticking; + this.nbtComponents = new ArrayList<>(); + this.tickingComponents = new ArrayList<>(); + this.components = this.initializeComponents(provider); } private Map> initializeComponents(ComponentProvider provider) { @@ -54,6 +59,15 @@ private Map> initializeComponents(ComponentProvider } private Lazy createLazy(ComponentType type) { + if (type.isStatic()) { + Component singleton = type.create(); + if (this.ticking && singleton instanceof TickingComponent) { + this.tickingComponents.add(type.id()); + } + + return Lazy.filled(singleton); + } + return Lazy.of(() -> { Component component = type.create(); if (component instanceof NbtComponent nbtComponent) { @@ -61,6 +75,10 @@ private Lazy createLazy(ComponentType type) { nbtComponent.setSaveOperation(this.saveOperation); } + if (this.ticking && component instanceof TickingComponent) { + this.tickingComponents.add(type.id()); + } + return component; }); } @@ -104,6 +122,19 @@ public void readNbt(@NotNull NbtCompound providerRootNbt) { })); } + @Override + public void tick(@NotNull ComponentProvider provider) { + if (!this.ticking) { + throw ErrorUtil.runtime("Attempted to tick a non-tickable ComponentContainer instance").get(); + } + + this.tickingComponents.stream() + .map(this::expose) + .map(Optional::orElseThrow) + .map(it -> ((TickingComponent) it)) + .forEach(tickingComponent -> tickingComponent.tick(provider)); + } + @Override public void moveComponents(ComponentContainer other) { if (other instanceof LazifiedComponentContainer otherContainer) { @@ -126,10 +157,14 @@ public void moveComponents(ComponentContainer other) { public static class Builder { private final ComponentProvider provider; + @Nullable private Runnable saveOperation; + private boolean ticking; private Builder(ComponentProvider provider) { this.provider = provider; + this.ticking = false; + this.saveOperation = null; } public Builder setSaveOperation(Runnable runnable) { @@ -137,8 +172,13 @@ public Builder setSaveOperation(Runnable runnable) { return this; } + public Builder ticking() { + this.ticking = true; + return this; + } + public LazifiedComponentContainer build() { - return new LazifiedComponentContainer(this.provider, this.saveOperation); + return new LazifiedComponentContainer(this.provider, this.saveOperation, this.ticking); } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 9fbc82780f..8ab7cc6732 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.*; import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.impl.util.StringConstants; import java.util.*; @@ -31,10 +32,12 @@ public class SimpleComponentContainer implements ComponentContainer { private final Map components; private final List nbtComponents; + private final List tickingComponents; protected SimpleComponentContainer(@Nullable Runnable saveOperation, Stream> types) { this.components = new HashMap<>(); this.nbtComponents = new ArrayList<>(); + this.tickingComponents = new ArrayList<>(); types.forEach(type -> { Component component = type.create(); @@ -44,6 +47,10 @@ protected SimpleComponentContainer(@Nullable Runnable saveOperation, Stream this.expose(id).ifPresent(component -> NbtComponent.readFrom((NbtComponent) component, id, rootQslNbt))); } + @Override + public void tick(@NotNull ComponentProvider provider) { + this.tickingComponents.stream() + .map(this.components::get) + .map(it -> ((TickingComponent) it)) + .forEach(tickingComponent -> tickingComponent.tick(provider)); + } + public static class Builder { @Nullable private Runnable saveOperation; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java new file mode 100644 index 0000000000..4be50d8950 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java @@ -0,0 +1,21 @@ +package org.quiltmc.qsl.component.impl.event; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.SaveProperties; +import net.minecraft.world.level.LevelProperties; +import org.quiltmc.qsl.base.api.event.ListenerPhase; +import org.quiltmc.qsl.lifecycle.api.event.ServerTickEvents; + +@ListenerPhase( + callbackTarget = ServerTickEvents.End.class, + namespace = "quilt_component", path = "tick_level_container" +) +public class ServerTickEventListener implements ServerTickEvents.End { + @Override + public void endServerTick(MinecraftServer server) { + SaveProperties saveProperties = server.getSaveProperties(); + if (saveProperties instanceof LevelProperties levelProperties) { + levelProperties.getContainer().tick(levelProperties); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java index 1c77423d54..ba03cbacef 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java @@ -36,11 +36,21 @@ private Lazy(@NotNull Supplier sup) { this.value = null; } + private Lazy(@NotNull T value) { + this.value = value; + this.sup = () -> value; + } + @NotNull public static Lazy of(@NotNull Supplier sup) { return new Lazy<>(sup); } + @NotNull + public static Lazy filled(@NotNull T value) { + return new Lazy<>(value); + } + @NotNull public Lazy compose(Function transformer) { return Lazy.of(() -> transformer.apply(this.sup.get())); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index a20027d2c4..6245f03b61 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -42,17 +42,18 @@ private void onReadNbt(NbtCompound nbt, CallbackInfo ci) { this.qsl$container.readNbt(nbt); } - @Shadow - public abstract void markDirty(); - @Inject(method = "", at = @At("RETURN")) private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { this.qsl$container = LazifiedComponentContainer.builder(this) .orElseThrow() .setSaveOperation(this::markDirty) + .ticking() .build(); } + @Shadow + public abstract void markDirty(); + @Inject(method = "toNbt", at = @At("TAIL")) private void onWriteNbt(CallbackInfoReturnable cir) { this.qsl$container.writeNbt(cir.getReturnValue()); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java new file mode 100644 index 0000000000..4a0b53f6d4 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java @@ -0,0 +1,26 @@ +package org.quiltmc.qsl.component.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.WorldChunk; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(WorldChunk.DirectBlockEntityTickInvoker.class) +public class MixinDirectBlockEntityTickInvoker { + @Shadow + @Final + private T blockEntity; + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/entity/BlockEntity;)V")) + private void tickContainer(BlockEntityTicker instance, World world, BlockPos blockPos, BlockState blockState, T t) { + instance.tick(world, blockPos, blockState, t); + this.blockEntity.getContainer().tick(this.blockEntity); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index d41ad2d3c2..d766b0cac8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -35,10 +35,11 @@ public abstract class MixinEntity implements ComponentProvider { private ComponentContainer qsl$container; - @Inject(method = "", at = @At("RETURN")) + @Inject(method = "", at = @At("RETURN")) // TODO: Mixin into the ServerWorld#spawnEntity method for this! private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { this.qsl$container = LazifiedComponentContainer.builder(this) .orElseThrow() + .ticking() .build(); } @@ -52,6 +53,11 @@ private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { this.qsl$container.readNbt(nbt); } + @Inject(method = "tick", at = @At("TAIL")) + private void tickContainer(CallbackInfo ci) { + this.getContainer().tick(this); + } + @Override public @NotNull ComponentContainer getContainer() { return this.qsl$container; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index 7ba955b1a2..794230b2ee 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -1,8 +1,10 @@ package org.quiltmc.qsl.component.mixin; +import net.minecraft.entity.Entity; import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; +import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; @@ -31,6 +33,7 @@ private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo this.qsl$container = LazifiedComponentContainer.builder(this) .orElseThrow() .setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) + .ticking() .build(); } @@ -39,6 +42,7 @@ private void readContainer(NbtCompound nbtCompound, CallbackInfo ci) { this.qsl$container = LazifiedComponentContainer.builder(this) .orElseThrow() .setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) + .ticking() .build(); if (this.nbt != null) { @@ -62,6 +66,11 @@ private void deserializeContainer(CallbackInfoReturnable cir) { } } + @Inject(method = "inventoryTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;inventoryTick(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;IZ)V")) + private void tickContainer(World world, Entity entity, int slot, boolean selected, CallbackInfo ci) { + + } + @Override public @NotNull ComponentContainer getContainer() { return this.qsl$container; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index f512cd00f1..527f8b9192 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -59,6 +59,7 @@ private static void readComponentData(Dynamic dynamic, DataFixer dat private void onInit(DataFixer dataFixer, int i, NbtCompound nbtCompound, boolean bl, int j, int k, int l, float f, long m, long n, int o, int p, int q, boolean bl2, int r, boolean bl3, boolean bl4, boolean bl5, WorldBorder.Properties properties, int s, int t, UUID uUID, Set set, Timer timer, NbtCompound nbtCompound2, NbtCompound nbtCompound3, LevelInfo levelInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfo ci) { this.qsl$container = LazifiedComponentContainer.builder(this) .orElseThrow() + .ticking() .build(); } diff --git a/library/data/component/src/main/resources/quilt_component.accesswidener b/library/data/component/src/main/resources/quilt_component.accesswidener index 2c01e93157..8bad5df4ac 100644 --- a/library/data/component/src/main/resources/quilt_component.accesswidener +++ b/library/data/component/src/main/resources/quilt_component.accesswidener @@ -1,3 +1,5 @@ accessWidener v2 named # TODO: Remove this once the Block Entity API is merged. extendable class net/minecraft/block/entity/BlockEntityType$BlockEntityFactory +# Using this to make the default implementation of the BlockEntityTickInvoker interface accessible to mixin. +transitive-accessible class net/minecraft/world/chunk/WorldChunk$DirectBlockEntityTickInvoker diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index 51c5e14d84..a8528b929f 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -6,6 +6,7 @@ "MixinBlockEntity", "MixinChunk", "MixinChunkSerializer", + "MixinDirectBlockEntityTickInvoker", "MixinEntity", "MixinItemStack", "MixinLevelProperties", diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 846d8d457e..c25e9ab709 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -24,20 +24,24 @@ import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.Hand; import net.minecraft.util.Identifier; +import net.minecraft.util.Unit; import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.registry.Registry; +import net.minecraft.world.WorldProperties; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.level.LevelProperties; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.components.FloatComponent; -import org.quiltmc.qsl.component.api.components.IntegerComponent; -import org.quiltmc.qsl.component.api.components.InventoryComponent; +import org.quiltmc.qsl.component.api.components.*; import org.quiltmc.qsl.component.api.event.ComponentEvents; public class ComponentTestMod implements ModInitializer { @@ -63,6 +67,37 @@ public class ComponentTestMod implements ModInitializer { public static final Block TEST_BLOCK = new TestBlock(AbstractBlock.Settings.copy(Blocks.STONE)); public static final ComponentType ITEMSTACK_INT = IntegerComponent.create(new Identifier(MODID, "itemstack_int")); + public static final ComponentType> FUNC_COMP = + Components.registerStatic(new Identifier(MODID, "player_thing"), () -> (provider, unused) -> { + if (provider instanceof PlayerEntity entity) { + entity.giveItemStack(new ItemStack(Items.WHEAT)); + } + return Unit.INSTANCE; + }); + public static final ComponentType PLAYER_TICK = + Components.registerTicking(new Identifier(MODID, "warden_tick"), + provider -> { + if (provider instanceof ServerPlayerEntity player) { + ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); + if (stackInHand.isOf(Items.WHEAT)) { + player.call(ComponentTestMod.FUNC_COMP, Unit.INSTANCE) + .ifPresent(unit -> player.sendMessage(Text.literal("Prankt"), true)); + } + + var props = player.getWorld().getServer().getSaveProperties(); + if (props instanceof LevelProperties levelProperties && player.getWorld().getTime() % 100 == 0) { + player.sendMessage(Text.literal( + levelProperties.expose(SAVE_FLOAT).map(FloatComponent::get).orElse(0f).toString() + ), false); + } + } + }); + public static final ComponentType SERVER_TICK = Components.registerTicking(new Identifier(MODID, "level_tick"), + provider -> { + if (provider instanceof LevelProperties properties) { + properties.expose(SAVE_FLOAT).ifPresent(floatComponent -> floatComponent.set(floatComponent.get() + 0.5f)); + } + }); @Override public void onInitialize(ModContainer mod) { @@ -77,9 +112,12 @@ public void onInitialize(ModContainer mod) { Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(LevelProperties.class, SAVE_FLOAT); + Components.injectInheritage(ServerPlayerEntity.class, FUNC_COMP); + Components.inject(LevelProperties.class, SERVER_TICK); ComponentEvents.DYNAMIC_INJECT.register((provider, injector) -> { injector.injectIf(provider instanceof ItemStack stack && stack.isOf(Items.BOOKSHELF), ITEMSTACK_INT); + injector.injectIf(provider instanceof PlayerEntity, PLAYER_TICK); }); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 50212d9254..a3e752b5f5 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -14,7 +14,6 @@ import net.minecraft.util.TypeFilter; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.explosion.Explosion; -import net.minecraft.world.level.LevelProperties; import org.quiltmc.qsl.base.api.event.ListenerPhase; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.components.IntegerComponent; @@ -34,7 +33,6 @@ public void endWorldTick(MinecraftServer server, ServerWorld world) { return; } Chunk chunk = world.getChunk(player.getBlockPos()); - LevelProperties props = ((LevelProperties) server.getSaveProperties()); ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); cowTick(world); @@ -42,7 +40,6 @@ public void endWorldTick(MinecraftServer server, ServerWorld world) { hostileTick(world); currentChunkBETick(world, chunk); currentChunkTick(player, chunk); - worldTick(world, player, props); stackInHandTick(player, stackInHand); } @@ -58,15 +55,6 @@ private void stackInHandTick(ServerPlayerEntity player, ItemStack stackInHand) { } } - private void worldTick(ServerWorld world, ServerPlayerEntity player, LevelProperties props) { - props.expose(ComponentTestMod.SAVE_FLOAT).ifPresent(floatComponent -> { - floatComponent.set(floatComponent.get() + 0.5f); - if (world.getTime() % 100 == 0) { - player.sendMessage(Text.literal("%.3f".formatted(floatComponent.get())), false); - } - }); - } - private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { chunk.expose(ComponentTestMod.CHUNK_INVENTORY).ifPresent(inventory -> { ItemStack playerStack = player.getInventory().getStack(9); From aee0845cb52033eac6b744e69b4bee0d1651f26e Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 27 Jun 2022 20:17:03 +0300 Subject: [PATCH 32/70] Finalized the FunctionComponent system. --- .../quiltmc/qsl/component/api/Components.java | 6 +- .../api/components/FloatComponent.java | 19 +--- .../api/components/IntegerComponent.java | 9 +- .../api/components/InventoryComponent.java | 27 ++--- .../{defaults => }/DefaultFloatComponent.java | 2 +- .../DefaultIntegerComponent.java | 2 +- .../DefaultInventoryComponent.java | 2 +- .../predicates/ClassInjectionPredicate.java | 2 +- .../FilteredInheritedInjectionPredicate.java | 2 +- .../InheritedInjectionPredicate.java | 2 +- .../qsl/component/test/ComponentTestMod.java | 104 ++++++++++-------- 11 files changed, 81 insertions(+), 96 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/{defaults => }/DefaultFloatComponent.java (95%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/{defaults => }/DefaultIntegerComponent.java (96%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/{defaults => }/DefaultInventoryComponent.java (96%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{api => impl}/predicates/ClassInjectionPredicate.java (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{api => impl}/predicates/FilteredInheritedInjectionPredicate.java (96%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{api => impl}/predicates/InheritedInjectionPredicate.java (96%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 0e27afa2aa..3fd781afa1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -20,9 +20,9 @@ import net.minecraft.util.registry.Registry; import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.api.predicates.ClassInjectionPredicate; -import org.quiltmc.qsl.component.api.predicates.FilteredInheritedInjectionPredicate; -import org.quiltmc.qsl.component.api.predicates.InheritedInjectionPredicate; +import org.quiltmc.qsl.component.impl.predicates.ClassInjectionPredicate; +import org.quiltmc.qsl.component.impl.predicates.FilteredInheritedInjectionPredicate; +import org.quiltmc.qsl.component.impl.predicates.InheritedInjectionPredicate; import java.util.Optional; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java index 545f2409aa..2a3de675e0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java @@ -18,36 +18,25 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtFloat; -import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.components.defaults.DefaultFloatComponent; public interface FloatComponent extends Component, NbtComponent { - static ComponentType create(Identifier id) { - return ComponentsImpl.register(id, DefaultFloatComponent::new); - } - - static ComponentType create(float initialValue, Identifier id) { - return ComponentsImpl.register(id, () -> new DefaultFloatComponent(initialValue)); - } - - float get(); - - void set(float value); @Override default NbtFloat write() { return NbtFloat.of(this.get()); } + float get(); + @Override default void read(NbtFloat nbt) { this.set(nbt.floatValue()); } + void set(float value); + @Override default byte nbtType() { return NbtElement.FLOAT_TYPE; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java index 6ad20ed5fa..1b72f85ed5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java @@ -21,16 +21,9 @@ import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.components.defaults.DefaultIntegerComponent; +import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; public interface IntegerComponent extends NbtComponent { - static ComponentType create(int initialValue, Identifier id) { - return ComponentsImpl.register(id, () -> new DefaultIntegerComponent(initialValue)); - } - - static ComponentType create(Identifier id) { - return ComponentsImpl.register(id, DefaultIntegerComponent::new); - } int get(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index 45de6debb9..55bfa7756e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -22,30 +22,17 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; -import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.components.defaults.DefaultInventoryComponent; - -import java.util.function.Supplier; public interface InventoryComponent extends NbtComponent, Inventory { - static ComponentType ofSize(int size, Identifier id) { - return ComponentsImpl.register(id, () -> new DefaultInventoryComponent(size)); - } - - static ComponentType of(Supplier> items, Identifier id) { - return ComponentsImpl.register(id, () -> new DefaultInventoryComponent(items)); - } - - DefaultedList getStacks(); @Override default int size() { return this.getStacks().size(); } + DefaultedList getStacks(); + @Override default boolean isEmpty() { for (ItemStack stack : this.getStacks()) { @@ -89,6 +76,11 @@ default void setStack(int slot, ItemStack stack) { this.saveNeeded(); } + @Override + default void markDirty() { + this.saveNeeded(); + } + @Override default boolean canPlayerUse(PlayerEntity player) { return true; @@ -114,9 +106,4 @@ default void clear() { this.getStacks().clear(); this.saveNeeded(); } - - @Override - default void markDirty() { - this.saveNeeded(); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java similarity index 95% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultFloatComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java index a4f267c356..a84cb09e37 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.components.defaults; +package org.quiltmc.qsl.component.impl.components; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.FloatComponent; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultIntegerComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java index b436e98454..fb26845650 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.components.defaults; +package org.quiltmc.qsl.component.impl.components; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.IntegerComponent; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultInventoryComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java index ef05eb5dbb..f6a4bcd7ed 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/defaults/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.components.defaults; +package org.quiltmc.qsl.component.impl.components; import net.minecraft.item.ItemStack; import net.minecraft.util.collection.DefaultedList; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/ClassInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java index 0f2193513f..667c505b34 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.predicates; +package org.quiltmc.qsl.component.impl.predicates; import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/FilteredInheritedInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java index c67fb4866f..e6db0a3389 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/FilteredInheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.predicates; +package org.quiltmc.qsl.component.impl.predicates; import java.util.ArrayList; import java.util.Arrays; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/InheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/InheritedInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java index 19b3db66bf..1dd218ca42 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicates/InheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.predicates; +package org.quiltmc.qsl.component.impl.predicates; import org.quiltmc.qsl.component.api.ComponentProvider; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index c25e9ab709..630ec0416a 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -34,7 +34,6 @@ import net.minecraft.util.Unit; import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.registry.Registry; -import net.minecraft.world.WorldProperties; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.level.LevelProperties; import org.quiltmc.loader.api.ModContainer; @@ -43,61 +42,77 @@ import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.components.*; import org.quiltmc.qsl.component.api.event.ComponentEvents; +import org.quiltmc.qsl.component.impl.components.DefaultFloatComponent; +import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; +import org.quiltmc.qsl.component.impl.components.DefaultInventoryComponent; public class ComponentTestMod implements ModInitializer { public static final String MODID = "quilt_component_test"; - // Registration Code - public static final ComponentType COW_INVENTORY = InventoryComponent.of( - () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64)), - new Identifier(MODID, "cow_inventory") + public static final ComponentType COW_INVENTORY = Components.register( + new Identifier(MODID, "cow_inventory"), + () -> new DefaultInventoryComponent(() -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64))) ); - public static final ComponentType CREEPER_EXPLODE_TIME = - IntegerComponent.create(200, new Identifier(MODID, "creeper_explode_time")); - public static final ComponentType HOSTILE_EXPLODE_TIME = - IntegerComponent.create(new Identifier(MODID, "hostile_explode_time")); - public static final ComponentType CHEST_NUMBER = - IntegerComponent.create(200, new Identifier(MODID, "chest_number")); - public static final ComponentType CHUNK_INVENTORY = InventoryComponent.ofSize(1, - new Identifier(MODID, "chunk_inventory") + public static final ComponentType CREEPER_EXPLODE_TIME = Components.register( + new Identifier(MODID, "creeper_explode_time"), + () -> new DefaultIntegerComponent(200) + ); + public static final ComponentType HOSTILE_EXPLODE_TIME = Components.register( + new Identifier(MODID, "hostile_explode_time"), + DefaultIntegerComponent::new + ); + public static final ComponentType CHEST_NUMBER = Components.register( + new Identifier(MODID, "chest_number"), + () -> new DefaultIntegerComponent(200) + ); + public static final ComponentType CHUNK_INVENTORY = Components.register( + new Identifier(MODID, "chunk_inventory"), + () -> new DefaultInventoryComponent(1) + ); + public static final ComponentType SAVE_FLOAT = Components.register( + new Identifier(MODID, "save_float"), + DefaultFloatComponent::new + ); + public static final ComponentType SERVER_TICK = Components.registerTicking( + new Identifier(MODID, "level_tick"), + provider -> { + if (provider instanceof LevelProperties properties) { + properties.expose(SAVE_FLOAT).ifPresent(floatComponent -> floatComponent.set(floatComponent.get() + 0.5f)); + } + } ); - public static final ComponentType SAVE_FLOAT = - FloatComponent.create(new Identifier(MODID, "save_float")); - public static final Block TEST_BLOCK = new TestBlock(AbstractBlock.Settings.copy(Blocks.STONE)); - public static final ComponentType ITEMSTACK_INT = - IntegerComponent.create(new Identifier(MODID, "itemstack_int")); - public static final ComponentType> FUNC_COMP = - Components.registerStatic(new Identifier(MODID, "player_thing"), () -> (provider, unused) -> { + public static final ComponentType ITEMSTACK_INT = Components.register( + new Identifier(MODID, "itemstack_int"), + DefaultIntegerComponent::new + ); + public static final ComponentType> FUNC_COMP = Components.registerStatic( + new Identifier(MODID, "player_thing"), + () -> (provider, unused) -> { if (provider instanceof PlayerEntity entity) { entity.giveItemStack(new ItemStack(Items.WHEAT)); } return Unit.INSTANCE; - }); - public static final ComponentType PLAYER_TICK = - Components.registerTicking(new Identifier(MODID, "warden_tick"), - provider -> { - if (provider instanceof ServerPlayerEntity player) { - ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); - if (stackInHand.isOf(Items.WHEAT)) { - player.call(ComponentTestMod.FUNC_COMP, Unit.INSTANCE) - .ifPresent(unit -> player.sendMessage(Text.literal("Prankt"), true)); - } - - var props = player.getWorld().getServer().getSaveProperties(); - if (props instanceof LevelProperties levelProperties && player.getWorld().getTime() % 100 == 0) { - player.sendMessage(Text.literal( - levelProperties.expose(SAVE_FLOAT).map(FloatComponent::get).orElse(0f).toString() - ), false); - } - } - }); - public static final ComponentType SERVER_TICK = Components.registerTicking(new Identifier(MODID, "level_tick"), + } + ); + public static final ComponentType PLAYER_TICK = Components.registerTicking( + new Identifier(MODID, "warden_tick"), provider -> { - if (provider instanceof LevelProperties properties) { - properties.expose(SAVE_FLOAT).ifPresent(floatComponent -> floatComponent.set(floatComponent.get() + 0.5f)); + if (provider instanceof ServerPlayerEntity player) { + ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); + if (stackInHand.isOf(Items.WHEAT)) { + player.call(ComponentTestMod.FUNC_COMP, Unit.INSTANCE) + .ifPresent(unit -> player.sendMessage(Text.literal("Prankt"), true)); + } + var props = player.getWorld().getServer().getSaveProperties(); + if (props instanceof LevelProperties levelProperties && player.getWorld().getTime() % 100 == 0) { + player.sendMessage(Text.literal( + levelProperties.expose(SAVE_FLOAT).map(FloatComponent::get).orElse(0f).toString() + ), false); + } } - }); + } + ); @Override public void onInitialize(ModContainer mod) { @@ -105,7 +120,7 @@ public void onInitialize(ModContainer mod) { Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(MODID, "block_entity"), TEST_BE_TYPE); Block.STATE_IDS.add(TEST_BLOCK.getDefaultState()); - // Application Code + // Cached Injection Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); Components.injectInheritage(CowEntity.class, COW_INVENTORY); Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); @@ -115,6 +130,7 @@ public void onInitialize(ModContainer mod) { Components.injectInheritage(ServerPlayerEntity.class, FUNC_COMP); Components.inject(LevelProperties.class, SERVER_TICK); + // Dynamic Injection ComponentEvents.DYNAMIC_INJECT.register((provider, injector) -> { injector.injectIf(provider instanceof ItemStack stack && stack.isOf(Items.BOOKSHELF), ITEMSTACK_INT); injector.injectIf(provider instanceof PlayerEntity, PLAYER_TICK); From 0c9fc00a2e76aced02b177105a65b96dc8b79592 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 27 Jun 2022 20:48:58 +0300 Subject: [PATCH 33/70] Code reformat --- .../api/ComponentInjectionPredicate.java | 2 - .../qsl/component/api/ComponentProvider.java | 8 +-- .../qsl/component/api/ComponentType.java | 3 +- .../api/components/FloatComponent.java | 16 ++--- .../api/components/IntegerComponent.java | 20 +++--- .../api/components/InventoryComponent.java | 8 +-- .../api/components/NbtComponent.java | 16 ++--- .../component/api/event/ComponentEvents.java | 4 +- .../components/DefaultFloatComponent.java | 8 +-- .../components/DefaultIntegerComponent.java | 30 ++++---- .../components/DefaultInventoryComponent.java | 14 ++-- .../container/LazifiedComponentContainer.java | 54 +++++++------- .../container/SimpleComponentContainer.java | 71 ++++++++++--------- .../predicates/ClassInjectionPredicate.java | 10 +-- .../FilteredInheritedInjectionPredicate.java | 10 +-- .../InheritedInjectionPredicate.java | 8 +-- .../quiltmc/qsl/component/impl/util/Lazy.java | 40 +++++------ .../qsl/component/mixin/MixinChunk.java | 6 +- .../qsl/component/mixin/MixinItemStack.java | 6 +- .../qsl/component/test/TestBlockEntity.java | 8 ++- 20 files changed, 172 insertions(+), 170 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java index 79f443d3bc..b8399faa32 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java @@ -17,7 +17,5 @@ package org.quiltmc.qsl.component.api; public interface ComponentInjectionPredicate { - boolean canInject(ComponentProvider provider); - } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 66ea056c40..356452d4d8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -38,11 +38,11 @@ public interface ComponentProvider { @NotNull ComponentContainer getContainer(); - default Optional expose(ComponentType id) { - return Components.expose(id, this); - } - default > Optional call(ComponentType type, T t) { return this.expose(type).map(func -> func.call(this, t)); } + + default Optional expose(ComponentType id) { + return Components.expose(id, this); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 2fd183adbc..3fa26a707e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -23,7 +23,8 @@ import java.util.Map; import java.util.Optional; -public record ComponentType(Identifier id, Component.Factory factory, boolean isStatic) implements Component.Factory { +public record ComponentType(Identifier id, Component.Factory factory, + boolean isStatic) implements Component.Factory { public static final Static STATIC_CACHE = new Static(); @SuppressWarnings("unchecked") diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java index 2a3de675e0..169e7dfe37 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java @@ -24,21 +24,21 @@ public interface FloatComponent extends Component, NbtComponent { @Override - default NbtFloat write() { - return NbtFloat.of(this.get()); + default byte nbtType() { + return NbtElement.FLOAT_TYPE; } - float get(); - @Override default void read(NbtFloat nbt) { this.set(nbt.floatValue()); } - void set(float value); - @Override - default byte nbtType() { - return NbtElement.FLOAT_TYPE; + default NbtFloat write() { + return NbtFloat.of(this.get()); } + + float get(); + + void set(float value); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java index 1b72f85ed5..1cd2a91b56 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java @@ -18,30 +18,26 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtInt; -import net.minecraft.util.Identifier; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; public interface IntegerComponent extends NbtComponent { - int get(); - - void set(int value); - void increment(); void decrement(); - default NbtInt write() { - return NbtInt.of(this.get()); + default byte nbtType() { + return NbtElement.INT_TYPE; } default void read(NbtInt nbt) { this.set(nbt.intValue()); } - default byte nbtType() { - return NbtElement.INT_TYPE; + void set(int value); + + default NbtInt write() { + return NbtInt.of(this.get()); } + + int get(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index 55bfa7756e..ce7e73ec38 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -87,8 +87,8 @@ default boolean canPlayerUse(PlayerEntity player) { } @Override - default NbtCompound write() { - return Inventories.writeNbt(new NbtCompound(), this.getStacks()); + default byte nbtType() { + return NbtElement.COMPOUND_TYPE; } @Override @@ -97,8 +97,8 @@ default void read(NbtCompound nbt) { } @Override - default byte nbtType() { - return NbtElement.COMPOUND_TYPE; + default NbtCompound write() { + return Inventories.writeNbt(new NbtCompound(), this.getStacks()); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index 5bf5f7055f..23ca736d47 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -29,10 +29,6 @@ static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier read(nbtComponent, nbtTarget); } - static void writeTo(@NotNull NbtCompound root, @NotNull NbtComponent nbtComponent, @NotNull Identifier id) { - root.put(id.toString(), nbtComponent.write()); - } - @SuppressWarnings("unchecked") // Suppressing because we know those values are hardcoded either way. static void read(@NotNull NbtComponent nbtComponent, NbtElement nbt) { @@ -54,11 +50,15 @@ static void read(@NotNull NbtComponent nbtComponent, NbtElement nbt) { } } - T write(); + byte nbtType(); void read(T nbt); - byte nbtType(); + static void writeTo(@NotNull NbtCompound root, @NotNull NbtComponent nbtComponent, @NotNull Identifier id) { + root.put(id.toString(), nbtComponent.write()); + } + + T write(); default void saveNeeded() { if (this.getSaveOperation() != null) { @@ -66,7 +66,7 @@ default void saveNeeded() { } } - void setSaveOperation(@Nullable Runnable runnable); - @Nullable Runnable getSaveOperation(); + + void setSaveOperation(@Nullable Runnable runnable); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java index 91a6d202f9..77e54a5070 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java @@ -19,12 +19,12 @@ public interface DynamicInject { @FunctionalInterface public interface Injector { - void inject(ComponentType type); - default void injectIf(boolean condition, ComponentType type) { if (condition) { this.inject(type); } } + + void inject(ComponentType type); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java index a84cb09e37..5c39ff9fb7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java @@ -44,12 +44,12 @@ public void set(float value) { } @Override - public void setSaveOperation(@Nullable Runnable runnable) { - this.saveOperation = runnable; + public @Nullable Runnable getSaveOperation() { + return this.saveOperation; } @Override - public @Nullable Runnable getSaveOperation() { - return this.saveOperation; + public void setSaveOperation(@Nullable Runnable runnable) { + this.saveOperation = runnable; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java index fb26845650..749609a1ee 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java @@ -25,23 +25,12 @@ public class DefaultIntegerComponent implements IntegerComponent { @Nullable private Runnable saveOperation; - public DefaultIntegerComponent(int defaultValue) { - this.value = defaultValue; - } - public DefaultIntegerComponent() { this(0); } - @Override - public int get() { - return this.value; - } - - @Override - public void set(int value) { - this.value = value; - this.saveNeeded(); + public DefaultIntegerComponent(int defaultValue) { + this.value = defaultValue; } @Override @@ -57,12 +46,23 @@ public void decrement() { } @Override - public void setSaveOperation(@Nullable Runnable runnable) { - this.saveOperation = runnable; + public void set(int value) { + this.value = value; + this.saveNeeded(); + } + + @Override + public int get() { + return this.value; } @Override public @Nullable Runnable getSaveOperation() { return this.saveOperation; } + + @Override + public void setSaveOperation(@Nullable Runnable runnable) { + this.saveOperation = runnable; + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java index f6a4bcd7ed..8a96a6b5ad 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java @@ -43,14 +43,19 @@ public DefaultedList getStacks() { return this.stacks; } + @Override + public @Nullable Runnable getSaveOperation() { + return this.saveOperation; + } + @Override public void setSaveOperation(@Nullable Runnable runnable) { this.saveOperation = runnable; } @Override - public @Nullable Runnable getSaveOperation() { - return this.saveOperation; + public int hashCode() { + return Objects.hash(stacks); } @Override @@ -59,9 +64,4 @@ public boolean equals(Object o) { if (!(o instanceof DefaultInventoryComponent that)) return false; return stacks.equals(that.stacks); } - - @Override - public int hashCode() { - return Objects.hash(stacks); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java index 7dbef7caba..97ee132070 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java @@ -91,6 +91,34 @@ public static Optional builder(T obj) { return Optional.of(new Builder(provider)); } + public static class Builder { + + private final ComponentProvider provider; + @Nullable + private Runnable saveOperation; + private boolean ticking; + + private Builder(ComponentProvider provider) { + this.provider = provider; + this.ticking = false; + this.saveOperation = null; + } + + public Builder setSaveOperation(Runnable runnable) { + this.saveOperation = runnable; + return this; + } + + public Builder ticking() { + this.ticking = true; + return this; + } + + public LazifiedComponentContainer build() { + return new LazifiedComponentContainer(this.provider, this.saveOperation, this.ticking); + } + } + @Override public Optional expose(Identifier id) { return Optional.ofNullable(this.components.get(id)).map(Lazy::get); @@ -154,31 +182,5 @@ public void moveComponents(ComponentContainer other) { } } - public static class Builder { - - private final ComponentProvider provider; - @Nullable - private Runnable saveOperation; - private boolean ticking; - - private Builder(ComponentProvider provider) { - this.provider = provider; - this.ticking = false; - this.saveOperation = null; - } - public Builder setSaveOperation(Runnable runnable) { - this.saveOperation = runnable; - return this; - } - - public Builder ticking() { - this.ticking = true; - return this; - } - - public LazifiedComponentContainer build() { - return new LazifiedComponentContainer(this.provider, this.saveOperation, this.ticking); - } - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 8ab7cc6732..8a5887b07d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -21,7 +21,10 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.*; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.components.NbtComponent; import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.impl.util.StringConstants; @@ -62,7 +65,38 @@ public static Builder builder() { return new Builder(); } - @Override + public static class Builder { + @NotNull + private final List> types; + @Nullable + private Runnable saveOperation; + + private Builder() { + this.types = new ArrayList<>(); + } + + @NotNull + public Builder setSaveOperation(@NotNull Runnable runnable) { + this.saveOperation = runnable; + return this; + } + + @NotNull + public Builder add(ComponentType type) { + this.types.add(type); + return this; + } + + @NotNull + public Builder add(ComponentType... types) { + this.types.addAll(Arrays.asList(types)); + return this; + } + + public SimpleComponentContainer build() { + return new SimpleComponentContainer(this.saveOperation, this.types.stream()); + } + } @Override public Optional expose(Identifier id) { return Optional.ofNullable(this.components.get(id)); } @@ -102,37 +136,4 @@ public void tick(@NotNull ComponentProvider provider) { .map(it -> ((TickingComponent) it)) .forEach(tickingComponent -> tickingComponent.tick(provider)); } - - public static class Builder { - @Nullable - private Runnable saveOperation; - @NotNull - private final List> types; - - private Builder() { - this.types = new ArrayList<>(); - } - - @NotNull - public Builder setSaveOperation(@NotNull Runnable runnable) { - this.saveOperation = runnable; - return this; - } - - @NotNull - public Builder add(ComponentType type) { - this.types.add(type); - return this; - } - - @NotNull - public Builder add(ComponentType... types) { - this.types.addAll(Arrays.asList(types)); - return this; - } - - public SimpleComponentContainer build() { - return new SimpleComponentContainer(this.saveOperation, this.types.stream()); - } - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java index 667c505b34..7f21047a1a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java @@ -42,6 +42,11 @@ public boolean canInject(ComponentProvider provider) { return provider.getClass() == clazz; } + @Override + public int hashCode() { + return Objects.hash(clazz); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -51,11 +56,6 @@ public boolean equals(Object o) { return false; } - @Override - public int hashCode() { - return Objects.hash(clazz); - } - @Override public String toString() { return "ClassInjectionPredicate{clazz=" + clazz + '}'; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java index e6db0a3389..b3dc315310 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java @@ -29,11 +29,6 @@ public FilteredInheritedInjectionPredicate(Class clazz, Class[] exceptions this.exceptions = new ArrayList<>(Arrays.asList(exceptions)); } - @Override - public boolean canInject(Class current) { - return !this.exceptions.contains(current) && super.canInject(current); - } - @Override public int hashCode() { return super.hashCode() + 37 * Objects.hash(this.exceptions); @@ -51,4 +46,9 @@ public boolean equals(Object o) { public String toString() { return "FilteredInheritedInjectionPredicate{clazz=" + clazz + ", exceptions=" + exceptions + '}'; } + + @Override + public boolean canInject(Class current) { + return !this.exceptions.contains(current) && super.canInject(current); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java index 1dd218ca42..352c0bb19c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java @@ -30,10 +30,6 @@ public boolean canInject(ComponentProvider provider) { return this.canInject(provider.getClass()); } - public boolean canInject(Class current) { - return this.clazz == current || (current != null && canInject(current.getSuperclass())); - } - @Override public int hashCode() { return super.hashCode() + Objects.hash(this.getClass()); @@ -48,4 +44,8 @@ public boolean equals(Object o) { public String toString() { return "InheritedInjectionPredicate{clazz=" + this.clazz + '}'; } + + public boolean canInject(Class current) { + return this.clazz == current || (current != null && canInject(current.getSuperclass())); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java index ba03cbacef..1a41b21eff 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java @@ -41,11 +41,6 @@ private Lazy(@NotNull T value) { this.sup = () -> value; } - @NotNull - public static Lazy of(@NotNull Supplier sup) { - return new Lazy<>(sup); - } - @NotNull public static Lazy filled(@NotNull T value) { return new Lazy<>(value); @@ -57,12 +52,8 @@ public Lazy compose(Function transformer) { } @NotNull - public T get() { - if (value == null) { - this.value = sup.get(); - } - - return value; + public static Lazy of(@NotNull Supplier sup) { + return new Lazy<>(sup); } @NotNull @@ -70,25 +61,39 @@ public Supplier getSupplier() { return sup; } - public boolean isEmpty() { - return this.value == null; - } - @NotNull public Lazy map(@NotNull Function func) { return Lazy.of(() -> func.apply(this.get())); } + @NotNull + public T get() { + if (value == null) { + this.value = sup.get(); + } + + return value; + } + public void ifPresent(@NotNull Consumer action) { if (!this.isEmpty()) { action.accept(this.get()); } } + public boolean isEmpty() { + return this.value == null; + } + public void compute(@NotNull Consumer action) { action.accept(this.get()); } + @Override + public int hashCode() { + return Objects.hash(sup, value); + } + @Override public boolean equals(Object o) { if (o instanceof Lazy other) { @@ -101,9 +106,4 @@ public boolean equals(Object o) { return false; } - - @Override - public int hashCode() { - return Objects.hash(sup, value); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 0ed6dd20a8..ff482c9b31 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -38,9 +38,6 @@ public abstract class MixinChunk implements ComponentProvider { private ComponentContainer qsl$container; - @Shadow - public abstract void setNeedsSaving(boolean needsSaving); - @Inject(method = "", at = @At("RETURN")) private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { this.qsl$container = LazifiedComponentContainer.builder(this) @@ -49,6 +46,9 @@ private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView .build(); } + @Shadow + public abstract void setNeedsSaving(boolean needsSaving); + @Override public @NotNull ComponentContainer getContainer() { return this.qsl$container; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index 794230b2ee..d63d46683d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -21,9 +21,6 @@ @Mixin(ItemStack.class) public abstract class MixinItemStack implements ComponentProvider { // TODO: Make sure nothing else may be broken before final PR. - @Shadow - public abstract NbtCompound getOrCreateNbt(); - @Shadow private @Nullable NbtCompound nbt; private LazifiedComponentContainer qsl$container; @@ -37,6 +34,9 @@ private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo .build(); } + @Shadow + public abstract NbtCompound getOrCreateNbt(); + @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;)V", at = @At("TAIL")) private void readContainer(NbtCompound nbtCompound, CallbackInfo ci) { this.qsl$container = LazifiedComponentContainer.builder(this) diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index a1124cb18d..8dc2978de4 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -31,8 +31,10 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.InventoryComponent; +import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; import java.util.Arrays; @@ -41,8 +43,10 @@ import java.util.Set; public class TestBlockEntity extends BlockEntity { - public static final ComponentType TEST_BE_INT = - IntegerComponent.create(new Identifier("quilt_component_test", "test_be_int")); + public static final ComponentType TEST_BE_INT = Components.register( + new Identifier(ComponentTestMod.MODID, "test_be_int"), + DefaultIntegerComponent::new + ); private final ComponentContainer container = SimpleComponentContainer.builder() .setSaveOperation(this::markDirty) From 5ccb0de4564efafd2f2f8e5265e09eb976a42b62 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 28 Jun 2022 23:08:06 +0300 Subject: [PATCH 34/70] Almost the whole implementation of network sync. --- library/data/component/build.gradle | 13 +- .../qsl/component/api/ComponentContainer.java | 7 +- .../api/components/FloatComponent.java | 17 +- .../api/components/IntegerComponent.java | 17 +- .../api/components/InventoryComponent.java | 15 +- .../api/components/NbtComponent.java | 45 ++-- .../api/components/SyncedComponent.java | 22 ++ .../qsl/component/impl/CommonInitializer.java | 31 +++ .../qsl/component/impl/ComponentsImpl.java | 18 +- .../impl/client/ClientInitializer.java | 21 ++ .../client/sync/ClientRegistryPacket.java | 48 +++++ .../impl/client/sync/ClientSyncHandler.java | 42 ++++ .../components/DefaultFloatComponent.java | 21 +- .../components/DefaultIntegerComponent.java | 23 +- .../container/LazifiedComponentContainer.java | 196 +++++++++++------- .../container/SimpleComponentContainer.java | 145 ++++++++----- .../impl/sync/ComponentHeaderRegistry.java | 19 ++ .../impl/sync/DefaultSyncPacketHeaders.java | 39 ++++ .../impl/sync/ServerSyncHandler.java | 42 ++++ .../impl/sync/codec/NetworkCodec.java | 18 ++ .../impl/sync/header/SyncPacketHeader.java | 18 ++ .../impl/sync/packet/ComponentSyncPacket.java | 39 ++++ .../component/impl/sync/packet/PacketIds.java | 10 + .../impl/sync/packet/RegistryPacket.java | 37 ++++ .../qsl/component/mixin/MixinBlockEntity.java | 4 + .../qsl/component/mixin/MixinChunk.java | 3 + .../qsl/component/mixin/MixinEntity.java | 5 + .../component/mixin/MixinLevelProperties.java | 3 + .../qsl/component/mixin/MixinWorldChunk.java | 6 +- .../qsl/component/test/ComponentTestMod.java | 21 +- .../component/test/ServerTickListener.java | 14 +- .../quiltmc/qsl/component/test/TestBlock.java | 3 +- .../qsl/component/test/TestBlockEntity.java | 30 ++- 33 files changed, 761 insertions(+), 231 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/DefaultSyncPacketHeaders.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/ComponentSyncPacket.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index 721d4bc57a..28b045c545 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -12,12 +12,23 @@ qslModule { core { api("qsl_base") api("lifecycle_events") + api("networking") } } entrypoints { events { - values = ["org.quiltmc.qsl.component.impl.event.ServerTickEventListener"] + values = [ + "org.quiltmc.qsl.component.impl.event.ServerTickEventListener" + ] + } + + init { + values = ["org.quiltmc.qsl.component.impl.CommonInitializer"] + } + + client_init { + values = ["org.quiltmc.qsl.component.impl.client.ClientInitializer"] } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index 7aa2759e3d..1f60acffcd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -17,6 +17,7 @@ package org.quiltmc.qsl.component.api; import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; @@ -25,11 +26,13 @@ public interface ComponentContainer { Optional expose(Identifier id); - void moveComponents(ComponentContainer other); - void writeNbt(@NotNull NbtCompound providerRootNbt); void readNbt(@NotNull NbtCompound providerRootNbt); void tick(@NotNull ComponentProvider provider); + + void receiveSyncPacket(@NotNull Identifier id, @NotNull PacketByteBuf buf); + + void sync(@NotNull ComponentProvider provider); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java index 169e7dfe37..3e60fbaa3c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java @@ -21,22 +21,7 @@ import org.quiltmc.qsl.component.api.Component; -public interface FloatComponent extends Component, NbtComponent { - - @Override - default byte nbtType() { - return NbtElement.FLOAT_TYPE; - } - - @Override - default void read(NbtFloat nbt) { - this.set(nbt.floatValue()); - } - - @Override - default NbtFloat write() { - return NbtFloat.of(this.get()); - } +public interface FloatComponent extends Component { float get(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java index 1cd2a91b56..bd174713de 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java @@ -16,28 +16,15 @@ package org.quiltmc.qsl.component.api.components; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtInt; +import org.quiltmc.qsl.component.api.Component; -public interface IntegerComponent extends NbtComponent { +public interface IntegerComponent extends Component { void increment(); void decrement(); - default byte nbtType() { - return NbtElement.INT_TYPE; - } - - default void read(NbtInt nbt) { - this.set(nbt.intValue()); - } - void set(int value); - default NbtInt write() { - return NbtInt.of(this.get()); - } - int get(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index ce7e73ec38..a9d901e851 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -51,18 +51,12 @@ default ItemStack getStack(int slot) { @Override default ItemStack removeStack(int slot, int amount) { - var result = Inventories.splitStack(this.getStacks(), slot, amount); - this.saveNeeded(); - - return result; + return Inventories.splitStack(this.getStacks(), slot, amount); } @Override default ItemStack removeStack(int slot) { - var result = Inventories.removeStack(this.getStacks(), slot); - this.saveNeeded(); - - return result; + return Inventories.removeStack(this.getStacks(), slot); } @Override @@ -72,13 +66,11 @@ default void setStack(int slot, ItemStack stack) { if (slotStack.getCount() > this.getMaxCountPerStack()) { slotStack.setCount(this.getMaxCountPerStack()); } - - this.saveNeeded(); } @Override default void markDirty() { - this.saveNeeded(); + this.save(); } @Override @@ -104,6 +96,5 @@ default NbtCompound write() { @Override default void clear() { this.getStacks().clear(); - this.saveNeeded(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index 23ca736d47..262b4346bd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -24,43 +24,40 @@ public interface NbtComponent extends Component { - static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier id, @NotNull NbtCompound nbt) { - NbtElement nbtTarget = nbt.get(id.toString()); - read(nbtComponent, nbtTarget); - } - @SuppressWarnings("unchecked") - // Suppressing because we know those values are hardcoded either way. - static void read(@NotNull NbtComponent nbtComponent, NbtElement nbt) { + static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier id, @NotNull NbtCompound root) { + NbtElement nbtTarget = root.get(id.toString()); switch (nbtComponent.nbtType()) { - case NbtElement.BYTE_TYPE -> ((NbtComponent) nbtComponent).read((NbtByte) nbt); - case NbtElement.SHORT_TYPE -> ((NbtComponent) nbtComponent).read((NbtShort) nbt); - case NbtElement.INT_TYPE -> ((NbtComponent) nbtComponent).read((NbtInt) nbt); - case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbt); - case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbt); - case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbt); - case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbt); - case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbt); - case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbt); - case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbt); - case NbtElement.INT_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtIntArray) nbt); - case NbtElement.LONG_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtLongArray) nbt); + case NbtElement.BYTE_TYPE -> ((NbtComponent) nbtComponent).read((NbtByte) nbtTarget); + case NbtElement.SHORT_TYPE -> ((NbtComponent) nbtComponent).read((NbtShort) nbtTarget); + case NbtElement.INT_TYPE -> ((NbtComponent) nbtComponent).read((NbtInt) nbtTarget); + case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); + case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); + case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); + case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); + case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); + case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); + case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); + case NbtElement.INT_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtIntArray) nbtTarget); + case NbtElement.LONG_ARRAY_TYPE -> + ((NbtComponent) nbtComponent).read((NbtLongArray) nbtTarget); default -> // TODO: Handle non-vanilla nbt types. throw new RuntimeException("The nbt data type with id %d is not handled at the moment!".formatted(nbtComponent.nbtType())); + } } - byte nbtType(); - - void read(T nbt); - static void writeTo(@NotNull NbtCompound root, @NotNull NbtComponent nbtComponent, @NotNull Identifier id) { root.put(id.toString(), nbtComponent.write()); } + byte nbtType(); + + void read(T nbt); + T write(); - default void saveNeeded() { + default void save() { if (this.getSaveOperation() != null) { this.getSaveOperation().run(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java new file mode 100644 index 0000000000..04188f3782 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java @@ -0,0 +1,22 @@ +package org.quiltmc.qsl.component.api.components; + +import net.minecraft.network.PacketByteBuf; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; + +public interface SyncedComponent extends Component { + void writeToBuf(@NotNull PacketByteBuf buf); + + void readFromBuf(@NotNull PacketByteBuf buf); + + @Nullable Runnable getSyncOperation(); + + void setSyncOperation(@NotNull Runnable runnable); + + default void sync() { + if (this.getSyncOperation() != null) { + this.getSyncOperation().run(); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java new file mode 100644 index 0000000000..936ded16cc --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -0,0 +1,31 @@ +package org.quiltmc.qsl.component.impl; + +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; +import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; +import org.quiltmc.qsl.component.impl.sync.ServerSyncHandler; +import org.quiltmc.qsl.lifecycle.api.event.ServerLifecycleEvents; +import org.quiltmc.qsl.networking.api.ServerLoginConnectionEvents; + +@ApiStatus.Internal +public final class CommonInitializer implements ModInitializer { + + @Override + public void onInitialize(ModContainer mod) { + DefaultSyncPacketHeaders.registerDefaults(); + ServerSyncHandler.getInstance().registerPackets(); + ServerLoginConnectionEvents.QUERY_START.register(id("component_sync"), ServerSyncHandler.getInstance()); + + ServerLifecycleEvents.STARTING.register( + id("freeze_component_registries"), + server -> ComponentsImpl.freezeRegistries() + ); + } + + public static @NotNull Identifier id(@NotNull String id) { + return new Identifier(ComponentsImpl.MODID, id); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 8f69614eba..3b17e628b8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -23,18 +23,24 @@ import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.SimpleRegistry; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.impl.sync.ComponentHeaderRegistry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; import java.util.stream.Collectors; @ApiStatus.Internal public class ComponentsImpl { - private static final Map> INJECTION_REGISTRY = new HashMap<>(); + private static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); + public static final String MODID = "quilt_component"; + private static final Map> INJECTION_REGISTRY = new HashMap<>(); private static final RegistryKey>> REGISTRY_KEY = RegistryKey.ofRegistry(new Identifier("quilt", "components")); public static final Registry> REGISTRY = @@ -91,4 +97,14 @@ public static ComponentType getEntry(Identifier id) { ErrorUtil.illegalArgument("Cannot access element with id %s in the component registry!".formatted(id)) ); } + + @NotNull + public static Logger getLogger() { + return LOGGER; + } + + public static void freezeRegistries() { + REGISTRY.freeze(); + ComponentHeaderRegistry.HEADERS.freeze(); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java new file mode 100644 index 0000000000..0fdd653753 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java @@ -0,0 +1,21 @@ +package org.quiltmc.qsl.component.impl.client; + +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; +import org.quiltmc.qsl.component.impl.CommonInitializer; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; +import org.quiltmc.qsl.lifecycle.api.client.event.ClientLifecycleEvents; + +public class ClientInitializer implements ClientModInitializer { + + @Override + public void onInitializeClient(ModContainer mod) { + ClientSyncHandler.getInstance().registerPackets(); + + ClientLifecycleEvents.READY.register( + CommonInitializer.id("freeze_component_registies"), + client -> ComponentsImpl.freezeRegistries() + ); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java new file mode 100644 index 0000000000..07691e7ba1 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java @@ -0,0 +1,48 @@ +package org.quiltmc.qsl.component.impl.client.sync; + +import com.mojang.datafixers.util.Either; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.IdList; +import net.minecraft.util.registry.Registry; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.networking.api.PacketByteBufs; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +public final class ClientRegistryPacket { + + @NotNull + public static CompletableFuture handleRegistryPacket(@NotNull PacketByteBuf buf, Registry registry, Consumer> action) { + return CompletableFuture.supplyAsync(() -> { + var finalEither = createIdList(buf, registry) + .ifLeft(action) + .mapLeft(clientHeaderList -> PacketByteBufs.create().writeString("Ok")) + .mapRight(PacketByteBufs.create()::writeIdentifier); + + return finalEither.left().isPresent() ? finalEither.left().get() : finalEither.right().get(); + }); + } + + @NotNull + public static Either, Identifier> createIdList(PacketByteBuf buf, Registry targetRegistry) { + int size = buf.readInt(); + IdList ret = new IdList<>(size); // size is dropped + + for (int i = 0; i < size; i++) { + Identifier id = buf.readIdentifier(); + int rawId = buf.readInt(); // a whole entry is dropped + + Optional type = targetRegistry.getOrEmpty(id); + if (type.isEmpty()) { + return Either.right(id); + } + + ret.set(type.get(), rawId); + } + + return Either.left(ret); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java new file mode 100644 index 0000000000..6b1a2c0a9d --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -0,0 +1,42 @@ +package org.quiltmc.qsl.component.impl.client.sync; + +import net.minecraft.util.collection.IdList; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.impl.sync.ComponentHeaderRegistry; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; +import org.quiltmc.qsl.networking.api.client.ClientLoginNetworking; + +public class ClientSyncHandler { + + private static ClientSyncHandler INSTANCE = null; + private IdList> componentList = null; + private IdList> headerList = null; + + public static ClientSyncHandler getInstance() { + if (INSTANCE == null) { + INSTANCE = new ClientSyncHandler(); + } + + return INSTANCE; + } + + public void registerPackets() { + ClientLoginNetworking.registerGlobalReceiver(PacketIds.TYPES, (client, handler, buf, listenerAdder) -> + ClientRegistryPacket.handleRegistryPacket(buf, Components.REGISTRY, list -> this.componentList = list) + ); + + ClientLoginNetworking.registerGlobalReceiver(PacketIds.HEADERS, (client, handler, buf, listenerAdder) -> + ClientRegistryPacket.handleRegistryPacket(buf, ComponentHeaderRegistry.HEADERS, list -> this.headerList = list) + ); + } + + public SyncPacketHeader getHeader(int rawId) { + return this.headerList.get(rawId); + } + + public ComponentType getType(int rawId) { + return this.componentList.get(rawId); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java index 5c39ff9fb7..796862e8a4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java @@ -16,10 +16,13 @@ package org.quiltmc.qsl.component.impl.components; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtFloat; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.FloatComponent; +import org.quiltmc.qsl.component.api.components.NbtComponent; -public class DefaultFloatComponent implements FloatComponent { +public class DefaultFloatComponent implements FloatComponent, NbtComponent { private float value; @Nullable private Runnable saveOperation; @@ -40,7 +43,21 @@ public float get() { @Override public void set(float value) { this.value = value; - this.saveNeeded(); + } + + @Override + public byte nbtType() { + return NbtElement.FLOAT_TYPE; + } + + @Override + public void read(NbtFloat nbt) { + this.value = nbt.floatValue(); + } + + @Override + public NbtFloat write() { + return NbtFloat.of(this.value); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java index 749609a1ee..ee17b1f4e6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java @@ -16,10 +16,13 @@ package org.quiltmc.qsl.component.impl.components; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtInt; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.IntegerComponent; +import org.quiltmc.qsl.component.api.components.NbtComponent; -public class DefaultIntegerComponent implements IntegerComponent { +public class DefaultIntegerComponent implements IntegerComponent, NbtComponent { private int value; @Nullable @@ -36,19 +39,16 @@ public DefaultIntegerComponent(int defaultValue) { @Override public void increment() { this.value++; - this.saveNeeded(); } @Override public void decrement() { this.value--; - this.saveNeeded(); } @Override public void set(int value) { this.value = value; - this.saveNeeded(); } @Override @@ -56,6 +56,21 @@ public int get() { return this.value; } + @Override + public byte nbtType() { + return NbtElement.INT_TYPE; + } + + @Override + public void read(NbtInt nbt) { + this.value = nbt.intValue(); + } + + @Override + public NbtInt write() { + return NbtInt.of(this.value); + } + @Override public @Nullable Runnable getSaveOperation() { return this.saveOperation; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java index 97ee132070..ffc9441a04 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java @@ -17,6 +17,8 @@ package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -25,14 +27,20 @@ import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.components.SyncedComponent; import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.api.event.ComponentEvents; import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.packet.ComponentSyncPacket; +import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.Lazy; import org.quiltmc.qsl.component.impl.util.StringConstants; +import org.quiltmc.qsl.networking.api.ServerPlayNetworking; import java.util.*; +import java.util.function.Supplier; public class LazifiedComponentContainer implements ComponentContainer { @@ -42,47 +50,26 @@ public class LazifiedComponentContainer implements ComponentContainer { @Nullable private final Runnable saveOperation; private final boolean ticking; - - protected LazifiedComponentContainer(@NotNull ComponentProvider provider, @Nullable Runnable saveOperation, boolean ticking) { + private final boolean syncing; + private final SyncContext syncContext; + private final Queue pendingSync; + + protected LazifiedComponentContainer( + @NotNull ComponentProvider provider, + @Nullable Runnable saveOperation, + boolean ticking, + @Nullable SyncContext syncContext + ) { this.saveOperation = saveOperation; this.ticking = ticking; + this.syncing = syncContext != null; + this.syncContext = syncContext; this.nbtComponents = new ArrayList<>(); this.tickingComponents = new ArrayList<>(); + this.pendingSync = new ArrayDeque<>(); this.components = this.initializeComponents(provider); } - private Map> initializeComponents(ComponentProvider provider) { - var map = new HashMap>(); - ComponentsImpl.getInjections(provider).forEach(type -> map.put(type.id(), this.createLazy(type))); - ComponentEvents.DYNAMIC_INJECT.invoker().onInject(provider, type -> map.put(type.id(), this.createLazy(type))); - return map; - } - - private Lazy createLazy(ComponentType type) { - if (type.isStatic()) { - Component singleton = type.create(); - if (this.ticking && singleton instanceof TickingComponent) { - this.tickingComponents.add(type.id()); - } - - return Lazy.filled(singleton); - } - - return Lazy.of(() -> { - Component component = type.create(); - if (component instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(type.id()); - nbtComponent.setSaveOperation(this.saveOperation); - } - - if (this.ticking && component instanceof TickingComponent) { - this.tickingComponents.add(type.id()); - } - - return component; - }); - } - public static Optional builder(T obj) { if (!(obj instanceof ComponentProvider provider)) { return Optional.empty(); @@ -91,32 +78,18 @@ public static Optional builder(T obj) { return Optional.of(new Builder(provider)); } - public static class Builder { - - private final ComponentProvider provider; - @Nullable - private Runnable saveOperation; - private boolean ticking; - - private Builder(ComponentProvider provider) { - this.provider = provider; - this.ticking = false; - this.saveOperation = null; - } - - public Builder setSaveOperation(Runnable runnable) { - this.saveOperation = runnable; - return this; - } + public static void move(@NotNull LazifiedComponentContainer from, @NotNull LazifiedComponentContainer into) { + from.components.forEach((id, componentLazy) -> componentLazy.ifPresent(component -> { + into.components.put(id, componentLazy); // Directly overriding our value. - public Builder ticking() { - this.ticking = true; - return this; - } + if (component instanceof NbtComponent nbtComponent) { + into.nbtComponents.add(id); + nbtComponent.setSaveOperation(into.saveOperation); + } + })); - public LazifiedComponentContainer build() { - return new LazifiedComponentContainer(this.provider, this.saveOperation, this.ticking); - } + from.components.clear(); + from.nbtComponents.clear(); } @Override @@ -161,26 +134,103 @@ public void tick(@NotNull ComponentProvider provider) { .map(Optional::orElseThrow) .map(it -> ((TickingComponent) it)) .forEach(tickingComponent -> tickingComponent.tick(provider)); + // Sync any queued components + this.sync(provider); + } + + @Override + public void receiveSyncPacket(@NotNull Identifier id, @NotNull PacketByteBuf buf) { + this.expose(id).map(it -> ((SyncedComponent) it)).ifPresent(syncedComponent -> syncedComponent.readFromBuf(buf)); } @Override - public void moveComponents(ComponentContainer other) { - if (other instanceof LazifiedComponentContainer otherContainer) { - otherContainer.components.forEach((id, componentLazy) -> componentLazy.ifPresent(component -> { - this.components.put(id, componentLazy); // Directly overriding our value. - - if (component instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(id); - nbtComponent.setSaveOperation(this.saveOperation); - } - })); - - otherContainer.components.clear(); - otherContainer.nbtComponents.clear(); - } else { - throw ErrorUtil.illegalArgument("Cannot move components from a non-lazified container to one that is!").get(); + public void sync(@NotNull ComponentProvider provider) { + var map = new HashMap(); + + while (!this.pendingSync.isEmpty()) { + var id = this.pendingSync.poll(); + map.put(id, (SyncedComponent) this.components.get(id).get()); + } + + if (!map.isEmpty()) { + var packet = ComponentSyncPacket.create(this.syncContext.header(), provider, map); + + this.syncContext.playerGenerator().get().forEach(serverPlayer -> + ServerPlayNetworking.send(serverPlayer, PacketIds.SYNC, packet) + ); } } + private Map> initializeComponents(ComponentProvider provider) { + var map = new HashMap>(); + ComponentsImpl.getInjections(provider).forEach(type -> map.put(type.id(), this.createLazy(type))); + ComponentEvents.DYNAMIC_INJECT.invoker().onInject(provider, type -> map.put(type.id(), this.createLazy(type))); + return map; + } + + private Lazy createLazy(ComponentType type) { + if (type.isStatic()) { + Component singleton = type.create(); + if (this.ticking && singleton instanceof TickingComponent) { + this.tickingComponents.add(type.id()); + } + + return Lazy.filled(singleton); + } + + return Lazy.of(() -> { + Component component = type.create(); + if (component instanceof NbtComponent nbtComponent) { + this.nbtComponents.add(type.id()); + nbtComponent.setSaveOperation(this.saveOperation); + } + + if (this.ticking && component instanceof TickingComponent) { + this.tickingComponents.add(type.id()); + } + + if (this.syncing && component instanceof SyncedComponent syncedComponent) { + syncedComponent.setSyncOperation(() -> this.pendingSync.add(type.id())); + } + + return component; + }); + } + + public static class Builder { + + private final ComponentProvider provider; + @Nullable + private Runnable saveOperation; + private boolean ticking; + private SyncContext syncContext; + + private Builder(ComponentProvider provider) { + this.provider = provider; + this.ticking = false; + this.saveOperation = null; + } + + public Builder setSaveOperation(Runnable runnable) { + this.saveOperation = runnable; + return this; + } + + public Builder ticking() { + this.ticking = true; + return this; + } + public Builder syncing(@NotNull SyncPacketHeader header, Supplier> playerGenerator) { + this.syncContext = new SyncContext(header, playerGenerator); + return this; + } + + public LazifiedComponentContainer build() { + return new LazifiedComponentContainer(this.provider, this.saveOperation, this.ticking, this.syncContext); + } + } + + public record SyncContext(SyncPacketHeader header, Supplier> playerGenerator) { + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 8a5887b07d..fd9a19ba1a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -17,6 +17,7 @@ package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -26,7 +27,10 @@ import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.components.SyncedComponent; import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.packet.ComponentSyncPacket; import org.quiltmc.qsl.component.impl.util.StringConstants; import java.util.*; @@ -36,26 +40,19 @@ public class SimpleComponentContainer implements ComponentContainer { private final Map components; private final List nbtComponents; private final List tickingComponents; + private Queue pendingSync; + private SyncPacketHeader header; - protected SimpleComponentContainer(@Nullable Runnable saveOperation, Stream> types) { + protected SimpleComponentContainer(@Nullable Runnable saveOperation, SyncPacketHeader header, Stream> types) { this.components = new HashMap<>(); this.nbtComponents = new ArrayList<>(); this.tickingComponents = new ArrayList<>(); + if (header != null) { + this.header = header; + this.pendingSync = new ArrayDeque<>(); + } - types.forEach(type -> { - Component component = type.create(); - this.components.put(type.id(), component); - - if (component instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(type.id()); - nbtComponent.setSaveOperation(saveOperation); - } - - if (component instanceof TickingComponent) { - this.tickingComponents.add(type.id()); - } - }); - + types.forEach(type -> this.initializeComponent(saveOperation, type)); types.close(); } @@ -65,47 +62,11 @@ public static Builder builder() { return new Builder(); } - public static class Builder { - @NotNull - private final List> types; - @Nullable - private Runnable saveOperation; - - private Builder() { - this.types = new ArrayList<>(); - } - - @NotNull - public Builder setSaveOperation(@NotNull Runnable runnable) { - this.saveOperation = runnable; - return this; - } - - @NotNull - public Builder add(ComponentType type) { - this.types.add(type); - return this; - } - - @NotNull - public Builder add(ComponentType... types) { - this.types.addAll(Arrays.asList(types)); - return this; - } - - public SimpleComponentContainer build() { - return new SimpleComponentContainer(this.saveOperation, this.types.stream()); - } - } @Override + @Override public Optional expose(Identifier id) { return Optional.ofNullable(this.components.get(id)); } - @Override - public void moveComponents(ComponentContainer other) { - throw new IllegalStateException("Cannot move components into a SimpleComponentContainer"); - } - @Override public void writeNbt(@NotNull NbtCompound providerRootNbt) { var rootQslNbt = new NbtCompound(); @@ -135,5 +96,85 @@ public void tick(@NotNull ComponentProvider provider) { .map(this.components::get) .map(it -> ((TickingComponent) it)) .forEach(tickingComponent -> tickingComponent.tick(provider)); + + this.sync(provider); + } + + @Override + public void receiveSyncPacket(@NotNull Identifier id, @NotNull PacketByteBuf buf) { + ((SyncedComponent) this.components.get(id)).readFromBuf(buf); + } + + @Override + public void sync(@NotNull ComponentProvider provider) { + var map = new HashMap(); + + while (!this.pendingSync.isEmpty()) { + var currentId = this.pendingSync.poll(); + map.put(currentId, (SyncedComponent) this.components.get(currentId)); + } + + if (!map.isEmpty()) { + var packet = ComponentSyncPacket.create(this.header, provider, map); + } + } + + private void initializeComponent(@Nullable Runnable saveOperation, ComponentType type) { + Component component = type.create(); + this.components.put(type.id(), component); + + if (component instanceof NbtComponent nbtComponent) { + this.nbtComponents.add(type.id()); + nbtComponent.setSaveOperation(saveOperation); + } + + if (component instanceof TickingComponent) { + this.tickingComponents.add(type.id()); + } + + if (component instanceof SyncedComponent synced) { + synced.setSyncOperation(() -> this.pendingSync.add(type.id())); + } + } + + public static class Builder { + @NotNull + private final List> types; + @Nullable + private Runnable saveOperation; + private SyncPacketHeader header; + + private Builder() { + this.types = new ArrayList<>(); + } + + @NotNull + public Builder setSaveOperation(@NotNull Runnable runnable) { + this.saveOperation = runnable; + return this; + } + + @NotNull + public Builder syncing(SyncPacketHeader header) { + this.header = header; + return this; + } + + @NotNull + public Builder add(ComponentType type) { + this.types.add(type); + return this; + } + + @NotNull + public Builder add(ComponentType... types) { + this.types.addAll(Arrays.asList(types)); + return this; + } + + @NotNull + public SimpleComponentContainer build() { + return new SimpleComponentContainer(this.saveOperation, this.header, this.types.stream()); + } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java new file mode 100644 index 0000000000..865304ac87 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java @@ -0,0 +1,19 @@ +package org.quiltmc.qsl.component.impl.sync; + +import com.mojang.serialization.Lifecycle; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.util.registry.SimpleRegistry; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.impl.CommonInitializer; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; + +public class ComponentHeaderRegistry { + public static final Registry> HEADERS = + new SimpleRegistry<>(RegistryKey.ofRegistry(CommonInitializer.id("sync_headers")), Lifecycle.experimental(), null); + + public static

SyncPacketHeader

register(Identifier id, SyncPacketHeader

header) { + return Registry.register(HEADERS, id, header); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/DefaultSyncPacketHeaders.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/DefaultSyncPacketHeaders.java new file mode 100644 index 0000000000..f58cc8bba2 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/DefaultSyncPacketHeaders.java @@ -0,0 +1,39 @@ +package org.quiltmc.qsl.component.impl.sync; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.Chunk; +import org.quiltmc.qsl.component.impl.CommonInitializer; +import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; + +@SuppressWarnings("ConstantConditions") // The accessed fields in this case will never be null since the only times this class is accessed are during play. +public final class DefaultSyncPacketHeaders { + private static final NetworkCodec BLOCK_ENTITY_CODEC = new NetworkCodec<>( + (blockEntity, packetByteBuf) -> packetByteBuf.writeBlockPos(blockEntity.getPos()), + packetByteBuf -> MinecraftClient.getInstance().world.getBlockEntity(packetByteBuf.readBlockPos()) + ); + public static final SyncPacketHeader BLOCK_ENTITY = new SyncPacketHeader<>(BLOCK_ENTITY_CODEC); + private static final NetworkCodec ENTITY_CODEC = new NetworkCodec<>( + (entity, packetByteBuf) -> packetByteBuf.writeInt(entity.getId()), + packetByteBuf -> MinecraftClient.getInstance().world.getEntityById(packetByteBuf.readInt()) + ); + public static final SyncPacketHeader ENTITY = new SyncPacketHeader<>(ENTITY_CODEC); + private static final NetworkCodec CHUNK_CODEC = new NetworkCodec<>( + (chunk, packetByteBuf) -> packetByteBuf.writeChunkPos(chunk.getPos()), + packetByteBuf -> { + ChunkPos pos = packetByteBuf.readChunkPos(); + return MinecraftClient.getInstance().world.getChunk(pos.x, pos.z); + } + ); + public static final SyncPacketHeader CHUNK = new SyncPacketHeader<>(CHUNK_CODEC); + // TODO: LevelProperties sync + + public static void registerDefaults() { + ComponentHeaderRegistry.register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); + ComponentHeaderRegistry.register(CommonInitializer.id("entity"), ENTITY); + ComponentHeaderRegistry.register(CommonInitializer.id("chunk"), CHUNK); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java new file mode 100644 index 0000000000..f35e4bfc6e --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java @@ -0,0 +1,42 @@ +package org.quiltmc.qsl.component.impl.sync; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerLoginNetworkHandler; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; +import org.quiltmc.qsl.component.impl.sync.packet.RegistryPacket; +import org.quiltmc.qsl.networking.api.PacketSender; +import org.quiltmc.qsl.networking.api.ServerLoginConnectionEvents; +import org.quiltmc.qsl.networking.api.ServerLoginNetworking; + +public final class ServerSyncHandler implements ServerLoginConnectionEvents.QueryStart { + + private static ServerSyncHandler INSTANCE = null; + + private ServerSyncHandler() { + + } + + public static ServerSyncHandler getInstance() { + if (INSTANCE == null) { + INSTANCE = new ServerSyncHandler(); + } + + return INSTANCE; + } + + public void registerPackets() { + ServerLoginNetworking.registerGlobalReceiver(PacketIds.TYPES, (server, handler, understood, buf, sync, sender) -> + RegistryPacket.handleRegistryResponse(buf, handler, "Component with id %s was not found in the client!") + ); + ServerLoginNetworking.registerGlobalReceiver(PacketIds.HEADERS, (server, handler, understood, buf, synchronizer, sender) -> + RegistryPacket.handleRegistryResponse(buf, handler, "Header with id %s was not found in the client!") + ); + } + + @Override + public void onLoginStart(ServerLoginNetworkHandler handler, MinecraftServer server, PacketSender sender, ServerLoginNetworking.LoginSynchronizer synchronizer) { + sender.sendPacket(PacketIds.TYPES, RegistryPacket.createRegistryPacket(Components.REGISTRY)); + sender.sendPacket(PacketIds.HEADERS, RegistryPacket.createRegistryPacket(ComponentHeaderRegistry.HEADERS)); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java new file mode 100644 index 0000000000..86750171f2 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java @@ -0,0 +1,18 @@ +package org.quiltmc.qsl.component.impl.sync.codec; + +import net.minecraft.network.PacketByteBuf; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Function; + +public record NetworkCodec(@NotNull BiConsumer encoder, @NotNull Function decoder) { + public void encode(@NotNull PacketByteBuf buf, T t) { + this.encoder.accept(t, buf); + } + + public Optional decode(@NotNull PacketByteBuf buf) { + return Optional.ofNullable(this.decoder.apply(buf)); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java new file mode 100644 index 0000000000..191df8d1ce --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -0,0 +1,18 @@ +package org.quiltmc.qsl.component.impl.sync.header; + +import net.minecraft.network.PacketByteBuf; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.impl.sync.ComponentHeaderRegistry; +import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; +import org.quiltmc.qsl.networking.api.PacketByteBufs; + +public record SyncPacketHeader

(@NotNull NetworkCodec

codec) { + public @NotNull PacketByteBuf start(@NotNull ComponentProvider provider) { + var buf = PacketByteBufs.create(); + buf.writeInt(ComponentHeaderRegistry.HEADERS.getRawId(this)); + this.codec.encode(buf, provider); + + return buf; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/ComponentSyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/ComponentSyncPacket.java new file mode 100644 index 0000000000..3cde6347b1 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/ComponentSyncPacket.java @@ -0,0 +1,39 @@ +package org.quiltmc.qsl.component.impl.sync.packet; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.components.SyncedComponent; +import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; + +import java.util.Map; + +public class ComponentSyncPacket { + @NotNull + public static PacketByteBuf create(SyncPacketHeader headerCreator, @NotNull ComponentProvider provider, Map components) { + PacketByteBuf buff = headerCreator.start(provider); + buff.writeVarInt(components.size()); + components.forEach((id, syncedComponent) -> { + int rawId = Components.REGISTRY.getRawId(Components.REGISTRY.get(id)); + buff.writeInt(rawId); + syncedComponent.writeToBuf(buff); + }); + + return buff; + } + + public static void handle(PacketByteBuf buf) { + int rawHeaderId = buf.readInt(); + var header = ClientSyncHandler.getInstance().getHeader(rawHeaderId); + + header.codec().decode(buf).ifPresent(provider -> { + ComponentType type = ClientSyncHandler.getInstance().getType(buf.readInt()); + + provider.getContainer().receiveSyncPacket(type.id(), buf); + }); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java new file mode 100644 index 0000000000..890b5eda1d --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java @@ -0,0 +1,10 @@ +package org.quiltmc.qsl.component.impl.sync.packet; + +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.impl.CommonInitializer; + +public final class PacketIds { + public static final Identifier HEADERS = CommonInitializer.id("headers"); + public static final Identifier TYPES = CommonInitializer.id("types"); + public static final Identifier SYNC = CommonInitializer.id("sync"); +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java new file mode 100644 index 0000000000..0ee553c544 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java @@ -0,0 +1,37 @@ +package org.quiltmc.qsl.component.impl.sync.packet; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.network.ServerLoginNetworkHandler; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.networking.api.PacketByteBufs; + +public final class RegistryPacket { + @NotNull + public static PacketByteBuf createRegistryPacket(@NotNull Registry registry) { + var buf = PacketByteBufs.create(); + buf.writeInt(registry.size()); + registry.forEach(t -> { + var id = registry.getId(t); + var rawId = registry.getRawId(t); + + buf.writeIdentifier(id).writeInt(rawId); + }); + + return buf; + } + + public static void handleRegistryResponse(@NotNull PacketByteBuf buf, ServerLoginNetworkHandler handler, String msg) { + String retString = buf.readString(); + + if (!retString.equals("Ok")) { + Identifier id = Identifier.tryParse(retString); + + handler.disconnect(Text.literal(msg.formatted(id))); + ComponentsImpl.getLogger().warn(msg.formatted(id)); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 6245f03b61..613423f9c4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -19,12 +19,15 @@ import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; +import org.quiltmc.qsl.networking.api.PlayerLookup; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -48,6 +51,7 @@ private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, Block .orElseThrow() .setSaveOperation(this::markDirty) .ticking() + .syncing(DefaultSyncPacketHeaders.BLOCK_ENTITY, () -> PlayerLookup.tracking((BlockEntity) (Object)this)) .build(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index ff482c9b31..f9bb444943 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -27,6 +27,8 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; +import org.quiltmc.qsl.networking.api.PlayerLookup; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -43,6 +45,7 @@ private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView this.qsl$container = LazifiedComponentContainer.builder(this) .orElseThrow() .setSaveOperation(() -> this.setNeedsSaving(true)) +// .syncing(DefaultSyncPacketHeaders.CHUNK, () -> ) TODO .build(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index d766b0cac8..60966b9677 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -19,12 +19,16 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; +import org.quiltmc.qsl.networking.api.PlayerLookup; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -40,6 +44,7 @@ private void onEntityInit(EntityType entityType, World world, CallbackInfo ci this.qsl$container = LazifiedComponentContainer.builder(this) .orElseThrow() .ticking() + .syncing(DefaultSyncPacketHeaders.ENTITY, () -> PlayerLookup.tracking((Entity) (Object)this)) .build(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index 527f8b9192..64d1a47b03 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -36,6 +36,8 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -60,6 +62,7 @@ private void onInit(DataFixer dataFixer, int i, NbtCompound nbtCompound, boolean this.qsl$container = LazifiedComponentContainer.builder(this) .orElseThrow() .ticking() +// .syncing(DefaultSyncPacketHeaders.LEVEL) TODO .build(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java index 5a341812b3..1f2d18f655 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -24,6 +24,7 @@ import net.minecraft.world.chunk.*; import net.minecraft.world.gen.chunk.BlendingData; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -38,6 +39,9 @@ public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitVi @Inject(method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/ProtoChunk;Lnet/minecraft/world/chunk/WorldChunk$PostLoadProcessor;)V", at = @At("TAIL")) private void copyComponentData(ServerWorld serverWorld, ProtoChunk protoChunk, WorldChunk.PostLoadProcessor postLoadProcessor, CallbackInfo ci) { var target = protoChunk instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : protoChunk; - this.getContainer().moveComponents(target.getContainer()); + LazifiedComponentContainer.move( + (LazifiedComponentContainer) target.getContainer(), + (LazifiedComponentContainer) this.getContainer() + ); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 630ec0416a..ce8d3ca781 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -53,15 +53,15 @@ public class ComponentTestMod implements ModInitializer { new Identifier(MODID, "cow_inventory"), () -> new DefaultInventoryComponent(() -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64))) ); - public static final ComponentType CREEPER_EXPLODE_TIME = Components.register( + public static final ComponentType CREEPER_EXPLODE_TIME = Components.register( new Identifier(MODID, "creeper_explode_time"), () -> new DefaultIntegerComponent(200) ); - public static final ComponentType HOSTILE_EXPLODE_TIME = Components.register( + public static final ComponentType HOSTILE_EXPLODE_TIME = Components.register( new Identifier(MODID, "hostile_explode_time"), DefaultIntegerComponent::new ); - public static final ComponentType CHEST_NUMBER = Components.register( + public static final ComponentType CHEST_NUMBER = Components.register( new Identifier(MODID, "chest_number"), () -> new DefaultIntegerComponent(200) ); @@ -69,7 +69,7 @@ public class ComponentTestMod implements ModInitializer { new Identifier(MODID, "chunk_inventory"), () -> new DefaultInventoryComponent(1) ); - public static final ComponentType SAVE_FLOAT = Components.register( + public static final ComponentType SAVE_FLOAT = Components.register( new Identifier(MODID, "save_float"), DefaultFloatComponent::new ); @@ -77,12 +77,15 @@ public class ComponentTestMod implements ModInitializer { new Identifier(MODID, "level_tick"), provider -> { if (provider instanceof LevelProperties properties) { - properties.expose(SAVE_FLOAT).ifPresent(floatComponent -> floatComponent.set(floatComponent.get() + 0.5f)); + properties.expose(SAVE_FLOAT).ifPresent(floatComponent -> { + floatComponent.set(floatComponent.get() + 0.5f); + floatComponent.save(); + }); } } ); public static final Block TEST_BLOCK = new TestBlock(AbstractBlock.Settings.copy(Blocks.STONE)); - public static final ComponentType ITEMSTACK_INT = Components.register( + public static final ComponentType ITEMSTACK_INT = Components.register( new Identifier(MODID, "itemstack_int"), DefaultIntegerComponent::new ); @@ -96,7 +99,7 @@ public class ComponentTestMod implements ModInitializer { } ); public static final ComponentType PLAYER_TICK = Components.registerTicking( - new Identifier(MODID, "warden_tick"), + new Identifier(MODID, "player_tick"), provider -> { if (provider instanceof ServerPlayerEntity player) { ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); @@ -113,6 +116,10 @@ public class ComponentTestMod implements ModInitializer { } } ); + public static final ComponentType TEST_BE_INT = Components.register( + new Identifier(ComponentTestMod.MODID, "test_be_int"), + DefaultIntegerComponent::new + ); @Override public void onInitialize(ModContainer mod) { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index a3e752b5f5..f884d50b88 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -16,7 +16,6 @@ import net.minecraft.world.explosion.Explosion; import org.quiltmc.qsl.base.api.event.ListenerPhase; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; import java.util.Objects; @@ -47,6 +46,7 @@ private void stackInHandTick(ServerPlayerEntity player, ItemStack stackInHand) { if (!stackInHand.isEmpty() && stackInHand.isOf(Items.BOOKSHELF)) { stackInHand.expose(ComponentTestMod.ITEMSTACK_INT).ifPresent(integerComponent -> { integerComponent.increment(); + integerComponent.save(); if (integerComponent.get() >= 200) { player.setStackInHand(Hand.MAIN_HAND, new ItemStack(Items.BOOK, 12)); @@ -64,13 +64,17 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { var newStack = playerStack.copy(); newStack.setCount(1); inventory.setStack(0, newStack); + inventory.save(); playerStack.decrement(1); } else { if (ItemStack.canCombine(stack, playerStack)) { stack.increment(1); playerStack.decrement(1); - stack.expose(ComponentTestMod.ITEMSTACK_INT).ifPresent(IntegerComponent::increment); - inventory.saveNeeded(); + stack.expose(ComponentTestMod.ITEMSTACK_INT).ifPresent(defaultIntegerComponent -> { + defaultIntegerComponent.increment(); + defaultIntegerComponent.save(); + }); + inventory.save(); } } } @@ -84,6 +88,7 @@ private void currentChunkBETick(ServerWorld world, Chunk chunk) { .filter(Objects::nonNull) .forEach(blockEntity -> blockEntity.expose(ComponentTestMod.CHEST_NUMBER).ifPresent(integerComponent -> { integerComponent.decrement(); + integerComponent.save(); if (integerComponent.get() <= 0) { world.setBlockState(blockEntity.getPos(), Blocks.DIAMOND_BLOCK.getDefaultState()); @@ -96,6 +101,7 @@ private void hostileTick(ServerWorld world) { .forEach(hostile -> hostile.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).ifPresent(explodeTime -> { if (explodeTime.get() <= 200) { explodeTime.increment(); + explodeTime.save(); } else { hostile.getWorld().createExplosion( null, @@ -112,6 +118,7 @@ private void creeperTick(ServerWorld world) { .forEach(creeper -> Components.expose(ComponentTestMod.CREEPER_EXPLODE_TIME, creeper).ifPresent(explodeTime -> { if (explodeTime.get() > 0) { explodeTime.decrement(); + explodeTime.save(); } else { creeper.ignite(); } @@ -130,6 +137,7 @@ private void cowTick(ServerWorld world) { entity.discard(); } else { inventoryComponent.removeStack(0, 1); + inventoryComponent.save(); } })); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index c8a23842fb..a6d25f3fdd 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -70,12 +70,13 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt var copied = handStack.copy(); copied.setCount(1); inventoryComponent.setStack(0, copied); + inventoryComponent.save(); ret.set(ActionResult.SUCCESS); } else { if (ItemStack.canCombine(stack, handStack)) { stack.increment(1); handStack.decrement(1); - inventoryComponent.saveNeeded(); + inventoryComponent.save(); ret.set(ActionResult.SUCCESS); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 8dc2978de4..3a48b4fc41 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -23,18 +23,13 @@ import net.minecraft.network.Packet; import net.minecraft.network.listener.ClientPlayPacketListener; import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; -import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.InventoryComponent; -import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; import java.util.Arrays; @@ -43,14 +38,14 @@ import java.util.Set; public class TestBlockEntity extends BlockEntity { - public static final ComponentType TEST_BE_INT = Components.register( - new Identifier(ComponentTestMod.MODID, "test_be_int"), - DefaultIntegerComponent::new - ); +// public static final ComponentType TEST_BE_INT = Components.register( +// new Identifier(ComponentTestMod.MODID, "test_be_int"), +// DefaultIntegerComponent::new +// ); Crashes due to our freezing the registry! private final ComponentContainer container = SimpleComponentContainer.builder() .setSaveOperation(this::markDirty) - .add(TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) + .add(ComponentTestMod.TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) .build(); public TestBlockEntity(BlockPos blockPos, BlockState blockState) { @@ -63,13 +58,14 @@ public static void tick(World world, BlockPos pos, Block } if (blockEntity.expose(ComponentTestMod.CHUNK_INVENTORY).map(InventoryComponent::isEmpty).orElse(true)) { - blockEntity.expose(TEST_BE_INT).ifPresent(integerComponent -> { + blockEntity.expose(ComponentTestMod.TEST_BE_INT).ifPresent(integerComponent -> { if (integerComponent.get() % 40 == 0) { HashSet set = new HashSet<>(List.of(pos)); expand(pos, pos, world, set); } integerComponent.increment(); + integerComponent.save(); }); } } @@ -99,12 +95,6 @@ public void readNbt(NbtCompound nbt) { this.container.readNbt(nbt); } - @Override - protected void writeNbt(NbtCompound nbt) { - super.writeNbt(nbt); - this.container.writeNbt(nbt); - } - @Nullable @Override public Packet toUpdatePacket() { @@ -115,4 +105,10 @@ public Packet toUpdatePacket() { public NbtCompound toInitialChunkDataNbt() { return this.toNbt(); } + + @Override + protected void writeNbt(NbtCompound nbt) { + super.writeNbt(nbt); + this.container.writeNbt(nbt); + } } From 25994bb4158baac044f49bb70e841b111b8cf535 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 29 Jun 2022 17:45:40 +0300 Subject: [PATCH 35/70] Finished network sync(still unstable). --- library/data/component/build.gradle | 4 + .../qsl/component/api/ComponentContainer.java | 2 +- .../qsl/component/api/ComponentProvider.java | 8 +- .../quiltmc/qsl/component/api/Components.java | 6 ++ .../qsl/component/impl/CommonInitializer.java | 12 +-- .../impl/client/sync/ClientSyncHandler.java | 5 + .../components/DefaultIntegerComponent.java | 27 +++++- .../components/DefaultInventoryComponent.java | 32 ++++++- .../container/LazifiedComponentContainer.java | 21 +++-- .../container/SimpleComponentContainer.java | 34 ++++--- .../RedirectedInjectionPredicate.java | 19 ++++ .../impl/sync/DefaultSyncPacketHeaders.java | 39 -------- .../component/impl/sync/SyncPlayerList.java | 37 ++++++++ .../impl/sync/codec/NetworkCodec.java | 92 ++++++++++++++++++- .../impl/sync/header/SyncPacketHeader.java | 19 +++- .../impl/sync/packet/ComponentSyncPacket.java | 39 -------- .../impl/sync/packet/SyncPacket.java | 57 ++++++++++++ .../qsl/component/mixin/MixinBlockEntity.java | 18 +++- .../qsl/component/mixin/MixinChunk.java | 28 +++--- .../qsl/component/mixin/MixinEntity.java | 10 +- .../component/mixin/MixinLevelProperties.java | 2 - .../qsl/component/mixin/MixinServerWorld.java | 29 ++++++ .../mixin/MixinThreadedChunkStorage.java | 27 ++++++ .../qsl/component/mixin/MixinWorldChunk.java | 3 +- .../mixin/client/MixinMinecraftClient.java | 27 ++++++ .../resources/quilt_component.mixins.json | 7 +- .../qsl/component/test/ComponentTestMod.java | 7 +- .../component/test/ServerTickListener.java | 3 + .../quiltmc/qsl/component/test/TestBlock.java | 3 +- .../qsl/component/test/TestBlockEntity.java | 4 + .../test/client/ComponentTestModClient.java | 13 +++ .../component/test/client/TestBeRenderer.java | 38 ++++++++ .../MixinBlockEntityRendererFactories.java | 27 ++++++ .../test/mixin/client/MixinInGameHud.java | 45 +++++++++ .../src/testmod/resources/quilt.mod.json | 6 +- .../quilt_component_test.mixins.json | 15 +++ 36 files changed, 627 insertions(+), 138 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/DefaultSyncPacketHeaders.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/ComponentSyncPacket.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java create mode 100644 library/data/component/src/testmod/resources/quilt_component_test.mixins.json diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index 28b045c545..6fd8932e82 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -53,4 +53,8 @@ qslModule { injectedInterface("net/minecraft/class_1799") { values = ["org/quiltmc/qsl/component/api/ComponentProvider"] } + + injectedInterface("net/minecraft/class_310") { + values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index 1f60acffcd..b19e681ca8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -23,7 +23,7 @@ import java.util.Optional; -public interface ComponentContainer { +public interface ComponentContainer { // TODO: Maybe split up responsibilities? Optional expose(Identifier id); void writeNbt(@NotNull NbtCompound providerRootNbt); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 356452d4d8..5744dd0e46 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -17,6 +17,7 @@ package org.quiltmc.qsl.component.api; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.world.chunk.Chunk; @@ -32,7 +33,8 @@ BlockEntity.class, Chunk.class, LevelProperties.class, - ItemStack.class + ItemStack.class, + MinecraftClient.class }) public interface ComponentProvider { @NotNull @@ -45,4 +47,8 @@ default > Optional call(ComponentType default Optional expose(ComponentType id) { return Components.expose(id, this); } + + default void sync() { + this.getContainer().sync(this); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 3fd781afa1..9762428080 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -23,8 +23,10 @@ import org.quiltmc.qsl.component.impl.predicates.ClassInjectionPredicate; import org.quiltmc.qsl.component.impl.predicates.FilteredInheritedInjectionPredicate; import org.quiltmc.qsl.component.impl.predicates.InheritedInjectionPredicate; +import org.quiltmc.qsl.component.impl.predicates.RedirectedInjectionPredicate; import java.util.Optional; +import java.util.Set; public final class Components { public static final Registry> REGISTRY = ComponentsImpl.REGISTRY; @@ -45,6 +47,10 @@ public static void injectInheritanceExcept(Class clazz, ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), component); } + public static void injectRedirected(Class mainClass, ComponentType type, Class others) { + ComponentsImpl.inject(new RedirectedInjectionPredicate(mainClass, Set.of(others)), type); + } + public static Optional expose(ComponentType id, S obj) { if (obj instanceof ComponentProvider provider) { return provider.getContainer().expose(id.id()) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 936ded16cc..85fc705a23 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -5,17 +5,21 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; -import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; import org.quiltmc.qsl.component.impl.sync.ServerSyncHandler; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.lifecycle.api.event.ServerLifecycleEvents; import org.quiltmc.qsl.networking.api.ServerLoginConnectionEvents; @ApiStatus.Internal public final class CommonInitializer implements ModInitializer { + public static @NotNull Identifier id(@NotNull String id) { + return new Identifier(ComponentsImpl.MODID, id); + } + @Override public void onInitialize(ModContainer mod) { - DefaultSyncPacketHeaders.registerDefaults(); + SyncPacketHeader.registerDefaults(); ServerSyncHandler.getInstance().registerPackets(); ServerLoginConnectionEvents.QUERY_START.register(id("component_sync"), ServerSyncHandler.getInstance()); @@ -24,8 +28,4 @@ public void onInitialize(ModContainer mod) { server -> ComponentsImpl.freezeRegistries() ); } - - public static @NotNull Identifier id(@NotNull String id) { - return new Identifier(ComponentsImpl.MODID, id); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java index 6b1a2c0a9d..b72f4a380b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -5,8 +5,10 @@ import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.impl.sync.ComponentHeaderRegistry; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; import org.quiltmc.qsl.networking.api.client.ClientLoginNetworking; +import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking; public class ClientSyncHandler { @@ -30,6 +32,9 @@ public void registerPackets() { ClientLoginNetworking.registerGlobalReceiver(PacketIds.HEADERS, (client, handler, buf, listenerAdder) -> ClientRegistryPacket.handleRegistryPacket(buf, ComponentHeaderRegistry.HEADERS, list -> this.headerList = list) ); + ClientPlayNetworking.registerGlobalReceiver(PacketIds.SYNC, (client, handler, buf, responseSender) -> + SyncPacket.handle(client, buf) + ); } public SyncPacketHeader getHeader(int rawId) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java index ee17b1f4e6..5c58e06b80 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java @@ -18,15 +18,20 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtInt; +import net.minecraft.network.PacketByteBuf; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.components.SyncedComponent; -public class DefaultIntegerComponent implements IntegerComponent, NbtComponent { +public class DefaultIntegerComponent implements IntegerComponent, NbtComponent, SyncedComponent { private int value; @Nullable private Runnable saveOperation; + @Nullable + private Runnable syncOperation; public DefaultIntegerComponent() { this(0); @@ -80,4 +85,24 @@ public NbtInt write() { public void setSaveOperation(@Nullable Runnable runnable) { this.saveOperation = runnable; } + + @Override + public void writeToBuf(@NotNull PacketByteBuf buf) { + buf.writeInt(this.value); + } + + @Override + public void readFromBuf(@NotNull PacketByteBuf buf) { + this.value = buf.readInt(); + } + + @Override + public @Nullable Runnable getSyncOperation() { + return this.syncOperation; + } + + @Override + public void setSyncOperation(@NotNull Runnable runnable) { + this.syncOperation = runnable; + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java index 8a96a6b5ad..dc513eb20d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java @@ -17,18 +17,24 @@ package org.quiltmc.qsl.component.impl.components; import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; import net.minecraft.util.collection.DefaultedList; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.InventoryComponent; +import org.quiltmc.qsl.component.api.components.SyncedComponent; +import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import java.util.Objects; import java.util.function.Supplier; -public class DefaultInventoryComponent implements InventoryComponent { +public class DefaultInventoryComponent implements InventoryComponent, SyncedComponent { private final DefaultedList stacks; @Nullable private Runnable saveOperation; + @Nullable + private Runnable syncOperation; public DefaultInventoryComponent(int size) { this.stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); @@ -64,4 +70,28 @@ public boolean equals(Object o) { if (!(o instanceof DefaultInventoryComponent that)) return false; return stacks.equals(that.stacks); } + + @Override + public void writeToBuf(@NotNull PacketByteBuf buf) { + NetworkCodec.INVENTORY.encode(buf, this.stacks); + } + + @Override + public void readFromBuf(@NotNull PacketByteBuf buf) { + NetworkCodec.INVENTORY.decode(buf).ifPresent(itemStacks -> { + for (int i = 0; i < itemStacks.size(); i++) { + this.stacks.set(i, itemStacks.get(i)); + } + }); + } + + @Override + public @Nullable Runnable getSyncOperation() { + return this.syncOperation; + } + + @Override + public void setSyncOperation(@NotNull Runnable runnable) { + this.syncOperation = runnable; + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java index ffc9441a04..bc867822ca 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java @@ -32,7 +32,7 @@ import org.quiltmc.qsl.component.api.event.ComponentEvents; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.quiltmc.qsl.component.impl.sync.packet.ComponentSyncPacket; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.Lazy; @@ -51,14 +51,14 @@ public class LazifiedComponentContainer implements ComponentContainer { private final Runnable saveOperation; private final boolean ticking; private final boolean syncing; - private final SyncContext syncContext; + private final SyncPacket.SyncContext syncContext; private final Queue pendingSync; protected LazifiedComponentContainer( @NotNull ComponentProvider provider, @Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncContext syncContext + @Nullable SyncPacket.SyncContext syncContext ) { this.saveOperation = saveOperation; this.ticking = ticking; @@ -134,13 +134,17 @@ public void tick(@NotNull ComponentProvider provider) { .map(Optional::orElseThrow) .map(it -> ((TickingComponent) it)) .forEach(tickingComponent -> tickingComponent.tick(provider)); + // Sync any queued components - this.sync(provider); + if (this.syncing) { + this.sync(provider); + } } @Override public void receiveSyncPacket(@NotNull Identifier id, @NotNull PacketByteBuf buf) { this.expose(id).map(it -> ((SyncedComponent) it)).ifPresent(syncedComponent -> syncedComponent.readFromBuf(buf)); + ComponentsImpl.getLogger().info("Received packet for {}", id); } @Override @@ -153,7 +157,7 @@ public void sync(@NotNull ComponentProvider provider) { } if (!map.isEmpty()) { - var packet = ComponentSyncPacket.create(this.syncContext.header(), provider, map); + var packet = SyncPacket.create(this.syncContext.header(), provider, map); this.syncContext.playerGenerator().get().forEach(serverPlayer -> ServerPlayNetworking.send(serverPlayer, PacketIds.SYNC, packet) @@ -203,7 +207,7 @@ public static class Builder { @Nullable private Runnable saveOperation; private boolean ticking; - private SyncContext syncContext; + private SyncPacket.SyncContext syncContext; private Builder(ComponentProvider provider) { this.provider = provider; @@ -222,7 +226,7 @@ public Builder ticking() { } public Builder syncing(@NotNull SyncPacketHeader header, Supplier> playerGenerator) { - this.syncContext = new SyncContext(header, playerGenerator); + this.syncContext = new SyncPacket.SyncContext(header, playerGenerator); return this; } @@ -231,6 +235,5 @@ public LazifiedComponentContainer build() { } } - public record SyncContext(SyncPacketHeader header, Supplier> playerGenerator) { - } + } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index fd9a19ba1a..eb471d309d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -18,6 +18,7 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -30,26 +31,31 @@ import org.quiltmc.qsl.component.api.components.SyncedComponent; import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.quiltmc.qsl.component.impl.sync.packet.ComponentSyncPacket; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; import java.util.*; +import java.util.function.Supplier; import java.util.stream.Stream; public class SimpleComponentContainer implements ComponentContainer { private final Map components; private final List nbtComponents; private final List tickingComponents; + @Nullable + private final SyncPacket.SyncContext syncContext; private Queue pendingSync; - private SyncPacketHeader header; - protected SimpleComponentContainer(@Nullable Runnable saveOperation, SyncPacketHeader header, Stream> types) { + protected SimpleComponentContainer(@Nullable Runnable saveOperation, SyncPacket.SyncContext syncContext, Stream> types) { this.components = new HashMap<>(); this.nbtComponents = new ArrayList<>(); this.tickingComponents = new ArrayList<>(); - if (header != null) { - this.header = header; + if (syncContext != null) { + this.syncContext = syncContext; this.pendingSync = new ArrayDeque<>(); + } else { + this.syncContext = null; } types.forEach(type -> this.initializeComponent(saveOperation, type)); @@ -87,7 +93,9 @@ public void readNbt(@NotNull NbtCompound providerRootNbt) { rootQslNbt.getKeys().stream() .map(Identifier::tryParse) .filter(Objects::nonNull) - .forEach(id -> this.expose(id).ifPresent(component -> NbtComponent.readFrom((NbtComponent) component, id, rootQslNbt))); + .forEach(id -> this.expose(id) + .ifPresent(component -> NbtComponent.readFrom((NbtComponent) component, id, rootQslNbt)) + ); } @Override @@ -107,6 +115,9 @@ public void receiveSyncPacket(@NotNull Identifier id, @NotNull PacketByteBuf buf @Override public void sync(@NotNull ComponentProvider provider) { + if (this.syncContext == null) { + throw ErrorUtil.illegalState("Cannot sync a non-syncable component container! Make sure you provider a context!").get(); + } var map = new HashMap(); while (!this.pendingSync.isEmpty()) { @@ -115,7 +126,7 @@ public void sync(@NotNull ComponentProvider provider) { } if (!map.isEmpty()) { - var packet = ComponentSyncPacket.create(this.header, provider, map); + SyncPacket.send(this.syncContext, provider, map); } } @@ -142,7 +153,8 @@ public static class Builder { private final List> types; @Nullable private Runnable saveOperation; - private SyncPacketHeader header; + @Nullable + private SyncPacket.SyncContext syncContext; private Builder() { this.types = new ArrayList<>(); @@ -155,8 +167,8 @@ public Builder setSaveOperation(@NotNull Runnable runnable) { } @NotNull - public Builder syncing(SyncPacketHeader header) { - this.header = header; + public Builder syncing(SyncPacketHeader header, Supplier> supplier) { + this.syncContext = new SyncPacket.SyncContext(header, supplier); return this; } @@ -174,7 +186,7 @@ public Builder add(ComponentType... types) { @NotNull public SimpleComponentContainer build() { - return new SimpleComponentContainer(this.saveOperation, this.header, this.types.stream()); + return new SimpleComponentContainer(this.saveOperation, this.syncContext, this.types.stream()); } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java new file mode 100644 index 0000000000..d88e059846 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java @@ -0,0 +1,19 @@ +package org.quiltmc.qsl.component.impl.predicates; + +import org.quiltmc.qsl.component.api.ComponentProvider; + +import java.util.Set; + +public class RedirectedInjectionPredicate extends ClassInjectionPredicate { + private final Set> redirections; + + public RedirectedInjectionPredicate(Class clazz, Set> redirections) { + super(clazz); + this.redirections = redirections; + } + + @Override + public boolean canInject(ComponentProvider provider) { + return super.canInject(provider) || this.redirections.contains(provider.getClass()); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/DefaultSyncPacketHeaders.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/DefaultSyncPacketHeaders.java deleted file mode 100644 index f58cc8bba2..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/DefaultSyncPacketHeaders.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.quiltmc.qsl.component.impl.sync; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.chunk.Chunk; -import org.quiltmc.qsl.component.impl.CommonInitializer; -import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; - -@SuppressWarnings("ConstantConditions") // The accessed fields in this case will never be null since the only times this class is accessed are during play. -public final class DefaultSyncPacketHeaders { - private static final NetworkCodec BLOCK_ENTITY_CODEC = new NetworkCodec<>( - (blockEntity, packetByteBuf) -> packetByteBuf.writeBlockPos(blockEntity.getPos()), - packetByteBuf -> MinecraftClient.getInstance().world.getBlockEntity(packetByteBuf.readBlockPos()) - ); - public static final SyncPacketHeader BLOCK_ENTITY = new SyncPacketHeader<>(BLOCK_ENTITY_CODEC); - private static final NetworkCodec ENTITY_CODEC = new NetworkCodec<>( - (entity, packetByteBuf) -> packetByteBuf.writeInt(entity.getId()), - packetByteBuf -> MinecraftClient.getInstance().world.getEntityById(packetByteBuf.readInt()) - ); - public static final SyncPacketHeader ENTITY = new SyncPacketHeader<>(ENTITY_CODEC); - private static final NetworkCodec CHUNK_CODEC = new NetworkCodec<>( - (chunk, packetByteBuf) -> packetByteBuf.writeChunkPos(chunk.getPos()), - packetByteBuf -> { - ChunkPos pos = packetByteBuf.readChunkPos(); - return MinecraftClient.getInstance().world.getChunk(pos.x, pos.z); - } - ); - public static final SyncPacketHeader CHUNK = new SyncPacketHeader<>(CHUNK_CODEC); - // TODO: LevelProperties sync - - public static void registerDefaults() { - ComponentHeaderRegistry.register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); - ComponentHeaderRegistry.register(CommonInitializer.id("entity"), ENTITY); - ComponentHeaderRegistry.register(CommonInitializer.id("chunk"), CHUNK); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java new file mode 100644 index 0000000000..e63110b3eb --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java @@ -0,0 +1,37 @@ +package org.quiltmc.qsl.component.impl.sync; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.Entity; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.WorldChunk; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.networking.api.PlayerLookup; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +public final class SyncPlayerList { + @NotNull + public static Collection create(World world, BlockPos pos) { + return world.isClient ? List.of() : PlayerLookup.tracking((ServerWorld) world, pos); + } + + @NotNull + public static Collection create(Entity entity) { + return entity.getWorld().isClient ? List.of() : PlayerLookup.tracking(entity); + } + + @NotNull + public static Collection create(BlockEntity blockEntity) { + return Objects.requireNonNull(blockEntity.getWorld()).isClient ? List.of() : PlayerLookup.tracking(blockEntity); + } + + @NotNull + public static Collection create(WorldChunk chunk) { + return chunk.getWorld().isClient ? List.of() : PlayerLookup.tracking((ServerWorld) chunk.getWorld(), chunk.getPos()); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java index 86750171f2..ff636404ea 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java @@ -1,15 +1,103 @@ package org.quiltmc.qsl.component.impl.sync.codec; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.Chunk; import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; +import java.util.List; import java.util.Optional; +import java.util.UUID; import java.util.function.BiConsumer; import java.util.function.Function; -public record NetworkCodec(@NotNull BiConsumer encoder, @NotNull Function decoder) { +public record NetworkCodec(@NotNull BiConsumer encoder, + @NotNull Function decoder) { + public static final NetworkCodec BLOCK_POS = new NetworkCodec<>( + PacketByteBuf::writeBlockPos, PacketByteBuf::readBlockPos + ); + public static final NetworkCodec INT = new NetworkCodec<>( + PacketByteBuf::writeInt, PacketByteBuf::readInt + ); + public static final NetworkCodec CHUNK_POS = new NetworkCodec<>( + PacketByteBuf::writeChunkPos, PacketByteBuf::readChunkPos + ); + public static final NetworkCodec FLOAT = new NetworkCodec<>( + PacketByteBuf::writeFloat, PacketByteBuf::readFloat + ); + // TODO: Handle the cases where MinecraftClient.getInstance().world is null + public static final NetworkCodec BLOCK_ENTITY = new NetworkCodec<>( + (buf, blockEntity) -> buf.writeBlockPos(blockEntity.getPos()), + buf -> MinecraftClient.getInstance().world.getBlockEntity(buf.readBlockPos()) + ); + public static final NetworkCodec ENTITY = new NetworkCodec<>( + (buf, entity) -> buf.writeInt(entity.getId()), + buf -> MinecraftClient.getInstance().world.getEntityById(buf.readInt()) + ); + public static final NetworkCodec CHUNK = new NetworkCodec<>( + (buf, chunk) -> buf.writeChunkPos(chunk.getPos()), + buf -> CHUNK_POS.decode(buf) + .map(chunkPos -> MinecraftClient.getInstance().world.getChunk(chunkPos.x, chunkPos.z)) + .orElseThrow() + ); + public static final NetworkCodec ITEMSTACK = new NetworkCodec<>( + PacketByteBuf::writeItemStack, PacketByteBuf::readItemStack + ); + public static final NetworkCodec LONG = new NetworkCodec<>( + PacketByteBuf::writeLong, PacketByteBuf::readLong + ); + public static final NetworkCodec STRING = new NetworkCodec<>( + PacketByteBuf::writeString, PacketByteBuf::readString + ); + public static final NetworkCodec IDENTIFIER = new NetworkCodec<>( + PacketByteBuf::writeIdentifier, PacketByteBuf::readIdentifier + ); + public static final NetworkCodec> INVENTORY = list(ITEMSTACK, integer -> DefaultedList.ofSize(integer, ItemStack.EMPTY)); + public static final NetworkCodec NBT_COMPOUND = new NetworkCodec<>( + PacketByteBuf::writeNbt, PacketByteBuf::readNbt + ); + public static final NetworkCodec UUID = new NetworkCodec<>( + PacketByteBuf::writeUuid, PacketByteBuf::readUuid + ); + public static final NetworkCodec> COMPONENT_TYPE = new NetworkCodec<>( + (buf, componentType) -> buf.writeInt(Components.REGISTRY.getRawId(componentType)), + buf -> ClientSyncHandler.getInstance().getType(buf.readInt()) + ); + + public static > NetworkCodec list(NetworkCodec entryCodec, Function function) { + return new NetworkCodec<>( + (buf, os) -> { + INT.encode(buf, os.size()); + for (O o : os) { + entryCodec.encode(buf, o); + } + }, + buf -> { + int size = INT.decode(buf).orElseThrow(); + L newList = function.apply(size); + + for (int i = 0; i < size; i++) { + newList.set(i, entryCodec.decode(buf).orElseThrow()); + } + + return newList; + } + ); + } + public void encode(@NotNull PacketByteBuf buf, T t) { - this.encoder.accept(t, buf); + this.encoder.accept(buf, t); } public Optional decode(@NotNull PacketByteBuf buf) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java index 191df8d1ce..cc4cf7c6f0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -1,17 +1,34 @@ package org.quiltmc.qsl.component.impl.sync.header; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.Entity; import net.minecraft.network.PacketByteBuf; +import net.minecraft.world.chunk.Chunk; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.impl.CommonInitializer; import org.quiltmc.qsl.component.impl.sync.ComponentHeaderRegistry; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import org.quiltmc.qsl.networking.api.PacketByteBufs; public record SyncPacketHeader

(@NotNull NetworkCodec

codec) { + public static final SyncPacketHeader BLOCK_ENTITY = new SyncPacketHeader<>(NetworkCodec.BLOCK_ENTITY); + public static final SyncPacketHeader ENTITY = new SyncPacketHeader<>(NetworkCodec.ENTITY); + public static final SyncPacketHeader CHUNK = new SyncPacketHeader<>(NetworkCodec.CHUNK); + // TODO: LevelProperties sync +// public static final SyncPacketHeader LEVEL = new SyncPacketHeader<>(NetworkCodec.LEVEL); + + public static void registerDefaults() { + ComponentHeaderRegistry.register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); + ComponentHeaderRegistry.register(CommonInitializer.id("entity"), ENTITY); + ComponentHeaderRegistry.register(CommonInitializer.id("chunk"), CHUNK); + } + public @NotNull PacketByteBuf start(@NotNull ComponentProvider provider) { var buf = PacketByteBufs.create(); buf.writeInt(ComponentHeaderRegistry.HEADERS.getRawId(this)); - this.codec.encode(buf, provider); + //noinspection unchecked the person calling is responsible to make sure we get a valid provider instance! + this.codec.encode(buf, (P) provider); return buf; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/ComponentSyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/ComponentSyncPacket.java deleted file mode 100644 index 3cde6347b1..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/ComponentSyncPacket.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.quiltmc.qsl.component.impl.sync.packet; - -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.components.SyncedComponent; -import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; - -import java.util.Map; - -public class ComponentSyncPacket { - @NotNull - public static PacketByteBuf create(SyncPacketHeader headerCreator, @NotNull ComponentProvider provider, Map components) { - PacketByteBuf buff = headerCreator.start(provider); - buff.writeVarInt(components.size()); - components.forEach((id, syncedComponent) -> { - int rawId = Components.REGISTRY.getRawId(Components.REGISTRY.get(id)); - buff.writeInt(rawId); - syncedComponent.writeToBuf(buff); - }); - - return buff; - } - - public static void handle(PacketByteBuf buf) { - int rawHeaderId = buf.readInt(); - var header = ClientSyncHandler.getInstance().getHeader(rawHeaderId); - - header.codec().decode(buf).ifPresent(provider -> { - ComponentType type = ClientSyncHandler.getInstance().getType(buf.readInt()); - - provider.getContainer().receiveSyncPacket(type.id(), buf); - }); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java new file mode 100644 index 0000000000..f827a405dc --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -0,0 +1,57 @@ +package org.quiltmc.qsl.component.impl.sync.packet; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.components.SyncedComponent; +import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; +import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.networking.api.ServerPlayNetworking; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +public class SyncPacket { + @NotNull + public static PacketByteBuf create(SyncPacketHeader headerCreator, @NotNull ComponentProvider provider, Map components) { + PacketByteBuf buff = headerCreator.start(provider); + buff.writeInt(components.size()); + components.forEach((id, syncedComponent) -> { + NetworkCodec.COMPONENT_TYPE.encode(buff, Components.REGISTRY.get(id)); + syncedComponent.writeToBuf(buff); + }); + + return buff; + } + + public static void handle(MinecraftClient client, PacketByteBuf buf) { + var header = ClientSyncHandler.getInstance().getHeader(buf.readInt()); + header.codec().decode(buf).ifPresent(provider -> { + var size = buf.readInt(); + + for (int i = 0; i < size; i++) { + NetworkCodec.COMPONENT_TYPE.decode(buf) + .map(Components.REGISTRY::getId) + .ifPresent(id -> provider.getContainer().receiveSyncPacket(id, buf)); + } + }); + } + + public static void send(SyncContext context, ComponentProvider provider, HashMap map) { + PacketByteBuf packet = create(context.header(), provider, map); + + context.playerGenerator().get().forEach(serverPlayer -> + ServerPlayNetworking.send(serverPlayer, PacketIds.SYNC, packet) + ); + } + + public record SyncContext(SyncPacketHeader header, Supplier> playerGenerator) { + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 613423f9c4..5467bd3575 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -16,17 +16,20 @@ package org.quiltmc.qsl.component.mixin; +import com.mojang.serialization.Lifecycle; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; -import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; +import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.networking.api.PlayerLookup; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -35,6 +38,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.List; + @Mixin(BlockEntity.class) public abstract class MixinBlockEntity implements ComponentProvider { @@ -51,13 +56,20 @@ private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, Block .orElseThrow() .setSaveOperation(this::markDirty) .ticking() - .syncing(DefaultSyncPacketHeaders.BLOCK_ENTITY, () -> PlayerLookup.tracking((BlockEntity) (Object)this)) + .syncing(SyncPacketHeader.BLOCK_ENTITY, () -> SyncPlayerList.create((BlockEntity) (Object)this)) .build(); } @Shadow public abstract void markDirty(); + @Shadow + @Nullable + protected World world; + + @Shadow + public abstract @Nullable World getWorld(); + @Inject(method = "toNbt", at = @At("TAIL")) private void onWriteNbt(CallbackInfoReturnable cir) { this.qsl$container.writeNbt(cir.getReturnValue()); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index f9bb444943..d702d6664b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -22,13 +22,14 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.chunk.UpgradeData; +import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.gen.chunk.BlendingData; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; -import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; -import org.quiltmc.qsl.networking.api.PlayerLookup; +import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -40,15 +41,6 @@ public abstract class MixinChunk implements ComponentProvider { private ComponentContainer qsl$container; - @Inject(method = "", at = @At("RETURN")) - private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.builder(this) - .orElseThrow() - .setSaveOperation(() -> this.setNeedsSaving(true)) -// .syncing(DefaultSyncPacketHeaders.CHUNK, () -> ) TODO - .build(); - } - @Shadow public abstract void setNeedsSaving(boolean needsSaving); @@ -56,4 +48,18 @@ private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView public @NotNull ComponentContainer getContainer() { return this.qsl$container; } + + @Inject(method = "", at = @At("RETURN")) + private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { + LazifiedComponentContainer.Builder builder = LazifiedComponentContainer.builder(this) + .orElseThrow() + .setSaveOperation(() -> this.setNeedsSaving(true)); + + //noinspection ConstantConditions + if ((Chunk) (Object) this instanceof WorldChunk worldChunk) { + builder.syncing(SyncPacketHeader.CHUNK, () -> SyncPlayerList.create(worldChunk)).ticking(); + } + + this.qsl$container = builder.build(); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 60966b9677..04f6686a66 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -19,16 +19,15 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; -import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; +import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.networking.api.PlayerLookup; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -39,12 +38,13 @@ public abstract class MixinEntity implements ComponentProvider { private ComponentContainer qsl$container; - @Inject(method = "", at = @At("RETURN")) // TODO: Mixin into the ServerWorld#spawnEntity method for this! + @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { + //noinspection ConstantConditions this.qsl$container = LazifiedComponentContainer.builder(this) .orElseThrow() .ticking() - .syncing(DefaultSyncPacketHeaders.ENTITY, () -> PlayerLookup.tracking((Entity) (Object)this)) + .syncing(SyncPacketHeader.ENTITY, () -> SyncPlayerList.create((Entity) (Object)this)) .build(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index 64d1a47b03..3a767fb3c7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -36,8 +36,6 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; -import org.quiltmc.qsl.component.impl.sync.DefaultSyncPacketHeaders; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java new file mode 100644 index 0000000000..e48aa56a46 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java @@ -0,0 +1,29 @@ +package org.quiltmc.qsl.component.mixin; + +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Holder; +import net.minecraft.util.profiler.Profiler; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.MutableWorldProperties; +import net.minecraft.world.World; +import net.minecraft.world.chunk.WorldChunk; +import net.minecraft.world.dimension.DimensionType; +import org.spongepowered.asm.mixin.Mixin; +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.function.Supplier; + +@Mixin(ServerWorld.class) +public abstract class MixinServerWorld extends World { + + protected MixinServerWorld(MutableWorldProperties mutableWorldProperties, RegistryKey registryKey, Holder holder, Supplier supplier, boolean bl, boolean bl2, long l, int i) { + super(mutableWorldProperties, registryKey, holder, supplier, bl, bl2, l, i); + } + + @Inject(method = "tickChunk", at = @At("TAIL")) + private void tickContainer(WorldChunk chunk, int randomTickSpeed, CallbackInfo ci) { + chunk.getContainer().tick(chunk); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java new file mode 100644 index 0000000000..efdcc7ded9 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java @@ -0,0 +1,27 @@ +package org.quiltmc.qsl.component.mixin; + +import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ThreadedAnvilChunkStorage; +import net.minecraft.util.math.ChunkPos; +import org.apache.commons.lang3.mutable.MutableObject; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ThreadedAnvilChunkStorage.class) +public abstract class MixinThreadedChunkStorage { + + @Inject( + method = "sendWatchPackets", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/server/world/ThreadedAnvilChunkStorage;sendChunkDataPackets(Lnet/minecraft/server/network/ServerPlayerEntity;Lorg/apache/commons/lang3/mutable/MutableObject;Lnet/minecraft/world/chunk/WorldChunk;)V", + shift = At.Shift.AFTER + ) + ) + private void syncChunkContainer(ServerPlayerEntity player, ChunkPos pos, MutableObject mutableObject, boolean withinMaxWatchDistance, boolean withinViewDistance, CallbackInfo ci) { + player.getWorld().getChunk(pos.x, pos.z).sync(); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java index 1f2d18f655..7f5f3b7579 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -24,6 +24,7 @@ import net.minecraft.world.chunk.*; import net.minecraft.world.gen.chunk.BlendingData; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -31,7 +32,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(WorldChunk.class) -public abstract class MixinWorldChunk extends Chunk { +public abstract class MixinWorldChunk extends Chunk implements ComponentProvider { public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, @Nullable ChunkSection[] chunkSections, @Nullable BlendingData blendingData) { super(chunkPos, upgradeData, heightLimitView, registry, l, chunkSections, blendingData); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java new file mode 100644 index 0000000000..3b928e9609 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java @@ -0,0 +1,27 @@ +package org.quiltmc.qsl.component.mixin.client; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.RunArgs; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class MixinMinecraftClient implements ComponentProvider { + private ComponentContainer qsl$container; + + @Override + public @NotNull ComponentContainer getContainer() { + return this.qsl$container; + } + + @Inject(method = "", at = @At("TAIL")) + private void initContainer(RunArgs runArgs, CallbackInfo ci) { + this.qsl$container = LazifiedComponentContainer.builder(this).orElseThrow().build(); + } +} diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index a8528b929f..a66519d3b1 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -10,9 +10,14 @@ "MixinEntity", "MixinItemStack", "MixinLevelProperties", + "MixinServerWorld", + "MixinThreadedChunkStorage", "MixinWorldChunk" ], "injectors": { "defaultRequire": 1 - } + }, + "client": [ + "client.MixinMinecraftClient" + ] } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index ce8d3ca781..c4d39f1811 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -40,7 +40,10 @@ import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.components.*; +import org.quiltmc.qsl.component.api.components.FloatComponent; +import org.quiltmc.qsl.component.api.components.FunctionComponent; +import org.quiltmc.qsl.component.api.components.InventoryComponent; +import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.api.event.ComponentEvents; import org.quiltmc.qsl.component.impl.components.DefaultFloatComponent; import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; @@ -65,7 +68,7 @@ public class ComponentTestMod implements ModInitializer { new Identifier(MODID, "chest_number"), () -> new DefaultIntegerComponent(200) ); - public static final ComponentType CHUNK_INVENTORY = Components.register( + public static final ComponentType CHUNK_INVENTORY = Components.register( new Identifier(MODID, "chunk_inventory"), () -> new DefaultInventoryComponent(1) ); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index f884d50b88..254c4cdf52 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -65,6 +65,7 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { newStack.setCount(1); inventory.setStack(0, newStack); inventory.save(); + inventory.sync(); playerStack.decrement(1); } else { if (ItemStack.canCombine(stack, playerStack)) { @@ -75,6 +76,7 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { defaultIntegerComponent.save(); }); inventory.save(); + inventory.sync(); } } } @@ -102,6 +104,7 @@ private void hostileTick(ServerWorld world) { if (explodeTime.get() <= 200) { explodeTime.increment(); explodeTime.save(); +// explodeTime.sync(); Causes mucho lag!! } else { hostile.getWorld().createExplosion( null, diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index a6d25f3fdd..4afbe4aba9 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -71,6 +71,7 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt copied.setCount(1); inventoryComponent.setStack(0, copied); inventoryComponent.save(); + inventoryComponent.sync(); ret.set(ActionResult.SUCCESS); } else { if (ItemStack.canCombine(stack, handStack)) { @@ -90,6 +91,6 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt @SuppressWarnings("deprecation") @Override public BlockRenderType getRenderType(BlockState state) { - return BlockRenderType.MODEL; + return BlockRenderType.ENTITYBLOCK_ANIMATED; } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 3a48b4fc41..a5bb960771 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -19,6 +19,7 @@ import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.Packet; import net.minecraft.network.listener.ClientPlayPacketListener; @@ -31,6 +32,8 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.components.InventoryComponent; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; +import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import java.util.Arrays; import java.util.HashSet; @@ -46,6 +49,7 @@ public class TestBlockEntity extends BlockEntity { private final ComponentContainer container = SimpleComponentContainer.builder() .setSaveOperation(this::markDirty) .add(ComponentTestMod.TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) + .syncing(SyncPacketHeader.BLOCK_ENTITY, () -> SyncPlayerList.create(this)) .build(); public TestBlockEntity(BlockPos blockPos, BlockState blockState) { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java new file mode 100644 index 0000000000..326aaaaca5 --- /dev/null +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java @@ -0,0 +1,13 @@ +package org.quiltmc.qsl.component.test.client; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; + +@Environment(EnvType.CLIENT) +public class ComponentTestModClient implements ClientModInitializer { + @Override + public void onInitializeClient(ModContainer mod) { + } +} diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java new file mode 100644 index 0000000000..11fabb499d --- /dev/null +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java @@ -0,0 +1,38 @@ +package org.quiltmc.qsl.component.test.client; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.render.model.json.ModelTransformation; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.Vec3f; +import org.quiltmc.qsl.component.test.ComponentTestMod; +import org.quiltmc.qsl.component.test.TestBlockEntity; + +import java.util.function.Predicate; + +public class TestBeRenderer implements BlockEntityRenderer { + @Override + public void render(TestBlockEntity entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { + entity.expose(ComponentTestMod.CHUNK_INVENTORY) + .map(inventoryComponent -> inventoryComponent.getStack(0)) + .filter(Predicate.not(ItemStack::isEmpty)) + .ifPresent(itemStack -> { + matrices.push(); + matrices.translate(0.5f, 1, 0.5f); + matrices.multiply(Vec3f.NEGATIVE_Y.getDegreesQuaternion(System.currentTimeMillis() % 360)); + MinecraftClient.getInstance().getItemRenderer().renderItem( + itemStack, + ModelTransformation.Mode.GROUND, + 0xffffff, + OverlayTexture.DEFAULT_UV, + matrices, + vertexConsumers, + 0 + ); + matrices.pop(); + }); + } +} diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java new file mode 100644 index 0000000000..ae69926e58 --- /dev/null +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java @@ -0,0 +1,27 @@ +package org.quiltmc.qsl.component.test.mixin.client; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.client.render.block.entity.BlockEntityRendererFactories; +import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; +import org.quiltmc.qsl.component.test.ComponentTestMod; +import org.quiltmc.qsl.component.test.client.TestBeRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(BlockEntityRendererFactories.class) +public abstract class MixinBlockEntityRendererFactories { + @Shadow + protected static void register(BlockEntityType type, BlockEntityRendererFactory factory) { + throw ErrorUtil.illegalState("This should never happen").get(); + } + + @Inject(method = "", at = @At("TAIL")) + private static void registerCustom(CallbackInfo ci) { + register(ComponentTestMod.TEST_BE_TYPE, context -> new TestBeRenderer()); + } +} diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java new file mode 100644 index 0000000000..a722acfbdc --- /dev/null +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -0,0 +1,45 @@ +package org.quiltmc.qsl.component.test.mixin.client; + +import net.minecraft.client.ClientGameSession; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.render.model.json.ModelTransformation; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.ChunkPos; +import org.quiltmc.qsl.component.api.components.IntegerComponent; +import org.quiltmc.qsl.component.test.ComponentTestMod; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(InGameHud.class) +public abstract class MixinInGameHud { + + @Shadow + public abstract TextRenderer getTextRenderer(); + + @Shadow + @Final + private ItemRenderer itemRenderer; + + @Inject(method = "render", at = @At("TAIL")) + private void renderCustom(MatrixStack matrices, float tickDelta, CallbackInfo ci) { + Entity entity = MinecraftClient.getInstance().targetedEntity; + if (entity != null) { + entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).map(IntegerComponent::get).ifPresent(integer -> { + this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa); + }); + } + ChunkPos chunkPos = MinecraftClient.getInstance().player.getChunkPos(); + MinecraftClient.getInstance().world.getChunk(chunkPos.x, chunkPos.z).expose(ComponentTestMod.CHUNK_INVENTORY) + .map(defaultInventoryComponent -> defaultInventoryComponent.getStack(0)) + .ifPresent(itemStack -> this.itemRenderer.renderInGui(itemStack, 10, 10)); + } +} diff --git a/library/data/component/src/testmod/resources/quilt.mod.json b/library/data/component/src/testmod/resources/quilt.mod.json index 5a0dc5db17..998aeefcbe 100644 --- a/library/data/component/src/testmod/resources/quilt.mod.json +++ b/library/data/component/src/testmod/resources/quilt.mod.json @@ -14,6 +14,9 @@ "init": [ "org.quiltmc.qsl.component.test.ComponentTestMod" ], + "client_init": [ + "org.quiltmc.qsl.component.test.client.ComponentTestModClient" + ], "events": [ "org.quiltmc.qsl.component.test.ServerTickListener" ] @@ -23,5 +26,6 @@ "quilt_component", "quilt_lifecycle_events" ] - } + }, + "mixin": "quilt_component_test.mixins.json" } diff --git a/library/data/component/src/testmod/resources/quilt_component_test.mixins.json b/library/data/component/src/testmod/resources/quilt_component_test.mixins.json new file mode 100644 index 0000000000..74e094c14b --- /dev/null +++ b/library/data/component/src/testmod/resources/quilt_component_test.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "package": "org.quiltmc.qsl.component.test.mixin", + "compatibilityLevel": "JAVA_17", + "minVersion": "0.8", + "mixins": [ + "client.MixinBlockEntityRendererFactories" + ], + "client": [ + "client.MixinInGameHud" + ], + "injectors": { + "defaultRequire": 1 + } +} From 16230e895bb705925af9f955a75a6c8a6a86b565 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 29 Jun 2022 17:52:12 +0300 Subject: [PATCH 36/70] Apply licenses before PR --- .../api/components/FunctionComponent.java | 16 ++++++++++++++++ .../api/components/SyncedComponent.java | 16 ++++++++++++++++ .../api/components/TickingComponent.java | 16 ++++++++++++++++ .../qsl/component/api/event/ComponentEvents.java | 16 ++++++++++++++++ .../qsl/component/api/wrapper/Wrapper.java | 16 ++++++++++++++++ .../qsl/component/impl/CommonInitializer.java | 16 ++++++++++++++++ .../component/impl/client/ClientInitializer.java | 16 ++++++++++++++++ .../impl/client/sync/ClientRegistryPacket.java | 16 ++++++++++++++++ .../impl/client/sync/ClientSyncHandler.java | 16 ++++++++++++++++ .../impl/event/ServerTickEventListener.java | 16 ++++++++++++++++ .../predicates/RedirectedInjectionPredicate.java | 16 ++++++++++++++++ .../impl/sync/ComponentHeaderRegistry.java | 16 ++++++++++++++++ .../component/impl/sync/ServerSyncHandler.java | 16 ++++++++++++++++ .../qsl/component/impl/sync/SyncPlayerList.java | 16 ++++++++++++++++ .../component/impl/sync/codec/NetworkCodec.java | 16 ++++++++++++++++ .../impl/sync/header/SyncPacketHeader.java | 16 ++++++++++++++++ .../component/impl/sync/packet/PacketIds.java | 16 ++++++++++++++++ .../impl/sync/packet/RegistryPacket.java | 16 ++++++++++++++++ .../component/impl/sync/packet/SyncPacket.java | 16 ++++++++++++++++ .../qsl/component/impl/util/ErrorUtil.java | 16 ++++++++++++++++ .../mixin/MixinDirectBlockEntityTickInvoker.java | 16 ++++++++++++++++ .../qsl/component/mixin/MixinItemStack.java | 16 ++++++++++++++++ .../qsl/component/mixin/MixinServerWorld.java | 16 ++++++++++++++++ .../mixin/MixinThreadedChunkStorage.java | 16 ++++++++++++++++ .../mixin/client/MixinMinecraftClient.java | 16 ++++++++++++++++ .../qsl/component/test/ServerTickListener.java | 16 ++++++++++++++++ .../test/client/ComponentTestModClient.java | 16 ++++++++++++++++ .../component/test/client/TestBeRenderer.java | 16 ++++++++++++++++ .../MixinBlockEntityRendererFactories.java | 16 ++++++++++++++++ .../test/mixin/client/MixinInGameHud.java | 16 ++++++++++++++++ 30 files changed, 480 insertions(+) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java index c185d7a97e..d3d3dbcbef 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.components; import org.jetbrains.annotations.NotNull; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java index 04188f3782..653c930180 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.components; import net.minecraft.network.PacketByteBuf; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java index a802f71b31..471d02f5de 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.components; import org.jetbrains.annotations.NotNull; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java index 77e54a5070..ff4eff0895 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.event; import org.quiltmc.qsl.base.api.event.Event; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java index bec895cbb9..69528bc88c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.wrapper; public class Wrapper { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 85fc705a23..2231cde658 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl; import net.minecraft.util.Identifier; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java index 0fdd653753..a2fb5ff9aa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.client; import org.quiltmc.loader.api.ModContainer; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java index 07691e7ba1..0f237b73bd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.client.sync; import com.mojang.datafixers.util.Either; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java index b72f4a380b..84619bcdf4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.client.sync; import net.minecraft.util.collection.IdList; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java index 4be50d8950..fb683d71a2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.event; import net.minecraft.server.MinecraftServer; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java index d88e059846..2cf749ece0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.predicates; import org.quiltmc.qsl.component.api.ComponentProvider; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java index 865304ac87..caa3de7229 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.sync; import com.mojang.serialization.Lifecycle; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java index f35e4bfc6e..4e7fd6377d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.sync; import net.minecraft.server.MinecraftServer; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java index e63110b3eb..ca2d4cccc8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.sync; import net.minecraft.block.entity.BlockEntity; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java index ff636404ea..7ae1906c0c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.sync.codec; import net.minecraft.block.entity.BlockEntity; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java index cc4cf7c6f0..1383cbde69 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.sync.header; import net.minecraft.block.entity.BlockEntity; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java index 890b5eda1d..ba3032a7f4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.sync.packet; import net.minecraft.util.Identifier; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java index 0ee553c544..7be5bfa029 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.sync.packet; import net.minecraft.network.PacketByteBuf; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index f827a405dc..75cb035877 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.sync.packet; import net.minecraft.client.MinecraftClient; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java index 9b1c628d0e..b90462c7a8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.util; import java.util.function.Supplier; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java index 4a0b53f6d4..d6c6f176f2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import net.minecraft.block.BlockState; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index d63d46683d..481607ebb1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import net.minecraft.entity.Entity; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java index e48aa56a46..8123785453 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import net.minecraft.server.world.ServerWorld; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java index efdcc7ded9..51b471a023 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin; import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java index 3b928e9609..1118300293 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin.client; import net.minecraft.client.MinecraftClient; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 254c4cdf52..6d94521cce 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.test; import net.minecraft.block.Blocks; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java index 326aaaaca5..6a3dba5c51 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.test.client; import net.fabricmc.api.EnvType; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java index 11fabb499d..2c048da3d0 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.test.client; import net.minecraft.client.MinecraftClient; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java index ae69926e58..bdd120b893 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.test.mixin.client; import net.minecraft.block.entity.BlockEntity; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index a722acfbdc..02e414466a 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.test.mixin.client; import net.minecraft.client.ClientGameSession; From 0636caade414800f97ee931eb51aa2bd219cb1d9 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 29 Jun 2022 21:14:15 +0300 Subject: [PATCH 37/70] Applied changes requested by Leo40Git. --- .../quiltmc/qsl/component/api/Component.java | 1 - .../api/components/FloatComponent.java | 3 -- .../api/components/IntegerComponent.java | 1 - .../api/components/InventoryComponent.java | 1 - .../api/components/NbtComponent.java | 4 +- .../component/api/event/ComponentEvents.java | 1 - .../qsl/component/api/wrapper/Wrapper.java | 33 ------------- .../qsl/component/impl/CommonInitializer.java | 3 +- .../impl/ComponentInjectionCache.java | 27 +++------- .../qsl/component/impl/ComponentsImpl.java | 49 ++++++++++--------- .../impl/client/ClientInitializer.java | 1 - .../client/sync/ClientRegistryPacket.java | 1 - .../impl/client/sync/ClientSyncHandler.java | 9 ++-- .../components/DefaultIntegerComponent.java | 1 - .../components/DefaultInventoryComponent.java | 1 - ...ainer.java => LazyComponentContainer.java} | 15 +++--- .../predicates/ClassInjectionPredicate.java | 8 ++- .../FilteredInheritedInjectionPredicate.java | 8 ++- .../InheritedInjectionPredicate.java | 2 +- .../RedirectedInjectionPredicate.java | 21 +++++++- .../impl/sync/ServerSyncHandler.java | 3 +- ...rRegistry.java => SyncHeaderRegistry.java} | 7 ++- .../impl/sync/header/SyncPacketHeader.java | 10 ++-- .../impl/sync/packet/SyncPacket.java | 2 +- .../quiltmc/qsl/component/impl/util/Lazy.java | 21 +------- .../qsl/component/mixin/MixinBlockEntity.java | 12 ++--- .../qsl/component/mixin/MixinChunk.java | 5 +- .../qsl/component/mixin/MixinEntity.java | 8 ++- .../qsl/component/mixin/MixinItemStack.java | 9 ++-- .../component/mixin/MixinLevelProperties.java | 5 +- .../qsl/component/mixin/MixinServerWorld.java | 1 - .../mixin/MixinThreadedChunkStorage.java | 2 +- .../qsl/component/mixin/MixinWorldChunk.java | 8 +-- .../mixin/client/MixinMinecraftClient.java | 4 +- .../resources/quilt_component.mixins.json | 8 +-- .../quiltmc/qsl/component/test/TestBlock.java | 9 ++-- .../qsl/component/test/TestBlockEntity.java | 10 ++-- 37 files changed, 128 insertions(+), 186 deletions(-) delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/{LazifiedComponentContainer.java => LazyComponentContainer.java} (94%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/{ComponentHeaderRegistry.java => SyncHeaderRegistry.java} (83%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java index 207c21d371..10713aba37 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java @@ -19,7 +19,6 @@ import org.jetbrains.annotations.NotNull; public interface Component { - @FunctionalInterface interface Factory { @NotNull diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java index 3e60fbaa3c..ccc6e2a6ce 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java @@ -16,13 +16,10 @@ package org.quiltmc.qsl.component.api.components; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtFloat; import org.quiltmc.qsl.component.api.Component; public interface FloatComponent extends Component { - float get(); void set(float value); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java index bd174713de..8302e87f65 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java @@ -19,7 +19,6 @@ import org.quiltmc.qsl.component.api.Component; public interface IntegerComponent extends Component { - void increment(); void decrement(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index a9d901e851..1ef0b12266 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -25,7 +25,6 @@ import net.minecraft.util.collection.DefaultedList; public interface InventoryComponent extends NbtComponent, Inventory { - @Override default int size() { return this.getStacks().size(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index 262b4346bd..d9d255ee57 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -23,7 +23,6 @@ import org.quiltmc.qsl.component.api.Component; public interface NbtComponent extends Component { - @SuppressWarnings("unchecked") static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier id, @NotNull NbtCompound root) { NbtElement nbtTarget = root.get(id.toString()); @@ -34,7 +33,8 @@ static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); - case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); + case NbtElement.BYTE_ARRAY_TYPE -> + ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java index ff4eff0895..f2d0bd7df6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java @@ -21,7 +21,6 @@ import org.quiltmc.qsl.component.api.ComponentType; public class ComponentEvents { - public static final Event DYNAMIC_INJECT = Event.create(DynamicInject.class, listeners -> (provider, injector) -> { for (DynamicInject listener : listeners) { listener.onInject(provider, injector); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java deleted file mode 100644 index 69528bc88c..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/wrapper/Wrapper.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.api.wrapper; - -public class Wrapper { - private T value; - - public Wrapper(T value) { - this.value = value; - } - - public void set(T value) { - this.value = value; - } - - public T get() { - return this.value; - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 2231cde658..236c94087d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -28,9 +28,10 @@ @ApiStatus.Internal public final class CommonInitializer implements ModInitializer { + public static final String MODID = "quilt_component"; public static @NotNull Identifier id(@NotNull String id) { - return new Identifier(ComponentsImpl.MODID, id); + return new Identifier(MODID, id); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java index 2cae52ac0b..4704048a01 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java @@ -22,37 +22,26 @@ import java.util.*; public class ComponentInjectionCache { - - private static ComponentInjectionCache INSTANCE; - - private final Map, List>> injectionCache = new HashMap<>(); + private static final Map, List>> INJECTION_CACHE = new HashMap<>(); private ComponentInjectionCache() { } - public static ComponentInjectionCache getInstance() { - if (INSTANCE == null) { - INSTANCE = new ComponentInjectionCache(); - } - - return INSTANCE; - } - - public Optional>> getCache(Class clazz) { - if (!this.injectionCache.containsKey(clazz)) { + public static Optional>> getCache(Class clazz) { + if (!INJECTION_CACHE.containsKey(clazz)) { return Optional.empty(); } - return Optional.of(this.injectionCache.get(clazz)); + return Optional.of(INJECTION_CACHE.get(clazz)); } - public void clear() { - this.injectionCache.clear(); + public static void clear() { + INJECTION_CACHE.clear(); } - public void record(Class clazz, List> components) { - if (this.injectionCache.put(clazz, Util.make(new ArrayList<>(), list -> list.addAll(components))) != null) { + public static void record(Class clazz, List> components) { + if (INJECTION_CACHE.put(clazz, Util.make(new ArrayList<>(), list -> list.addAll(components))) != null) { // If there was a value there, it means we attempted an override, and so we throw. throw new IllegalStateException("Cannot register cache twice for class %s".formatted(clazz)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 3b17e628b8..610832792b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -28,7 +28,7 @@ import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.impl.sync.ComponentHeaderRegistry; +import org.quiltmc.qsl.component.impl.sync.SyncHeaderRegistry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,47 +38,51 @@ @ApiStatus.Internal public class ComponentsImpl { - private static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); - public static final String MODID = "quilt_component"; - private static final Map> INJECTION_REGISTRY = new HashMap<>(); - private static final RegistryKey>> REGISTRY_KEY = - RegistryKey.ofRegistry(new Identifier("quilt", "components")); + public static final RegistryKey>> REGISTRY_KEY = + RegistryKey.ofRegistry(CommonInitializer.id("component_types")); public static final Registry> REGISTRY = new SimpleRegistry<>(REGISTRY_KEY, Lifecycle.experimental(), null); - public static void inject(ComponentInjectionPredicate predicate, ComponentType id) { - if (REGISTRY.get(id.id()) == null) { - throw new IllegalArgumentException( - "The target id %s does not match any registered component!".formatted(id.toString()) - ); + private static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); + + private static final Map> INJECTION_REGISTRY = new HashMap<>(); + + public static void inject(ComponentInjectionPredicate predicate, ComponentType type) { + if (REGISTRY.get(type.id()) == null) { + throw ErrorUtil.illegalArgument( + "The target id %s does not match any registered component".formatted(type) + ).get(); } if (INJECTION_REGISTRY.containsKey(predicate)) { - if (!INJECTION_REGISTRY.get(predicate).add(id.id())) { - throw new IllegalStateException( - "Cannot inject the predicate %s with %s more than once! Consider creating a new component!" - .formatted(predicate.toString(), id.id().toString()) - ); + if (!INJECTION_REGISTRY.get(predicate).add(type.id())) { + throw ErrorUtil.illegalArgument( + "Cannot inject the predicate %s with id %s more than once! Consider creating a new component type!" + .formatted(predicate, type) + ).get(); } } else { - INJECTION_REGISTRY.put(predicate, Util.make(new HashSet<>(), set -> set.add(id.id()))); + INJECTION_REGISTRY.put(predicate, Util.make(new HashSet<>(), set -> set.add(type.id()))); } - ComponentInjectionCache.getInstance().clear(); // Always clear the cache after an injection is registered. + ComponentInjectionCache.clear(); // Always clear the cache after an injection is registered. } + @NotNull public static ComponentType register(Identifier id, Component.Factory factory) { var componentType = new ComponentType<>(id, factory, false); return Registry.register(REGISTRY, id, componentType); } + @NotNull public static ComponentType registerStatic(Identifier id, Component.Factory factory) { var componentType = new ComponentType<>(id, factory, true); return Registry.register(REGISTRY, id, componentType); } - public static List> getInjections(ComponentProvider provider) { - return ComponentInjectionCache.getInstance().getCache(provider.getClass()).orElseGet(() -> { + @NotNull + public static List> getInjections(@NotNull ComponentProvider provider) { + return ComponentInjectionCache.getCache(provider.getClass()).orElseGet(() -> { List> injectedTypes = INJECTION_REGISTRY.entrySet().stream() .filter(it -> it.getKey().canInject(provider)) .map(Map.Entry::getValue) @@ -86,12 +90,13 @@ public static List> getInjections(ComponentProvider provider) { .map(ComponentsImpl::getEntry) .collect(Collectors.toList()); - ComponentInjectionCache.getInstance().record(provider.getClass(), injectedTypes); + ComponentInjectionCache.record(provider.getClass(), injectedTypes); return injectedTypes; }); } + @NotNull public static ComponentType getEntry(Identifier id) { return REGISTRY.getOrEmpty(id).orElseThrow( ErrorUtil.illegalArgument("Cannot access element with id %s in the component registry!".formatted(id)) @@ -105,6 +110,6 @@ public static Logger getLogger() { public static void freezeRegistries() { REGISTRY.freeze(); - ComponentHeaderRegistry.HEADERS.freeze(); + SyncHeaderRegistry.HEADERS.freeze(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java index a2fb5ff9aa..706731ac54 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java @@ -24,7 +24,6 @@ import org.quiltmc.qsl.lifecycle.api.client.event.ClientLifecycleEvents; public class ClientInitializer implements ClientModInitializer { - @Override public void onInitializeClient(ModContainer mod) { ClientSyncHandler.getInstance().registerPackets(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java index 0f237b73bd..ab40c49358 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java @@ -29,7 +29,6 @@ import java.util.function.Consumer; public final class ClientRegistryPacket { - @NotNull public static CompletableFuture handleRegistryPacket(@NotNull PacketByteBuf buf, Registry registry, Consumer> action) { return CompletableFuture.supplyAsync(() -> { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java index 84619bcdf4..89aae4dfc1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -19,7 +19,7 @@ import net.minecraft.util.collection.IdList; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.impl.sync.ComponentHeaderRegistry; +import org.quiltmc.qsl.component.impl.sync.SyncHeaderRegistry; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; @@ -27,9 +27,10 @@ import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking; public class ClientSyncHandler { - private static ClientSyncHandler INSTANCE = null; + private IdList> componentList = null; + private IdList> headerList = null; public static ClientSyncHandler getInstance() { @@ -46,10 +47,10 @@ public void registerPackets() { ); ClientLoginNetworking.registerGlobalReceiver(PacketIds.HEADERS, (client, handler, buf, listenerAdder) -> - ClientRegistryPacket.handleRegistryPacket(buf, ComponentHeaderRegistry.HEADERS, list -> this.headerList = list) + ClientRegistryPacket.handleRegistryPacket(buf, SyncHeaderRegistry.HEADERS, list -> this.headerList = list) ); ClientPlayNetworking.registerGlobalReceiver(PacketIds.SYNC, (client, handler, buf, responseSender) -> - SyncPacket.handle(client, buf) + SyncPacket.handle(buf) ); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java index 5c58e06b80..5ce4d99f51 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java @@ -26,7 +26,6 @@ import org.quiltmc.qsl.component.api.components.SyncedComponent; public class DefaultIntegerComponent implements IntegerComponent, NbtComponent, SyncedComponent { - private int value; @Nullable private Runnable saveOperation; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java index dc513eb20d..965d230d0f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java @@ -29,7 +29,6 @@ import java.util.function.Supplier; public class DefaultInventoryComponent implements InventoryComponent, SyncedComponent { - private final DefaultedList stacks; @Nullable private Runnable saveOperation; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java similarity index 94% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index bc867822ca..252d492900 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazifiedComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -32,8 +32,8 @@ import org.quiltmc.qsl.component.api.event.ComponentEvents; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.Lazy; import org.quiltmc.qsl.component.impl.util.StringConstants; @@ -42,8 +42,7 @@ import java.util.*; import java.util.function.Supplier; -public class LazifiedComponentContainer implements ComponentContainer { - +public class LazyComponentContainer implements ComponentContainer { private final Map> components; private final List nbtComponents; private final List tickingComponents; @@ -54,7 +53,7 @@ public class LazifiedComponentContainer implements ComponentContainer { private final SyncPacket.SyncContext syncContext; private final Queue pendingSync; - protected LazifiedComponentContainer( + protected LazyComponentContainer( @NotNull ComponentProvider provider, @Nullable Runnable saveOperation, boolean ticking, @@ -70,7 +69,7 @@ protected LazifiedComponentContainer( this.components = this.initializeComponents(provider); } - public static Optional builder(T obj) { + public static Optional builder(T obj) { if (!(obj instanceof ComponentProvider provider)) { return Optional.empty(); } @@ -78,7 +77,7 @@ public static Optional builder(T obj) { return Optional.of(new Builder(provider)); } - public static void move(@NotNull LazifiedComponentContainer from, @NotNull LazifiedComponentContainer into) { + public static void move(@NotNull LazyComponentContainer from, @NotNull LazyComponentContainer into) { from.components.forEach((id, componentLazy) -> componentLazy.ifPresent(component -> { into.components.put(id, componentLazy); // Directly overriding our value. @@ -230,8 +229,8 @@ public Builder syncing(@NotNull SyncPacketHeader header, Supplier clazz) { if (implementsComponentProvider(clazz)) { this.clazz = clazz; } else { - throw new IllegalArgumentException("Cannot create an injection predicate for a class that isn't a ComponentProvider"); + throw ErrorUtil.illegalArgument( + "Cannot create an injection predicate for a class that isn't a ComponentProvider" + ).get(); } } private static boolean implementsComponentProvider(Class clazz) { - return Arrays.stream(clazz.getInterfaces()).anyMatch(it -> it == ComponentProvider.class) || (clazz.getSuperclass() != null && implementsComponentProvider(clazz.getSuperclass())); + return Arrays.stream(clazz.getInterfaces()).anyMatch(it -> it == ComponentProvider.class) || + (clazz.getSuperclass() != null && implementsComponentProvider(clazz.getSuperclass())); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java index b3dc315310..213fbaa3ad 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java @@ -16,17 +16,15 @@ package org.quiltmc.qsl.component.impl.predicates; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.Objects; +import java.util.Set; public class FilteredInheritedInjectionPredicate extends InheritedInjectionPredicate { - private final List> exceptions; + private final Set> exceptions; public FilteredInheritedInjectionPredicate(Class clazz, Class[] exceptions) { super(clazz); - this.exceptions = new ArrayList<>(Arrays.asList(exceptions)); + this.exceptions = Set.of(exceptions); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java index 352c0bb19c..9de5fd31bc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java @@ -32,7 +32,7 @@ public boolean canInject(ComponentProvider provider) { @Override public int hashCode() { - return super.hashCode() + Objects.hash(this.getClass()); + return super.hashCode() + 67 * Objects.hash(this.getClass()); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java index 2cf749ece0..c584a27e3e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java @@ -18,6 +18,7 @@ import org.quiltmc.qsl.component.api.ComponentProvider; +import java.util.Objects; import java.util.Set; public class RedirectedInjectionPredicate extends ClassInjectionPredicate { @@ -25,11 +26,29 @@ public class RedirectedInjectionPredicate extends ClassInjectionPredicate { public RedirectedInjectionPredicate(Class clazz, Set> redirections) { super(clazz); - this.redirections = redirections; + this.redirections = Set.copyOf(redirections); } @Override public boolean canInject(ComponentProvider provider) { return super.canInject(provider) || this.redirections.contains(provider.getClass()); } + + @Override + public String toString() { + return "RedirectedInjectionPredicate{redirections=" + redirections + ", clazz=" + clazz + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof RedirectedInjectionPredicate that)) return false; + if (!super.equals(o)) return false; + return redirections.equals(that.redirections); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), redirections); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java index 4e7fd6377d..b91be7f17e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java @@ -26,7 +26,6 @@ import org.quiltmc.qsl.networking.api.ServerLoginNetworking; public final class ServerSyncHandler implements ServerLoginConnectionEvents.QueryStart { - private static ServerSyncHandler INSTANCE = null; private ServerSyncHandler() { @@ -53,6 +52,6 @@ public void registerPackets() { @Override public void onLoginStart(ServerLoginNetworkHandler handler, MinecraftServer server, PacketSender sender, ServerLoginNetworking.LoginSynchronizer synchronizer) { sender.sendPacket(PacketIds.TYPES, RegistryPacket.createRegistryPacket(Components.REGISTRY)); - sender.sendPacket(PacketIds.HEADERS, RegistryPacket.createRegistryPacket(ComponentHeaderRegistry.HEADERS)); + sender.sendPacket(PacketIds.HEADERS, RegistryPacket.createRegistryPacket(SyncHeaderRegistry.HEADERS)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncHeaderRegistry.java similarity index 83% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncHeaderRegistry.java index caa3de7229..8f3ed5f508 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ComponentHeaderRegistry.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncHeaderRegistry.java @@ -25,9 +25,12 @@ import org.quiltmc.qsl.component.impl.CommonInitializer; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -public class ComponentHeaderRegistry { +public class SyncHeaderRegistry { + private static final RegistryKey>> HEADERS_KEY = + RegistryKey.ofRegistry(CommonInitializer.id("sync_headers")); + public static final Registry> HEADERS = - new SimpleRegistry<>(RegistryKey.ofRegistry(CommonInitializer.id("sync_headers")), Lifecycle.experimental(), null); + new SimpleRegistry<>(HEADERS_KEY, Lifecycle.experimental(), null); public static

SyncPacketHeader

register(Identifier id, SyncPacketHeader

header) { return Registry.register(HEADERS, id, header); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java index 1383cbde69..3e78cd6ed6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.CommonInitializer; -import org.quiltmc.qsl.component.impl.sync.ComponentHeaderRegistry; +import org.quiltmc.qsl.component.impl.sync.SyncHeaderRegistry; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import org.quiltmc.qsl.networking.api.PacketByteBufs; @@ -35,14 +35,14 @@ public record SyncPacketHeader

(@NotNull NetworkCode // public static final SyncPacketHeader LEVEL = new SyncPacketHeader<>(NetworkCodec.LEVEL); public static void registerDefaults() { - ComponentHeaderRegistry.register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); - ComponentHeaderRegistry.register(CommonInitializer.id("entity"), ENTITY); - ComponentHeaderRegistry.register(CommonInitializer.id("chunk"), CHUNK); + SyncHeaderRegistry.register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); + SyncHeaderRegistry.register(CommonInitializer.id("entity"), ENTITY); + SyncHeaderRegistry.register(CommonInitializer.id("chunk"), CHUNK); } public @NotNull PacketByteBuf start(@NotNull ComponentProvider provider) { var buf = PacketByteBufs.create(); - buf.writeInt(ComponentHeaderRegistry.HEADERS.getRawId(this)); + buf.writeInt(SyncHeaderRegistry.HEADERS.getRawId(this)); //noinspection unchecked the person calling is responsible to make sure we get a valid provider instance! this.codec.encode(buf, (P) provider); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index 75cb035877..4fef937cf8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -47,7 +47,7 @@ public static PacketByteBuf create(SyncPacketHeader headerCreator, @NotNull C return buff; } - public static void handle(MinecraftClient client, PacketByteBuf buf) { + public static void handle(PacketByteBuf buf) { var header = ClientSyncHandler.getInstance().getHeader(buf.readInt()); header.codec().decode(buf).ifPresent(provider -> { var size = buf.readInt(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java index 1a41b21eff..286114795c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java @@ -25,7 +25,6 @@ import java.util.function.Supplier; public class Lazy { - @NotNull private final Supplier sup; @Nullable @@ -48,7 +47,7 @@ public static Lazy filled(@NotNull T value) { @NotNull public Lazy compose(Function transformer) { - return Lazy.of(() -> transformer.apply(this.sup.get())); + return Lazy.of(() -> transformer.apply(this.get())); } @NotNull @@ -88,22 +87,4 @@ public boolean isEmpty() { public void compute(@NotNull Consumer action) { action.accept(this.get()); } - - @Override - public int hashCode() { - return Objects.hash(sup, value); - } - - @Override - public boolean equals(Object o) { - if (o instanceof Lazy other) { - if (other.isEmpty() == this.isEmpty()) { - return this.sup == other.sup; - } else { - return this.value == other.value; - } - } - - return false; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 5467bd3575..7efd5841f7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -16,7 +16,6 @@ package org.quiltmc.qsl.component.mixin; -import com.mojang.serialization.Lifecycle; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -27,10 +26,9 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.quiltmc.qsl.networking.api.PlayerLookup; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -38,11 +36,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.List; - @Mixin(BlockEntity.class) public abstract class MixinBlockEntity implements ComponentProvider { - private ComponentContainer qsl$container; @Inject(method = "readNbt", at = @At("TAIL")) @@ -52,11 +47,12 @@ private void onReadNbt(NbtCompound nbt, CallbackInfo ci) { @Inject(method = "", at = @At("RETURN")) private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.builder(this) + //noinspection ConstantConditions + this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() .setSaveOperation(this::markDirty) .ticking() - .syncing(SyncPacketHeader.BLOCK_ENTITY, () -> SyncPlayerList.create((BlockEntity) (Object)this)) + .syncing(SyncPacketHeader.BLOCK_ENTITY, () -> SyncPlayerList.create((BlockEntity) (Object) this)) .build(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index d702d6664b..9855609171 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.spongepowered.asm.mixin.Mixin; @@ -38,7 +38,6 @@ @Mixin(Chunk.class) public abstract class MixinChunk implements ComponentProvider { - private ComponentContainer qsl$container; @Shadow @@ -51,7 +50,7 @@ public abstract class MixinChunk implements ComponentProvider { @Inject(method = "", at = @At("RETURN")) private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { - LazifiedComponentContainer.Builder builder = LazifiedComponentContainer.builder(this) + LazyComponentContainer.Builder builder = LazyComponentContainer.builder(this) .orElseThrow() .setSaveOperation(() -> this.setNeedsSaving(true)); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 04f6686a66..1bd6f7ef44 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -23,10 +23,9 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.quiltmc.qsl.networking.api.PlayerLookup; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -35,16 +34,15 @@ @Mixin(Entity.class) public abstract class MixinEntity implements ComponentProvider { - private ComponentContainer qsl$container; @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { //noinspection ConstantConditions - this.qsl$container = LazifiedComponentContainer.builder(this) + this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() .ticking() - .syncing(SyncPacketHeader.ENTITY, () -> SyncPlayerList.create((Entity) (Object)this)) + .syncing(SyncPacketHeader.ENTITY, () -> SyncPlayerList.create((Entity) (Object) this)) .build(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index 481607ebb1..9b8569e1fc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -36,14 +36,13 @@ @SuppressWarnings("ConstantConditions") @Mixin(ItemStack.class) public abstract class MixinItemStack implements ComponentProvider { // TODO: Make sure nothing else may be broken before final PR. - @Shadow private @Nullable NbtCompound nbt; - private LazifiedComponentContainer qsl$container; + private LazyComponentContainer qsl$container; @Inject(method = "(Lnet/minecraft/item/ItemConvertible;I)V", at = @At("TAIL")) private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.builder(this) + this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() .setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) .ticking() @@ -55,7 +54,7 @@ private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;)V", at = @At("TAIL")) private void readContainer(NbtCompound nbtCompound, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.builder(this) + this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() .setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) .ticking() diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index 3a767fb3c7..3fd0e245c7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -35,7 +35,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -47,7 +47,6 @@ @Mixin(LevelProperties.class) public abstract class MixinLevelProperties implements ServerWorldProperties, SaveProperties, ComponentProvider { - private ComponentContainer qsl$container; @Inject(method = "readProperties", at = @At("RETURN")) @@ -57,7 +56,7 @@ private static void readComponentData(Dynamic dynamic, DataFixer dat @Inject(method = "(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/NbtCompound;ZIIIFJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lcom/mojang/serialization/Lifecycle;)V", at = @At("TAIL")) private void onInit(DataFixer dataFixer, int i, NbtCompound nbtCompound, boolean bl, int j, int k, int l, float f, long m, long n, int o, int p, int q, boolean bl2, int r, boolean bl3, boolean bl4, boolean bl5, WorldBorder.Properties properties, int s, int t, UUID uUID, Set set, Timer timer, NbtCompound nbtCompound2, NbtCompound nbtCompound3, LevelInfo levelInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.builder(this) + this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() .ticking() // .syncing(DefaultSyncPacketHeaders.LEVEL) TODO diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java index 8123785453..946f7eed83 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java @@ -33,7 +33,6 @@ @Mixin(ServerWorld.class) public abstract class MixinServerWorld extends World { - protected MixinServerWorld(MutableWorldProperties mutableWorldProperties, RegistryKey registryKey, Holder holder, Supplier supplier, boolean bl, boolean bl2, long l, int i) { super(mutableWorldProperties, registryKey, holder, supplier, bl, bl2, l, i); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java index 51b471a023..a5b436ece3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java @@ -38,6 +38,6 @@ public abstract class MixinThreadedChunkStorage { ) ) private void syncChunkContainer(ServerPlayerEntity player, ChunkPos pos, MutableObject mutableObject, boolean withinMaxWatchDistance, boolean withinViewDistance, CallbackInfo ci) { - player.getWorld().getChunk(pos.x, pos.z).sync(); + player.getWorld().getChunk(pos.x, pos.z).sync(); // FIXME: Initial chunk sync } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java index 7f5f3b7579..28994f3f41 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -25,7 +25,7 @@ import net.minecraft.world.gen.chunk.BlendingData; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -40,9 +40,9 @@ public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitVi @Inject(method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/ProtoChunk;Lnet/minecraft/world/chunk/WorldChunk$PostLoadProcessor;)V", at = @At("TAIL")) private void copyComponentData(ServerWorld serverWorld, ProtoChunk protoChunk, WorldChunk.PostLoadProcessor postLoadProcessor, CallbackInfo ci) { var target = protoChunk instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : protoChunk; - LazifiedComponentContainer.move( - (LazifiedComponentContainer) target.getContainer(), - (LazifiedComponentContainer) this.getContainer() + LazyComponentContainer.move( + (LazyComponentContainer) target.getContainer(), + (LazyComponentContainer) this.getContainer() ); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java index 1118300293..8764c66388 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java @@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazifiedComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -38,6 +38,6 @@ public class MixinMinecraftClient implements ComponentProvider { @Inject(method = "", at = @At("TAIL")) private void initContainer(RunArgs runArgs, CallbackInfo ci) { - this.qsl$container = LazifiedComponentContainer.builder(this).orElseThrow().build(); + this.qsl$container = LazyComponentContainer.builder(this).orElseThrow().build(); } } diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index a66519d3b1..85844670a9 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -14,10 +14,10 @@ "MixinThreadedChunkStorage", "MixinWorldChunk" ], - "injectors": { - "defaultRequire": 1 - }, "client": [ "client.MixinMinecraftClient" - ] + ], + "injectors": { + "defaultRequire": 1 + } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index 4afbe4aba9..4424b79b20 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -31,7 +31,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.wrapper.Wrapper; public class TestBlock extends Block implements BlockEntityProvider { public TestBlock(Settings settings) { @@ -61,7 +60,7 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt ItemStack handStack = player.getStackInHand(hand); if (!handStack.isEmpty()) { - final Wrapper ret = new Wrapper<>(ActionResult.PASS); + final ActionResult[] ret = new ActionResult[]{ActionResult.PASS}; be.expose(ComponentTestMod.CHUNK_INVENTORY).ifPresent(inventoryComponent -> { var stack = inventoryComponent.getStack(0); @@ -72,18 +71,18 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt inventoryComponent.setStack(0, copied); inventoryComponent.save(); inventoryComponent.sync(); - ret.set(ActionResult.SUCCESS); + ret[0] = ActionResult.SUCCESS; } else { if (ItemStack.canCombine(stack, handStack)) { stack.increment(1); handStack.decrement(1); inventoryComponent.save(); - ret.set(ActionResult.SUCCESS); + ret[0] = ActionResult.SUCCESS; } } }); - return ret.get(); + return ret[0]; } return super.onUse(state, world, pos, player, hand, hit); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index a5bb960771..915c34f2a9 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -19,7 +19,6 @@ import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.Packet; import net.minecraft.network.listener.ClientPlayPacketListener; @@ -41,11 +40,10 @@ import java.util.Set; public class TestBlockEntity extends BlockEntity { -// public static final ComponentType TEST_BE_INT = Components.register( -// new Identifier(ComponentTestMod.MODID, "test_be_int"), -// DefaultIntegerComponent::new -// ); Crashes due to our freezing the registry! - + // public static final ComponentType TEST_BE_INT = Components.register( + // new Identifier(ComponentTestMod.MODID, "test_be_int"), + // DefaultIntegerComponent::new + // ); Crashes due to our freezing the registry! private final ComponentContainer container = SimpleComponentContainer.builder() .setSaveOperation(this::markDirty) .add(ComponentTestMod.TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) From af64a98c1472577a2adf9cac8da80995177046ce Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 29 Jun 2022 21:23:37 +0300 Subject: [PATCH 38/70] Exposed as in part of the public API. --- .../main/java/org/quiltmc/qsl/component/api/Components.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 9762428080..2668cdde49 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -18,6 +18,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.predicates.ClassInjectionPredicate; @@ -29,6 +30,8 @@ import java.util.Set; public final class Components { + public static final RegistryKey>> REGISTRY_KEY = ComponentsImpl.REGISTRY_KEY; + public static final Registry> REGISTRY = ComponentsImpl.REGISTRY; public static void inject(ComponentInjectionPredicate predicate, ComponentType component) { From 33e5d4a32c2fe4f73506a63f6da7e22f6bfb9dcb Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 29 Jun 2022 21:52:24 +0300 Subject: [PATCH 39/70] Fixed runtime crash with FilteredInheritedInjectionPredicate --- .../FilteredInheritedInjectionPredicate.java | 8 +++++--- .../qsl/component/mixin/MixinThreadedChunkStorage.java | 10 +++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java index 213fbaa3ad..ee0004e7f8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java @@ -16,13 +16,15 @@ package org.quiltmc.qsl.component.impl.predicates; +import org.quiltmc.qsl.component.api.ComponentProvider; + import java.util.Objects; import java.util.Set; public class FilteredInheritedInjectionPredicate extends InheritedInjectionPredicate { private final Set> exceptions; - public FilteredInheritedInjectionPredicate(Class clazz, Class[] exceptions) { + public FilteredInheritedInjectionPredicate(Class clazz, Class... exceptions) { super(clazz); this.exceptions = Set.of(exceptions); } @@ -46,7 +48,7 @@ public String toString() { } @Override - public boolean canInject(Class current) { - return !this.exceptions.contains(current) && super.canInject(current); + public boolean canInject(ComponentProvider provider) { + return !this.exceptions.contains(provider.getClass()) && super.canInject(provider.getClass()); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java index a5b436ece3..a9aaab6ef4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java @@ -19,7 +19,7 @@ import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ThreadedAnvilChunkStorage; -import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.WorldChunk; import org.apache.commons.lang3.mutable.MutableObject; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -30,14 +30,14 @@ public abstract class MixinThreadedChunkStorage { @Inject( - method = "sendWatchPackets", + method = "sendChunkDataPackets", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/world/ThreadedAnvilChunkStorage;sendChunkDataPackets(Lnet/minecraft/server/network/ServerPlayerEntity;Lorg/apache/commons/lang3/mutable/MutableObject;Lnet/minecraft/world/chunk/WorldChunk;)V", + target = "Lnet/minecraft/server/network/ServerPlayerEntity;sendInitialChunkPackets(Lnet/minecraft/util/math/ChunkPos;Lnet/minecraft/network/Packet;)V", shift = At.Shift.AFTER ) ) - private void syncChunkContainer(ServerPlayerEntity player, ChunkPos pos, MutableObject mutableObject, boolean withinMaxWatchDistance, boolean withinViewDistance, CallbackInfo ci) { - player.getWorld().getChunk(pos.x, pos.z).sync(); // FIXME: Initial chunk sync + private void syncChunkContainer(ServerPlayerEntity player, MutableObject mutableObject, WorldChunk chunk, CallbackInfo ci) { + chunk.sync(); } } From c058bbce73f472f559252be0f9915e5760d2a60e Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 29 Jun 2022 21:57:56 +0300 Subject: [PATCH 40/70] Applied LambdaAurora's requested changes. --- .../org/quiltmc/qsl/component/api/ComponentProvider.java | 6 +++--- .../main/java/org/quiltmc/qsl/component/api/Components.java | 2 +- .../qsl/component/impl/event/ServerTickEventListener.java | 2 +- .../quiltmc/qsl/component/impl/sync/packet/SyncPacket.java | 3 +-- .../org/quiltmc/qsl/component/mixin/MixinBlockEntity.java | 2 +- .../java/org/quiltmc/qsl/component/mixin/MixinChunk.java | 2 +- .../quiltmc/qsl/component/mixin/MixinChunkSerializer.java | 4 ++-- .../component/mixin/MixinDirectBlockEntityTickInvoker.java | 2 +- .../java/org/quiltmc/qsl/component/mixin/MixinEntity.java | 4 ++-- .../org/quiltmc/qsl/component/mixin/MixinItemStack.java | 4 ++-- .../quiltmc/qsl/component/mixin/MixinLevelProperties.java | 4 ++-- .../org/quiltmc/qsl/component/mixin/MixinServerWorld.java | 2 +- .../qsl/component/mixin/MixinThreadedChunkStorage.java | 2 +- .../org/quiltmc/qsl/component/mixin/MixinWorldChunk.java | 4 ++-- .../qsl/component/mixin/client/MixinMinecraftClient.java | 2 +- 15 files changed, 22 insertions(+), 23 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index 5744dd0e46..cf4ba8226b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -38,7 +38,7 @@ }) public interface ComponentProvider { @NotNull - ComponentContainer getContainer(); + ComponentContainer getComponentContainer(); default > Optional call(ComponentType type, T t) { return this.expose(type).map(func -> func.call(this, t)); @@ -48,7 +48,7 @@ default Optional expose(ComponentType id) { return Components.expose(id, this); } - default void sync() { - this.getContainer().sync(this); + default void syncComponents() { + this.getComponentContainer().sync(this); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 2668cdde49..57585c1df3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -56,7 +56,7 @@ public static void injectRedirected(Class mainClass, Co public static Optional expose(ComponentType id, S obj) { if (obj instanceof ComponentProvider provider) { - return provider.getContainer().expose(id.id()) + return provider.getComponentContainer().expose(id.id()) .map(id::cast) .map(Optional::orElseThrow); // If the casting fails something is wrong with the provided ComponentType. In that case we just throw. } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java index fb683d71a2..ee08acd438 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java @@ -31,7 +31,7 @@ public class ServerTickEventListener implements ServerTickEvents.End { public void endServerTick(MinecraftServer server) { SaveProperties saveProperties = server.getSaveProperties(); if (saveProperties instanceof LevelProperties levelProperties) { - levelProperties.getContainer().tick(levelProperties); + levelProperties.getComponentContainer().tick(levelProperties); } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index 4fef937cf8..46055bb96c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -16,7 +16,6 @@ package org.quiltmc.qsl.component.impl.sync.packet; -import net.minecraft.client.MinecraftClient; import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; @@ -55,7 +54,7 @@ public static void handle(PacketByteBuf buf) { for (int i = 0; i < size; i++) { NetworkCodec.COMPONENT_TYPE.decode(buf) .map(Components.REGISTRY::getId) - .ifPresent(id -> provider.getContainer().receiveSyncPacket(id, buf)); + .ifPresent(id -> provider.getComponentContainer().receiveSyncPacket(id, buf)); } }); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index 7efd5841f7..cf6e4515d6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -72,7 +72,7 @@ private void onWriteNbt(CallbackInfoReturnable cir) { } @Override - public @NotNull ComponentContainer getContainer() { + public @NotNull ComponentContainer getComponentContainer() { return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 9855609171..5f9a5484ca 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -44,7 +44,7 @@ public abstract class MixinChunk implements ComponentProvider { public abstract void setNeedsSaving(boolean needsSaving); @Override - public @NotNull ComponentContainer getContainer() { + public @NotNull ComponentContainer getComponentContainer() { return this.qsl$container; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java index 31b14a8f80..07b51e7876 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java @@ -35,14 +35,14 @@ public class MixinChunkSerializer { private static void deserializeComponents(ServerWorld world, PointOfInterestStorage poiStorage, ChunkPos pos, NbtCompound nbt, CallbackInfoReturnable cir) { var ret = cir.getReturnValue(); var target = ret instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : ret; - target.getContainer().readNbt(nbt); + target.getComponentContainer().readNbt(nbt); cir.setReturnValue(ret); } @Inject(method = "serialize", at = @At("RETURN"), cancellable = true) private static void serializeComponents(ServerWorld world, Chunk chunk, CallbackInfoReturnable cir) { var ret = cir.getReturnValue(); - chunk.getContainer().writeNbt(ret); + chunk.getComponentContainer().writeNbt(ret); cir.setReturnValue(ret); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java index d6c6f176f2..3892c78303 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java @@ -37,6 +37,6 @@ public class MixinDirectBlockEntityTickInvoker { @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/entity/BlockEntity;)V")) private void tickContainer(BlockEntityTicker instance, World world, BlockPos blockPos, BlockState blockState, T t) { instance.tick(world, blockPos, blockState, t); - this.blockEntity.getContainer().tick(this.blockEntity); + this.blockEntity.getComponentContainer().tick(this.blockEntity); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index 1bd6f7ef44..d75df537ed 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -58,11 +58,11 @@ private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { @Inject(method = "tick", at = @At("TAIL")) private void tickContainer(CallbackInfo ci) { - this.getContainer().tick(this); + this.getComponentContainer().tick(this); } @Override - public @NotNull ComponentContainer getContainer() { + public @NotNull ComponentContainer getComponentContainer() { return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index 9b8569e1fc..4cd174923e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -77,7 +77,7 @@ private void deserializeContainer(CallbackInfoReturnable cir) { ItemStack copiedStack = cir.getReturnValue(); NbtCompound nbt = copiedStack.getNbt(); if (nbt != null) { - copiedStack.getContainer().readNbt(nbt); + copiedStack.getComponentContainer().readNbt(nbt); } } @@ -87,7 +87,7 @@ private void tickContainer(World world, Entity entity, int slot, boolean selecte } @Override - public @NotNull ComponentContainer getContainer() { + public @NotNull ComponentContainer getComponentContainer() { return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index 3fd0e245c7..f52a7e521c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -51,7 +51,7 @@ public abstract class MixinLevelProperties implements ServerWorldProperties, Sav @Inject(method = "readProperties", at = @At("RETURN")) private static void readComponentData(Dynamic dynamic, DataFixer dataFixer, int dataVersion, @Nullable NbtCompound playerData, LevelInfo levelInfo, SaveVersionInfo saveVersionInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfoReturnable cir) { - cir.getReturnValue().getContainer().readNbt((NbtCompound) dynamic.getValue()); + cir.getReturnValue().getComponentContainer().readNbt((NbtCompound) dynamic.getValue()); } @Inject(method = "(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/NbtCompound;ZIIIFJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lcom/mojang/serialization/Lifecycle;)V", at = @At("TAIL")) @@ -69,7 +69,7 @@ private void writeComponentData(DynamicRegistryManager registryManager, NbtCompo } @Override - public @NotNull ComponentContainer getContainer() { + public @NotNull ComponentContainer getComponentContainer() { return this.qsl$container; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java index 946f7eed83..fe75279615 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java @@ -39,6 +39,6 @@ protected MixinServerWorld(MutableWorldProperties mutableWorldProperties, Regist @Inject(method = "tickChunk", at = @At("TAIL")) private void tickContainer(WorldChunk chunk, int randomTickSpeed, CallbackInfo ci) { - chunk.getContainer().tick(chunk); + chunk.getComponentContainer().tick(chunk); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java index a9aaab6ef4..642ac402d0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java @@ -38,6 +38,6 @@ public abstract class MixinThreadedChunkStorage { ) ) private void syncChunkContainer(ServerPlayerEntity player, MutableObject mutableObject, WorldChunk chunk, CallbackInfo ci) { - chunk.sync(); + chunk.syncComponents(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java index 28994f3f41..120f56b8dd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java @@ -41,8 +41,8 @@ public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitVi private void copyComponentData(ServerWorld serverWorld, ProtoChunk protoChunk, WorldChunk.PostLoadProcessor postLoadProcessor, CallbackInfo ci) { var target = protoChunk instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : protoChunk; LazyComponentContainer.move( - (LazyComponentContainer) target.getContainer(), - (LazyComponentContainer) this.getContainer() + (LazyComponentContainer) target.getComponentContainer(), + (LazyComponentContainer) this.getComponentContainer() ); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java index 8764c66388..7d44901ce0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java @@ -32,7 +32,7 @@ public class MixinMinecraftClient implements ComponentProvider { private ComponentContainer qsl$container; @Override - public @NotNull ComponentContainer getContainer() { + public @NotNull ComponentContainer getComponentContainer() { return this.qsl$container; } From 74658dea51beb88649afca88b2f84bbc5ca021dd Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 29 Jun 2022 22:39:22 +0300 Subject: [PATCH 41/70] Added the block_entity module as a dependency of the testmod and removed old code handling it. --- library/data/component/build.gradle | 8 +++++--- .../src/main/resources/quilt_component.accesswidener | 2 -- .../org/quiltmc/qsl/component/test/ComponentTestMod.java | 4 ++-- .../org/quiltmc/qsl/component/test/TestBlockEntity.java | 2 +- .../data/component/src/testmod/resources/quilt.mod.json | 3 ++- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index 6fd8932e82..59ffd7b983 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -14,13 +14,15 @@ qslModule { api("lifecycle_events") api("networking") } + + block { + testmodOnly("block_entity") + } } entrypoints { events { - values = [ - "org.quiltmc.qsl.component.impl.event.ServerTickEventListener" - ] + values = ["org.quiltmc.qsl.component.impl.event.ServerTickEventListener"] } init { diff --git a/library/data/component/src/main/resources/quilt_component.accesswidener b/library/data/component/src/main/resources/quilt_component.accesswidener index 8bad5df4ac..adc1776cf0 100644 --- a/library/data/component/src/main/resources/quilt_component.accesswidener +++ b/library/data/component/src/main/resources/quilt_component.accesswidener @@ -1,5 +1,3 @@ accessWidener v2 named -# TODO: Remove this once the Block Entity API is merged. -extendable class net/minecraft/block/entity/BlockEntityType$BlockEntityFactory # Using this to make the default implementation of the BlockEntityTickInvoker interface accessible to mixin. transitive-accessible class net/minecraft/world/chunk/WorldChunk$DirectBlockEntityTickInvoker diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index c4d39f1811..fe7d3b7dcd 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -38,6 +38,7 @@ import net.minecraft.world.level.LevelProperties; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; +import org.quiltmc.qsl.block.entity.api.QuiltBlockEntityTypeBuilder; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.components.FloatComponent; @@ -148,6 +149,5 @@ public void onInitialize(ModContainer mod) { } public static final BlockEntityType TEST_BE_TYPE = - BlockEntityType.Builder.create(TestBlockEntity::new, TEST_BLOCK, Blocks.NOTE_BLOCK).build(null); - + QuiltBlockEntityTypeBuilder.create(TestBlockEntity::new, TEST_BLOCK).build(); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 915c34f2a9..10966bdfc4 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -87,7 +87,7 @@ private static void expand(BlockPos initialPos, BlockPos pos, World world, Set Date: Thu, 30 Jun 2022 16:17:17 +0300 Subject: [PATCH 42/70] Made the LOGGER fields public and removed the getLogger method. --- .../org/quiltmc/qsl/component/impl/ComponentsImpl.java | 7 +------ .../component/impl/container/LazyComponentContainer.java | 2 +- .../qsl/component/impl/sync/packet/RegistryPacket.java | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 610832792b..7ec379ffa9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -43,7 +43,7 @@ public class ComponentsImpl { public static final Registry> REGISTRY = new SimpleRegistry<>(REGISTRY_KEY, Lifecycle.experimental(), null); - private static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); + public static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); private static final Map> INJECTION_REGISTRY = new HashMap<>(); @@ -103,11 +103,6 @@ public static ComponentType getEntry(Identifier id) { ); } - @NotNull - public static Logger getLogger() { - return LOGGER; - } - public static void freezeRegistries() { REGISTRY.freeze(); SyncHeaderRegistry.HEADERS.freeze(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 252d492900..0a796eda39 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -143,7 +143,7 @@ public void tick(@NotNull ComponentProvider provider) { @Override public void receiveSyncPacket(@NotNull Identifier id, @NotNull PacketByteBuf buf) { this.expose(id).map(it -> ((SyncedComponent) it)).ifPresent(syncedComponent -> syncedComponent.readFromBuf(buf)); - ComponentsImpl.getLogger().info("Received packet for {}", id); + ComponentsImpl.LOGGER.info("Received packet for {}", id); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java index 7be5bfa029..dab8a014f8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java @@ -47,7 +47,7 @@ public static void handleRegistryResponse(@NotNull PacketByteBuf buf, ServerLogi Identifier id = Identifier.tryParse(retString); handler.disconnect(Text.literal(msg.formatted(id))); - ComponentsImpl.getLogger().warn(msg.formatted(id)); + ComponentsImpl.LOGGER.warn(msg.formatted(id)); } } } From fb8741a9cb7fbe8084f55e697592737131f110c2 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 30 Jun 2022 19:19:34 +0300 Subject: [PATCH 43/70] Switched to IdentityHashMap and Component type keys. --- library/data/component/build.gradle | 1 + .../qsl/component/api/ComponentContainer.java | 4 +- .../quiltmc/qsl/component/api/Components.java | 2 +- .../container/LazyComponentContainer.java | 59 ++++++++----------- .../container/SimpleComponentContainer.java | 50 ++++++++-------- .../impl/sync/packet/RegistryPacket.java | 2 +- .../impl/sync/packet/SyncPacket.java | 15 ++--- .../quiltmc/qsl/component/impl/util/Lazy.java | 9 ++- .../resources/quilt_component.accesswidener | 3 +- .../quilt_component_test.mixins.json | 4 +- 10 files changed, 70 insertions(+), 79 deletions(-) diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index 59ffd7b983..7cf8c4af57 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -13,6 +13,7 @@ qslModule { api("qsl_base") api("lifecycle_events") api("networking") + testmodOnly("registry") // Required by block_entity } block { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index b19e681ca8..81c4b99698 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -24,7 +24,7 @@ import java.util.Optional; public interface ComponentContainer { // TODO: Maybe split up responsibilities? - Optional expose(Identifier id); + Optional expose(ComponentType type); void writeNbt(@NotNull NbtCompound providerRootNbt); @@ -32,7 +32,7 @@ public interface ComponentContainer { // TODO: Maybe split up responsibilities? void tick(@NotNull ComponentProvider provider); - void receiveSyncPacket(@NotNull Identifier id, @NotNull PacketByteBuf buf); + void receiveSyncPacket(@NotNull ComponentType type, @NotNull PacketByteBuf buf); void sync(@NotNull ComponentProvider provider); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 57585c1df3..4674ffb7ab 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -56,7 +56,7 @@ public static void injectRedirected(Class mainClass, Co public static Optional expose(ComponentType id, S obj) { if (obj instanceof ComponentProvider provider) { - return provider.getComponentContainer().expose(id.id()) + return provider.getComponentContainer().expose(id) .map(id::cast) .map(Optional::orElseThrow); // If the casting fails something is wrong with the provided ComponentType. In that case we just throw. } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 0a796eda39..479b11ed43 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -22,36 +22,31 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.*; import org.quiltmc.qsl.component.api.components.NbtComponent; import org.quiltmc.qsl.component.api.components.SyncedComponent; import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.api.event.ComponentEvents; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.Lazy; import org.quiltmc.qsl.component.impl.util.StringConstants; -import org.quiltmc.qsl.networking.api.ServerPlayNetworking; import java.util.*; import java.util.function.Supplier; public class LazyComponentContainer implements ComponentContainer { - private final Map> components; - private final List nbtComponents; - private final List tickingComponents; + private final IdentityHashMap, Lazy> components; + private final List> nbtComponents; + private final List> tickingComponents; @Nullable private final Runnable saveOperation; private final boolean ticking; private final boolean syncing; private final SyncPacket.SyncContext syncContext; - private final Queue pendingSync; + private final Queue> pendingSync; protected LazyComponentContainer( @NotNull ComponentProvider provider, @@ -92,15 +87,15 @@ public static void move(@NotNull LazyComponentContainer from, @NotNull LazyCompo } @Override - public Optional expose(Identifier id) { + public Optional expose(ComponentType id) { return Optional.ofNullable(this.components.get(id)).map(Lazy::get); } @Override public void writeNbt(@NotNull NbtCompound providerRootNbt) { var rootQslNbt = new NbtCompound(); - this.nbtComponents.forEach(id -> this.components.get(id).ifPresent(component -> - NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, id) + this.nbtComponents.forEach(type -> this.components.get(type).ifPresent(component -> + NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, type.id()) )); if (!rootQslNbt.isEmpty()) { @@ -114,10 +109,12 @@ public void readNbt(@NotNull NbtCompound providerRootNbt) { rootQslNbt.getKeys().stream() .map(Identifier::tryParse) + .filter(Objects::nonNull)// TODO: Looks a bit suspicous... + .map(Components.REGISTRY::get) .filter(Objects::nonNull) - .forEach(id -> this.expose(id).ifPresent(component -> { + .forEach(type -> this.expose(type).ifPresent(component -> { if (component instanceof NbtComponent nbtComponent) { - NbtComponent.readFrom(nbtComponent, id, rootQslNbt); + NbtComponent.readFrom(nbtComponent, type.id(), rootQslNbt); } })); } @@ -141,14 +138,14 @@ public void tick(@NotNull ComponentProvider provider) { } @Override - public void receiveSyncPacket(@NotNull Identifier id, @NotNull PacketByteBuf buf) { - this.expose(id).map(it -> ((SyncedComponent) it)).ifPresent(syncedComponent -> syncedComponent.readFromBuf(buf)); - ComponentsImpl.LOGGER.info("Received packet for {}", id); + public void receiveSyncPacket(@NotNull ComponentType type, @NotNull PacketByteBuf buf) { + this.expose(type).map(it -> ((SyncedComponent) it)).ifPresent(syncedComponent -> syncedComponent.readFromBuf(buf)); + ComponentsImpl.LOGGER.info("Received packet for {}", type); } @Override public void sync(@NotNull ComponentProvider provider) { - var map = new HashMap(); + var map = new HashMap, SyncedComponent>(); while (!this.pendingSync.isEmpty()) { var id = this.pendingSync.poll(); @@ -156,18 +153,14 @@ public void sync(@NotNull ComponentProvider provider) { } if (!map.isEmpty()) { - var packet = SyncPacket.create(this.syncContext.header(), provider, map); - - this.syncContext.playerGenerator().get().forEach(serverPlayer -> - ServerPlayNetworking.send(serverPlayer, PacketIds.SYNC, packet) - ); + SyncPacket.send(this.syncContext, provider, map); } } - private Map> initializeComponents(ComponentProvider provider) { - var map = new HashMap>(); - ComponentsImpl.getInjections(provider).forEach(type -> map.put(type.id(), this.createLazy(type))); - ComponentEvents.DYNAMIC_INJECT.invoker().onInject(provider, type -> map.put(type.id(), this.createLazy(type))); + private IdentityHashMap, Lazy> initializeComponents(ComponentProvider provider) { + var map = new IdentityHashMap, Lazy>(); + ComponentsImpl.getInjections(provider).forEach(type -> map.put(type, this.createLazy(type))); + ComponentEvents.DYNAMIC_INJECT.invoker().onInject(provider, type -> map.put(type, this.createLazy(type))); return map; } @@ -175,7 +168,7 @@ private Lazy createLazy(ComponentType type) { if (type.isStatic()) { Component singleton = type.create(); if (this.ticking && singleton instanceof TickingComponent) { - this.tickingComponents.add(type.id()); + this.tickingComponents.add(type); } return Lazy.filled(singleton); @@ -184,16 +177,16 @@ private Lazy createLazy(ComponentType type) { return Lazy.of(() -> { Component component = type.create(); if (component instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(type.id()); + this.nbtComponents.add(type); nbtComponent.setSaveOperation(this.saveOperation); } if (this.ticking && component instanceof TickingComponent) { - this.tickingComponents.add(type.id()); + this.tickingComponents.add(type); } if (this.syncing && component instanceof SyncedComponent syncedComponent) { - syncedComponent.setSyncOperation(() -> this.pendingSync.add(type.id())); + syncedComponent.setSyncOperation(() -> this.pendingSync.add(type)); } return component; @@ -233,6 +226,4 @@ public LazyComponentContainer build() { return new LazyComponentContainer(this.provider, this.saveOperation, this.ticking, this.syncContext); } } - - } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index eb471d309d..db5658b4c1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -23,10 +23,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.*; import org.quiltmc.qsl.component.api.components.NbtComponent; import org.quiltmc.qsl.component.api.components.SyncedComponent; import org.quiltmc.qsl.component.api.components.TickingComponent; @@ -40,15 +37,15 @@ import java.util.stream.Stream; public class SimpleComponentContainer implements ComponentContainer { - private final Map components; - private final List nbtComponents; - private final List tickingComponents; + private final IdentityHashMap, Component> components; + private final List> nbtComponents; + private final List> tickingComponents; @Nullable private final SyncPacket.SyncContext syncContext; - private Queue pendingSync; + private Queue> pendingSync; - protected SimpleComponentContainer(@Nullable Runnable saveOperation, SyncPacket.SyncContext syncContext, Stream> types) { - this.components = new HashMap<>(); + protected SimpleComponentContainer(@Nullable Runnable saveOperation, SyncPacket.@Nullable SyncContext syncContext, Stream> types) { + this.components = new IdentityHashMap<>(); this.nbtComponents = new ArrayList<>(); this.tickingComponents = new ArrayList<>(); if (syncContext != null) { @@ -69,14 +66,17 @@ public static Builder builder() { } @Override - public Optional expose(Identifier id) { - return Optional.ofNullable(this.components.get(id)); + public Optional expose(ComponentType type) { + return Optional.ofNullable(this.components.get(type)); } @Override public void writeNbt(@NotNull NbtCompound providerRootNbt) { var rootQslNbt = new NbtCompound(); - this.nbtComponents.forEach(id -> this.expose(id).ifPresent(component -> NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, id))); + this.nbtComponents.forEach(id -> this.expose(id) + .ifPresent(component -> NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, id.id())) + ); + if (!rootQslNbt.isEmpty()) { providerRootNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); } @@ -93,8 +93,10 @@ public void readNbt(@NotNull NbtCompound providerRootNbt) { rootQslNbt.getKeys().stream() .map(Identifier::tryParse) .filter(Objects::nonNull) + .map(Components.REGISTRY::get) + .filter(Objects::nonNull) .forEach(id -> this.expose(id) - .ifPresent(component -> NbtComponent.readFrom((NbtComponent) component, id, rootQslNbt)) + .ifPresent(component -> NbtComponent.readFrom((NbtComponent) component, id.id(), rootQslNbt)) ); } @@ -109,20 +111,20 @@ public void tick(@NotNull ComponentProvider provider) { } @Override - public void receiveSyncPacket(@NotNull Identifier id, @NotNull PacketByteBuf buf) { - ((SyncedComponent) this.components.get(id)).readFromBuf(buf); + public void receiveSyncPacket(@NotNull ComponentType type, @NotNull PacketByteBuf buf) { + ((SyncedComponent) this.components.get(type)).readFromBuf(buf); } @Override public void sync(@NotNull ComponentProvider provider) { if (this.syncContext == null) { - throw ErrorUtil.illegalState("Cannot sync a non-syncable component container! Make sure you provider a context!").get(); + throw ErrorUtil.illegalState("Cannot sync a non-syncable component container! Make sure you provide a context!").get(); } - var map = new HashMap(); + var map = new HashMap, SyncedComponent>(); while (!this.pendingSync.isEmpty()) { - var currentId = this.pendingSync.poll(); - map.put(currentId, (SyncedComponent) this.components.get(currentId)); + var currentType = this.pendingSync.poll(); + map.put(currentType, (SyncedComponent) this.components.get(currentType)); } if (!map.isEmpty()) { @@ -132,19 +134,19 @@ public void sync(@NotNull ComponentProvider provider) { private void initializeComponent(@Nullable Runnable saveOperation, ComponentType type) { Component component = type.create(); - this.components.put(type.id(), component); + this.components.put(type, component); if (component instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(type.id()); + this.nbtComponents.add(type); nbtComponent.setSaveOperation(saveOperation); } if (component instanceof TickingComponent) { - this.tickingComponents.add(type.id()); + this.tickingComponents.add(type); } if (component instanceof SyncedComponent synced) { - synced.setSyncOperation(() -> this.pendingSync.add(type.id())); + synced.setSyncOperation(() -> this.pendingSync.add(type)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java index dab8a014f8..10ac39cfdb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java @@ -25,7 +25,7 @@ import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.networking.api.PacketByteBufs; -public final class RegistryPacket { +public final class RegistryPacket { // TODO: Fix this with registry sync maybe?! @NotNull public static PacketByteBuf createRegistryPacket(@NotNull Registry registry) { var buf = PacketByteBufs.create(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index 46055bb96c..0192861af8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -18,10 +18,9 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.components.SyncedComponent; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; @@ -29,17 +28,16 @@ import org.quiltmc.qsl.networking.api.ServerPlayNetworking; import java.util.Collection; -import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; public class SyncPacket { @NotNull - public static PacketByteBuf create(SyncPacketHeader headerCreator, @NotNull ComponentProvider provider, Map components) { + public static PacketByteBuf create(SyncPacketHeader headerCreator, @NotNull ComponentProvider provider, Map, SyncedComponent> components) { PacketByteBuf buff = headerCreator.start(provider); buff.writeInt(components.size()); - components.forEach((id, syncedComponent) -> { - NetworkCodec.COMPONENT_TYPE.encode(buff, Components.REGISTRY.get(id)); + components.forEach((type, syncedComponent) -> { + NetworkCodec.COMPONENT_TYPE.encode(buff, type); syncedComponent.writeToBuf(buff); }); @@ -53,13 +51,12 @@ public static void handle(PacketByteBuf buf) { for (int i = 0; i < size; i++) { NetworkCodec.COMPONENT_TYPE.decode(buf) - .map(Components.REGISTRY::getId) - .ifPresent(id -> provider.getComponentContainer().receiveSyncPacket(id, buf)); + .ifPresent(type -> provider.getComponentContainer().receiveSyncPacket(type, buf)); } }); } - public static void send(SyncContext context, ComponentProvider provider, HashMap map) { + public static void send(SyncContext context, ComponentProvider provider, Map, SyncedComponent> map) { PacketByteBuf packet = create(context.header(), provider, map); context.playerGenerator().get().forEach(serverPlayer -> diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java index 286114795c..af2b38a1bd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java @@ -19,7 +19,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -46,13 +45,13 @@ public static Lazy filled(@NotNull T value) { } @NotNull - public Lazy compose(Function transformer) { - return Lazy.of(() -> transformer.apply(this.get())); + public static Lazy of(@NotNull Supplier sup) { + return new Lazy<>(sup); } @NotNull - public static Lazy of(@NotNull Supplier sup) { - return new Lazy<>(sup); + public Lazy compose(Function transformer) { + return Lazy.of(() -> transformer.apply(this.get())); } @NotNull diff --git a/library/data/component/src/main/resources/quilt_component.accesswidener b/library/data/component/src/main/resources/quilt_component.accesswidener index adc1776cf0..5d6895d1d7 100644 --- a/library/data/component/src/main/resources/quilt_component.accesswidener +++ b/library/data/component/src/main/resources/quilt_component.accesswidener @@ -1,3 +1,4 @@ accessWidener v2 named # Using this to make the default implementation of the BlockEntityTickInvoker interface accessible to mixin. -transitive-accessible class net/minecraft/world/chunk/WorldChunk$DirectBlockEntityTickInvoker +transitive-accessible class net/minecraft/world/chunk/WorldChunk$DirectBlockEntityTickInvoker +transitive-extendable class net/minecraft/block/entity/BlockEntityType$BlockEntityFactory # TODO: Remove this when the issue is resolved. diff --git a/library/data/component/src/testmod/resources/quilt_component_test.mixins.json b/library/data/component/src/testmod/resources/quilt_component_test.mixins.json index 74e094c14b..2e67077741 100644 --- a/library/data/component/src/testmod/resources/quilt_component_test.mixins.json +++ b/library/data/component/src/testmod/resources/quilt_component_test.mixins.json @@ -4,10 +4,10 @@ "compatibilityLevel": "JAVA_17", "minVersion": "0.8", "mixins": [ - "client.MixinBlockEntityRendererFactories" ], "client": [ - "client.MixinInGameHud" + "client.MixinInGameHud", + "client.MixinBlockEntityRendererFactories" ], "injectors": { "defaultRequire": 1 From 1907f44c01475ddd42fa46754d76ae31839305a5 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 30 Jun 2022 20:30:09 +0300 Subject: [PATCH 44/70] Added GenericComponent --- .../api/components/GenericComponent.java | 67 +++++++++++++++++++ .../api/components/SyncedComponent.java | 2 +- .../components/SyncedGenericComponent.java | 38 +++++++++++ .../components/DefaultIntegerComponent.java | 2 +- .../components/DefaultInventoryComponent.java | 2 +- .../qsl/component/test/ComponentTestMod.java | 42 +++++++++--- 6 files changed, 142 insertions(+), 11 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java new file mode 100644 index 0000000000..0ce5b7b45d --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java @@ -0,0 +1,67 @@ +package org.quiltmc.qsl.component.api.components; + +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtOps; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class GenericComponent implements NbtComponent { + protected final Codec codec; + protected T value; + @Nullable + private Runnable saveOperation; + + protected GenericComponent(@NotNull Codec codec) { + this.codec = codec; + } + + @NotNull + public static GenericComponent create(@NotNull Codec codec) { + return new GenericComponent<>(codec); + } + + public T getValue() { + return this.value; + } + + public void setValue(T value) { + this.value = value; + } + + @Override + public byte nbtType() { + return NbtElement.COMPOUND_TYPE; + } + + @Override + public void read(NbtCompound nbt) { + this.codec.decode(NbtOps.INSTANCE, nbt.get("Value")).result() + .map(Pair::getFirst) + .ifPresent(this::setValue); + } + + @Override + public NbtCompound write() { + var nbt = new NbtCompound(); + if (this.value != null) { + this.codec.encodeStart(NbtOps.INSTANCE, this.value).result() + .ifPresent(nbtElement -> { + nbt.put("Value", nbtElement); + }); + } + return nbt; + } + + @Override + public @Nullable Runnable getSaveOperation() { + return this.saveOperation; + } + + @Override + public void setSaveOperation(@Nullable Runnable runnable) { + this.saveOperation = runnable; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java index 653c930180..fc440451b0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java @@ -28,7 +28,7 @@ public interface SyncedComponent extends Component { @Nullable Runnable getSyncOperation(); - void setSyncOperation(@NotNull Runnable runnable); + void setSyncOperation(@Nullable Runnable runnable); default void sync() { if (this.getSyncOperation() != null) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java new file mode 100644 index 0000000000..41cece7dd7 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java @@ -0,0 +1,38 @@ +package org.quiltmc.qsl.component.api.components; + +import com.mojang.serialization.Codec; +import net.minecraft.network.PacketByteBuf; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; + +public class SyncedGenericComponent extends GenericComponent implements SyncedComponent { + private final NetworkCodec networkCodec; + @Nullable + private Runnable syncOperation; + + protected SyncedGenericComponent(@NotNull Codec codec, @NotNull NetworkCodec networkCodec) { + super(codec); + this.networkCodec = networkCodec; + } + + @Override + public void writeToBuf(@NotNull PacketByteBuf buf) { + this.networkCodec.encode(buf, this.value); + } + + @Override + public void readFromBuf(@NotNull PacketByteBuf buf) { + this.networkCodec.decode(buf).ifPresent(t -> this.value = t); + } + + @Override + public @Nullable Runnable getSyncOperation() { + return this.syncOperation; + } + + @Override + public void setSyncOperation(@Nullable Runnable runnable) { + this.syncOperation = runnable; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java index 5ce4d99f51..de18914d39 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java @@ -101,7 +101,7 @@ public void readFromBuf(@NotNull PacketByteBuf buf) { } @Override - public void setSyncOperation(@NotNull Runnable runnable) { + public void setSyncOperation(@Nullable Runnable runnable) { this.syncOperation = runnable; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java index 965d230d0f..4d3c280525 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java @@ -90,7 +90,7 @@ public void readFromBuf(@NotNull PacketByteBuf buf) { } @Override - public void setSyncOperation(@NotNull Runnable runnable) { + public void setSyncOperation(@Nullable Runnable runnable) { this.syncOperation = runnable; } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index fe7d3b7dcd..d3f07d6dd5 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -21,6 +21,7 @@ import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.ChestBlockEntity; +import net.minecraft.entity.Entity; import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; @@ -33,6 +34,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.Unit; import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.dynamic.Codecs; import net.minecraft.util.registry.Registry; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.level.LevelProperties; @@ -41,15 +43,14 @@ import org.quiltmc.qsl.block.entity.api.QuiltBlockEntityTypeBuilder; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.components.FloatComponent; -import org.quiltmc.qsl.component.api.components.FunctionComponent; -import org.quiltmc.qsl.component.api.components.InventoryComponent; -import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.api.components.*; import org.quiltmc.qsl.component.api.event.ComponentEvents; import org.quiltmc.qsl.component.impl.components.DefaultFloatComponent; import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; import org.quiltmc.qsl.component.impl.components.DefaultInventoryComponent; +import java.util.UUID; + public class ComponentTestMod implements ModInitializer { public static final String MODID = "quilt_component_test"; @@ -102,6 +103,14 @@ public class ComponentTestMod implements ModInitializer { return Unit.INSTANCE; } ); + public static final ComponentType TEST_BE_INT = Components.register( + new Identifier(ComponentTestMod.MODID, "test_be_int"), + DefaultIntegerComponent::new + ); + public static final ComponentType> UUID_THING = Components.register( + new Identifier(MODID, "uuid_thing"), + () -> GenericComponent.create(Codecs.UUID) + ); public static final ComponentType PLAYER_TICK = Components.registerTicking( new Identifier(MODID, "player_tick"), provider -> { @@ -117,13 +126,29 @@ public class ComponentTestMod implements ModInitializer { levelProperties.expose(SAVE_FLOAT).map(FloatComponent::get).orElse(0f).toString() ), false); } + player.expose(UUID_THING).ifPresent(uuidGenericComponent -> { + Entity vehicle = player.getVehicle(); + + if (vehicle != null) { + if (uuidGenericComponent.getValue() == null) { + uuidGenericComponent.setValue(vehicle.getUuid()); + uuidGenericComponent.save(); + } else { + Entity vehicle1 = player.getWorld().getEntity(uuidGenericComponent.getValue()); + + if (vehicle1 == null) { + uuidGenericComponent.setValue(null); + uuidGenericComponent.save(); + return; + } + + player.getWorld().setBlockState(vehicle1.getBlockPos().down(), Blocks.DIAMOND_BLOCK.getDefaultState()); + } + } + }); } } ); - public static final ComponentType TEST_BE_INT = Components.register( - new Identifier(ComponentTestMod.MODID, "test_be_int"), - DefaultIntegerComponent::new - ); @Override public void onInitialize(ModContainer mod) { @@ -140,6 +165,7 @@ public void onInitialize(ModContainer mod) { Components.inject(LevelProperties.class, SAVE_FLOAT); Components.injectInheritage(ServerPlayerEntity.class, FUNC_COMP); Components.inject(LevelProperties.class, SERVER_TICK); + Components.inject(ServerPlayerEntity.class, UUID_THING); // Dynamic Injection ComponentEvents.DYNAMIC_INJECT.register((provider, injector) -> { From 71a3679e4656f602bdcdc7b3eeca503d3240a45e Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 2 Jul 2022 15:09:52 +0300 Subject: [PATCH 45/70] Removed FunctionComponents after discussion. --- .../qsl/component/api/ComponentProvider.java | 5 -- .../qsl/component/api/ComponentType.java | 10 +-- .../api/components/FunctionComponent.java | 26 -------- .../api/components/GenericComponent.java | 4 +- .../api/components/NbtComponent.java | 35 +++++++---- .../impl/client/sync/ClientSyncHandler.java | 2 +- .../container/OnAccessComponentContainer.java | 58 ++++++++++++++++++ .../impl/sync/packet/SyncPacket.java | 22 ++++--- .../qsl/component/mixin/MixinItemStack.java | 1 + .../mixin/MixinThreadedChunkStorage.java | 2 +- .../resources/assets/quilt_component/icon.png | Bin 261 -> 623 bytes .../qsl/component/test/ComponentTestMod.java | 28 ++++----- 12 files changed, 116 insertions(+), 77 deletions(-) delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java index cf4ba8226b..f7a624aed3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java @@ -24,7 +24,6 @@ import net.minecraft.world.level.LevelProperties; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.base.api.util.InjectedInterface; -import org.quiltmc.qsl.component.api.components.FunctionComponent; import java.util.Optional; @@ -40,10 +39,6 @@ public interface ComponentProvider { @NotNull ComponentContainer getComponentContainer(); - default > Optional call(ComponentType type, T t) { - return this.expose(type).map(func -> func.call(this, t)); - } - default Optional expose(ComponentType id) { return Components.expose(id, this); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 3fa26a707e..890cdaf65b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -19,7 +19,7 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; -import java.util.HashMap; +import java.util.IdentityHashMap; import java.util.Map; import java.util.Optional; @@ -45,7 +45,7 @@ public Optional cast(Component component) { } public static class Static { - private final Map staticInstances = new HashMap<>(); + private final Map, Component> staticInstances = new IdentityHashMap<>(); private Static() { @@ -53,11 +53,11 @@ private Static() { @SuppressWarnings("unchecked") @NotNull C getOrCreate(ComponentType type) { - if (this.staticInstances.containsKey(type.id())) { - return (C) this.staticInstances.get(type.id()); + if (this.staticInstances.containsKey(type)) { + return (C) this.staticInstances.get(type); } else { C singleton = type.factory.create(); - this.staticInstances.put(type.id(), singleton); + this.staticInstances.put(type, singleton); return singleton; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java deleted file mode 100644 index d3d3dbcbef..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FunctionComponent.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.api.components; - -import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.ComponentProvider; - -@FunctionalInterface -public interface FunctionComponent extends Component { - U call(@NotNull ComponentProvider provider, T t); -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java index 0ce5b7b45d..f84472e1f5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java @@ -48,9 +48,7 @@ public NbtCompound write() { var nbt = new NbtCompound(); if (this.value != null) { this.codec.encodeStart(NbtOps.INSTANCE, this.value).result() - .ifPresent(nbtElement -> { - nbt.put("Value", nbtElement); - }); + .ifPresent(nbtElement -> nbt.put("Value", nbtElement)); } return nbt; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index d9d255ee57..b3abe8acbf 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -27,23 +27,32 @@ public interface NbtComponent extends Component { static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier id, @NotNull NbtCompound root) { NbtElement nbtTarget = root.get(id.toString()); switch (nbtComponent.nbtType()) { - case NbtElement.BYTE_TYPE -> ((NbtComponent) nbtComponent).read((NbtByte) nbtTarget); - case NbtElement.SHORT_TYPE -> ((NbtComponent) nbtComponent).read((NbtShort) nbtTarget); - case NbtElement.INT_TYPE -> ((NbtComponent) nbtComponent).read((NbtInt) nbtTarget); - case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); - case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); - case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); + case NbtElement.BYTE_TYPE -> + ((NbtComponent) nbtComponent).read((NbtByte) nbtTarget); + case NbtElement.SHORT_TYPE -> + ((NbtComponent) nbtComponent).read((NbtShort) nbtTarget); + case NbtElement.INT_TYPE -> + ((NbtComponent) nbtComponent).read((NbtInt) nbtTarget); + case NbtElement.LONG_TYPE -> + ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); + case NbtElement.FLOAT_TYPE -> + ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); + case NbtElement.DOUBLE_TYPE -> + ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); - case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); - case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); - case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); - case NbtElement.INT_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtIntArray) nbtTarget); + case NbtElement.STRING_TYPE -> + ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); + case NbtElement.LIST_TYPE -> + ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); + case NbtElement.COMPOUND_TYPE -> + ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); + case NbtElement.INT_ARRAY_TYPE -> + ((NbtComponent) nbtComponent).read((NbtIntArray) nbtTarget); case NbtElement.LONG_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtLongArray) nbtTarget); - default -> // TODO: Handle non-vanilla nbt types. - throw new RuntimeException("The nbt data type with id %d is not handled at the moment!".formatted(nbtComponent.nbtType())); - + default -> // We throw if we ever find a non-vanilla type trying to be used for component serialization! + throw new RuntimeException("The nbt data type with id %d is not vanilla!".formatted(nbtComponent.nbtType())); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java index 89aae4dfc1..ee794b25bc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -50,7 +50,7 @@ public void registerPackets() { ClientRegistryPacket.handleRegistryPacket(buf, SyncHeaderRegistry.HEADERS, list -> this.headerList = list) ); ClientPlayNetworking.registerGlobalReceiver(PacketIds.SYNC, (client, handler, buf, responseSender) -> - SyncPacket.handle(buf) + SyncPacket.handle(buf, client) ); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java new file mode 100644 index 0000000000..2a235d4aea --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -0,0 +1,58 @@ +package org.quiltmc.qsl.component.impl.container; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; +import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.ComponentType; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Optional; + +// Suggestion from Technici4n from fabric. May help improve performance and memory footprint once done. +public class OnAccessComponentContainer implements ComponentContainer { // TODO: Check how to make this work?! + private final Map, Component> components; + + private OnAccessComponentContainer() { + this.components = new IdentityHashMap<>(); + } + + @Override + public Optional expose(ComponentType type) { + if (this.components.containsKey(type)) { + return Optional.ofNullable(this.components.get(type)); + } + + Component created = type.create(); + this.components.put(type, created); + return Optional.of(created); + } + + @Override + public void writeNbt(@NotNull NbtCompound providerRootNbt) { + + } + + @Override + public void readNbt(@NotNull NbtCompound providerRootNbt) { + + } + + @Override + public void tick(@NotNull ComponentProvider provider) { + + } + + @Override + public void receiveSyncPacket(@NotNull ComponentType type, @NotNull PacketByteBuf buf) { + + } + + @Override + public void sync(@NotNull ComponentProvider provider) { + + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index 0192861af8..5cb1e88246 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -16,6 +16,7 @@ package org.quiltmc.qsl.component.impl.sync.packet; +import net.minecraft.client.MinecraftClient; import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import org.jetbrains.annotations.NotNull; @@ -44,15 +45,20 @@ public static PacketByteBuf create(SyncPacketHeader headerCreator, @NotNull C return buff; } - public static void handle(PacketByteBuf buf) { - var header = ClientSyncHandler.getInstance().getHeader(buf.readInt()); - header.codec().decode(buf).ifPresent(provider -> { - var size = buf.readInt(); + public static void handle(PacketByteBuf buf, MinecraftClient client) { + buf.retain(); - for (int i = 0; i < size; i++) { - NetworkCodec.COMPONENT_TYPE.decode(buf) - .ifPresent(type -> provider.getComponentContainer().receiveSyncPacket(type, buf)); - } + client.execute(() -> { + var header = ClientSyncHandler.getInstance().getHeader(buf.readInt()); + header.codec().decode(buf).ifPresent(provider -> { + var size = buf.readInt(); + + for (int i = 0; i < size; i++) { + NetworkCodec.COMPONENT_TYPE.decode(buf) + .ifPresent(type -> provider.getComponentContainer().receiveSyncPacket(type, buf)); + } + }); + buf.release(); }); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index 4cd174923e..96fdc0fd34 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -34,6 +34,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @SuppressWarnings("ConstantConditions") +@Deprecated @Mixin(ItemStack.class) public abstract class MixinItemStack implements ComponentProvider { // TODO: Make sure nothing else may be broken before final PR. @Shadow diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java index 642ac402d0..ec361a3a78 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java @@ -27,7 +27,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ThreadedAnvilChunkStorage.class) -public abstract class MixinThreadedChunkStorage { +public abstract class MixinThreadedChunkStorage { // TODO: This still doesn't work @Inject( method = "sendChunkDataPackets", diff --git a/library/data/component/src/main/resources/assets/quilt_component/icon.png b/library/data/component/src/main/resources/assets/quilt_component/icon.png index 8d54ad0021bbf0258acfe2ba452ccc0e6f36f566..6515b9f4bc0de65d8d1354d21df98c27e5b69241 100644 GIT binary patch delta 609 zcmV-n0-pVa0`CNn8Gi-<0047(dh`GQ00eVFNmK|32nc)#WQYI&0wzgBK~z|U?Uv7L z6HyR=zhq;6Ro%o;voX?2jG(kM2agJ(Cr^6w;H@`%(*K|c(u0Tu&w~C1(k342WyKb1 zp^XqNB7}rgp-B_tOG28)xNAJbMnl%6NJ<1Vr?8P^^OtJ_PtD z0BlCe#YY?D66TKS7~B(+06bVtk|>(n$1@gcx2N_8kV~`!n8|A91$f)%M6n&fOj7GA z0R#QOOE3f&0t^8R`#?JO^PQW>2jZP`JYylXuA17n-aR+eTmJiTY*>PqbMv$|%pE1w z%BB3Z9=$x{B7dq>n4YyG&$s|O-%su~nVz+G*&CKXy*ZDhnkQ$W8slO8ahLAg`2dQd zkk9AQH0_VRspPN8Wtf4#5&4!2<<9A?DrMhJn|>qQ6w&^Z^1-D9(F0MS5&`)hed z+-`!t5Mz>`Z~je2gX4U01UTOK2+#x2w@Y{@C!=W^LVpNsWrd?F*RgM(B70nq?j=(>)O1xpuSA!I=$ zd77Qt4qBeL4X4w&KLAO!vQRZ&3g6Vbx7KK&!W@SI*!-NOd7?>fYYUMQOk_^7OM~4; vz2`rDodstiqX5`!Hq(amdm|bSqanZ#kIu?mxJB=I00000NkvXXu0mjf)@2&u delta 244 zcmVeC+5Eb2|I?%Y*=yU{m)qPa-CH5t_y7O^fk{L` zR5;7!li3P@AP_}u(kWYP^Z&m!syi*D1<^y$d2{YTWG*VYL2Z3T=vv^2ni80u&^k~M zl?EjL6I=l@B9j31Y8OKfyv(bk(0fp0Y}sB4mRXFTFy&%|ge7Oz5kd0BI13eTq>pY0 uzQNZZpO1RWBdgYH9_vC&9xW?<@9T}T!xgPB&AY1r0000> FUNC_COMP = Components.registerStatic( - new Identifier(MODID, "player_thing"), - () -> (provider, unused) -> { - if (provider instanceof PlayerEntity entity) { - entity.giveItemStack(new ItemStack(Items.WHEAT)); - } - return Unit.INSTANCE; - } - ); public static final ComponentType TEST_BE_INT = Components.register( new Identifier(ComponentTestMod.MODID, "test_be_int"), DefaultIntegerComponent::new @@ -117,8 +110,8 @@ public class ComponentTestMod implements ModInitializer { if (provider instanceof ServerPlayerEntity player) { ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); if (stackInHand.isOf(Items.WHEAT)) { - player.call(ComponentTestMod.FUNC_COMP, Unit.INSTANCE) - .ifPresent(unit -> player.sendMessage(Text.literal("Prankt"), true)); + player.giveItemStack(new ItemStack(Items.WHEAT)); + player.sendMessage(Text.literal("Prankt"), true); } var props = player.getWorld().getServer().getSaveProperties(); if (props instanceof LevelProperties levelProperties && player.getWorld().getTime() % 100 == 0) { @@ -142,8 +135,13 @@ public class ComponentTestMod implements ModInitializer { return; } - player.getWorld().setBlockState(vehicle1.getBlockPos().down(), Blocks.DIAMOND_BLOCK.getDefaultState()); + player.getWorld().setBlockState( + vehicle1.getBlockPos().down(), + Blocks.DIAMOND_BLOCK.getDefaultState() + ); } + } else { + uuidGenericComponent.setValue(null); } }); } @@ -163,7 +161,7 @@ public void onInitialize(ModContainer mod) { Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(LevelProperties.class, SAVE_FLOAT); - Components.injectInheritage(ServerPlayerEntity.class, FUNC_COMP); + // Components.injectInheritage(ServerPlayerEntity.class, FUNC_COMP); Function components have been removed Components.inject(LevelProperties.class, SERVER_TICK); Components.inject(ServerPlayerEntity.class, UUID_THING); From 6372ac5c3a23b5bdfdd8bedca1e3db6a3b5591c9 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 2 Jul 2022 16:05:21 +0300 Subject: [PATCH 46/70] Minor changes here and there. --- .../api/components/NbtComponent.java | 6 ++++- .../qsl/component/impl/ComponentsImpl.java | 12 ++++----- .../impl/client/sync/ClientSyncHandler.java | 2 +- .../container/LazyComponentContainer.java | 4 +-- .../impl/sync/ServerSyncHandler.java | 1 + .../sync/{ => header}/SyncHeaderRegistry.java | 3 +-- .../impl/sync/header/SyncPacketHeader.java | 10 ++++--- .../impl/sync/packet/SyncPacket.java | 5 ++-- .../qsl/component/impl/util/ErrorUtil.java | 8 +++--- .../qsl/component/mixin/MixinBlockEntity.java | 27 +++++++------------ .../qsl/component/mixin/MixinChunk.java | 2 +- .../qsl/component/mixin/MixinItemStack.java | 4 +-- .../component/mixin/MixinLevelProperties.java | 15 ++++++----- 13 files changed, 50 insertions(+), 49 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/{ => header}/SyncHeaderRegistry.java (92%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index b3abe8acbf..a231df7834 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; public interface NbtComponent extends Component { @SuppressWarnings("unchecked") @@ -52,7 +53,10 @@ static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier case NbtElement.LONG_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtLongArray) nbtTarget); default -> // We throw if we ever find a non-vanilla type trying to be used for component serialization! - throw new RuntimeException("The nbt data type with id %d is not vanilla!".formatted(nbtComponent.nbtType())); + throw ErrorUtil.runtime( + "The nbt data type with id %D is not vanilla!", + nbtComponent.nbtType() + ).get(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 7ec379ffa9..e496425b6d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -28,7 +28,7 @@ import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.impl.sync.SyncHeaderRegistry; +import org.quiltmc.qsl.component.impl.sync.header.SyncHeaderRegistry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,16 +49,14 @@ public class ComponentsImpl { public static void inject(ComponentInjectionPredicate predicate, ComponentType type) { if (REGISTRY.get(type.id()) == null) { - throw ErrorUtil.illegalArgument( - "The target id %s does not match any registered component".formatted(type) - ).get(); + throw ErrorUtil.illegalArgument("The target id %s does not match any registered component", type).get(); } if (INJECTION_REGISTRY.containsKey(predicate)) { if (!INJECTION_REGISTRY.get(predicate).add(type.id())) { throw ErrorUtil.illegalArgument( - "Cannot inject the predicate %s with id %s more than once! Consider creating a new component type!" - .formatted(predicate, type) + "Cannot inject the predicate %s with id %s more than once! Consider creating a new component type!", + predicate, type.id() ).get(); } } else { @@ -99,7 +97,7 @@ public static List> getInjections(@NotNull ComponentProvider pr @NotNull public static ComponentType getEntry(Identifier id) { return REGISTRY.getOrEmpty(id).orElseThrow( - ErrorUtil.illegalArgument("Cannot access element with id %s in the component registry!".formatted(id)) + ErrorUtil.illegalArgument("Cannot access element with id %s in the component registry!", id) ); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java index ee794b25bc..2336d44b47 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -19,7 +19,7 @@ import net.minecraft.util.collection.IdList; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.impl.sync.SyncHeaderRegistry; +import org.quiltmc.qsl.component.impl.sync.header.SyncHeaderRegistry; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 479b11ed43..86917ce906 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -207,8 +207,8 @@ private Builder(ComponentProvider provider) { this.saveOperation = null; } - public Builder setSaveOperation(Runnable runnable) { - this.saveOperation = runnable; + public Builder saving(Runnable saveOperation) { + this.saveOperation = saveOperation; return this; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java index b91be7f17e..5f982379a1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java @@ -19,6 +19,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerLoginNetworkHandler; import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.impl.sync.header.SyncHeaderRegistry; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; import org.quiltmc.qsl.component.impl.sync.packet.RegistryPacket; import org.quiltmc.qsl.networking.api.PacketSender; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncHeaderRegistry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java similarity index 92% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncHeaderRegistry.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java index 8f3ed5f508..3465526a4f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncHeaderRegistry.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.sync; +package org.quiltmc.qsl.component.impl.sync.header; import com.mojang.serialization.Lifecycle; import net.minecraft.util.Identifier; @@ -23,7 +23,6 @@ import net.minecraft.util.registry.SimpleRegistry; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.CommonInitializer; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; public class SyncHeaderRegistry { private static final RegistryKey>> HEADERS_KEY = diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java index 3e78cd6ed6..d88163df20 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -17,13 +17,13 @@ package org.quiltmc.qsl.component.impl.sync.header; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; import net.minecraft.network.PacketByteBuf; import net.minecraft.world.chunk.Chunk; import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.CommonInitializer; -import org.quiltmc.qsl.component.impl.sync.SyncHeaderRegistry; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import org.quiltmc.qsl.networking.api.PacketByteBufs; @@ -31,13 +31,17 @@ public record SyncPacketHeader

(@NotNull NetworkCode public static final SyncPacketHeader BLOCK_ENTITY = new SyncPacketHeader<>(NetworkCodec.BLOCK_ENTITY); public static final SyncPacketHeader ENTITY = new SyncPacketHeader<>(NetworkCodec.ENTITY); public static final SyncPacketHeader CHUNK = new SyncPacketHeader<>(NetworkCodec.CHUNK); - // TODO: LevelProperties sync -// public static final SyncPacketHeader LEVEL = new SyncPacketHeader<>(NetworkCodec.LEVEL); + private static final NetworkCodec LEVEL_CODEC = new NetworkCodec<>( + (buf, provider) -> {}, + buf -> MinecraftClient.getInstance() + ); + public static final SyncPacketHeader LEVEL = new SyncPacketHeader<>(LEVEL_CODEC); public static void registerDefaults() { SyncHeaderRegistry.register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); SyncHeaderRegistry.register(CommonInitializer.id("entity"), ENTITY); SyncHeaderRegistry.register(CommonInitializer.id("chunk"), CHUNK); + SyncHeaderRegistry.register(CommonInitializer.id("level"), LEVEL); } public @NotNull PacketByteBuf start(@NotNull ComponentProvider provider) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index 5cb1e88246..a58d2cfa12 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -54,8 +54,9 @@ public static void handle(PacketByteBuf buf, MinecraftClient client) { var size = buf.readInt(); for (int i = 0; i < size; i++) { - NetworkCodec.COMPONENT_TYPE.decode(buf) - .ifPresent(type -> provider.getComponentContainer().receiveSyncPacket(type, buf)); + NetworkCodec.COMPONENT_TYPE.decode(buf).ifPresent( + type -> provider.getComponentContainer().receiveSyncPacket(type, buf) + ); } }); buf.release(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java index b90462c7a8..47b763bf5b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ErrorUtil.java @@ -19,15 +19,15 @@ import java.util.function.Supplier; public class ErrorUtil { - public static Supplier illegalArgument(String message) { - return () -> new IllegalArgumentException(message); + public static Supplier illegalArgument(String message, Object... args) { + return () -> new IllegalArgumentException(message.formatted(args)); } public static Supplier illegalState(String message) { return () -> new IllegalStateException(message); } - public static Supplier runtime(String msg) { - return () -> new RuntimeException(msg); + public static Supplier runtime(String msg, Object... formattingArguments) { + return () -> new RuntimeException(msg.formatted(formattingArguments)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index cf6e4515d6..bdb7956929 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -21,9 +21,7 @@ import net.minecraft.block.entity.BlockEntityType; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; @@ -40,6 +38,14 @@ public abstract class MixinBlockEntity implements ComponentProvider { private ComponentContainer qsl$container; + @Shadow + public abstract void markDirty(); + + @Override + public @NotNull ComponentContainer getComponentContainer() { + return this.qsl$container; + } + @Inject(method = "readNbt", at = @At("TAIL")) private void onReadNbt(NbtCompound nbt, CallbackInfo ci) { this.qsl$container.readNbt(nbt); @@ -50,29 +56,14 @@ private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, Block //noinspection ConstantConditions this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() - .setSaveOperation(this::markDirty) + .saving(this::markDirty) .ticking() .syncing(SyncPacketHeader.BLOCK_ENTITY, () -> SyncPlayerList.create((BlockEntity) (Object) this)) .build(); } - @Shadow - public abstract void markDirty(); - - @Shadow - @Nullable - protected World world; - - @Shadow - public abstract @Nullable World getWorld(); - @Inject(method = "toNbt", at = @At("TAIL")) private void onWriteNbt(CallbackInfoReturnable cir) { this.qsl$container.writeNbt(cir.getReturnValue()); } - - @Override - public @NotNull ComponentContainer getComponentContainer() { - return this.qsl$container; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 5f9a5484ca..071e1597cd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -52,7 +52,7 @@ public abstract class MixinChunk implements ComponentProvider { private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { LazyComponentContainer.Builder builder = LazyComponentContainer.builder(this) .orElseThrow() - .setSaveOperation(() -> this.setNeedsSaving(true)); + .saving(() -> this.setNeedsSaving(true)); //noinspection ConstantConditions if ((Chunk) (Object) this instanceof WorldChunk worldChunk) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java index 96fdc0fd34..5a3c26e127 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java @@ -45,7 +45,7 @@ public abstract class MixinItemStack implements ComponentProvider { // TODO: Mak private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo ci) { this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() - .setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) + .saving(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) .ticking() .build(); } @@ -57,7 +57,7 @@ private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo private void readContainer(NbtCompound nbtCompound, CallbackInfo ci) { this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() - .setSaveOperation(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) + .saving(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) .ticking() .build(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java index f52a7e521c..66d64ef263 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java @@ -36,15 +36,18 @@ import org.quiltmc.qsl.component.api.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.List; import java.util.Set; import java.util.UUID; +// TODO: Try saving using an external file so that worlds can also be handled and this is easier to save/sync @Mixin(LevelProperties.class) public abstract class MixinLevelProperties implements ServerWorldProperties, SaveProperties, ComponentProvider { private ComponentContainer qsl$container; @@ -54,12 +57,17 @@ private static void readComponentData(Dynamic dynamic, DataFixer dat cir.getReturnValue().getComponentContainer().readNbt((NbtCompound) dynamic.getValue()); } + @Override + public @NotNull ComponentContainer getComponentContainer() { + return this.qsl$container; + } + @Inject(method = "(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/NbtCompound;ZIIIFJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lcom/mojang/serialization/Lifecycle;)V", at = @At("TAIL")) private void onInit(DataFixer dataFixer, int i, NbtCompound nbtCompound, boolean bl, int j, int k, int l, float f, long m, long n, int o, int p, int q, boolean bl2, int r, boolean bl3, boolean bl4, boolean bl5, WorldBorder.Properties properties, int s, int t, UUID uUID, Set set, Timer timer, NbtCompound nbtCompound2, NbtCompound nbtCompound3, LevelInfo levelInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfo ci) { this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() .ticking() -// .syncing(DefaultSyncPacketHeaders.LEVEL) TODO + .syncing(SyncPacketHeader.LEVEL, List::of) // TODO .build(); } @@ -67,9 +75,4 @@ private void onInit(DataFixer dataFixer, int i, NbtCompound nbtCompound, boolean private void writeComponentData(DynamicRegistryManager registryManager, NbtCompound levelNbt, NbtCompound playerNbt, CallbackInfo ci) { this.qsl$container.writeNbt(levelNbt); } - - @Override - public @NotNull ComponentContainer getComponentContainer() { - return this.qsl$container; - } } From 8c4f500a10fe54d92c19f73c96886114cef60ac5 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 2 Jul 2022 19:17:15 +0300 Subject: [PATCH 47/70] Added OnAccessComponentContainer and restructured a bit. --- .../qsl/component/api/ComponentContainer.java | 2 - .../qsl/component/api/ComponentType.java | 2 +- .../quiltmc/qsl/component/api/Components.java | 12 +- .../impl/ComponentInjectionCache.java | 8 +- .../qsl/component/impl/ComponentsImpl.java | 37 ++---- .../container/LazyComponentContainer.java | 63 ++++------ .../container/OnAccessComponentContainer.java | 119 ++++++++++++++---- .../container/SimpleComponentContainer.java | 34 ++--- .../impl/sync/header/SyncPacketHeader.java | 3 +- .../impl/sync/packet/SyncPacket.java | 30 ++++- .../quiltmc/qsl/component/impl/util/Lazy.java | 5 - .../qsl/component/test/ComponentTestMod.java | 4 +- 12 files changed, 185 insertions(+), 134 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java index 81c4b99698..7a11388ab1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java @@ -32,7 +32,5 @@ public interface ComponentContainer { // TODO: Maybe split up responsibilities? void tick(@NotNull ComponentProvider provider); - void receiveSyncPacket(@NotNull ComponentType type, @NotNull PacketByteBuf buf); - void sync(@NotNull ComponentProvider provider); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 890cdaf65b..1b457dc0de 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -24,7 +24,7 @@ import java.util.Optional; public record ComponentType(Identifier id, Component.Factory factory, - boolean isStatic) implements Component.Factory { + boolean isStatic, boolean isInstant) implements Component.Factory { public static final Static STATIC_CACHE = new Static(); @SuppressWarnings("unchecked") diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 4674ffb7ab..f108dc2bbb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -56,23 +56,21 @@ public static void injectRedirected(Class mainClass, Co public static Optional expose(ComponentType id, S obj) { if (obj instanceof ComponentProvider provider) { - return provider.getComponentContainer().expose(id) - .map(id::cast) - .map(Optional::orElseThrow); // If the casting fails something is wrong with the provided ComponentType. In that case we just throw. + return provider.getComponentContainer().expose(id).flatMap(id::cast); } return Optional.empty(); } public static ComponentType register(Identifier id, Component.Factory factory) { - return ComponentsImpl.register(id, factory); + return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, false)); } public static ComponentType registerStatic(Identifier id, Component.Factory factory) { - return ComponentsImpl.registerStatic(id, factory); + return ComponentsImpl.register(id, new ComponentType<>(id, factory, true, false)); } - public static ComponentType registerTicking(Identifier id, C component) { - return ComponentsImpl.registerStatic(id, () -> component); + public static ComponentType registerTicking(Identifier id, Component.Factory factory) { + return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, true)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java index 4704048a01..02e05e8709 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java @@ -22,13 +22,13 @@ import java.util.*; public class ComponentInjectionCache { - private static final Map, List>> INJECTION_CACHE = new HashMap<>(); + private static final Map, Set>> INJECTION_CACHE = new HashMap<>(); private ComponentInjectionCache() { } - public static Optional>> getCache(Class clazz) { + public static Optional>> getCache(Class clazz) { if (!INJECTION_CACHE.containsKey(clazz)) { return Optional.empty(); } @@ -40,8 +40,8 @@ public static void clear() { INJECTION_CACHE.clear(); } - public static void record(Class clazz, List> components) { - if (INJECTION_CACHE.put(clazz, Util.make(new ArrayList<>(), list -> list.addAll(components))) != null) { + public static void record(Class clazz, Set> components) { + if (INJECTION_CACHE.put(clazz, Util.make(new HashSet<>(), list -> list.addAll(components))) != null) { // If there was a value there, it means we attempted an override, and so we throw. throw new IllegalStateException("Cannot register cache twice for class %s".formatted(clazz)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index e496425b6d..9d78fbad15 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -33,11 +33,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; @ApiStatus.Internal public class ComponentsImpl { + // TODO: Maybe move this to the ComponentType class?! public static final RegistryKey>> REGISTRY_KEY = RegistryKey.ofRegistry(CommonInitializer.id("component_types")); public static final Registry> REGISTRY = @@ -45,7 +49,7 @@ public class ComponentsImpl { public static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); - private static final Map> INJECTION_REGISTRY = new HashMap<>(); + private static final Map>> INJECTION_REGISTRY = new HashMap<>(); public static void inject(ComponentInjectionPredicate predicate, ComponentType type) { if (REGISTRY.get(type.id()) == null) { @@ -53,40 +57,27 @@ public static void inject(ComponentInjectionPredicate pred } if (INJECTION_REGISTRY.containsKey(predicate)) { - if (!INJECTION_REGISTRY.get(predicate).add(type.id())) { + if (!INJECTION_REGISTRY.get(predicate).add(type)) { throw ErrorUtil.illegalArgument( "Cannot inject the predicate %s with id %s more than once! Consider creating a new component type!", predicate, type.id() ).get(); } } else { - INJECTION_REGISTRY.put(predicate, Util.make(new HashSet<>(), set -> set.add(type.id()))); + INJECTION_REGISTRY.put(predicate, Util.make(new HashSet<>(), set -> set.add(type))); } ComponentInjectionCache.clear(); // Always clear the cache after an injection is registered. } @NotNull - public static ComponentType register(Identifier id, Component.Factory factory) { - var componentType = new ComponentType<>(id, factory, false); - return Registry.register(REGISTRY, id, componentType); - } - - @NotNull - public static ComponentType registerStatic(Identifier id, Component.Factory factory) { - var componentType = new ComponentType<>(id, factory, true); - return Registry.register(REGISTRY, id, componentType); - } - - @NotNull - public static List> getInjections(@NotNull ComponentProvider provider) { + public static Set> getInjections(@NotNull ComponentProvider provider) { return ComponentInjectionCache.getCache(provider.getClass()).orElseGet(() -> { - List> injectedTypes = INJECTION_REGISTRY.entrySet().stream() + Set> injectedTypes = INJECTION_REGISTRY.entrySet().stream() .filter(it -> it.getKey().canInject(provider)) .map(Map.Entry::getValue) .flatMap(Set::stream) - .map(ComponentsImpl::getEntry) - .collect(Collectors.toList()); + .collect(Collectors.toSet()); ComponentInjectionCache.record(provider.getClass(), injectedTypes); @@ -95,10 +86,8 @@ public static List> getInjections(@NotNull ComponentProvider pr } @NotNull - public static ComponentType getEntry(Identifier id) { - return REGISTRY.getOrEmpty(id).orElseThrow( - ErrorUtil.illegalArgument("Cannot access element with id %s in the component registry!", id) - ); + public static ComponentType register(Identifier id, @NotNull ComponentType type) { + return Registry.register(REGISTRY, id, type); } public static void freezeRegistries() { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 86917ce906..9f9aaeacdf 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -17,7 +17,6 @@ package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; @@ -40,12 +39,13 @@ public class LazyComponentContainer implements ComponentContainer { private final IdentityHashMap, Lazy> components; private final List> nbtComponents; + @Nullable private final List> tickingComponents; @Nullable private final Runnable saveOperation; - private final boolean ticking; - private final boolean syncing; + @Nullable private final SyncPacket.SyncContext syncContext; + @Nullable private final Queue> pendingSync; protected LazyComponentContainer( @@ -55,12 +55,10 @@ protected LazyComponentContainer( @Nullable SyncPacket.SyncContext syncContext ) { this.saveOperation = saveOperation; - this.ticking = ticking; - this.syncing = syncContext != null; this.syncContext = syncContext; this.nbtComponents = new ArrayList<>(); - this.tickingComponents = new ArrayList<>(); - this.pendingSync = new ArrayDeque<>(); + this.tickingComponents = ticking ? new ArrayList<>() : null; + this.pendingSync = this.syncContext != null ? new ArrayDeque<>() : null; this.components = this.initializeComponents(provider); } @@ -75,13 +73,17 @@ public static Optional builder(T obj) { public static void move(@NotNull LazyComponentContainer from, @NotNull LazyComponentContainer into) { from.components.forEach((id, componentLazy) -> componentLazy.ifPresent(component -> { into.components.put(id, componentLazy); // Directly overriding our value. - - if (component instanceof NbtComponent nbtComponent) { - into.nbtComponents.add(id); - nbtComponent.setSaveOperation(into.saveOperation); - } })); + into.nbtComponents.addAll(from.nbtComponents); + if (into.pendingSync != null && from.pendingSync != null) { + into.pendingSync.addAll(from.pendingSync); + } + + if (into.tickingComponents != null && from.tickingComponents != null) { + into.tickingComponents.addAll(from.tickingComponents); + } + from.components.clear(); from.nbtComponents.clear(); } @@ -121,10 +123,9 @@ public void readNbt(@NotNull NbtCompound providerRootNbt) { @Override public void tick(@NotNull ComponentProvider provider) { - if (!this.ticking) { - throw ErrorUtil.runtime("Attempted to tick a non-tickable ComponentContainer instance").get(); + if (this.tickingComponents == null) { + throw ErrorUtil.illegalState("Attempted to tick a non-ticking component container!").get(); } - this.tickingComponents.stream() .map(this::expose) .map(Optional::orElseThrow) @@ -132,28 +133,18 @@ public void tick(@NotNull ComponentProvider provider) { .forEach(tickingComponent -> tickingComponent.tick(provider)); // Sync any queued components - if (this.syncing) { - this.sync(provider); - } - } - - @Override - public void receiveSyncPacket(@NotNull ComponentType type, @NotNull PacketByteBuf buf) { - this.expose(type).map(it -> ((SyncedComponent) it)).ifPresent(syncedComponent -> syncedComponent.readFromBuf(buf)); - ComponentsImpl.LOGGER.info("Received packet for {}", type); + this.sync(provider); } @Override public void sync(@NotNull ComponentProvider provider) { - var map = new HashMap, SyncedComponent>(); - - while (!this.pendingSync.isEmpty()) { - var id = this.pendingSync.poll(); - map.put(id, (SyncedComponent) this.components.get(id).get()); - } - - if (!map.isEmpty()) { - SyncPacket.send(this.syncContext, provider, map); + if (this.syncContext != null && this.pendingSync != null /* this is not needed but IJ complains, so I'll leave it in*/) { + SyncPacket.syncFromQueue( + this.pendingSync, + this.syncContext, + type -> ((SyncedComponent) this.components.get(type).get()), + provider + ); } } @@ -167,7 +158,7 @@ private IdentityHashMap, Lazy> initializeComponents( private Lazy createLazy(ComponentType type) { if (type.isStatic()) { Component singleton = type.create(); - if (this.ticking && singleton instanceof TickingComponent) { + if (singleton instanceof TickingComponent && this.tickingComponents != null) { this.tickingComponents.add(type); } @@ -181,11 +172,11 @@ private Lazy createLazy(ComponentType type) { nbtComponent.setSaveOperation(this.saveOperation); } - if (this.ticking && component instanceof TickingComponent) { + if (component instanceof TickingComponent && this.tickingComponents != null) { this.tickingComponents.add(type); } - if (this.syncing && component instanceof SyncedComponent syncedComponent) { + if (component instanceof SyncedComponent syncedComponent && this.syncContext != null && this.pendingSync != null /* also not needed */) { syncedComponent.setSyncOperation(() -> this.pendingSync.add(type)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index 2a235d4aea..2a74e54dfc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -1,58 +1,129 @@ package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.ComponentType; - -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Optional; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.*; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.components.SyncedComponent; +import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.impl.util.StringConstants; + +import java.util.*; +import java.util.function.Predicate; // Suggestion from Technici4n from fabric. May help improve performance and memory footprint once done. -public class OnAccessComponentContainer implements ComponentContainer { // TODO: Check how to make this work?! +public class OnAccessComponentContainer implements ComponentContainer { private final Map, Component> components; - - private OnAccessComponentContainer() { - this.components = new IdentityHashMap<>(); + private final Set> supportedTypes; + private final Set> tickingComponents; + private final Set> nbtComponents; + @Nullable + private final Runnable saveOperation; + @Nullable + private final Queue> pendingSync; + @Nullable + private final SyncPacket.SyncContext syncContext; + + private OnAccessComponentContainer(@NotNull ComponentProvider provider, @Nullable Runnable saveOperation, @Nullable SyncPacket.SyncContext syncContext) { + this.syncContext = syncContext; + this.saveOperation = saveOperation; + this.nbtComponents = new HashSet<>(); + this.tickingComponents = new HashSet<>(); + this.pendingSync = this.syncContext != null ? new ArrayDeque<>() : null; + this.supportedTypes = ComponentsImpl.getInjections(provider); + this.components = this.getInitialComponents(); } @Override public Optional expose(ComponentType type) { - if (this.components.containsKey(type)) { - return Optional.ofNullable(this.components.get(type)); - } - - Component created = type.create(); - this.components.put(type, created); - return Optional.of(created); + return Optional.ofNullable(this.components.get(type)) + .or(() -> this.supportedTypes.contains(type) ? Optional.of(this.createComponent(type)) : Optional.empty()); } @Override public void writeNbt(@NotNull NbtCompound providerRootNbt) { + if (this.nbtComponents.isEmpty()) { + return; + } + + var rootQslNbt = new NbtCompound(); + this.nbtComponents.forEach(type -> { + var component = (NbtComponent) this.components.get(type); + NbtComponent.writeTo(rootQslNbt, component, type.id()); + }); + + if (!rootQslNbt.isEmpty()) { + providerRootNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + } } @Override public void readNbt(@NotNull NbtCompound providerRootNbt) { + if (providerRootNbt.isEmpty() || !providerRootNbt.contains(StringConstants.COMPONENT_ROOT)) { + return; + } + var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); + + rootQslNbt.getKeys().stream() + .map(Identifier::tryParse) + .filter(Objects::nonNull) + .forEach(id -> this.expose(Components.REGISTRY.get(id)) + .map(it -> ((NbtComponent) it)) + .ifPresent(nbtComponent -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)) + ); } @Override public void tick(@NotNull ComponentProvider provider) { - + this.tickingComponents.stream() + .map(this.components::get) + .map(it -> ((TickingComponent) it)) + .forEach(tickingComponent -> tickingComponent.tick(provider)); } @Override - public void receiveSyncPacket(@NotNull ComponentType type, @NotNull PacketByteBuf buf) { + public void sync(@NotNull ComponentProvider provider) { + if (this.syncContext != null) { + // pendingsync will be null if synccontext is null and the other way around + //noinspection ConstantConditions + SyncPacket.syncFromQueue( + this.pendingSync, + this.syncContext, + type -> ((SyncedComponent) this.components.get(type)), + provider + ); + } + } + private Map, Component> getInitialComponents() { + return this.supportedTypes.stream() // TODO: We can cache this value. + .filter(((Predicate>) ComponentType::isStatic).or(ComponentType::isInstant)) + .collect(IdentityHashMap::new, (map, type) -> map.put(type, this.createComponent(type)), Map::putAll); } - @Override - public void sync(@NotNull ComponentProvider provider) { + private Component createComponent(@NotNull ComponentType type) { + var component = type.create(); + if (component instanceof NbtComponent nbtComponent) { + this.nbtComponents.add(type); + nbtComponent.setSaveOperation(this.saveOperation); + } + + if (component instanceof TickingComponent) { + this.tickingComponents.add(type); + } + + if (component instanceof SyncedComponent synced && this.syncContext != null) { + // pendingsync will be null if synccontext is null and the other way around + //noinspection ConstantConditions + synced.setSyncOperation(() -> this.pendingSync.add(type)); + } + return component; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index db5658b4c1..de0ef6927e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -17,7 +17,6 @@ package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Contract; @@ -42,18 +41,14 @@ public class SimpleComponentContainer implements ComponentContainer { private final List> tickingComponents; @Nullable private final SyncPacket.SyncContext syncContext; - private Queue> pendingSync; + private final Queue> pendingSync; protected SimpleComponentContainer(@Nullable Runnable saveOperation, SyncPacket.@Nullable SyncContext syncContext, Stream> types) { this.components = new IdentityHashMap<>(); this.nbtComponents = new ArrayList<>(); this.tickingComponents = new ArrayList<>(); - if (syncContext != null) { - this.syncContext = syncContext; - this.pendingSync = new ArrayDeque<>(); - } else { - this.syncContext = null; - } + this.syncContext = syncContext; + this.pendingSync = new ArrayDeque<>(); types.forEach(type -> this.initializeComponent(saveOperation, type)); types.close(); @@ -110,29 +105,20 @@ public void tick(@NotNull ComponentProvider provider) { this.sync(provider); } - @Override - public void receiveSyncPacket(@NotNull ComponentType type, @NotNull PacketByteBuf buf) { - ((SyncedComponent) this.components.get(type)).readFromBuf(buf); - } - @Override public void sync(@NotNull ComponentProvider provider) { if (this.syncContext == null) { throw ErrorUtil.illegalState("Cannot sync a non-syncable component container! Make sure you provide a context!").get(); } - var map = new HashMap, SyncedComponent>(); - - while (!this.pendingSync.isEmpty()) { - var currentType = this.pendingSync.poll(); - map.put(currentType, (SyncedComponent) this.components.get(currentType)); - } - - if (!map.isEmpty()) { - SyncPacket.send(this.syncContext, provider, map); - } + SyncPacket.syncFromQueue( + this.pendingSync, + this.syncContext, + type -> ((SyncedComponent) this.components.get(type)), + provider + ); } - private void initializeComponent(@Nullable Runnable saveOperation, ComponentType type) { + private void initializeComponent(@Nullable Runnable saveOperation, @NotNull ComponentType type) { Component component = type.create(); this.components.put(type, component); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java index d88163df20..cf7b6a7219 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -47,7 +47,8 @@ public static void registerDefaults() { public @NotNull PacketByteBuf start(@NotNull ComponentProvider provider) { var buf = PacketByteBufs.create(); buf.writeInt(SyncHeaderRegistry.HEADERS.getRawId(this)); - //noinspection unchecked the person calling is responsible to make sure we get a valid provider instance! + // the person calling is responsible to make sure we get a valid provider instance! + //noinspection unchecked this.codec.encode(buf, (P) provider); return buf; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index a58d2cfa12..5e9a59cb22 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -29,12 +29,15 @@ import org.quiltmc.qsl.networking.api.ServerPlayNetworking; import java.util.Collection; +import java.util.HashMap; import java.util.Map; +import java.util.Queue; +import java.util.function.Function; import java.util.function.Supplier; public class SyncPacket { @NotNull - public static PacketByteBuf create(SyncPacketHeader headerCreator, @NotNull ComponentProvider provider, Map, SyncedComponent> components) { + public static PacketByteBuf create(@NotNull SyncPacketHeader headerCreator, @NotNull ComponentProvider provider, @NotNull Map, SyncedComponent> components) { PacketByteBuf buff = headerCreator.start(provider); buff.writeInt(components.size()); components.forEach((type, syncedComponent) -> { @@ -54,9 +57,10 @@ public static void handle(PacketByteBuf buf, MinecraftClient client) { var size = buf.readInt(); for (int i = 0; i < size; i++) { - NetworkCodec.COMPONENT_TYPE.decode(buf).ifPresent( - type -> provider.getComponentContainer().receiveSyncPacket(type, buf) - ); + NetworkCodec.COMPONENT_TYPE.decode(buf) + .flatMap(provider::expose) + .map(it -> ((SyncedComponent) it)) + .ifPresent(synced -> synced.readFromBuf(buf)); } }); buf.release(); @@ -71,6 +75,24 @@ public static void send(SyncContext context, ComponentProvider provider, Map> pendingSync, + SyncPacket.SyncContext context, + Function, SyncedComponent> mapper, + ComponentProvider provider + ) { + var map = new HashMap, SyncedComponent>(); // TODO: Find a way to *not* create this map?! + + while (!pendingSync.isEmpty()) { + var currentType = pendingSync.poll(); + map.put(currentType, mapper.apply(currentType)); + } + + if (!map.isEmpty()) { + SyncPacket.send(context, provider, map); + } + } + public record SyncContext(SyncPacketHeader header, Supplier> playerGenerator) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java index af2b38a1bd..ee8f6bb636 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java @@ -49,11 +49,6 @@ public static Lazy of(@NotNull Supplier sup) { return new Lazy<>(sup); } - @NotNull - public Lazy compose(Function transformer) { - return Lazy.of(() -> transformer.apply(this.get())); - } - @NotNull public Supplier getSupplier() { return sup; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 1de7922e2d..1ff766b4f7 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -82,7 +82,7 @@ public class ComponentTestMod implements ModInitializer { ); public static final ComponentType SERVER_TICK = Components.registerTicking( new Identifier(MODID, "level_tick"), - provider -> { + () -> provider -> { if (provider instanceof LevelProperties properties) { properties.expose(SAVE_FLOAT).ifPresent(floatComponent -> { floatComponent.set(floatComponent.get() + 0.5f); @@ -106,7 +106,7 @@ public class ComponentTestMod implements ModInitializer { ); public static final ComponentType PLAYER_TICK = Components.registerTicking( new Identifier(MODID, "player_tick"), - provider -> { + () -> provider -> { if (provider instanceof ServerPlayerEntity player) { ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); if (stackInHand.isOf(Items.WHEAT)) { From 315d2de9b088b30edf7713ad77e3a986c90ad2c2 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sun, 3 Jul 2022 14:40:58 +0300 Subject: [PATCH 48/70] Applied changed requested from Leo40Git --- .../api/components/GenericComponent.java | 16 ++++++++ .../components/SyncedGenericComponent.java | 16 ++++++++ .../container/LazyComponentContainer.java | 16 ++++---- .../container/OnAccessComponentContainer.java | 40 +++++++++++++------ .../container/SimpleComponentContainer.java | 6 ++- .../impl/sync/codec/NetworkCodec.java | 9 +++-- .../impl/sync/header/SyncHeaderRegistry.java | 2 +- .../impl/sync/header/SyncPacketHeader.java | 2 +- .../qsl/component/mixin/MixinBlockEntity.java | 2 +- .../qsl/component/mixin/MixinChunk.java | 2 +- .../qsl/component/mixin/MixinEntity.java | 2 +- 11 files changed, 83 insertions(+), 30 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java index f84472e1f5..493baa7cef 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.components; import com.mojang.datafixers.util.Pair; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java index 41cece7dd7..e3d30433c3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.components; import com.mojang.serialization.Codec; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 9f9aaeacdf..df75977600 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -136,16 +136,18 @@ public void tick(@NotNull ComponentProvider provider) { this.sync(provider); } + @SuppressWarnings("ConstantConditions") // pendingSync will be null if syncContext is null and the other way around @Override public void sync(@NotNull ComponentProvider provider) { - if (this.syncContext != null && this.pendingSync != null /* this is not needed but IJ complains, so I'll leave it in*/) { - SyncPacket.syncFromQueue( - this.pendingSync, - this.syncContext, - type -> ((SyncedComponent) this.components.get(type).get()), - provider - ); + if (this.syncContext == null) { + throw ErrorUtil.illegalState("Cannot sync a non-syncable component container! Make sure you provide a context!").get(); } + SyncPacket.syncFromQueue( + this.pendingSync, + this.syncContext, + type -> ((SyncedComponent) this.components.get(type).get()), + provider + ); } private IdentityHashMap, Lazy> initializeComponents(ComponentProvider provider) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index 2a74e54dfc..993b476fa8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; @@ -10,6 +26,7 @@ import org.quiltmc.qsl.component.api.components.TickingComponent; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; import java.util.*; @@ -87,18 +104,19 @@ public void tick(@NotNull ComponentProvider provider) { .forEach(tickingComponent -> tickingComponent.tick(provider)); } + + @SuppressWarnings("ConstantConditions") // pendingSync will be null if syncContext is null and the other way around @Override public void sync(@NotNull ComponentProvider provider) { - if (this.syncContext != null) { - // pendingsync will be null if synccontext is null and the other way around - //noinspection ConstantConditions - SyncPacket.syncFromQueue( - this.pendingSync, - this.syncContext, - type -> ((SyncedComponent) this.components.get(type)), - provider - ); + if (this.syncContext == null) { + throw ErrorUtil.illegalState("Cannot sync a non-syncable component container! Make sure you provide a context!").get(); } + SyncPacket.syncFromQueue( + this.pendingSync, + this.syncContext, + type -> ((SyncedComponent) this.components.get(type)), + provider + ); } private Map, Component> getInitialComponents() { @@ -118,9 +136,7 @@ private Component createComponent(@NotNull ComponentType type) { this.tickingComponents.add(type); } - if (component instanceof SyncedComponent synced && this.syncContext != null) { - // pendingsync will be null if synccontext is null and the other way around - //noinspection ConstantConditions + if (component instanceof SyncedComponent synced && this.pendingSync != null) { synced.setSyncOperation(() -> this.pendingSync.add(type)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index de0ef6927e..35c6731293 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -41,6 +41,7 @@ public class SimpleComponentContainer implements ComponentContainer { private final List> tickingComponents; @Nullable private final SyncPacket.SyncContext syncContext; + @Nullable private final Queue> pendingSync; protected SimpleComponentContainer(@Nullable Runnable saveOperation, SyncPacket.@Nullable SyncContext syncContext, Stream> types) { @@ -48,7 +49,7 @@ protected SimpleComponentContainer(@Nullable Runnable saveOperation, SyncPacket. this.nbtComponents = new ArrayList<>(); this.tickingComponents = new ArrayList<>(); this.syncContext = syncContext; - this.pendingSync = new ArrayDeque<>(); + this.pendingSync = this.syncContext != null ? new ArrayDeque<>() : null; types.forEach(type -> this.initializeComponent(saveOperation, type)); types.close(); @@ -105,6 +106,7 @@ public void tick(@NotNull ComponentProvider provider) { this.sync(provider); } + @SuppressWarnings("ConstantConditions") // pendingSync will be null if syncContext is null and the other way around @Override public void sync(@NotNull ComponentProvider provider) { if (this.syncContext == null) { @@ -131,7 +133,7 @@ private void initializeComponent(@Nullable Runnable saveOperation, @NotNull Comp this.tickingComponents.add(type); } - if (component instanceof SyncedComponent synced) { + if (component instanceof SyncedComponent synced && this.pendingSync != null) { synced.setSyncOperation(() -> this.pendingSync.add(type)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java index 7ae1906c0c..0101f46f84 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java @@ -67,7 +67,7 @@ public record NetworkCodec(@NotNull BiConsumer encoder, .map(chunkPos -> MinecraftClient.getInstance().world.getChunk(chunkPos.x, chunkPos.z)) .orElseThrow() ); - public static final NetworkCodec ITEMSTACK = new NetworkCodec<>( + public static final NetworkCodec ITEM_STACK = new NetworkCodec<>( PacketByteBuf::writeItemStack, PacketByteBuf::readItemStack ); public static final NetworkCodec LONG = new NetworkCodec<>( @@ -79,7 +79,8 @@ public record NetworkCodec(@NotNull BiConsumer encoder, public static final NetworkCodec IDENTIFIER = new NetworkCodec<>( PacketByteBuf::writeIdentifier, PacketByteBuf::readIdentifier ); - public static final NetworkCodec> INVENTORY = list(ITEMSTACK, integer -> DefaultedList.ofSize(integer, ItemStack.EMPTY)); + public static final NetworkCodec> INVENTORY = + list(ITEM_STACK, size -> DefaultedList.ofSize(size, ItemStack.EMPTY)); public static final NetworkCodec NBT_COMPOUND = new NetworkCodec<>( PacketByteBuf::writeNbt, PacketByteBuf::readNbt ); @@ -91,7 +92,7 @@ public record NetworkCodec(@NotNull BiConsumer encoder, buf -> ClientSyncHandler.getInstance().getType(buf.readInt()) ); - public static > NetworkCodec list(NetworkCodec entryCodec, Function function) { + public static > NetworkCodec list(NetworkCodec entryCodec, Function listFactory) { return new NetworkCodec<>( (buf, os) -> { INT.encode(buf, os.size()); @@ -101,7 +102,7 @@ public static > NetworkCodec list(NetworkCodec entryC }, buf -> { int size = INT.decode(buf).orElseThrow(); - L newList = function.apply(size); + L newList = listFactory.apply(size); for (int i = 0; i < size; i++) { newList.set(i, entryCodec.decode(buf).orElseThrow()); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java index 3465526a4f..b4556032e9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java @@ -25,7 +25,7 @@ import org.quiltmc.qsl.component.impl.CommonInitializer; public class SyncHeaderRegistry { - private static final RegistryKey>> HEADERS_KEY = + public static final RegistryKey>> HEADERS_KEY = RegistryKey.ofRegistry(CommonInitializer.id("sync_headers")); public static final Registry> HEADERS = diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java index cf7b6a7219..aa6bcc109a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -44,11 +44,11 @@ public static void registerDefaults() { SyncHeaderRegistry.register(CommonInitializer.id("level"), LEVEL); } + @SuppressWarnings("unchecked") public @NotNull PacketByteBuf start(@NotNull ComponentProvider provider) { var buf = PacketByteBufs.create(); buf.writeInt(SyncHeaderRegistry.HEADERS.getRawId(this)); // the person calling is responsible to make sure we get a valid provider instance! - //noinspection unchecked this.codec.encode(buf, (P) provider); return buf; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java index bdb7956929..48acbfe2d0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java @@ -51,9 +51,9 @@ private void onReadNbt(NbtCompound nbt, CallbackInfo ci) { this.qsl$container.readNbt(nbt); } + @SuppressWarnings("ConstantConditions") @Inject(method = "", at = @At("RETURN")) private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { - //noinspection ConstantConditions this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() .saving(this::markDirty) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java index 071e1597cd..3629e38cff 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java @@ -48,13 +48,13 @@ public abstract class MixinChunk implements ComponentProvider { return this.qsl$container; } + @SuppressWarnings("ConstantConditions") @Inject(method = "", at = @At("RETURN")) private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { LazyComponentContainer.Builder builder = LazyComponentContainer.builder(this) .orElseThrow() .saving(() -> this.setNeedsSaving(true)); - //noinspection ConstantConditions if ((Chunk) (Object) this instanceof WorldChunk worldChunk) { builder.syncing(SyncPacketHeader.CHUNK, () -> SyncPlayerList.create(worldChunk)).ticking(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java index d75df537ed..030b8e8e76 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java @@ -36,9 +36,9 @@ public abstract class MixinEntity implements ComponentProvider { private ComponentContainer qsl$container; + @SuppressWarnings("ConstantConditions") @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { - //noinspection ConstantConditions this.qsl$container = LazyComponentContainer.builder(this) .orElseThrow() .ticking() From 07e3b211e51f7e576677ef78767a1de0781a2c07 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 11 Jul 2022 17:51:37 +0300 Subject: [PATCH 49/70] Added the Maybe monad class to the base QSL module. --- .../org/quiltmc/qsl/base/api/util/Maybe.java | 517 ++++++++++++++++++ 1 file changed, 517 insertions(+) create mode 100644 library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java new file mode 100644 index 0000000000..f4ba765bff --- /dev/null +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java @@ -0,0 +1,517 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.base.api.util; + +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +/** + * Represents a monad that can either contain a value or no value.
+ * Similar to the {@link Optional} class but with some performance improvements + * and quality of life changes.
+ * + * Can either be {@link Just} or {@link Nothing}.
+ * {@link Just} instances contain a value of type {@link T}.
+ * {@link Nothing} instance all reference the {@link Nothing} singleton and contain no data.
+ * + * @param The type of the wrapped object + * @author 0xJoeMama + */ +public sealed abstract class Maybe permits Maybe.Just, Maybe.Nothing { + /** + * Similar function to {@link Optional#ofNullable} function.
+ * Wraps a {@link T} value into an {@link Maybe}. + * + * @param value A {@link Nullable} value that will be wrapped into a {@link Maybe}. + * @param The type of object the {@link Maybe} instance will hold. + * @return An instance of {@link Just} if the provided value is not null,
+ * otherwise the singleton {@link Nothing} instance. + * @see Optional#ofNullable + */ + public static Maybe wrap(@Nullable T value) { + return value != null ? just(value) : nothing(); + } + + /** + * Similar function to {@link Optional#of}.
+ * Wraps the provided value into a {@link Just} instance. + * + * @param value A {@linkplain org.jetbrains.annotations.NotNull non-null} value that is to be wrapped. + * @param The type of object the {@link Maybe} instance will hold. + * @return A {@link Just} instance containing the provided value. + * @see Optional#of + */ + public static Maybe just(T value) { + return new Just<>(value); + } + + /** + * Similar function to {@link Optional#empty()}. + * + * @param The type the {@link Nothing} instance will take the form of. + * @return the singleton {@link Nothing} instance after casting it to the proper type. + * @see Optional#empty() + */ + @SuppressWarnings("unchecked") // Nothing doesn't contain a value, so we can freely cast it! + public static Maybe nothing() { + return (Maybe) Nothing.INSTANCE; + } + + /** + * Converts an {@link Optional} into a {@link Maybe}.
+ * Exists for the sake of inter-operability. + * + * @param opt The {@link Optional} whose value will be wrapped in a {@link Maybe}. + * @param The type of the value, which the {@link Maybe} instance will contain. + * @return A {@link Maybe} instance containing the value contained in the provided {@link Optional}. + */ + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + // Obviously since we need to convert, the parameter is Optional. + public static Maybe fromOptional(Optional opt) { + return opt.map(Maybe::just).orElseGet(Maybe::nothing); + } + + /** + * Maps the internal value of this {@link Maybe} into a new {@link Maybe} with a different value
+ * using the provided {@link Function}. + * + * @param transformer A {@link T} -> {@link U} function used in the mapping process. + * @param The type of the value after the mapping operation. + * @return A new {@link Just} instance containing the mapped value if the current instance is a {@link Just}, + * otherwise {@link Nothing}. + * @see Optional#map + */ + public abstract Maybe map(Function transformer); + + /** + * Filters the current instance, based on whether it follows the provided {@link Predicate}. + * + * @param predicate A {@link Predicate} instance which may use the current value. + * @return The current instance if {@link Predicate#test} returns true, otherwise {@link Nothing}. + * @see Optional#filter + */ + public abstract Maybe filter(Predicate predicate); + + /** + * Filters the current instance based on whether mapping it with the provided {@link Function} provides {@link Nothing} or {@link Just}. + * Can be used as {@link Optional#flatMap} or as the bind operation of this monad. + * The table below explains in detail. + * + * @param transform A {@link Function} returning a {@link Maybe} instance instead of directly returning the mapping value. + * @param The value the returned {@link Maybe} will contain. + * @return + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ThisFunction ValueReturn Value
{@link Just}{@link Nothing}{@link Nothing}
{@link Nothing}Skipped{@link Nothing}
{@link Just} A{@link Just} B{@link Just} B
+ * @see Optional#flatMap + */ + public abstract Maybe filterMap(Function> transform); + + /** + * Whether the current instance is {@link Nothing} or not. + * + * @return A boolean expressing the aforementioned fact. + * @see Optional#isEmpty() + */ + public abstract boolean isNothing(); + + /** + * Whether the current instance is {@link Just} or not. + * + * @return A boolean expressing the aforementioned fact. + * @see Optional#isPresent() + */ + public abstract boolean isJust(); + + /** + * Applies the provided {@link Consumer} to the current value, if the current instance is {@link Just}. + * + * @param action A {@link Consumer} that may use the current value. + * @return This instance(for chaining). + * @see Optional#ifPresent + */ + public abstract Maybe ifJust(Consumer action); + + /** + * Runs the provided {@link Runnable} if the current instance is {@link Nothing}. + * + * @param runnable The action to run. + * @return This instance(for chaining). + */ + public abstract Maybe ifNothing(Runnable runnable); + + /** + * Performs an operation similar to the boolean or operation on the current instance, using the one provided. + * The table below describes the different return values. + * + * @param supplier A {@link Supplier} of a {@link Maybe}, be it {@link Just} or {@link Nothing}. + * @return + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ThisSupplierReturn Value
{@link Just}SkippedThis instance
{@link Nothing}{@link Just}The created {@link Just}
{@link Nothing}{@link Nothing}{@link Nothing}
+ * @see Optional#or + */ + public abstract Maybe or(Supplier> supplier); + + /** + * Performs an operation similar to the boolean and operation on the current instance using the one provided. + * The table below describes the different return values. + * + * @param other A {@link Supplier} of a {@link Maybe} instance, be it {@link Nothing} or {@link Just}. + * @return + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ThisSupplierReturn Value
{@link Nothing}Skipped{@link Nothing}
{@link Just}{@link Nothing}{@link Nothing}
{@link Just} A{@link Just} B{@link Just} A
+ */ + public abstract Maybe and(Supplier> other); + + /** + * Returns the {@link T} value container in the current {@link Maybe} instance. + * + * @return The {@link T} value that was wrapped. + * @throws IllegalStateException if the current instance is {@link Nothing}. + * @see Optional#orElseThrow() + */ + public abstract T unwrap() throws IllegalStateException; + + /** + * Works like {@link Maybe#unwrap()} except that it doesn't throw if the current instance if {@link Nothing}. + * In that case it returns the provided {@link T} value. + * + * @param defaultValue The value to get if the current instance if {@link Nothing}. + * @return The current {@link T} value if the current instance is {@link Just}, otherwise the provided {@link T} value. + * @see Optional#orElse + */ + public abstract T unwrapOr(T defaultValue); + + /** + * Works like {@link Maybe#unwrapOr} except that it lazily evaluated the return value using the provided {@link Supplier}. + * + * @param supplier A {@link Supplier} that will create the {@link T} value to be returns if the current instance is {@link Nothing}. + * @return The current {@link T} value if the current instance if {@link Just}, + * otherwise the value produces by calling {@link Supplier#get()} on the provided {@link Supplier}. + * @see Optional#orElseGet + */ + public abstract T unwrapOrGet(Supplier supplier); + + /** + * Turns the current {@link Maybe} instance into an {@link Optional}, for inter-operability. + * + * @return {@link Optional#empty()} if the current instance is {@link Nothing}, + * otherwise an {@link Optional} containing the current value. + */ + public abstract Optional toOptional(); + + /** + * The {@link Maybe} state representing the absence of a value. + * + * @param In this case this type parameter is unused. + */ + public static final class Nothing extends Maybe { + /** + * A singleton instance is used for Nothing since it doesn't contain data and can therefore be cast to any Maybe type. + */ + private static final Nothing INSTANCE = new Nothing<>(); + + private Nothing() { + } + + /** + * @see Maybe#map + */ + @Override + public Maybe map(Function transformer) { + return nothing(); + } + + /** + * @see Maybe#filter + */ + @Override + public Maybe filter(Predicate predicate) { + return this; + } + + /** + * @see Maybe#filterMap + */ + @Override + public Maybe filterMap(Function> transform) { + return nothing(); + } + + /** + * @see Maybe#isNothing + */ + @Override + public boolean isNothing() { + return true; + } + + /** + * @see Maybe#isJust + */ + @Override + public boolean isJust() { + return false; + } + + /** + * @see Maybe#ifJust + */ + @Override + public Maybe ifJust(Consumer action) { + return this; + } + + /** + * @see Maybe#ifNothing + */ + @Override + public Maybe ifNothing(Runnable runnable) { + runnable.run(); + return this; + } + + /** + * @see Maybe#or + */ + @Override + public Maybe or(Supplier> supplier) { + return supplier.get(); + } + + /** + * @see Maybe#and + */ + @Override + public Maybe and(Supplier> other) { + return this; + } + + /** + * @see Maybe#unwrap + */ + @Override + public T unwrap() throws IllegalStateException { + throw new IllegalStateException("Attempted to unwrap a None!"); + } + + /** + * @see Maybe#unwrapOr + */ + @Override + public T unwrapOr(T defaultValue) { + return defaultValue; + } + + /** + * @see Maybe#unwrapOrGet + */ + @Override + public T unwrapOrGet(Supplier supplier) { + return supplier.get(); + } + + /** + * @see Maybe#toOptional + */ + @Override + public Optional toOptional() { + return Optional.empty(); + } + } + + /** + * The {@link Maybe} state representing the existence of a {@link T} value. + * + * @param The type of the contained value. + */ + public static final class Just extends Maybe { + private final T value; + + private Just(T value) { + this.value = value; + } + + /** + * @see Maybe#map + */ + @Override + public Maybe map(Function transformer) { + return just(transformer.apply(this.unwrap())); + } + + /** + * @see Maybe#filter + */ + @Override + public Maybe filter(Predicate predicate) { + return predicate.test(this.unwrap()) ? this : nothing(); + } + + /** + * @see Maybe#filterMap + */ + @Override + public Maybe filterMap(Function> transform) { + return transform.apply(this.unwrap()); + } + + /** + * @see Maybe#isNothing + */ + @Override + public boolean isNothing() { + return false; + } + + /** + * @see Maybe#isJust + */ + @Override + public boolean isJust() { + return true; + } + + /** + * @see Maybe#ifJust + */ + @Override + public Maybe ifJust(Consumer action) { + action.accept(this.unwrap()); + return this; + } + + /** + * @see Maybe#ifNothing + */ + @Override + public Maybe ifNothing(Runnable runnable) { + return this; + } + + /** + * @see Maybe#or + */ + @Override + public Maybe or(Supplier> supplier) { + return this; + } + + /** + * @see Maybe#and + */ + @Override + public Maybe and(Supplier> other) { + Maybe otherMaybe = other.get(); + return otherMaybe.isNothing() ? nothing() : this; + } + + /** + * @see Maybe#unwrap + */ + @Override + public T unwrap() { + return this.value; + } + + /** + * @see Maybe#unwrapOr + */ + @Override + public T unwrapOr(T defaultValue) { + return this.unwrap(); + } + + /** + * @see Maybe#unwrapOrGet + */ + @Override + public T unwrapOrGet(Supplier supplier) { + return this.unwrap(); + } + + /** + * @see Maybe#toOptional + */ + @Override + public Optional toOptional() { + // Using Optional$of since our value should never be null! + return Optional.of(this.value); + } + } +} From 5f72bd8dbe7490c4b60e66d36a300a2e191cc3f4 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 12 Jul 2022 14:05:58 +0300 Subject: [PATCH 50/70] Major rewrite of injections and removed notnulls. --- CONTRIBUTING.md | 2 +- library/data/component/build.gradle | 16 +- ...ate.java => CachedInjectionPredicate.java} | 4 +- .../quiltmc/qsl/component/api/Component.java | 5 +- .../qsl/component/api/ComponentType.java | 27 +-- .../quiltmc/qsl/component/api/Components.java | 54 +++-- ...er.java => DynamicInjectionPredicate.java} | 19 +- .../api/components/GenericComponent.java | 39 +--- .../api/components/NbtComponent.java | 37 ++-- .../api/components/SyncedComponent.java | 11 +- .../components/SyncedGenericComponent.java | 23 +-- .../api/components/TickingComponent.java | 5 +- .../api/container/ComponentContainer.java | 121 +++++++++++ .../component/api/event/ComponentEvents.java | 45 ----- .../api/{ => provider}/ComponentProvider.java | 21 +- .../qsl/component/impl/CommonInitializer.java | 3 +- .../impl/ComponentInjectionCache.java | 49 ----- .../qsl/component/impl/ComponentsImpl.java | 71 +++---- .../impl/client/ClientResolution.java | 38 ++++ .../client/sync/ClientRegistryPacket.java | 13 +- .../impl/client/sync/ClientSyncHandler.java | 6 +- .../components/DefaultFloatComponent.java | 14 +- .../components/DefaultIntegerComponent.java | 27 +-- .../components/DefaultInventoryComponent.java | 33 ++- .../container/AbstractComponentContainer.java | 119 +++++++++++ .../container/EmptyComponentContainer.java | 60 ++++++ .../container/LazyComponentContainer.java | 190 +++--------------- .../container/OnAccessComponentContainer.java | 134 +++--------- .../container/SimpleComponentContainer.java | 173 +++------------- .../impl/event/ServerTickEventListener.java | 8 +- .../impl/injection/ComponentEntry.java | 30 +++ .../injection/manager/InjectionManager.java | 75 +++++++ .../cached/CachedInjectionManager.java | 45 +++++ .../dynamic/DynamicInjectionManager.java | 59 ++++++ .../cached}/ClassInjectionPredicate.java | 14 +- .../FilteredInheritedInjectionPredicate.java | 8 +- .../cached}/InheritedInjectionPredicate.java | 12 +- .../cached}/RedirectedInjectionPredicate.java | 8 +- .../DynamicClassInjectionPredicate.java | 37 ++++ .../impl/sync/ServerSyncHandler.java | 5 +- .../component/impl/sync/SyncPlayerList.java | 9 +- .../impl/sync/codec/NetworkCodec.java | 120 +++++++---- .../impl/sync/header/SyncHeaderRegistry.java | 37 ---- .../impl/sync/header/SyncPacketHeader.java | 51 +++-- .../impl/sync/packet/RegistryPacket.java | 6 +- .../impl/sync/packet/SyncPacket.java | 54 +++-- .../impl/util/ComponentProviderState.java | 87 ++++++++ .../component/mixin/MixinLevelProperties.java | 78 ------- .../{ => block/entity}/MixinBlockEntity.java | 15 +- .../MixinDirectBlockEntityTickInvoker.java | 2 +- .../mixin/{ => chunk}/MixinChunk.java | 15 +- .../{ => chunk}/MixinChunkSerializer.java | 2 +- .../MixinThreadedChunkStorage.java | 6 +- .../mixin/{ => chunk}/MixinWorldChunk.java | 4 +- .../{ => level}/MixinMinecraftClient.java | 11 +- .../mixin/{ => entity}/MixinEntity.java | 23 +-- .../{ => item/stack}/MixinItemStack.java | 37 ++-- .../mixin/level/MixinMinecraftServer.java | 31 +++ .../mixin/{ => world}/MixinServerWorld.java | 12 +- .../resources/quilt_component.mixins.json | 22 +- .../qsl/component/test/ComponentTestMod.java | 48 ++--- .../component/test/ServerTickListener.java | 14 +- .../quiltmc/qsl/component/test/TestBlock.java | 2 +- .../qsl/component/test/TestBlockEntity.java | 28 +-- .../component/test/client/TestBeRenderer.java | 2 +- .../test/component/SaveFloatComponent.java | 34 ++++ .../MixinBlockEntityRendererFactories.java | 2 +- .../test/mixin/client/MixinInGameHud.java | 13 +- 68 files changed, 1291 insertions(+), 1134 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{ComponentInjectionPredicate.java => CachedInjectionPredicate.java} (86%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{ComponentContainer.java => DynamicInjectionPredicate.java} (54%) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{ => provider}/ComponentProvider.java (71%) delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/{predicates => injection/predicate/cached}/ClassInjectionPredicate.java (77%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/{predicates => injection/predicate/cached}/FilteredInheritedInjectionPredicate.java (84%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/{predicates => injection/predicate/cached}/InheritedInjectionPredicate.java (76%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/{predicates => injection/predicate/cached}/RedirectedInjectionPredicate.java (84%) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{ => block/entity}/MixinBlockEntity.java (86%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{ => block/entity}/MixinDirectBlockEntityTickInvoker.java (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{ => chunk}/MixinChunk.java (84%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{ => chunk}/MixinChunkSerializer.java (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{ => chunk}/MixinThreadedChunkStorage.java (91%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{ => chunk}/MixinWorldChunk.java (95%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/{ => level}/MixinMinecraftClient.java (78%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{ => entity}/MixinEntity.java (88%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{ => item/stack}/MixinItemStack.java (86%) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MixinMinecraftServer.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{ => world}/MixinServerWorld.java (78%) create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc3fbf4357..eebca9f8b3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -234,7 +234,7 @@ the actual name of the variable and the namespace. `@Unique` fields must be prefixed with `quilt$`, but `@Unique` methods don't need prefixes. In the case of a pseudo-local variable (a field used briefly to pass around a local variable of a method between 2 -injections of said method), the field should be named with the namespace first, then the name of the injected method, +componentEntries of said method), the field should be named with the namespace first, then the name of the injected method, and finally the name of the local (`quilt$injectedMethod$localName`). ## Gradle Conventions diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index 7cf8c4af57..03b635cde1 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -11,8 +11,8 @@ qslModule { moduleDependencies { core { api("qsl_base") - api("lifecycle_events") - api("networking") + impl("lifecycle_events") + impl("networking") testmodOnly("registry") // Required by block_entity } @@ -37,27 +37,27 @@ qslModule { accessWidener() - injectedInterface("net/minecraft/class_2586") { + injectedInterface("net/minecraft/class_2586") { // BlockEntity values = ["org/quiltmc/qsl/component/api/ComponentProvider"] } - injectedInterface("net/minecraft/class_1297") { + injectedInterface("net/minecraft/class_1297") { // Entity values = ["org/quiltmc/qsl/component/api/ComponentProvider"] } - injectedInterface("net/minecraft/class_2791") { + injectedInterface("net/minecraft/class_2791") { // Chunk values = ["org/quiltmc/qsl/component/api/ComponentProvider"] } - injectedInterface("net/minecraft/class_31") { + injectedInterface("net/minecraft/class_1799") { // ItemStack values = ["org/quiltmc/qsl/component/api/ComponentProvider"] } - injectedInterface("net/minecraft/class_1799") { + injectedInterface("net/minecraft/class_310") { // MinecraftClient values = ["org/quiltmc/qsl/component/api/ComponentProvider"] } - injectedInterface("net/minecraft/class_310") { + injectedInterface("net/minecraft/server/MinecraftServer") { // MinecraftServer values = ["org/quiltmc/qsl/component/api/ComponentProvider"] } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/CachedInjectionPredicate.java similarity index 86% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/CachedInjectionPredicate.java index b8399faa32..1a79d87e06 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/CachedInjectionPredicate.java @@ -16,6 +16,6 @@ package org.quiltmc.qsl.component.api; -public interface ComponentInjectionPredicate { - boolean canInject(ComponentProvider provider); +public interface CachedInjectionPredicate { + boolean isClassValid(Class clazz); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java index 10713aba37..7ac60904a4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java @@ -16,12 +16,9 @@ package org.quiltmc.qsl.component.api; -import org.jetbrains.annotations.NotNull; - public interface Component { @FunctionalInterface interface Factory { - @NotNull - T create(); + T create(Runnable saveOperation, Runnable syncOperation); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 1b457dc0de..5e8ae5f13d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -17,31 +17,34 @@ package org.quiltmc.qsl.component.api; import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; +import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import java.util.IdentityHashMap; import java.util.Map; -import java.util.Optional; -public record ComponentType(Identifier id, Component.Factory factory, +public record ComponentType(Identifier id, Component.Factory defaultFactory, boolean isStatic, boolean isInstant) implements Component.Factory { - public static final Static STATIC_CACHE = new Static(); + public static final NetworkCodec> NETWORK_CODEC = + NetworkCodec.INT.map(Components.REGISTRY::getRawId, ClientSyncHandler.getInstance()::getType); + private static final Static STATIC_CACHE = new Static(); @SuppressWarnings("unchecked") - public Optional cast(Component component) { + public Maybe cast(Component component) { try { - return Optional.of((T) component); + return Maybe.just((T) component); } catch (ClassCastException ignored) { - return Optional.empty(); + return Maybe.nothing(); } } @Override - public @NotNull T create() { + public T create(Runnable saveOperation, Runnable syncOperation) { if (this.isStatic) { - return STATIC_CACHE.getOrCreate(this); + return STATIC_CACHE.getOrCreate(this, saveOperation, syncOperation); } - return this.factory.create(); + return this.defaultFactory.create(saveOperation, syncOperation); } public static class Static { @@ -52,11 +55,11 @@ private Static() { } @SuppressWarnings("unchecked") - @NotNull C getOrCreate(ComponentType type) { + C getOrCreate(ComponentType type, Runnable saveOperation, Runnable syncOperation) { if (this.staticInstances.containsKey(type)) { return (C) this.staticInstances.get(type); } else { - C singleton = type.factory.create(); + C singleton = type.defaultFactory.create(saveOperation, syncOperation); this.staticInstances.put(type, singleton); return singleton; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index f108dc2bbb..1600404cc4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -19,50 +19,66 @@ import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; +import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.predicates.ClassInjectionPredicate; -import org.quiltmc.qsl.component.impl.predicates.FilteredInheritedInjectionPredicate; -import org.quiltmc.qsl.component.impl.predicates.InheritedInjectionPredicate; -import org.quiltmc.qsl.component.impl.predicates.RedirectedInjectionPredicate; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; +import org.quiltmc.qsl.component.impl.injection.predicate.cached.FilteredInheritedInjectionPredicate; +import org.quiltmc.qsl.component.impl.injection.predicate.cached.InheritedInjectionPredicate; +import org.quiltmc.qsl.component.impl.injection.predicate.cached.RedirectedInjectionPredicate; +import org.quiltmc.qsl.component.impl.injection.predicate.dynamic.DynamicClassInjectionPredicate; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import java.util.Optional; import java.util.Set; +import java.util.function.Predicate; public final class Components { public static final RegistryKey>> REGISTRY_KEY = ComponentsImpl.REGISTRY_KEY; - public static final Registry> REGISTRY = ComponentsImpl.REGISTRY; - public static void inject(ComponentInjectionPredicate predicate, ComponentType component) { - ComponentsImpl.inject(predicate, component); + public static void inject(CachedInjectionPredicate predicate, ComponentType type) { + ComponentsImpl.inject(predicate, new ComponentEntry<>(type)); + } + + public static void inject(Class clazz, ComponentType type) { + ComponentsImpl.inject(new ClassInjectionPredicate(clazz), new ComponentEntry<>(type)); } - public static void inject(Class clazz, ComponentType component) { - ComponentsImpl.inject(new ClassInjectionPredicate(clazz), component); + public static void injectInheritage(Class clazz, ComponentType type) { + ComponentsImpl.inject(new InheritedInjectionPredicate(clazz), new ComponentEntry<>(type)); } - public static void injectInheritage(Class clazz, ComponentType component) { - ComponentsImpl.inject(new InheritedInjectionPredicate(clazz), component); + public static void injectInheritanceExcept(Class clazz, ComponentType type, Class... exceptions) { + ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), new ComponentEntry<>(type)); } - public static void injectInheritanceExcept(Class clazz, ComponentType component, Class... exceptions) { - ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), component); + public static void injectRedirected(Class mainClass, ComponentType type, Class... others) { + ComponentsImpl.inject(new RedirectedInjectionPredicate(mainClass, Set.of(others)), new ComponentEntry<>(type)); } - public static void injectRedirected(Class mainClass, ComponentType type, Class others) { - ComponentsImpl.inject(new RedirectedInjectionPredicate(mainClass, Set.of(others)), type); + public static void injectDynamic(Class

clazz, ComponentType type, Predicate

predicate) { + // TODO: Fix evil hack if possible + ComponentsImpl.inject(new DynamicClassInjectionPredicate<>(clazz, predicate), new ComponentEntry<>(type)); } - public static Optional expose(ComponentType id, S obj) { + public static Maybe expose(ComponentType id, S obj) { if (obj instanceof ComponentProvider provider) { - return provider.getComponentContainer().expose(id).flatMap(id::cast); + return provider.getComponentContainer().expose(id).filterMap(id::cast); } - return Optional.empty(); + return Maybe.nothing(); + } + + public static ComponentType register(Identifier id, ComponentType type) { + return ComponentsImpl.register(id, type); } public static ComponentType register(Identifier id, Component.Factory factory) { + if (factory instanceof ComponentType) { + throw ErrorUtil.illegalArgument("Do NOT register ComponentTypes as factories, use the correct method").get(); + } return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, false)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/DynamicInjectionPredicate.java similarity index 54% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/DynamicInjectionPredicate.java index 7a11388ab1..d47abddee8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/DynamicInjectionPredicate.java @@ -16,21 +16,8 @@ package org.quiltmc.qsl.component.api; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import java.util.Optional; - -public interface ComponentContainer { // TODO: Maybe split up responsibilities? - Optional expose(ComponentType type); - - void writeNbt(@NotNull NbtCompound providerRootNbt); - - void readNbt(@NotNull NbtCompound providerRootNbt); - - void tick(@NotNull ComponentProvider provider); - - void sync(@NotNull ComponentProvider provider); +public interface DynamicInjectionPredicate extends CachedInjectionPredicate { + boolean canInject(ComponentProvider provider); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java index 493baa7cef..ea2ade771b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java @@ -16,29 +16,23 @@ package org.quiltmc.qsl.component.api.components; -import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; -import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtNull; import net.minecraft.nbt.NbtOps; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class GenericComponent implements NbtComponent { +public class GenericComponent implements NbtComponent { protected final Codec codec; - protected T value; @Nullable - private Runnable saveOperation; + private final Runnable saveOperation; + protected T value; - protected GenericComponent(@NotNull Codec codec) { + public GenericComponent(@Nullable Runnable saveOperation, Codec codec) { + this.saveOperation = saveOperation; this.codec = codec; } - @NotNull - public static GenericComponent create(@NotNull Codec codec) { - return new GenericComponent<>(codec); - } - public T getValue() { return this.value; } @@ -53,29 +47,18 @@ public byte nbtType() { } @Override - public void read(NbtCompound nbt) { - this.codec.decode(NbtOps.INSTANCE, nbt.get("Value")).result() - .map(Pair::getFirst) - .ifPresent(this::setValue); + public void read(E nbt) { + NbtOps.INSTANCE.withParser(this.codec).apply(nbt).result().ifPresent(t -> this.value = t); } + @SuppressWarnings("unchecked") @Override - public NbtCompound write() { - var nbt = new NbtCompound(); - if (this.value != null) { - this.codec.encodeStart(NbtOps.INSTANCE, this.value).result() - .ifPresent(nbtElement -> nbt.put("Value", nbtElement)); - } - return nbt; + public E write() { // TODO: Make sure this doesn't cause problems. + return (E) NbtOps.INSTANCE.withEncoder(this.codec).apply(this.value).result().orElse(NbtNull.INSTANCE); } @Override public @Nullable Runnable getSaveOperation() { return this.saveOperation; } - - @Override - public void setSaveOperation(@Nullable Runnable runnable) { - this.saveOperation = runnable; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java index a231df7834..9dd11218f2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java @@ -18,38 +18,27 @@ import net.minecraft.nbt.*; import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.impl.util.ErrorUtil; public interface NbtComponent extends Component { @SuppressWarnings("unchecked") - static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier id, @NotNull NbtCompound root) { + static void readFrom(NbtComponent nbtComponent, Identifier id, NbtCompound root) { NbtElement nbtTarget = root.get(id.toString()); switch (nbtComponent.nbtType()) { - case NbtElement.BYTE_TYPE -> - ((NbtComponent) nbtComponent).read((NbtByte) nbtTarget); - case NbtElement.SHORT_TYPE -> - ((NbtComponent) nbtComponent).read((NbtShort) nbtTarget); - case NbtElement.INT_TYPE -> - ((NbtComponent) nbtComponent).read((NbtInt) nbtTarget); - case NbtElement.LONG_TYPE -> - ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); - case NbtElement.FLOAT_TYPE -> - ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); - case NbtElement.DOUBLE_TYPE -> - ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); + case NbtElement.BYTE_TYPE -> ((NbtComponent) nbtComponent).read((NbtByte) nbtTarget); + case NbtElement.SHORT_TYPE -> ((NbtComponent) nbtComponent).read((NbtShort) nbtTarget); + case NbtElement.INT_TYPE -> ((NbtComponent) nbtComponent).read((NbtInt) nbtTarget); + case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); + case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); + case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); - case NbtElement.STRING_TYPE -> - ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); - case NbtElement.LIST_TYPE -> - ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); - case NbtElement.COMPOUND_TYPE -> - ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); - case NbtElement.INT_ARRAY_TYPE -> - ((NbtComponent) nbtComponent).read((NbtIntArray) nbtTarget); + case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); + case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); + case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); + case NbtElement.INT_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtIntArray) nbtTarget); case NbtElement.LONG_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtLongArray) nbtTarget); default -> // We throw if we ever find a non-vanilla type trying to be used for component serialization! @@ -60,7 +49,7 @@ static void readFrom(@NotNull NbtComponent nbtComponent, @NotNull Identifier } } - static void writeTo(@NotNull NbtCompound root, @NotNull NbtComponent nbtComponent, @NotNull Identifier id) { + static void writeTo(NbtCompound root, NbtComponent nbtComponent, Identifier id) { root.put(id.toString(), nbtComponent.write()); } @@ -77,6 +66,4 @@ default void save() { } @Nullable Runnable getSaveOperation(); - - void setSaveOperation(@Nullable Runnable runnable); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java index fc440451b0..65c52f1505 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java @@ -17,19 +17,20 @@ package org.quiltmc.qsl.component.api.components; import net.minecraft.network.PacketByteBuf; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; + +import java.util.function.Consumer; public interface SyncedComponent extends Component { - void writeToBuf(@NotNull PacketByteBuf buf); + void writeToBuf(PacketByteBuf buf); - void readFromBuf(@NotNull PacketByteBuf buf); + void readFromBuf(PacketByteBuf buf); // Investigate what happens when the server doesn't send correct data?! @Nullable Runnable getSyncOperation(); - void setSyncOperation(@Nullable Runnable runnable); - default void sync() { if (this.getSyncOperation() != null) { this.getSyncOperation().run(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java index e3d30433c3..5b06c5c2ef 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java @@ -17,38 +17,35 @@ package org.quiltmc.qsl.component.api.components; import com.mojang.serialization.Codec; +import net.minecraft.nbt.NbtElement; import net.minecraft.network.PacketByteBuf; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; -public class SyncedGenericComponent extends GenericComponent implements SyncedComponent { +public class SyncedGenericComponent extends GenericComponent implements SyncedComponent { private final NetworkCodec networkCodec; @Nullable - private Runnable syncOperation; + private final Runnable syncOperation; - protected SyncedGenericComponent(@NotNull Codec codec, @NotNull NetworkCodec networkCodec) { - super(codec); + protected SyncedGenericComponent( + @Nullable Runnable saveOperation, @Nullable Runnable syncOperation, Codec codec, NetworkCodec networkCodec) { + super(saveOperation, codec); + this.syncOperation = syncOperation; this.networkCodec = networkCodec; } @Override - public void writeToBuf(@NotNull PacketByteBuf buf) { + public void writeToBuf(PacketByteBuf buf) { this.networkCodec.encode(buf, this.value); } @Override - public void readFromBuf(@NotNull PacketByteBuf buf) { - this.networkCodec.decode(buf).ifPresent(t -> this.value = t); + public void readFromBuf(PacketByteBuf buf) { + this.networkCodec.decode(buf).ifJust(t -> this.value = t); } @Override public @Nullable Runnable getSyncOperation() { return this.syncOperation; } - - @Override - public void setSyncOperation(@Nullable Runnable runnable) { - this.syncOperation = runnable; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java index 471d02f5de..fb57049c5c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java @@ -16,10 +16,9 @@ package org.quiltmc.qsl.component.api.components; -import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; public interface TickingComponent extends Component { - void tick(@NotNull ComponentProvider provider); + void tick(ComponentProvider provider); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java new file mode 100644 index 0000000000..911edc8e3f --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -0,0 +1,121 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.api.container; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.server.network.ServerPlayerEntity; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.container.EmptyComponentContainer; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.impl.util.Lazy; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Supplier; + +public interface ComponentContainer { + ComponentContainer EMPTY = EmptyComponentContainer.INSTANCE; + + static Maybe builder(Object obj) { + return obj instanceof ComponentProvider provider ? Maybe.just(new Builder(provider)) : Maybe.nothing(); + } + + Maybe expose(ComponentType type); + + void writeNbt(NbtCompound providerRootNbt); + + void readNbt(NbtCompound providerRootNbt); + + void tick(ComponentProvider provider); + + void sync(ComponentProvider provider); + + @FunctionalInterface + interface Factory { + T generate(ComponentProvider provider, + Lazy>> injections, + @Nullable Runnable saveOperation, + boolean ticking, + SyncPacket.SyncContext syncContext); + } + + class Builder { + private final ComponentProvider provider; + private final Lazy>> injections; + private boolean ticking; + @Nullable + private Runnable saveOperation; + @Nullable + private SyncPacket.SyncContext syncContext; + + private Builder(ComponentProvider provider) { + this.provider = provider; + this.injections = Lazy.of(ArrayList::new); + this.saveOperation = null; + this.syncContext = null; + } + + public Builder saving(Runnable saveOperation) { + this.saveOperation = saveOperation; + return this; + } + + public Builder ticking() { + this.ticking = true; + return this; + } + + public Builder syncing(SyncPacketHeader header, Supplier> playerGenerator) { + this.syncContext = new SyncPacket.SyncContext(header, playerGenerator); + return this; + } + + public Builder add(ComponentEntry componentEntry) { + this.injections.get().add(componentEntry); + return this; + } + + public Builder add(ComponentType type) { + this.add(new ComponentEntry<>(type)); + return this; + } + + public Builder add(ComponentType type, Component.Factory factory) { + this.add(new ComponentEntry<>(type, factory)); + return this; + } + + public Builder add(ComponentType... types) { + for (var type : types) { + this.add(type); + } + + return this; + } + + public T build(ComponentContainer.Factory factory) { + return factory.generate(this.provider, this.injections, this.saveOperation, this.ticking, this.syncContext); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java deleted file mode 100644 index f2d0bd7df6..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/event/ComponentEvents.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.api.event; - -import org.quiltmc.qsl.base.api.event.Event; -import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.ComponentType; - -public class ComponentEvents { - public static final Event DYNAMIC_INJECT = Event.create(DynamicInject.class, listeners -> (provider, injector) -> { - for (DynamicInject listener : listeners) { - listener.onInject(provider, injector); - } - }); - - @FunctionalInterface - public interface DynamicInject { - void onInject(ComponentProvider provider, Injector injector); - } - - @FunctionalInterface - public interface Injector { - default void injectIf(boolean condition, ComponentType type) { - if (condition) { - this.inject(type); - } - } - - void inject(ComponentType type); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java similarity index 71% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java index f7a624aed3..1afc065ec6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java @@ -14,36 +14,33 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api; +package org.quiltmc.qsl.component.api.provider; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; +import net.minecraft.server.MinecraftServer; import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.level.LevelProperties; -import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.base.api.util.InjectedInterface; - -import java.util.Optional; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.Components; @InjectedInterface({ Entity.class, BlockEntity.class, Chunk.class, - LevelProperties.class, ItemStack.class, + MinecraftServer.class, MinecraftClient.class }) public interface ComponentProvider { - @NotNull ComponentContainer getComponentContainer(); - default Optional expose(ComponentType id) { + default Maybe expose(ComponentType id) { return Components.expose(id, this); } - - default void syncComponents() { - this.getComponentContainer().sync(this); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 236c94087d..4f7a8ad9ae 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -18,7 +18,6 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.impl.sync.ServerSyncHandler; @@ -30,7 +29,7 @@ public final class CommonInitializer implements ModInitializer { public static final String MODID = "quilt_component"; - public static @NotNull Identifier id(@NotNull String id) { + public static Identifier id(String id) { return new Identifier(MODID, id); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java deleted file mode 100644 index 02e05e8709..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentInjectionCache.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.impl; - -import net.minecraft.util.Util; -import org.quiltmc.qsl.component.api.ComponentType; - -import java.util.*; - -public class ComponentInjectionCache { - private static final Map, Set>> INJECTION_CACHE = new HashMap<>(); - - private ComponentInjectionCache() { - - } - - public static Optional>> getCache(Class clazz) { - if (!INJECTION_CACHE.containsKey(clazz)) { - return Optional.empty(); - } - - return Optional.of(INJECTION_CACHE.get(clazz)); - } - - public static void clear() { - INJECTION_CACHE.clear(); - } - - public static void record(Class clazz, Set> components) { - if (INJECTION_CACHE.put(clazz, Util.make(new HashSet<>(), list -> list.addAll(components))) != null) { - // If there was a value there, it means we attempted an override, and so we throw. - throw new IllegalStateException("Cannot register cache twice for class %s".formatted(clazz)); - } - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 9d78fbad15..d9a005207d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -18,80 +18,55 @@ import com.mojang.serialization.Lifecycle; import net.minecraft.util.Identifier; -import net.minecraft.util.Util; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.SimpleRegistry; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; -import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.impl.sync.header.SyncHeaderRegistry; -import org.quiltmc.qsl.component.impl.util.ErrorUtil; +import org.quiltmc.qsl.component.api.*; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.injection.manager.cached.CachedInjectionManager; +import org.quiltmc.qsl.component.impl.injection.manager.dynamic.DynamicInjectionManager; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.List; @ApiStatus.Internal public class ComponentsImpl { - // TODO: Maybe move this to the ComponentType class?! public static final RegistryKey>> REGISTRY_KEY = RegistryKey.ofRegistry(CommonInitializer.id("component_types")); - public static final Registry> REGISTRY = + public static final Registry> REGISTRY = // TODO: Register this, maybe?! new SimpleRegistry<>(REGISTRY_KEY, Lifecycle.experimental(), null); - public static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); - - private static final Map>> INJECTION_REGISTRY = new HashMap<>(); + public static final CachedInjectionManager CACHED_MANAGER = new CachedInjectionManager(); + public static final DynamicInjectionManager DYNAMIC_MANAGER = new DynamicInjectionManager(); - public static void inject(ComponentInjectionPredicate predicate, ComponentType type) { - if (REGISTRY.get(type.id()) == null) { - throw ErrorUtil.illegalArgument("The target id %s does not match any registered component", type).get(); - } + public static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); - if (INJECTION_REGISTRY.containsKey(predicate)) { - if (!INJECTION_REGISTRY.get(predicate).add(type)) { - throw ErrorUtil.illegalArgument( - "Cannot inject the predicate %s with id %s more than once! Consider creating a new component type!", - predicate, type.id() - ).get(); - } + public static void inject(CachedInjectionPredicate predicate, ComponentEntry componentEntry) { + if (predicate instanceof DynamicInjectionPredicate dynamicPredicate) { + DYNAMIC_MANAGER.inject(dynamicPredicate, componentEntry); } else { - INJECTION_REGISTRY.put(predicate, Util.make(new HashSet<>(), set -> set.add(type))); + CACHED_MANAGER.inject(predicate, componentEntry); } - - ComponentInjectionCache.clear(); // Always clear the cache after an injection is registered. } - @NotNull - public static Set> getInjections(@NotNull ComponentProvider provider) { - return ComponentInjectionCache.getCache(provider.getClass()).orElseGet(() -> { - Set> injectedTypes = INJECTION_REGISTRY.entrySet().stream() - .filter(it -> it.getKey().canInject(provider)) - .map(Map.Entry::getValue) - .flatMap(Set::stream) - .collect(Collectors.toSet()); - - ComponentInjectionCache.record(provider.getClass(), injectedTypes); - - return injectedTypes; - }); + public static List> getInjections(ComponentProvider provider) { + var result = new ArrayList>(); + result.addAll(CACHED_MANAGER.getInjections(provider)); + result.addAll(DYNAMIC_MANAGER.getInjections(provider)); + return result; } - @NotNull - public static ComponentType register(Identifier id, @NotNull ComponentType type) { + public static ComponentType register(Identifier id, ComponentType type) { return Registry.register(REGISTRY, id, type); } public static void freezeRegistries() { REGISTRY.freeze(); - SyncHeaderRegistry.HEADERS.freeze(); + SyncPacketHeader.REGISTRY.freeze(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java new file mode 100644 index 0000000000..b9d435e089 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java @@ -0,0 +1,38 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.impl.client; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.Chunk; + +public final class ClientResolution { + public static BlockEntity getBlockEntity(BlockPos pos) { + return MinecraftClient.getInstance().world.getBlockEntity(pos); + } + + public static Entity getEntity(int id) { + return MinecraftClient.getInstance().world.getEntityById(id); + } + + public static Chunk getChunk(ChunkPos pos) { + return MinecraftClient.getInstance().world.getChunk(pos.x, pos.z); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java index ab40c49358..a7a9a17f60 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java @@ -21,16 +21,14 @@ import net.minecraft.util.Identifier; import net.minecraft.util.collection.IdList; import net.minecraft.util.registry.Registry; -import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.networking.api.PacketByteBufs; -import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; public final class ClientRegistryPacket { - @NotNull - public static CompletableFuture handleRegistryPacket(@NotNull PacketByteBuf buf, Registry registry, Consumer> action) { + public static CompletableFuture handleRegistryPacket(PacketByteBuf buf, Registry registry, Consumer> action) { return CompletableFuture.supplyAsync(() -> { var finalEither = createIdList(buf, registry) .ifLeft(action) @@ -41,7 +39,6 @@ public static CompletableFuture handleRegistryPacket(@NotNull }); } - @NotNull public static Either, Identifier> createIdList(PacketByteBuf buf, Registry targetRegistry) { int size = buf.readInt(); IdList ret = new IdList<>(size); // size is dropped @@ -50,12 +47,12 @@ public static Either, Identifier> createIdList(PacketByteBuf buf, Identifier id = buf.readIdentifier(); int rawId = buf.readInt(); // a whole entry is dropped - Optional type = targetRegistry.getOrEmpty(id); - if (type.isEmpty()) { + Maybe type = Maybe.fromOptional(targetRegistry.getOrEmpty(id)); + if (type.isNothing()) { return Either.right(id); } - ret.set(type.get(), rawId); + ret.set(type.unwrap(), rawId); } return Either.left(ret); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java index 2336d44b47..8cfb0afea7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -19,10 +19,9 @@ import net.minecraft.util.collection.IdList; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.impl.sync.header.SyncHeaderRegistry; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.networking.api.client.ClientLoginNetworking; import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking; @@ -47,8 +46,9 @@ public void registerPackets() { ); ClientLoginNetworking.registerGlobalReceiver(PacketIds.HEADERS, (client, handler, buf, listenerAdder) -> - ClientRegistryPacket.handleRegistryPacket(buf, SyncHeaderRegistry.HEADERS, list -> this.headerList = list) + ClientRegistryPacket.handleRegistryPacket(buf, SyncPacketHeader.REGISTRY, list -> this.headerList = list) ); + ClientPlayNetworking.registerGlobalReceiver(PacketIds.SYNC, (client, handler, buf, responseSender) -> SyncPacket.handle(buf, client) ); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java index 796862e8a4..2c81977d36 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java @@ -25,14 +25,15 @@ public class DefaultFloatComponent implements FloatComponent, NbtComponent { private float value; @Nullable - private Runnable saveOperation; + private final Runnable saveOperation; - public DefaultFloatComponent() { - this(0); + public DefaultFloatComponent(@Nullable Runnable saveOperation) { + this(saveOperation, 0); } - public DefaultFloatComponent(float initialValue) { + public DefaultFloatComponent(@Nullable Runnable saveOperation, float initialValue) { this.value = initialValue; + this.saveOperation = saveOperation; } @Override @@ -64,9 +65,4 @@ public NbtFloat write() { public @Nullable Runnable getSaveOperation() { return this.saveOperation; } - - @Override - public void setSaveOperation(@Nullable Runnable runnable) { - this.saveOperation = runnable; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java index de18914d39..b2d54ca954 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java @@ -19,7 +19,6 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtInt; import net.minecraft.network.PacketByteBuf; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.IntegerComponent; import org.quiltmc.qsl.component.api.components.NbtComponent; @@ -28,16 +27,18 @@ public class DefaultIntegerComponent implements IntegerComponent, NbtComponent, SyncedComponent { private int value; @Nullable - private Runnable saveOperation; + private final Runnable saveOperation; @Nullable - private Runnable syncOperation; + private final Runnable syncOperation; - public DefaultIntegerComponent() { - this(0); + public DefaultIntegerComponent(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation) { + this(saveOperation, syncOperation, 0); } - public DefaultIntegerComponent(int defaultValue) { + public DefaultIntegerComponent(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation, int defaultValue) { this.value = defaultValue; + this.saveOperation = saveOperation; + this.syncOperation = syncOperation; } @Override @@ -81,17 +82,12 @@ public NbtInt write() { } @Override - public void setSaveOperation(@Nullable Runnable runnable) { - this.saveOperation = runnable; - } - - @Override - public void writeToBuf(@NotNull PacketByteBuf buf) { + public void writeToBuf(PacketByteBuf buf) { buf.writeInt(this.value); } @Override - public void readFromBuf(@NotNull PacketByteBuf buf) { + public void readFromBuf(PacketByteBuf buf) { this.value = buf.readInt(); } @@ -99,9 +95,4 @@ public void readFromBuf(@NotNull PacketByteBuf buf) { public @Nullable Runnable getSyncOperation() { return this.syncOperation; } - - @Override - public void setSyncOperation(@Nullable Runnable runnable) { - this.syncOperation = runnable; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java index 4d3c280525..45ea522943 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java @@ -19,7 +19,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.collection.DefaultedList; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.components.InventoryComponent; import org.quiltmc.qsl.component.api.components.SyncedComponent; @@ -31,16 +30,20 @@ public class DefaultInventoryComponent implements InventoryComponent, SyncedComponent { private final DefaultedList stacks; @Nullable - private Runnable saveOperation; + private final Runnable saveOperation; @Nullable - private Runnable syncOperation; + private final Runnable syncOperation; - public DefaultInventoryComponent(int size) { + public DefaultInventoryComponent(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation, int size) { this.stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); + this.saveOperation = saveOperation; + this.syncOperation = syncOperation; } - public DefaultInventoryComponent(Supplier> stacks) { + public DefaultInventoryComponent(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation, Supplier> stacks) { + this.syncOperation = syncOperation; this.stacks = stacks.get(); + this.saveOperation = saveOperation; } @Override @@ -54,8 +57,8 @@ public DefaultedList getStacks() { } @Override - public void setSaveOperation(@Nullable Runnable runnable) { - this.saveOperation = runnable; + public @Nullable Runnable getSyncOperation() { + return this.syncOperation; } @Override @@ -71,26 +74,16 @@ public boolean equals(Object o) { } @Override - public void writeToBuf(@NotNull PacketByteBuf buf) { + public void writeToBuf(PacketByteBuf buf) { NetworkCodec.INVENTORY.encode(buf, this.stacks); } @Override - public void readFromBuf(@NotNull PacketByteBuf buf) { - NetworkCodec.INVENTORY.decode(buf).ifPresent(itemStacks -> { + public void readFromBuf(PacketByteBuf buf) { + NetworkCodec.INVENTORY.decode(buf).ifJust(itemStacks -> { for (int i = 0; i < itemStacks.size(); i++) { this.stacks.set(i, itemStacks.get(i)); } }); } - - @Override - public @Nullable Runnable getSyncOperation() { - return this.syncOperation; - } - - @Override - public void setSyncOperation(@Nullable Runnable runnable) { - this.syncOperation = runnable; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java new file mode 100644 index 0000000000..02990fa384 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -0,0 +1,119 @@ +package org.quiltmc.qsl.component.impl.container; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.*; +import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.components.SyncedComponent; +import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; +import org.quiltmc.qsl.component.impl.util.StringConstants; + +import java.util.*; +import java.util.function.Function; + +public abstract class AbstractComponentContainer implements ComponentContainer { + protected final ContainerOperations operations; + protected final List> nbtComponents; + protected final Maybe>> ticking; + protected final Maybe>> pendingSync; + protected final Maybe syncContext; + + public AbstractComponentContainer(Runnable saveOperation, + boolean ticking, + @Nullable SyncPacket.SyncContext syncContext) { + this.ticking = ticking ? Maybe.just(new ArrayList<>()) : Maybe.nothing(); + this.nbtComponents = new ArrayList<>(); + this.syncContext = Maybe.wrap(syncContext); + this.pendingSync = this.syncContext.map(it -> new ArrayDeque<>()); + this.operations = new ContainerOperations( + saveOperation, + type -> () -> this.pendingSync.ifJust(pending -> pending.add(type)) + ); + } + + @Override + public void writeNbt(NbtCompound providerRootNbt) { + var rootQslNbt = new NbtCompound(); + this.nbtComponents.forEach(type -> this.expose(type) + .map(it -> ((NbtComponent) it)) + .ifJust(nbtComponent -> NbtComponent.writeTo(rootQslNbt, nbtComponent, type.id())) + ); + + if (!rootQslNbt.isEmpty()) { + providerRootNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); + } + } + + @Override + public void readNbt(NbtCompound providerRootNbt) { + var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); + + rootQslNbt.getKeys().stream() + .map(Identifier::new) + .map(Components.REGISTRY::get) + .filter(Objects::nonNull) + .forEach(type -> this.expose(type) + .map(component -> ((NbtComponent) component)) + .ifJust(component -> NbtComponent.readFrom(component, type.id(), rootQslNbt)) + ); + } + + @Override + public void tick(ComponentProvider provider) { + this.ticking.ifJust(componentTypes -> componentTypes.forEach(type -> + this.expose(type) + .map(it -> ((TickingComponent) it)) + .ifJust(tickingComponent -> tickingComponent.tick(provider))) + ).ifNothing(() -> { + throw ErrorUtil.illegalState("Attempted to tick a non-ticking container").get(); + }); + + this.sync(provider); + } + + @Override + public void sync(ComponentProvider provider) { + this.syncContext.ifJust(ctx -> SyncPacket.syncFromQueue( + this.pendingSync.unwrap(), + ctx, + type -> (SyncedComponent) this.expose(type).unwrap(), + provider + )).ifNothing(() -> { + throw ErrorUtil.illegalState("Attempted to sync a non-syncable container!").get(); + }); + } + + protected abstract void addComponent(ComponentType type, Component component); + + protected COMP initializeComponent(ComponentEntry componentEntry) { + ComponentType type = componentEntry.type(); + Runnable syncOperation = this.operations.syncOperationFactory().apply(type); + + COMP component = componentEntry.apply(this.operations.saveOperation(), syncOperation); + + if (component instanceof NbtComponent) { + this.nbtComponents.add(type); + } + + this.ticking.ifJust(componentTypes -> { + if (component instanceof TickingComponent) { + componentTypes.add(type); + } + }); + + this.addComponent(type, component); + + return component; + } + + public record ContainerOperations(Runnable saveOperation, + Function, Runnable> syncOperationFactory) { + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java new file mode 100644 index 0000000000..9a2e6e7666 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java @@ -0,0 +1,60 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.impl.container; + +import net.minecraft.nbt.NbtCompound; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.api.ComponentType; + +public final class EmptyComponentContainer implements ComponentContainer { + public static final EmptyComponentContainer INSTANCE = new EmptyComponentContainer(); + + public static final ComponentContainer.Factory FACTORY = + (provider, injections, saveOperation, ticking, syncContext) -> INSTANCE; + + private EmptyComponentContainer() { + + } + + @Override + public Maybe expose(ComponentType type) { + return Maybe.nothing(); + } + + @Override + public void writeNbt(NbtCompound providerRootNbt) { + + } + + @Override + public void readNbt(NbtCompound providerRootNbt) { + + } + + @Override + public void tick(ComponentProvider provider) { + + } + + @Override + public void sync(ComponentProvider provider) { + + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index df75977600..71aeb10c00 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -16,207 +16,77 @@ package org.quiltmc.qsl.component.impl.container; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.*; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.components.SyncedComponent; -import org.quiltmc.qsl.component.api.components.TickingComponent; -import org.quiltmc.qsl.component.api.event.ComponentEvents; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; -import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.Lazy; -import org.quiltmc.qsl.component.impl.util.StringConstants; -import java.util.*; -import java.util.function.Supplier; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Queue; -public class LazyComponentContainer implements ComponentContainer { +public class LazyComponentContainer extends AbstractComponentContainer { + public static final ComponentContainer.Factory FACTORY = + (provider, injections, saveOperation, ticking, syncContext) -> + new LazyComponentContainer(provider, saveOperation, ticking, syncContext); private final IdentityHashMap, Lazy> components; - private final List> nbtComponents; - @Nullable - private final List> tickingComponents; - @Nullable - private final Runnable saveOperation; - @Nullable - private final SyncPacket.SyncContext syncContext; - @Nullable - private final Queue> pendingSync; protected LazyComponentContainer( - @NotNull ComponentProvider provider, + ComponentProvider provider, @Nullable Runnable saveOperation, boolean ticking, @Nullable SyncPacket.SyncContext syncContext ) { - this.saveOperation = saveOperation; - this.syncContext = syncContext; - this.nbtComponents = new ArrayList<>(); - this.tickingComponents = ticking ? new ArrayList<>() : null; - this.pendingSync = this.syncContext != null ? new ArrayDeque<>() : null; + super(saveOperation, ticking, syncContext); this.components = this.initializeComponents(provider); } - public static Optional builder(T obj) { - if (!(obj instanceof ComponentProvider provider)) { - return Optional.empty(); - } - - return Optional.of(new Builder(provider)); - } - - public static void move(@NotNull LazyComponentContainer from, @NotNull LazyComponentContainer into) { + public static void move(LazyComponentContainer from, LazyComponentContainer into) { from.components.forEach((id, componentLazy) -> componentLazy.ifPresent(component -> { into.components.put(id, componentLazy); // Directly overriding our value. })); into.nbtComponents.addAll(from.nbtComponents); - if (into.pendingSync != null && from.pendingSync != null) { - into.pendingSync.addAll(from.pendingSync); - } - - if (into.tickingComponents != null && from.tickingComponents != null) { - into.tickingComponents.addAll(from.tickingComponents); - } + into.pendingSync.ifJust(intoPending -> from.pendingSync.ifJust(intoPending::addAll)); + into.ticking.ifJust(intoTicking -> from.ticking.ifJust(intoTicking::addAll)); from.components.clear(); from.nbtComponents.clear(); + from.ticking.ifJust(List::clear); + from.pendingSync.ifJust(Queue::clear); } @Override - public Optional expose(ComponentType id) { - return Optional.ofNullable(this.components.get(id)).map(Lazy::get); + public Maybe expose(ComponentType id) { + return Maybe.wrap(this.components.get(id)).map(Lazy::get); } @Override - public void writeNbt(@NotNull NbtCompound providerRootNbt) { - var rootQslNbt = new NbtCompound(); - this.nbtComponents.forEach(type -> this.components.get(type).ifPresent(component -> - NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, type.id()) - )); - - if (!rootQslNbt.isEmpty()) { - providerRootNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); - } - } + protected void addComponent(ComponentType type, Component component) { - @Override - public void readNbt(@NotNull NbtCompound providerRootNbt) { - var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); - - rootQslNbt.getKeys().stream() - .map(Identifier::tryParse) - .filter(Objects::nonNull)// TODO: Looks a bit suspicous... - .map(Components.REGISTRY::get) - .filter(Objects::nonNull) - .forEach(type -> this.expose(type).ifPresent(component -> { - if (component instanceof NbtComponent nbtComponent) { - NbtComponent.readFrom(nbtComponent, type.id(), rootQslNbt); - } - })); - } - - @Override - public void tick(@NotNull ComponentProvider provider) { - if (this.tickingComponents == null) { - throw ErrorUtil.illegalState("Attempted to tick a non-ticking component container!").get(); - } - this.tickingComponents.stream() - .map(this::expose) - .map(Optional::orElseThrow) - .map(it -> ((TickingComponent) it)) - .forEach(tickingComponent -> tickingComponent.tick(provider)); - - // Sync any queued components - this.sync(provider); - } - - @SuppressWarnings("ConstantConditions") // pendingSync will be null if syncContext is null and the other way around - @Override - public void sync(@NotNull ComponentProvider provider) { - if (this.syncContext == null) { - throw ErrorUtil.illegalState("Cannot sync a non-syncable component container! Make sure you provide a context!").get(); - } - SyncPacket.syncFromQueue( - this.pendingSync, - this.syncContext, - type -> ((SyncedComponent) this.components.get(type).get()), - provider - ); } private IdentityHashMap, Lazy> initializeComponents(ComponentProvider provider) { var map = new IdentityHashMap, Lazy>(); - ComponentsImpl.getInjections(provider).forEach(type -> map.put(type, this.createLazy(type))); - ComponentEvents.DYNAMIC_INJECT.invoker().onInject(provider, type -> map.put(type, this.createLazy(type))); + ComponentsImpl.getInjections(provider).forEach(injection -> map.put(injection.type(), this.createLazy(injection))); return map; } - private Lazy createLazy(ComponentType type) { - if (type.isStatic()) { - Component singleton = type.create(); - if (singleton instanceof TickingComponent && this.tickingComponents != null) { - this.tickingComponents.add(type); - } - - return Lazy.filled(singleton); - } - - return Lazy.of(() -> { - Component component = type.create(); - if (component instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(type); - nbtComponent.setSaveOperation(this.saveOperation); - } - - if (component instanceof TickingComponent && this.tickingComponents != null) { - this.tickingComponents.add(type); - } - - if (component instanceof SyncedComponent syncedComponent && this.syncContext != null && this.pendingSync != null /* also not needed */) { - syncedComponent.setSyncOperation(() -> this.pendingSync.add(type)); - } - - return component; - }); - } - - public static class Builder { - - private final ComponentProvider provider; - @Nullable - private Runnable saveOperation; - private boolean ticking; - private SyncPacket.SyncContext syncContext; - - private Builder(ComponentProvider provider) { - this.provider = provider; - this.ticking = false; - this.saveOperation = null; - } - - public Builder saving(Runnable saveOperation) { - this.saveOperation = saveOperation; - return this; - } + private Lazy createLazy(ComponentEntry componentEntry) { + ComponentType type = componentEntry.type(); - public Builder ticking() { - this.ticking = true; - return this; - } + if (type.isStatic() || type.isInstant()) { + var component = this.initializeComponent(componentEntry); - public Builder syncing(@NotNull SyncPacketHeader header, Supplier> playerGenerator) { - this.syncContext = new SyncPacket.SyncContext(header, playerGenerator); - return this; + return Lazy.filled(component); } - public LazyComponentContainer build() { - return new LazyComponentContainer(this.provider, this.saveOperation, this.ticking, this.syncContext); - } + return Lazy.of(() -> this.initializeComponent(componentEntry)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index 993b476fa8..41b68db5a4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -16,130 +16,52 @@ package org.quiltmc.qsl.component.impl.container; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.*; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.components.SyncedComponent; -import org.quiltmc.qsl.component.api.components.TickingComponent; -import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; -import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import org.quiltmc.qsl.component.impl.util.StringConstants; -import java.util.*; -import java.util.function.Predicate; +import java.util.HashMap; +import java.util.Map; // Suggestion from Technici4n from fabric. May help improve performance and memory footprint once done. -public class OnAccessComponentContainer implements ComponentContainer { +public class OnAccessComponentContainer extends AbstractComponentContainer { private final Map, Component> components; - private final Set> supportedTypes; - private final Set> tickingComponents; - private final Set> nbtComponents; - @Nullable - private final Runnable saveOperation; - @Nullable - private final Queue> pendingSync; - @Nullable - private final SyncPacket.SyncContext syncContext; - private OnAccessComponentContainer(@NotNull ComponentProvider provider, @Nullable Runnable saveOperation, @Nullable SyncPacket.SyncContext syncContext) { - this.syncContext = syncContext; - this.saveOperation = saveOperation; - this.nbtComponents = new HashSet<>(); - this.tickingComponents = new HashSet<>(); - this.pendingSync = this.syncContext != null ? new ArrayDeque<>() : null; - this.supportedTypes = ComponentsImpl.getInjections(provider); - this.components = this.getInitialComponents(); + private OnAccessComponentContainer(ComponentProvider provider, + @Nullable Runnable saveOperation, + boolean ticking, + @Nullable SyncPacket.SyncContext syncContext) { + super(saveOperation, ticking, syncContext); + this.components = this.getInitialComponents(provider); } @Override - public Optional expose(ComponentType type) { - return Optional.ofNullable(this.components.get(type)) - .or(() -> this.supportedTypes.contains(type) ? Optional.of(this.createComponent(type)) : Optional.empty()); + public Maybe expose(ComponentType type) { + return Maybe.wrap(this.components.get(type)) + .or(() -> this.supports(type) ? Maybe.just(this.initializeComponent(this.getInjection(type))) : Maybe.nothing()); } @Override - public void writeNbt(@NotNull NbtCompound providerRootNbt) { - if (this.nbtComponents.isEmpty()) { - return; - } - - var rootQslNbt = new NbtCompound(); - - this.nbtComponents.forEach(type -> { - var component = (NbtComponent) this.components.get(type); - NbtComponent.writeTo(rootQslNbt, component, type.id()); - }); - - if (!rootQslNbt.isEmpty()) { - providerRootNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); - } - } - - @Override - public void readNbt(@NotNull NbtCompound providerRootNbt) { - if (providerRootNbt.isEmpty() || !providerRootNbt.contains(StringConstants.COMPONENT_ROOT)) { - return; - } - - var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); - - rootQslNbt.getKeys().stream() - .map(Identifier::tryParse) - .filter(Objects::nonNull) - .forEach(id -> this.expose(Components.REGISTRY.get(id)) - .map(it -> ((NbtComponent) it)) - .ifPresent(nbtComponent -> NbtComponent.readFrom(nbtComponent, id, rootQslNbt)) - ); + protected void addComponent(ComponentType type, Component component) { + this.components.put(type, component); } - @Override - public void tick(@NotNull ComponentProvider provider) { - this.tickingComponents.stream() - .map(this.components::get) - .map(it -> ((TickingComponent) it)) - .forEach(tickingComponent -> tickingComponent.tick(provider)); - } - - - @SuppressWarnings("ConstantConditions") // pendingSync will be null if syncContext is null and the other way around - @Override - public void sync(@NotNull ComponentProvider provider) { - if (this.syncContext == null) { - throw ErrorUtil.illegalState("Cannot sync a non-syncable component container! Make sure you provide a context!").get(); - } - SyncPacket.syncFromQueue( - this.pendingSync, - this.syncContext, - type -> ((SyncedComponent) this.components.get(type)), - provider - ); + private ComponentEntry getInjection(ComponentType type) { + throw new UnsupportedOperationException("TODO: NOT IMPLEMENTED"); } - private Map, Component> getInitialComponents() { - return this.supportedTypes.stream() // TODO: We can cache this value. - .filter(((Predicate>) ComponentType::isStatic).or(ComponentType::isInstant)) - .collect(IdentityHashMap::new, (map, type) -> map.put(type, this.createComponent(type)), Map::putAll); + private boolean supports(ComponentType type) { + throw new UnsupportedOperationException("TODO: NOT IMPLEMENTED"); } - private Component createComponent(@NotNull ComponentType type) { - var component = type.create(); - if (component instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(type); - nbtComponent.setSaveOperation(this.saveOperation); - } - - if (component instanceof TickingComponent) { - this.tickingComponents.add(type); - } - - if (component instanceof SyncedComponent synced && this.pendingSync != null) { - synced.setSyncOperation(() -> this.pendingSync.add(type)); - } - - return component; + private Map, Component> getInitialComponents(ComponentProvider provider) { +// return this.supportedTypes.stream() // TODO: We can cache this value. +// .filter(((Predicate>) ComponentType::isStatic).or(ComponentType::isInstant)) +// .collect(IdentityHashMap::new, (map, type) -> map.put(type, this.createComponent(type)), Map::putAll); + return new HashMap<>(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 35c6731293..18d343ebf6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -16,167 +16,46 @@ package org.quiltmc.qsl.component.impl.container; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.*; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.components.SyncedComponent; -import org.quiltmc.qsl.component.api.components.TickingComponent; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import org.quiltmc.qsl.component.impl.util.StringConstants; -import java.util.*; -import java.util.function.Supplier; +import java.util.IdentityHashMap; +import java.util.Map; import java.util.stream.Stream; -public class SimpleComponentContainer implements ComponentContainer { - private final IdentityHashMap, Component> components; - private final List> nbtComponents; - private final List> tickingComponents; - @Nullable - private final SyncPacket.SyncContext syncContext; - @Nullable - private final Queue> pendingSync; - - protected SimpleComponentContainer(@Nullable Runnable saveOperation, SyncPacket.@Nullable SyncContext syncContext, Stream> types) { +public class SimpleComponentContainer extends AbstractComponentContainer { + public static final ComponentContainer.Factory FACTORY = + (provider, injections, saveOperation, ticking, syncContext) -> new SimpleComponentContainer( + saveOperation, ticking, syncContext, injections.get().stream() + ); + private final Map, Component> components; + + protected SimpleComponentContainer(Runnable saveOperation, + boolean ticking, + @Nullable SyncPacket.SyncContext syncContext, + Stream> types) { + super(saveOperation, ticking, syncContext); this.components = new IdentityHashMap<>(); - this.nbtComponents = new ArrayList<>(); - this.tickingComponents = new ArrayList<>(); - this.syncContext = syncContext; - this.pendingSync = this.syncContext != null ? new ArrayDeque<>() : null; - - types.forEach(type -> this.initializeComponent(saveOperation, type)); + types.forEach(this::initializeComponent); types.close(); } - @Contract("-> new") - @NotNull - public static Builder builder() { - return new Builder(); - } - @Override - public Optional expose(ComponentType type) { - return Optional.ofNullable(this.components.get(type)); + public Maybe expose(ComponentType type) { + return Maybe.wrap(this.components.get(type)); } @Override - public void writeNbt(@NotNull NbtCompound providerRootNbt) { - var rootQslNbt = new NbtCompound(); - this.nbtComponents.forEach(id -> this.expose(id) - .ifPresent(component -> NbtComponent.writeTo(rootQslNbt, (NbtComponent) component, id.id())) - ); - - if (!rootQslNbt.isEmpty()) { - providerRootNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); - } - } - - @Override - public void readNbt(@NotNull NbtCompound providerRootNbt) { - var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); - - if (rootQslNbt.isEmpty()) { - return; - } - - rootQslNbt.getKeys().stream() - .map(Identifier::tryParse) - .filter(Objects::nonNull) - .map(Components.REGISTRY::get) - .filter(Objects::nonNull) - .forEach(id -> this.expose(id) - .ifPresent(component -> NbtComponent.readFrom((NbtComponent) component, id.id(), rootQslNbt)) - ); - } - - @Override - public void tick(@NotNull ComponentProvider provider) { - this.tickingComponents.stream() - .map(this.components::get) - .map(it -> ((TickingComponent) it)) - .forEach(tickingComponent -> tickingComponent.tick(provider)); - - this.sync(provider); - } - - @SuppressWarnings("ConstantConditions") // pendingSync will be null if syncContext is null and the other way around - @Override - public void sync(@NotNull ComponentProvider provider) { - if (this.syncContext == null) { - throw ErrorUtil.illegalState("Cannot sync a non-syncable component container! Make sure you provide a context!").get(); - } - SyncPacket.syncFromQueue( - this.pendingSync, - this.syncContext, - type -> ((SyncedComponent) this.components.get(type)), - provider - ); - } - - private void initializeComponent(@Nullable Runnable saveOperation, @NotNull ComponentType type) { - Component component = type.create(); - this.components.put(type, component); - - if (component instanceof NbtComponent nbtComponent) { - this.nbtComponents.add(type); - nbtComponent.setSaveOperation(saveOperation); - } - - if (component instanceof TickingComponent) { - this.tickingComponents.add(type); - } - - if (component instanceof SyncedComponent synced && this.pendingSync != null) { - synced.setSyncOperation(() -> this.pendingSync.add(type)); - } - } - - public static class Builder { - @NotNull - private final List> types; - @Nullable - private Runnable saveOperation; - @Nullable - private SyncPacket.SyncContext syncContext; - - private Builder() { - this.types = new ArrayList<>(); - } - - @NotNull - public Builder setSaveOperation(@NotNull Runnable runnable) { - this.saveOperation = runnable; - return this; - } - - @NotNull - public Builder syncing(SyncPacketHeader header, Supplier> supplier) { - this.syncContext = new SyncPacket.SyncContext(header, supplier); - return this; - } - - @NotNull - public Builder add(ComponentType type) { - this.types.add(type); - return this; - } - - @NotNull - public Builder add(ComponentType... types) { - this.types.addAll(Arrays.asList(types)); - return this; - } - - @NotNull - public SimpleComponentContainer build() { - return new SimpleComponentContainer(this.saveOperation, this.syncContext, this.types.stream()); + protected void addComponent(ComponentType type, Component component) { + Component result = this.components.put(type, component); + if (result != null) { + throw ErrorUtil.illegalState("Attempted to override a component on a simple container!").get(); } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java index ee08acd438..449abf0c04 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java @@ -17,9 +17,8 @@ package org.quiltmc.qsl.component.impl.event; import net.minecraft.server.MinecraftServer; -import net.minecraft.world.SaveProperties; -import net.minecraft.world.level.LevelProperties; import org.quiltmc.qsl.base.api.event.ListenerPhase; +import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.quiltmc.qsl.lifecycle.api.event.ServerTickEvents; @ListenerPhase( @@ -29,9 +28,6 @@ public class ServerTickEventListener implements ServerTickEvents.End { @Override public void endServerTick(MinecraftServer server) { - SaveProperties saveProperties = server.getSaveProperties(); - if (saveProperties instanceof LevelProperties levelProperties) { - levelProperties.getComponentContainer().tick(levelProperties); - } + server.getComponentContainer().tick(server); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java new file mode 100644 index 0000000000..b189c88109 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java @@ -0,0 +1,30 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.impl.injection; + +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; + +public record ComponentEntry(ComponentType type, Component.Factory factory) { + public ComponentEntry(ComponentType type) { + this(type, type); + } + + public C apply(Runnable saveOperation, Runnable syncOperation) { + return this.factory.create(saveOperation, syncOperation); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java new file mode 100644 index 0000000000..d9706aad05 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java @@ -0,0 +1,75 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.impl.injection.manager; + +import net.minecraft.util.Util; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.*; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; + +import java.util.*; +import java.util.stream.Stream; + +public abstract class InjectionManager

{ + private final Map>> injections = new HashMap<>(); + private final Map, List> cache = new IdentityHashMap<>(); + + public void inject(P predicate, ComponentEntry componentEntry) { + ComponentType type = componentEntry.type(); + if (Components.REGISTRY.get(type.id()) == null) { + throw ErrorUtil.illegalArgument("The target id %s does not match any registered component", type).get(); + } + + if (this.injections.containsKey(predicate)) { + List> componentEntries = this.injections.get(predicate); + if (componentEntries.stream().anyMatch(applied -> applied.type() == type)) { + throw ErrorUtil.illegalArgument( + "Cannot inject the predicate %s with id %s more than once! Consider creating a new component type!", + predicate, type.id() + ).get(); + } + + componentEntries.add(componentEntry); + } else { + this.injections.put(predicate, Util.make(new ArrayList<>(), injections -> injections.add(componentEntry))); + } + this.cache.clear(); + } + + public abstract List> getInjections(ComponentProvider provider); + + protected Stream>>> streamEntries() { + return this.injections.entrySet().stream(); + } + + protected Maybe> getCache(Class clazz) { + if (!this.cache.containsKey(clazz)) { + return Maybe.nothing(); + } + + return Maybe.just(this.cache.get(clazz)); + } + + protected void record(Class providerClass, List injections) { + if (this.cache.put(providerClass, Util.make(new ArrayList<>(), list -> list.addAll(injections))) != null) { + // If there was a value there, it means we attempted an override, and so we throw. + throw ErrorUtil.illegalArgument("Cannot register cache twice for class %s", providerClass).get(); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java new file mode 100644 index 0000000000..385e3be8fc --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java @@ -0,0 +1,45 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.impl.injection.manager.cached; + +import org.quiltmc.qsl.component.api.CachedInjectionPredicate; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.injection.manager.InjectionManager; + +import java.util.List; +import java.util.Objects; + +public class CachedInjectionManager extends InjectionManager> { + @Override + public List> getInjections(ComponentProvider provider) { + Class providerClass = provider.getClass(); + return this.getCache(providerClass).unwrapOrGet(() -> { + List> componentEntries = this.initInjections(providerClass); + this.record(providerClass, componentEntries); + return componentEntries; + }); + } + + private List> initInjections(Class providerClass) { + return this.streamEntries() + .map(entry -> entry.getKey().isClassValid(providerClass) ? entry.getValue() : null) + .filter(Objects::nonNull) + .flatMap(List::stream) + .toList(); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java new file mode 100644 index 0000000000..8bdf35981b --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java @@ -0,0 +1,59 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.impl.injection.manager.dynamic; + +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.api.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.injection.manager.InjectionManager; +import org.quiltmc.qsl.base.api.util.Maybe; + +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class DynamicInjectionManager extends InjectionManager { + @Override + public List> getInjections(ComponentProvider provider) { + Class providerClass = provider.getClass(); + return this.getCache(providerClass).or(() -> { + var injections = this.initInjections(providerClass); + this.record(providerClass, injections); + return Maybe.just(injections); + }).unwrap().stream() + .map(dynamicInjection -> dynamicInjection.test(provider) ? dynamicInjection.componentEntries() : null) + .filter(Objects::nonNull) + .flatMap(List::stream) + .collect(Collectors.toList()); + } + + private List initInjections(Class clazz) { + return this.streamEntries() + .filter(entry -> entry.getKey().isClassValid(clazz)) + .map(entry -> new DynamicInjection(entry.getKey(), entry.getValue())) + .toList(); + } + + public record DynamicInjection(DynamicInjectionPredicate predicate, + List> componentEntries) implements Predicate { + @Override + public boolean test(ComponentProvider provider) { + return this.predicate.canInject(provider); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java similarity index 77% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java index b6851bf38b..791e21b082 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java @@ -14,16 +14,16 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.predicates; +package org.quiltmc.qsl.component.impl.injection.predicate.cached; -import org.quiltmc.qsl.component.api.ComponentInjectionPredicate; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.CachedInjectionPredicate; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import java.util.Arrays; import java.util.Objects; -public class ClassInjectionPredicate implements ComponentInjectionPredicate { +public class ClassInjectionPredicate implements CachedInjectionPredicate { protected final Class clazz; public ClassInjectionPredicate(Class clazz) { @@ -31,7 +31,7 @@ public ClassInjectionPredicate(Class clazz) { this.clazz = clazz; } else { throw ErrorUtil.illegalArgument( - "Cannot create an injection predicate for a class that isn't a ComponentProvider" + "Cannot create an injection predicate for a class that doesn't implement ComponentProvider" ).get(); } } @@ -42,8 +42,8 @@ private static boolean implementsComponentProvider(Class clazz) { } @Override - public boolean canInject(ComponentProvider provider) { - return provider.getClass() == clazz; + public boolean isClassValid(Class clazz) { + return clazz == this.clazz; } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java similarity index 84% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java index ee0004e7f8..e227061e05 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/FilteredInheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.predicates; - -import org.quiltmc.qsl.component.api.ComponentProvider; +package org.quiltmc.qsl.component.impl.injection.predicate.cached; import java.util.Objects; import java.util.Set; @@ -48,7 +46,7 @@ public String toString() { } @Override - public boolean canInject(ComponentProvider provider) { - return !this.exceptions.contains(provider.getClass()) && super.canInject(provider.getClass()); + public boolean isClassValid(Class clazz) { + return !this.exceptions.contains(clazz) && this.clazz == clazz || (clazz != null && this.isClassValid(clazz.getSuperclass())); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/InheritedInjectionPredicate.java similarity index 76% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/InheritedInjectionPredicate.java index 9de5fd31bc..9bfa501fb0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/InheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/InheritedInjectionPredicate.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.predicates; - -import org.quiltmc.qsl.component.api.ComponentProvider; +package org.quiltmc.qsl.component.impl.injection.predicate.cached; import java.util.Objects; @@ -26,8 +24,8 @@ public InheritedInjectionPredicate(Class clazz) { } @Override - public boolean canInject(ComponentProvider provider) { - return this.canInject(provider.getClass()); + public boolean isClassValid(Class clazz) { + return this.clazz == clazz || (clazz != null && this.isClassValid(clazz.getSuperclass())); } @Override @@ -44,8 +42,4 @@ public boolean equals(Object o) { public String toString() { return "InheritedInjectionPredicate{clazz=" + this.clazz + '}'; } - - public boolean canInject(Class current) { - return this.clazz == current || (current != null && canInject(current.getSuperclass())); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/RedirectedInjectionPredicate.java similarity index 84% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/RedirectedInjectionPredicate.java index c584a27e3e..a96580d946 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/predicates/RedirectedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/RedirectedInjectionPredicate.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.predicates; - -import org.quiltmc.qsl.component.api.ComponentProvider; +package org.quiltmc.qsl.component.impl.injection.predicate.cached; import java.util.Objects; import java.util.Set; @@ -30,8 +28,8 @@ public RedirectedInjectionPredicate(Class clazz, Set> redirections) } @Override - public boolean canInject(ComponentProvider provider) { - return super.canInject(provider) || this.redirections.contains(provider.getClass()); + public boolean isClassValid(Class clazz) { + return super.isClassValid(clazz) || this.redirections.contains(clazz); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java new file mode 100644 index 0000000000..83fad5bb81 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java @@ -0,0 +1,37 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.impl.injection.predicate.dynamic; + +import org.quiltmc.qsl.component.api.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; + +import java.util.function.Predicate; + +public class DynamicClassInjectionPredicate

extends ClassInjectionPredicate implements DynamicInjectionPredicate { + private final Predicate

predicate; + + public DynamicClassInjectionPredicate(Class

clazz, Predicate

predicate) { + super(clazz); + this.predicate = predicate; + } + + @Override + public boolean canInject(ComponentProvider provider) { + return this.predicate.test((P) provider); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java index 5f982379a1..e2d17e4968 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java @@ -19,7 +19,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerLoginNetworkHandler; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.impl.sync.header.SyncHeaderRegistry; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; import org.quiltmc.qsl.component.impl.sync.packet.RegistryPacket; import org.quiltmc.qsl.networking.api.PacketSender; @@ -52,7 +52,8 @@ public void registerPackets() { @Override public void onLoginStart(ServerLoginNetworkHandler handler, MinecraftServer server, PacketSender sender, ServerLoginNetworking.LoginSynchronizer synchronizer) { + // TODO: Maybe use regitry sync for this?! sender.sendPacket(PacketIds.TYPES, RegistryPacket.createRegistryPacket(Components.REGISTRY)); - sender.sendPacket(PacketIds.HEADERS, RegistryPacket.createRegistryPacket(SyncHeaderRegistry.HEADERS)); + sender.sendPacket(PacketIds.HEADERS, RegistryPacket.createRegistryPacket(SyncPacketHeader.REGISTRY)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java index ca2d4cccc8..2e83cd9539 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java @@ -23,7 +23,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; -import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.networking.api.PlayerLookup; import java.util.Collection; @@ -31,23 +30,23 @@ import java.util.Objects; public final class SyncPlayerList { - @NotNull public static Collection create(World world, BlockPos pos) { return world.isClient ? List.of() : PlayerLookup.tracking((ServerWorld) world, pos); } - @NotNull public static Collection create(Entity entity) { return entity.getWorld().isClient ? List.of() : PlayerLookup.tracking(entity); } - @NotNull public static Collection create(BlockEntity blockEntity) { return Objects.requireNonNull(blockEntity.getWorld()).isClient ? List.of() : PlayerLookup.tracking(blockEntity); } - @NotNull public static Collection create(WorldChunk chunk) { return chunk.getWorld().isClient ? List.of() : PlayerLookup.tracking((ServerWorld) chunk.getWorld(), chunk.getPos()); } + + public static Collection create(ServerWorld world) { + return PlayerLookup.world(world); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java index 0101f46f84..f9b580fc8d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java @@ -16,8 +16,8 @@ package org.quiltmc.qsl.component.impl.sync.codec; +import com.mojang.datafixers.util.Pair; import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; @@ -27,51 +27,38 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.chunk.Chunk; -import org.jetbrains.annotations.NotNull; +import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.impl.client.ClientResolution; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; import java.util.List; -import java.util.Optional; +import java.util.Map; import java.util.UUID; import java.util.function.BiConsumer; import java.util.function.Function; +import java.util.function.IntFunction; -public record NetworkCodec(@NotNull BiConsumer encoder, - @NotNull Function decoder) { - public static final NetworkCodec BLOCK_POS = new NetworkCodec<>( - PacketByteBuf::writeBlockPos, PacketByteBuf::readBlockPos +public record NetworkCodec(BiConsumer encoder, + Function decoder) { + public static final NetworkCodec BYTE = new NetworkCodec<>( + (buf, aByte) -> buf.writeByte(aByte), PacketByteBuf::readByte ); public static final NetworkCodec INT = new NetworkCodec<>( PacketByteBuf::writeInt, PacketByteBuf::readInt ); - public static final NetworkCodec CHUNK_POS = new NetworkCodec<>( - PacketByteBuf::writeChunkPos, PacketByteBuf::readChunkPos + public static final NetworkCodec SHORT = new NetworkCodec<>( + (buf, aShort) -> buf.writeShort(aShort), PacketByteBuf::readShort + ); + public static final NetworkCodec LONG = new NetworkCodec<>( + PacketByteBuf::writeLong, PacketByteBuf::readLong ); public static final NetworkCodec FLOAT = new NetworkCodec<>( PacketByteBuf::writeFloat, PacketByteBuf::readFloat ); - // TODO: Handle the cases where MinecraftClient.getInstance().world is null - public static final NetworkCodec BLOCK_ENTITY = new NetworkCodec<>( - (buf, blockEntity) -> buf.writeBlockPos(blockEntity.getPos()), - buf -> MinecraftClient.getInstance().world.getBlockEntity(buf.readBlockPos()) - ); - public static final NetworkCodec ENTITY = new NetworkCodec<>( - (buf, entity) -> buf.writeInt(entity.getId()), - buf -> MinecraftClient.getInstance().world.getEntityById(buf.readInt()) - ); - public static final NetworkCodec CHUNK = new NetworkCodec<>( - (buf, chunk) -> buf.writeChunkPos(chunk.getPos()), - buf -> CHUNK_POS.decode(buf) - .map(chunkPos -> MinecraftClient.getInstance().world.getChunk(chunkPos.x, chunkPos.z)) - .orElseThrow() - ); - public static final NetworkCodec ITEM_STACK = new NetworkCodec<>( - PacketByteBuf::writeItemStack, PacketByteBuf::readItemStack - ); - public static final NetworkCodec LONG = new NetworkCodec<>( - PacketByteBuf::writeLong, PacketByteBuf::readLong + public static final NetworkCodec DOUBLE = new NetworkCodec<>( + PacketByteBuf::writeDouble, PacketByteBuf::readDouble ); public static final NetworkCodec STRING = new NetworkCodec<>( PacketByteBuf::writeString, PacketByteBuf::readString @@ -79,33 +66,42 @@ public record NetworkCodec(@NotNull BiConsumer encoder, public static final NetworkCodec IDENTIFIER = new NetworkCodec<>( PacketByteBuf::writeIdentifier, PacketByteBuf::readIdentifier ); - public static final NetworkCodec> INVENTORY = - list(ITEM_STACK, size -> DefaultedList.ofSize(size, ItemStack.EMPTY)); public static final NetworkCodec NBT_COMPOUND = new NetworkCodec<>( PacketByteBuf::writeNbt, PacketByteBuf::readNbt ); public static final NetworkCodec UUID = new NetworkCodec<>( PacketByteBuf::writeUuid, PacketByteBuf::readUuid ); - public static final NetworkCodec> COMPONENT_TYPE = new NetworkCodec<>( - (buf, componentType) -> buf.writeInt(Components.REGISTRY.getRawId(componentType)), - buf -> ClientSyncHandler.getInstance().getType(buf.readInt()) + public static final NetworkCodec CHUNK_POS = new NetworkCodec<>( + PacketByteBuf::writeChunkPos, PacketByteBuf::readChunkPos + ); + public static final NetworkCodec BLOCK_POS = new NetworkCodec<>( + PacketByteBuf::writeBlockPos, PacketByteBuf::readBlockPos + ); + public static final NetworkCodec ITEM_STACK = new NetworkCodec<>( + PacketByteBuf::writeItemStack, PacketByteBuf::readItemStack ); + public static final NetworkCodec> INVENTORY = + list(ITEM_STACK, size -> DefaultedList.ofSize(size, ItemStack.EMPTY)); + public static final NetworkCodec BLOCK_ENTITY = + BLOCK_POS.map(BlockEntity::getPos, ClientResolution::getBlockEntity); + public static final NetworkCodec ENTITY = + INT.map(Entity::getId, ClientResolution::getEntity); + public static final NetworkCodec CHUNK = + CHUNK_POS.map(Chunk::getPos, ClientResolution::getChunk); - public static > NetworkCodec list(NetworkCodec entryCodec, Function listFactory) { + public static > NetworkCodec list(NetworkCodec entryCodec, IntFunction listFactory) { return new NetworkCodec<>( (buf, os) -> { INT.encode(buf, os.size()); - for (O o : os) { - entryCodec.encode(buf, o); - } + os.forEach(o -> entryCodec.encode(buf, o)); }, buf -> { - int size = INT.decode(buf).orElseThrow(); + int size = INT.decode(buf).unwrap(); L newList = listFactory.apply(size); for (int i = 0; i < size; i++) { - newList.set(i, entryCodec.decode(buf).orElseThrow()); + newList.set(i, entryCodec.decode(buf).unwrap()); } return newList; @@ -113,11 +109,49 @@ public static > NetworkCodec list(NetworkCodec entryC ); } - public void encode(@NotNull PacketByteBuf buf, T t) { + public static > NetworkCodec map(NetworkCodec> entryCodec, IntFunction mapFactory) { + return new NetworkCodec<>( + (buf, m) -> { + INT.encode(buf, m.size()); + m.forEach((key, value) -> entryCodec.encode(buf, Pair.of(key, value))); + }, + buf -> { + int size = INT.decode(buf).unwrap(); + var map = mapFactory.apply(size); + for (int i = 0; i < size; i++) { + entryCodec.decode(buf).ifJust(ovPair -> map.put(ovPair.getFirst(), ovPair.getSecond())); + } + + return map; + } + ); + } + + public static NetworkCodec> pair(NetworkCodec keyCodec, NetworkCodec valueCodec) { + return new NetworkCodec<>( + (buf, kvPair) -> { + keyCodec.encode(buf, kvPair.getFirst()); + valueCodec.encode(buf, kvPair.getSecond()); + }, + buf -> Pair.of(keyCodec.decoder.apply(buf), valueCodec.decoder.apply(buf)) + ); + } + + public void encode(PacketByteBuf buf, T t) { this.encoder.accept(buf, t); } - public Optional decode(@NotNull PacketByteBuf buf) { - return Optional.ofNullable(this.decoder.apply(buf)); + public Maybe decode(PacketByteBuf buf) { + return Maybe.wrap(this.decoder.apply(buf)); + } + + public NetworkCodec map(Function decoder, Function encoder) { + return new NetworkCodec<>( + (buf, u) -> this.encoder.accept(buf, decoder.apply(u)), + buf -> encoder.apply(this.decoder.apply(buf)) + ); + } + + public record Thingy(Identifier id, String idString, int twelve) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java deleted file mode 100644 index b4556032e9..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncHeaderRegistry.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.impl.sync.header; - -import com.mojang.serialization.Lifecycle; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryKey; -import net.minecraft.util.registry.SimpleRegistry; -import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.CommonInitializer; - -public class SyncHeaderRegistry { - public static final RegistryKey>> HEADERS_KEY = - RegistryKey.ofRegistry(CommonInitializer.id("sync_headers")); - - public static final Registry> HEADERS = - new SimpleRegistry<>(HEADERS_KEY, Lifecycle.experimental(), null); - - public static

SyncPacketHeader

register(Identifier id, SyncPacketHeader

header) { - return Registry.register(HEADERS, id, header); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java index aa6bcc109a..cf38f20848 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -16,41 +16,68 @@ package org.quiltmc.qsl.component.impl.sync.header; +import com.mojang.serialization.Lifecycle; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.util.registry.SimpleRegistry; import net.minecraft.world.chunk.Chunk; -import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.CommonInitializer; +import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import org.quiltmc.qsl.networking.api.PacketByteBufs; -public record SyncPacketHeader

(@NotNull NetworkCodec

codec) { +public record SyncPacketHeader

(NetworkCodec

codec) { + // Registry TODO: Maybe register this?! + public static final RegistryKey>> REGISTRY_KEY = + RegistryKey.ofRegistry(CommonInitializer.id("sync_headers")); + public static final Registry> REGISTRY = + new SimpleRegistry<>(REGISTRY_KEY, Lifecycle.experimental(), null); + + // Codec + public static final NetworkCodec> NETWORK_CODEC = + NetworkCodec.INT.map(REGISTRY::getRawId, ClientSyncHandler.getInstance()::getHeader); + + // The default implemented types, that can sync. public static final SyncPacketHeader BLOCK_ENTITY = new SyncPacketHeader<>(NetworkCodec.BLOCK_ENTITY); public static final SyncPacketHeader ENTITY = new SyncPacketHeader<>(NetworkCodec.ENTITY); public static final SyncPacketHeader CHUNK = new SyncPacketHeader<>(NetworkCodec.CHUNK); private static final NetworkCodec LEVEL_CODEC = new NetworkCodec<>( - (buf, provider) -> {}, + (buf, provider) -> { + }, buf -> MinecraftClient.getInstance() ); - public static final SyncPacketHeader LEVEL = new SyncPacketHeader<>(LEVEL_CODEC); + public static final SyncPacketHeader SAVE = new SyncPacketHeader<>(LEVEL_CODEC); public static void registerDefaults() { - SyncHeaderRegistry.register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); - SyncHeaderRegistry.register(CommonInitializer.id("entity"), ENTITY); - SyncHeaderRegistry.register(CommonInitializer.id("chunk"), CHUNK); - SyncHeaderRegistry.register(CommonInitializer.id("level"), LEVEL); + register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); + register(CommonInitializer.id("entity"), ENTITY); + register(CommonInitializer.id("chunk"), CHUNK); + register(CommonInitializer.id("level"), SAVE); + } + + public static

void register(Identifier id, SyncPacketHeader

header) { + Registry.register(REGISTRY, id, header); + } + + public static Maybe toProvider(PacketByteBuf buf) { + return NETWORK_CODEC.decode(buf) + .map(SyncPacketHeader::codec) + .filterMap(networkCodec -> networkCodec.decode(buf)); } @SuppressWarnings("unchecked") - public @NotNull PacketByteBuf start(@NotNull ComponentProvider provider) { + public PacketByteBuf start(ComponentProvider provider) { var buf = PacketByteBufs.create(); - buf.writeInt(SyncHeaderRegistry.HEADERS.getRawId(this)); + buf.writeInt(REGISTRY.getRawId(this)); // the person calling is responsible to make sure we get a valid provider instance! this.codec.encode(buf, (P) provider); - return buf; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java index 10ac39cfdb..c90faaa745 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java @@ -21,13 +21,11 @@ import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; -import org.jetbrains.annotations.NotNull; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.networking.api.PacketByteBufs; public final class RegistryPacket { // TODO: Fix this with registry sync maybe?! - @NotNull - public static PacketByteBuf createRegistryPacket(@NotNull Registry registry) { + public static PacketByteBuf createRegistryPacket(Registry registry) { var buf = PacketByteBufs.create(); buf.writeInt(registry.size()); registry.forEach(t -> { @@ -40,7 +38,7 @@ public static PacketByteBuf createRegistryPacket(@NotNull Registry regist return buf; } - public static void handleRegistryResponse(@NotNull PacketByteBuf buf, ServerLoginNetworkHandler handler, String msg) { + public static void handleRegistryResponse(PacketByteBuf buf, ServerLoginNetworkHandler handler, String msg) { String retString = buf.readString(); if (!retString.equals("Ok")) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index 5e9a59cb22..bd4aa8b03e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -19,57 +19,45 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; -import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.components.SyncedComponent; -import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; -import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.networking.api.ServerPlayNetworking; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; import java.util.Queue; import java.util.function.Function; import java.util.function.Supplier; public class SyncPacket { - @NotNull - public static PacketByteBuf create(@NotNull SyncPacketHeader headerCreator, @NotNull ComponentProvider provider, @NotNull Map, SyncedComponent> components) { - PacketByteBuf buff = headerCreator.start(provider); - buff.writeInt(components.size()); - components.forEach((type, syncedComponent) -> { - NetworkCodec.COMPONENT_TYPE.encode(buff, type); - syncedComponent.writeToBuf(buff); - }); - - return buff; - } - + /** + *

+ *     		Handled by SyncPacketHeader		The data we add
+	 *        HEADER_ID PROVIDER_DATA       SIZE [TYPE DATA]
+	 *        	32bit		var				32bit	 var
+	 * 
+ */ public static void handle(PacketByteBuf buf, MinecraftClient client) { buf.retain(); client.execute(() -> { - var header = ClientSyncHandler.getInstance().getHeader(buf.readInt()); - header.codec().decode(buf).ifPresent(provider -> { + SyncPacketHeader.toProvider(buf).ifJust(provider -> { var size = buf.readInt(); for (int i = 0; i < size; i++) { - NetworkCodec.COMPONENT_TYPE.decode(buf) - .flatMap(provider::expose) + ComponentType.NETWORK_CODEC.decode(buf) + .filterMap(provider::expose) .map(it -> ((SyncedComponent) it)) - .ifPresent(synced -> synced.readFromBuf(buf)); + .ifJust(synced -> synced.readFromBuf(buf)); } }); + buf.release(); }); } - public static void send(SyncContext context, ComponentProvider provider, Map, SyncedComponent> map) { - PacketByteBuf packet = create(context.header(), provider, map); - + public static void send(SyncContext context, PacketByteBuf packet) { context.playerGenerator().get().forEach(serverPlayer -> ServerPlayNetworking.send(serverPlayer, PacketIds.SYNC, packet) ); @@ -81,16 +69,20 @@ public static void syncFromQueue( Function, SyncedComponent> mapper, ComponentProvider provider ) { - var map = new HashMap, SyncedComponent>(); // TODO: Find a way to *not* create this map?! + if (pendingSync.isEmpty()) { + return; + } + + PacketByteBuf buf = context.header().start(provider); + buf.writeInt(pendingSync.size()); while (!pendingSync.isEmpty()) { var currentType = pendingSync.poll(); - map.put(currentType, mapper.apply(currentType)); + ComponentType.NETWORK_CODEC.encode(buf, currentType); + mapper.apply(currentType).writeToBuf(buf); } - if (!map.isEmpty()) { - SyncPacket.send(context, provider, map); - } + SyncPacket.send(context, buf); } public record SyncContext(SyncPacketHeader header, Supplier> playerGenerator) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java new file mode 100644 index 0000000000..a11ed7686f --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java @@ -0,0 +1,87 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.impl.util; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.PersistentState; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; +import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; + +public class ComponentProviderState extends PersistentState implements ComponentProvider { + public static final String ID = "components"; + public static final String GLOBAL_ID = "save_components"; + + private final ComponentContainer container; + + public ComponentProviderState(ServerWorld world) { + this.container = this.initContainer(world); + } + + public ComponentProviderState(NbtCompound rootQslNbt, ServerWorld world) { + this.container = this.initContainer(world); + this.container.readNbt(rootQslNbt); + } + + public static ComponentProviderState get(Object obj) { + if (!(obj instanceof ServerWorld world)) { + throw ErrorUtil.illegalArgument("A ServerWorld instance needs to be provided to initialize a container!").get(); + } + + return world.getPersistentStateManager().getOrCreate( + nbtCompound -> new ComponentProviderState(nbtCompound, world), + () -> new ComponentProviderState(world), + ID + ); + } + + public static ComponentProviderState getGlobal(Object obj) { + if (!(obj instanceof MinecraftServer server)) { + throw ErrorUtil.illegalArgument("A MinecraftServer instance needs to be provided to initialize a container!").get(); + } + + ServerWorld overworld = server.getOverworld(); + return overworld.getPersistentStateManager().getOrCreate( + nbtCompound -> new ComponentProviderState(nbtCompound, overworld), + () -> new ComponentProviderState(overworld), + GLOBAL_ID + ); + } + + @Override + public NbtCompound writeNbt(NbtCompound nbt) { + this.container.writeNbt(nbt); + return nbt; + } + + @Override + public ComponentContainer getComponentContainer() { + return this.container; + } + + private LazyComponentContainer initContainer(ServerWorld world) { + return ComponentContainer.builder(this) + .unwrap() + .saving(this::markDirty) + .syncing(SyncPacketHeader.SAVE, world::getPlayers) + .ticking() + .build(LazyComponentContainer.FACTORY); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java deleted file mode 100644 index 66d64ef263..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinLevelProperties.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.mixin; - -import com.mojang.datafixers.DataFixer; -import com.mojang.serialization.Dynamic; -import com.mojang.serialization.Lifecycle; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.registry.DynamicRegistryManager; -import net.minecraft.world.SaveProperties; -import net.minecraft.world.border.WorldBorder; -import net.minecraft.world.gen.GeneratorOptions; -import net.minecraft.world.level.LevelInfo; -import net.minecraft.world.level.LevelProperties; -import net.minecraft.world.level.ServerWorldProperties; -import net.minecraft.world.level.storage.SaveVersionInfo; -import net.minecraft.world.timer.Timer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.List; -import java.util.Set; -import java.util.UUID; - -// TODO: Try saving using an external file so that worlds can also be handled and this is easier to save/sync -@Mixin(LevelProperties.class) -public abstract class MixinLevelProperties implements ServerWorldProperties, SaveProperties, ComponentProvider { - private ComponentContainer qsl$container; - - @Inject(method = "readProperties", at = @At("RETURN")) - private static void readComponentData(Dynamic dynamic, DataFixer dataFixer, int dataVersion, @Nullable NbtCompound playerData, LevelInfo levelInfo, SaveVersionInfo saveVersionInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfoReturnable cir) { - cir.getReturnValue().getComponentContainer().readNbt((NbtCompound) dynamic.getValue()); - } - - @Override - public @NotNull ComponentContainer getComponentContainer() { - return this.qsl$container; - } - - @Inject(method = "(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/NbtCompound;ZIIIFJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lcom/mojang/serialization/Lifecycle;)V", at = @At("TAIL")) - private void onInit(DataFixer dataFixer, int i, NbtCompound nbtCompound, boolean bl, int j, int k, int l, float f, long m, long n, int o, int p, int q, boolean bl2, int r, boolean bl3, boolean bl4, boolean bl5, WorldBorder.Properties properties, int s, int t, UUID uUID, Set set, Timer timer, NbtCompound nbtCompound2, NbtCompound nbtCompound3, LevelInfo levelInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle, CallbackInfo ci) { - this.qsl$container = LazyComponentContainer.builder(this) - .orElseThrow() - .ticking() - .syncing(SyncPacketHeader.LEVEL, List::of) // TODO - .build(); - } - - @Inject(method = "updateProperties", at = @At("TAIL")) - private void writeComponentData(DynamicRegistryManager registryManager, NbtCompound levelNbt, NbtCompound playerNbt, CallbackInfo ci) { - this.qsl$container.writeNbt(levelNbt); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinBlockEntity.java similarity index 86% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinBlockEntity.java index 48acbfe2d0..f50c0f76ff 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinBlockEntity.java @@ -14,16 +14,15 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin; +package org.quiltmc.qsl.component.mixin.block.entity; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.BlockPos; -import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; @@ -42,7 +41,7 @@ public abstract class MixinBlockEntity implements ComponentProvider { public abstract void markDirty(); @Override - public @NotNull ComponentContainer getComponentContainer() { + public ComponentContainer getComponentContainer() { return this.qsl$container; } @@ -54,12 +53,12 @@ private void onReadNbt(NbtCompound nbt, CallbackInfo ci) { @SuppressWarnings("ConstantConditions") @Inject(method = "", at = @At("RETURN")) private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { - this.qsl$container = LazyComponentContainer.builder(this) - .orElseThrow() + this.qsl$container = ComponentContainer.builder(this) + .unwrap() .saving(this::markDirty) .ticking() .syncing(SyncPacketHeader.BLOCK_ENTITY, () -> SyncPlayerList.create((BlockEntity) (Object) this)) - .build(); + .build(LazyComponentContainer.FACTORY); } @Inject(method = "toNbt", at = @At("TAIL")) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinDirectBlockEntityTickInvoker.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinDirectBlockEntityTickInvoker.java index 3892c78303..db95321d32 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinDirectBlockEntityTickInvoker.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinDirectBlockEntityTickInvoker.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin; +package org.quiltmc.qsl.component.mixin.block.entity; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunk.java similarity index 84% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunk.java index 3629e38cff..877c61fb7b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunk.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin; +package org.quiltmc.qsl.component.mixin.chunk; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.Registry; @@ -24,9 +24,8 @@ import net.minecraft.world.chunk.UpgradeData; import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.gen.chunk.BlendingData; -import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; @@ -44,21 +43,21 @@ public abstract class MixinChunk implements ComponentProvider { public abstract void setNeedsSaving(boolean needsSaving); @Override - public @NotNull ComponentContainer getComponentContainer() { + public ComponentContainer getComponentContainer() { return this.qsl$container; } @SuppressWarnings("ConstantConditions") @Inject(method = "", at = @At("RETURN")) private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { - LazyComponentContainer.Builder builder = LazyComponentContainer.builder(this) - .orElseThrow() + LazyComponentContainer.Builder builder = ComponentContainer.builder(this) + .unwrap() .saving(() -> this.setNeedsSaving(true)); if ((Chunk) (Object) this instanceof WorldChunk worldChunk) { builder.syncing(SyncPacketHeader.CHUNK, () -> SyncPlayerList.create(worldChunk)).ticking(); } - this.qsl$container = builder.build(); + this.qsl$container = builder.build(LazyComponentContainer.FACTORY); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunkSerializer.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunkSerializer.java index 07b51e7876..679049a22a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunkSerializer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin; +package org.quiltmc.qsl.component.mixin.chunk; import net.minecraft.nbt.NbtCompound; import net.minecraft.server.world.ServerWorld; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinThreadedChunkStorage.java similarity index 91% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinThreadedChunkStorage.java index ec361a3a78..53ff9cf2a0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinThreadedChunkStorage.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinThreadedChunkStorage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin; +package org.quiltmc.qsl.component.mixin.chunk; import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; @@ -27,7 +27,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ThreadedAnvilChunkStorage.class) -public abstract class MixinThreadedChunkStorage { // TODO: This still doesn't work +public abstract class MixinThreadedChunkStorage { @Inject( method = "sendChunkDataPackets", @@ -38,6 +38,6 @@ public abstract class MixinThreadedChunkStorage { // TODO: This still doesn't wo ) ) private void syncChunkContainer(ServerPlayerEntity player, MutableObject mutableObject, WorldChunk chunk, CallbackInfo ci) { - chunk.syncComponents(); + // FIXME: Make this work } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinWorldChunk.java similarity index 95% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinWorldChunk.java index 120f56b8dd..9ac4d9951d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinWorldChunk.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin; +package org.quiltmc.qsl.component.mixin.chunk; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.ChunkPos; @@ -24,7 +24,7 @@ import net.minecraft.world.chunk.*; import net.minecraft.world.gen.chunk.BlendingData; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MixinMinecraftClient.java similarity index 78% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MixinMinecraftClient.java index 7d44901ce0..b675aa746c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/MixinMinecraftClient.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MixinMinecraftClient.java @@ -14,13 +14,12 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin.client; +package org.quiltmc.qsl.component.mixin.client.level; import net.minecraft.client.MinecraftClient; import net.minecraft.client.RunArgs; -import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -32,12 +31,12 @@ public class MixinMinecraftClient implements ComponentProvider { private ComponentContainer qsl$container; @Override - public @NotNull ComponentContainer getComponentContainer() { + public ComponentContainer getComponentContainer() { return this.qsl$container; } @Inject(method = "", at = @At("TAIL")) private void initContainer(RunArgs runArgs, CallbackInfo ci) { - this.qsl$container = LazyComponentContainer.builder(this).orElseThrow().build(); + this.qsl$container = ComponentContainer.builder(this).unwrap().build(LazyComponentContainer.FACTORY); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/MixinEntity.java similarity index 88% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/MixinEntity.java index 030b8e8e76..c7c8e31e09 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/MixinEntity.java @@ -14,15 +14,14 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin; +package org.quiltmc.qsl.component.mixin.entity; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.nbt.NbtCompound; import net.minecraft.world.World; -import org.jetbrains.annotations.NotNull; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; @@ -36,14 +35,19 @@ public abstract class MixinEntity implements ComponentProvider { private ComponentContainer qsl$container; + @Override + public ComponentContainer getComponentContainer() { + return this.qsl$container; + } + @SuppressWarnings("ConstantConditions") @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { - this.qsl$container = LazyComponentContainer.builder(this) - .orElseThrow() + this.qsl$container = ComponentContainer.builder(this) + .unwrap() .ticking() .syncing(SyncPacketHeader.ENTITY, () -> SyncPlayerList.create((Entity) (Object) this)) - .build(); + .build(LazyComponentContainer.FACTORY); } @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) @@ -60,9 +64,4 @@ private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { private void tickContainer(CallbackInfo ci) { this.getComponentContainer().tick(this); } - - @Override - public @NotNull ComponentContainer getComponentContainer() { - return this.qsl$container; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/item/stack/MixinItemStack.java similarity index 86% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/item/stack/MixinItemStack.java index 5a3c26e127..cc2d5b2f43 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinItemStack.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/item/stack/MixinItemStack.java @@ -14,17 +14,16 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin; +package org.quiltmc.qsl.component.mixin.item.stack; import net.minecraft.entity.Entity; import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.world.World; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentProvider; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -41,25 +40,30 @@ public abstract class MixinItemStack implements ComponentProvider { // TODO: Mak private @Nullable NbtCompound nbt; private LazyComponentContainer qsl$container; + @Shadow + public abstract NbtCompound getOrCreateNbt(); + + @Override + public ComponentContainer getComponentContainer() { + return this.qsl$container; + } + @Inject(method = "(Lnet/minecraft/item/ItemConvertible;I)V", at = @At("TAIL")) private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo ci) { - this.qsl$container = LazyComponentContainer.builder(this) - .orElseThrow() + this.qsl$container = ComponentContainer.builder(this) + .unwrap() .saving(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) .ticking() - .build(); + .build(LazyComponentContainer.FACTORY); } - @Shadow - public abstract NbtCompound getOrCreateNbt(); - @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;)V", at = @At("TAIL")) private void readContainer(NbtCompound nbtCompound, CallbackInfo ci) { - this.qsl$container = LazyComponentContainer.builder(this) - .orElseThrow() + this.qsl$container = ComponentContainer.builder(this) + .unwrap() .saving(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) .ticking() - .build(); + .build(LazyComponentContainer.FACTORY); if (this.nbt != null) { this.qsl$container.readNbt(this.nbt); @@ -84,11 +88,6 @@ private void deserializeContainer(CallbackInfoReturnable cir) { @Inject(method = "inventoryTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;inventoryTick(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;IZ)V")) private void tickContainer(World world, Entity entity, int slot, boolean selected, CallbackInfo ci) { - - } - - @Override - public @NotNull ComponentContainer getComponentContainer() { - return this.qsl$container; + this.qsl$container.tick(this); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MixinMinecraftServer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MixinMinecraftServer.java new file mode 100644 index 0000000000..e7c0f39be3 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MixinMinecraftServer.java @@ -0,0 +1,31 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.mixin.level; + +import net.minecraft.server.MinecraftServer; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.util.ComponentProviderState; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(MinecraftServer.class) +public abstract class MixinMinecraftServer implements ComponentProvider { + @Override + public ComponentContainer getComponentContainer() { + return ComponentProviderState.getGlobal(this).getComponentContainer(); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/MixinServerWorld.java similarity index 78% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/MixinServerWorld.java index fe75279615..60d96986f6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/MixinServerWorld.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/MixinServerWorld.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin; +package org.quiltmc.qsl.component.mixin.world; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Holder; @@ -24,6 +24,9 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.dimension.DimensionType; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -32,11 +35,16 @@ import java.util.function.Supplier; @Mixin(ServerWorld.class) -public abstract class MixinServerWorld extends World { +public abstract class MixinServerWorld extends World implements ComponentProvider { protected MixinServerWorld(MutableWorldProperties mutableWorldProperties, RegistryKey registryKey, Holder holder, Supplier supplier, boolean bl, boolean bl2, long l, int i) { super(mutableWorldProperties, registryKey, holder, supplier, bl, bl2, l, i); } + @Override + public ComponentContainer getComponentContainer() { + return ComponentProviderState.get(this).getComponentContainer(); + } + @Inject(method = "tickChunk", at = @At("TAIL")) private void tickContainer(WorldChunk chunk, int randomTickSpeed, CallbackInfo ci) { chunk.getComponentContainer().tick(chunk); diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index 85844670a9..75ae4e96a7 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -3,19 +3,19 @@ "package": "org.quiltmc.qsl.component.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "MixinBlockEntity", - "MixinChunk", - "MixinChunkSerializer", - "MixinDirectBlockEntityTickInvoker", - "MixinEntity", - "MixinItemStack", - "MixinLevelProperties", - "MixinServerWorld", - "MixinThreadedChunkStorage", - "MixinWorldChunk" + "block.entity.MixinBlockEntity", + "chunk.MixinChunk", + "chunk.MixinChunkSerializer", + "block.entity.MixinDirectBlockEntityTickInvoker", + "entity.MixinEntity", + "item.stack.MixinItemStack", + "level.MixinMinecraftServer", + "world.MixinServerWorld", + "chunk.MixinThreadedChunkStorage", + "chunk.MixinWorldChunk" ], "client": [ - "client.MixinMinecraftClient" + "client.level.MixinMinecraftClient" ], "injectors": { "defaultRequire": 1 diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 1ff766b4f7..c08a9cf822 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -28,6 +28,8 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.nbt.NbtLongArray; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.Hand; @@ -46,10 +48,10 @@ import org.quiltmc.qsl.component.api.components.GenericComponent; import org.quiltmc.qsl.component.api.components.InventoryComponent; import org.quiltmc.qsl.component.api.components.TickingComponent; -import org.quiltmc.qsl.component.api.event.ComponentEvents; -import org.quiltmc.qsl.component.impl.components.DefaultFloatComponent; import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; import org.quiltmc.qsl.component.impl.components.DefaultInventoryComponent; +import org.quiltmc.qsl.component.impl.util.ComponentProviderState; +import org.quiltmc.qsl.component.test.component.SaveFloatComponent; import java.util.UUID; @@ -58,11 +60,11 @@ public class ComponentTestMod implements ModInitializer { public static final ComponentType COW_INVENTORY = Components.register( new Identifier(MODID, "cow_inventory"), - () -> new DefaultInventoryComponent(() -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64))) + (saveOp, syncOp) -> new DefaultInventoryComponent(saveOp, syncOp, () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64))) ); public static final ComponentType CREEPER_EXPLODE_TIME = Components.register( new Identifier(MODID, "creeper_explode_time"), - () -> new DefaultIntegerComponent(200) + (saveOp, syncOp) -> new DefaultIntegerComponent(saveOp, syncOp, 200) ); public static final ComponentType HOSTILE_EXPLODE_TIME = Components.register( new Identifier(MODID, "hostile_explode_time"), @@ -70,21 +72,21 @@ public class ComponentTestMod implements ModInitializer { ); public static final ComponentType CHEST_NUMBER = Components.register( new Identifier(MODID, "chest_number"), - () -> new DefaultIntegerComponent(200) + (saveOp, syncOp) -> new DefaultIntegerComponent(saveOp, syncOp, 200) ); public static final ComponentType CHUNK_INVENTORY = Components.register( new Identifier(MODID, "chunk_inventory"), - () -> new DefaultInventoryComponent(1) + (saveOp, syncOp) -> new DefaultInventoryComponent(saveOp, syncOp, 1) ); - public static final ComponentType SAVE_FLOAT = Components.register( + public static final ComponentType SAVE_FLOAT = Components.registerTicking( new Identifier(MODID, "save_float"), - DefaultFloatComponent::new + SaveFloatComponent::new ); public static final ComponentType SERVER_TICK = Components.registerTicking( new Identifier(MODID, "level_tick"), - () -> provider -> { - if (provider instanceof LevelProperties properties) { - properties.expose(SAVE_FLOAT).ifPresent(floatComponent -> { + (saveOp, syncOP) -> provider -> { + if (provider instanceof MinecraftServer properties) { + properties.expose(SAVE_FLOAT).ifJust(floatComponent -> { floatComponent.set(floatComponent.get() + 0.5f); floatComponent.save(); }); @@ -100,13 +102,13 @@ public class ComponentTestMod implements ModInitializer { new Identifier(ComponentTestMod.MODID, "test_be_int"), DefaultIntegerComponent::new ); - public static final ComponentType> UUID_THING = Components.register( + public static final ComponentType> UUID_THING = Components.register( new Identifier(MODID, "uuid_thing"), - () -> GenericComponent.create(Codecs.UUID) + (saveOperation, syncOperation) -> new GenericComponent<>(saveOperation, Codecs.UUID) ); public static final ComponentType PLAYER_TICK = Components.registerTicking( new Identifier(MODID, "player_tick"), - () -> provider -> { + (saveOP, syncOp) -> provider -> { if (provider instanceof ServerPlayerEntity player) { ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); if (stackInHand.isOf(Items.WHEAT)) { @@ -114,12 +116,12 @@ public class ComponentTestMod implements ModInitializer { player.sendMessage(Text.literal("Prankt"), true); } var props = player.getWorld().getServer().getSaveProperties(); - if (props instanceof LevelProperties levelProperties && player.getWorld().getTime() % 100 == 0) { + if (props instanceof MinecraftServer levelProperties && player.getWorld().getTime() % 100 == 0) { player.sendMessage(Text.literal( - levelProperties.expose(SAVE_FLOAT).map(FloatComponent::get).orElse(0f).toString() + levelProperties.expose(SAVE_FLOAT).map(FloatComponent::get).unwrapOr(0f).toString() ), false); } - player.expose(UUID_THING).ifPresent(uuidGenericComponent -> { + player.expose(UUID_THING).ifJust(uuidGenericComponent -> { Entity vehicle = player.getVehicle(); if (vehicle != null) { @@ -160,16 +162,14 @@ public void onInitialize(ModContainer mod) { Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); - Components.inject(LevelProperties.class, SAVE_FLOAT); - // Components.injectInheritage(ServerPlayerEntity.class, FUNC_COMP); Function components have been removed - Components.inject(LevelProperties.class, SERVER_TICK); +// Components.inject(LevelProperties.class, SAVE_FLOAT); + Components.injectInheritage(ServerPlayerEntity.class, PLAYER_TICK); + Components.inject(MinecraftServer.class, SERVER_TICK); Components.inject(ServerPlayerEntity.class, UUID_THING); + Components.inject(ComponentProviderState.class, SAVE_FLOAT); // FIXME // Dynamic Injection - ComponentEvents.DYNAMIC_INJECT.register((provider, injector) -> { - injector.injectIf(provider instanceof ItemStack stack && stack.isOf(Items.BOOKSHELF), ITEMSTACK_INT); - injector.injectIf(provider instanceof PlayerEntity, PLAYER_TICK); - }); + Components.injectDynamic(PlayerEntity.class, SAVE_FLOAT, player -> player.world.isClient); } public static final BlockEntityType TEST_BE_TYPE = diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 6d94521cce..700b510831 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -60,7 +60,7 @@ public void endWorldTick(MinecraftServer server, ServerWorld world) { private void stackInHandTick(ServerPlayerEntity player, ItemStack stackInHand) { if (!stackInHand.isEmpty() && stackInHand.isOf(Items.BOOKSHELF)) { - stackInHand.expose(ComponentTestMod.ITEMSTACK_INT).ifPresent(integerComponent -> { + stackInHand.expose(ComponentTestMod.ITEMSTACK_INT).ifJust(integerComponent -> { integerComponent.increment(); integerComponent.save(); @@ -72,7 +72,7 @@ private void stackInHandTick(ServerPlayerEntity player, ItemStack stackInHand) { } private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { - chunk.expose(ComponentTestMod.CHUNK_INVENTORY).ifPresent(inventory -> { + chunk.expose(ComponentTestMod.CHUNK_INVENTORY).ifJust(inventory -> { ItemStack playerStack = player.getInventory().getStack(9); ItemStack stack = inventory.getStack(0); if (!playerStack.isEmpty()) { @@ -87,7 +87,7 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { if (ItemStack.canCombine(stack, playerStack)) { stack.increment(1); playerStack.decrement(1); - stack.expose(ComponentTestMod.ITEMSTACK_INT).ifPresent(defaultIntegerComponent -> { + stack.expose(ComponentTestMod.ITEMSTACK_INT).ifJust(defaultIntegerComponent -> { defaultIntegerComponent.increment(); defaultIntegerComponent.save(); }); @@ -104,7 +104,7 @@ private void currentChunkBETick(ServerWorld world, Chunk chunk) { chunk.getBlockEntityPositions().stream() .map(chunk::getBlockEntity) .filter(Objects::nonNull) - .forEach(blockEntity -> blockEntity.expose(ComponentTestMod.CHEST_NUMBER).ifPresent(integerComponent -> { + .forEach(blockEntity -> blockEntity.expose(ComponentTestMod.CHEST_NUMBER).ifJust(integerComponent -> { integerComponent.decrement(); integerComponent.save(); @@ -116,7 +116,7 @@ private void currentChunkBETick(ServerWorld world, Chunk chunk) { private void hostileTick(ServerWorld world) { world.getEntitiesByType(TypeFilter.instanceOf(HostileEntity.class), hostile -> true) - .forEach(hostile -> hostile.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).ifPresent(explodeTime -> { + .forEach(hostile -> hostile.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).ifJust(explodeTime -> { if (explodeTime.get() <= 200) { explodeTime.increment(); explodeTime.save(); @@ -134,7 +134,7 @@ private void hostileTick(ServerWorld world) { private void creeperTick(ServerWorld world) { world.getEntitiesByType(EntityType.CREEPER, creeper -> true) - .forEach(creeper -> Components.expose(ComponentTestMod.CREEPER_EXPLODE_TIME, creeper).ifPresent(explodeTime -> { + .forEach(creeper -> Components.expose(ComponentTestMod.CREEPER_EXPLODE_TIME, creeper).ifJust(explodeTime -> { if (explodeTime.get() > 0) { explodeTime.decrement(); explodeTime.save(); @@ -146,7 +146,7 @@ private void creeperTick(ServerWorld world) { private void cowTick(ServerWorld world) { world.getEntitiesByType(TypeFilter.instanceOf(CowEntity.class), cowEntity -> true).forEach(entity -> - entity.expose(ComponentTestMod.COW_INVENTORY).ifPresent(inventoryComponent -> { + entity.expose(ComponentTestMod.COW_INVENTORY).ifJust(inventoryComponent -> { if (inventoryComponent.isEmpty()) { world.createExplosion( entity, diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index 4424b79b20..7b5cf9a791 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -62,7 +62,7 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt if (!handStack.isEmpty()) { final ActionResult[] ret = new ActionResult[]{ActionResult.PASS}; - be.expose(ComponentTestMod.CHUNK_INVENTORY).ifPresent(inventoryComponent -> { + be.expose(ComponentTestMod.CHUNK_INVENTORY).ifJust(inventoryComponent -> { var stack = inventoryComponent.getStack(0); if (stack.isEmpty()) { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 10966bdfc4..c5cc629903 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -26,9 +26,11 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.ComponentContainer; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.components.InventoryComponent; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; @@ -40,15 +42,12 @@ import java.util.Set; public class TestBlockEntity extends BlockEntity { - // public static final ComponentType TEST_BE_INT = Components.register( - // new Identifier(ComponentTestMod.MODID, "test_be_int"), - // DefaultIntegerComponent::new - // ); Crashes due to our freezing the registry! - private final ComponentContainer container = SimpleComponentContainer.builder() - .setSaveOperation(this::markDirty) + private final ComponentContainer container = ComponentContainer.builder(this) + .unwrap() + .saving(this::markDirty) .add(ComponentTestMod.TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) .syncing(SyncPacketHeader.BLOCK_ENTITY, () -> SyncPlayerList.create(this)) - .build(); + .build(SimpleComponentContainer.FACTORY); public TestBlockEntity(BlockPos blockPos, BlockState blockState) { super(ComponentTestMod.TEST_BE_TYPE, blockPos, blockState); @@ -59,8 +58,8 @@ public static void tick(World world, BlockPos pos, Block return; } - if (blockEntity.expose(ComponentTestMod.CHUNK_INVENTORY).map(InventoryComponent::isEmpty).orElse(true)) { - blockEntity.expose(ComponentTestMod.TEST_BE_INT).ifPresent(integerComponent -> { + if (blockEntity.expose(ComponentTestMod.CHUNK_INVENTORY).map(InventoryComponent::isEmpty).unwrapOr(true)) { + blockEntity.expose(ComponentTestMod.TEST_BE_INT).ifJust(integerComponent -> { if (integerComponent.get() % 40 == 0) { HashSet set = new HashSet<>(List.of(pos)); expand(pos, pos, world, set); @@ -87,10 +86,15 @@ private static void expand(BlockPos initialPos, BlockPos pos, World world, Set Maybe expose(ComponentType id) { + return super.expose(id).or(() -> this.container.expose(id).filterMap(id::cast)); + } + @Override public void readNbt(NbtCompound nbt) { super.readNbt(nbt); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java index 2c048da3d0..d3b05781b0 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java @@ -35,7 +35,7 @@ public void render(TestBlockEntity entity, float tickDelta, MatrixStack matrices entity.expose(ComponentTestMod.CHUNK_INVENTORY) .map(inventoryComponent -> inventoryComponent.getStack(0)) .filter(Predicate.not(ItemStack::isEmpty)) - .ifPresent(itemStack -> { + .ifJust(itemStack -> { matrices.push(); matrices.translate(0.5f, 1, 0.5f); matrices.multiply(Vec3f.NEGATIVE_Y.getDegreesQuaternion(System.currentTimeMillis() % 360)); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java new file mode 100644 index 0000000000..fb72284016 --- /dev/null +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java @@ -0,0 +1,34 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.test.component; + +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.impl.components.DefaultFloatComponent; + +public class SaveFloatComponent extends DefaultFloatComponent implements TickingComponent { + public SaveFloatComponent(@Nullable Runnable saveOperation, @Nullable Runnable ignored) { + super(saveOperation); + } + + @Override + public void tick(ComponentProvider provider) { + this.set(this.get() + 0.5f); + this.save(); + } +} diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java index bdd120b893..ec28c99872 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java @@ -32,7 +32,7 @@ @Mixin(BlockEntityRendererFactories.class) public abstract class MixinBlockEntityRendererFactories { @Shadow - protected static void register(BlockEntityType type, BlockEntityRendererFactory factory) { + private static void register(BlockEntityType type, BlockEntityRendererFactory factory) { throw ErrorUtil.illegalState("This should never happen").get(); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index 02e414466a..0ae222e918 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -16,13 +16,10 @@ package org.quiltmc.qsl.component.test.mixin.client; -import net.minecraft.client.ClientGameSession; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.hud.InGameHud; -import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.util.math.ChunkPos; @@ -38,24 +35,24 @@ @Mixin(InGameHud.class) public abstract class MixinInGameHud { - @Shadow - public abstract TextRenderer getTextRenderer(); - @Shadow @Final private ItemRenderer itemRenderer; + @Shadow + public abstract TextRenderer getTextRenderer(); + @Inject(method = "render", at = @At("TAIL")) private void renderCustom(MatrixStack matrices, float tickDelta, CallbackInfo ci) { Entity entity = MinecraftClient.getInstance().targetedEntity; if (entity != null) { - entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).map(IntegerComponent::get).ifPresent(integer -> { + entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).map(IntegerComponent::get).ifJust(integer -> { this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa); }); } ChunkPos chunkPos = MinecraftClient.getInstance().player.getChunkPos(); MinecraftClient.getInstance().world.getChunk(chunkPos.x, chunkPos.z).expose(ComponentTestMod.CHUNK_INVENTORY) .map(defaultInventoryComponent -> defaultInventoryComponent.getStack(0)) - .ifPresent(itemStack -> this.itemRenderer.renderInGui(itemStack, 10, 10)); + .ifJust(itemStack -> this.itemRenderer.renderInGui(itemStack, 10, 10)); } } From 4b72357003711c36f37ecdc5d9a7133aa546fa73 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 12 Jul 2022 19:57:39 +0300 Subject: [PATCH 51/70] Removed ItemStacks from ComponentProviders. * Various other fixes. --- library/data/component/build.gradle | 21 +++-- .../quiltmc/qsl/component/api/Components.java | 6 +- .../api/components/GenericComponent.java | 23 +++-- .../api/components/InventoryComponent.java | 18 +++- .../components/SyncedGenericComponent.java | 2 +- .../DynamicInjectionPredicate.java | 4 +- .../InjectionPredicate.java} | 4 +- .../api/provider/ComponentProvider.java | 5 +- .../qsl/component/impl/ComponentsImpl.java | 4 +- .../impl/client/ClientResolution.java | 6 ++ .../impl/event/ServerTickEventListener.java | 4 + .../event/ServerWorldTickEventListener.java | 19 ++++ .../injection/manager/InjectionManager.java | 3 +- .../cached/CachedInjectionManager.java | 4 +- .../dynamic/DynamicInjectionManager.java | 2 +- .../cached/ClassInjectionPredicate.java | 4 +- .../FilteredInheritedInjectionPredicate.java | 2 +- .../DynamicClassInjectionPredicate.java | 2 +- .../dynamic/DynamicWrappedPredicate.java | 27 ++++++ .../impl/sync/codec/NetworkCodec.java | 20 ++-- .../impl/sync/header/SyncPacketHeader.java | 37 +++++--- .../impl/util/ComponentProviderState.java | 2 +- ...BlockEntity.java => BlockEntityMixin.java} | 2 +- ...=> DirectBlockEntityTickInvokerMixin.java} | 2 +- .../{MixinChunk.java => ChunkMixin.java} | 2 +- ...ializer.java => ChunkSerializerMixin.java} | 2 +- .../ServerWorldMixin.java} | 15 +-- ...ge.java => ThreadedChunkStorageMixin.java} | 2 +- ...inWorldChunk.java => WorldChunkMixin.java} | 4 +- ...tClient.java => MinecraftClientMixin.java} | 2 +- .../{MixinEntity.java => EntityMixin.java} | 2 +- .../mixin/item/stack/MixinItemStack.java | 93 ------------------- ...tServer.java => MinecraftServerMixin.java} | 2 +- .../qsl/component/mixin/world/WorldMixin.java | 15 +++ .../resources/quilt_component.mixins.json | 22 ++--- .../qsl/component/test/ComponentTestMod.java | 11 +-- 36 files changed, 204 insertions(+), 191 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{ => predicate}/DynamicInjectionPredicate.java (85%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{CachedInjectionPredicate.java => predicate/InjectionPredicate.java} (87%) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/{MixinBlockEntity.java => BlockEntityMixin.java} (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/{MixinDirectBlockEntityTickInvoker.java => DirectBlockEntityTickInvokerMixin.java} (96%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/{MixinChunk.java => ChunkMixin.java} (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/{MixinChunkSerializer.java => ChunkSerializerMixin.java} (98%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/{world/MixinServerWorld.java => chunk/ServerWorldMixin.java} (75%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/{MixinThreadedChunkStorage.java => ThreadedChunkStorageMixin.java} (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/{MixinWorldChunk.java => WorldChunkMixin.java} (94%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/{MixinMinecraftClient.java => MinecraftClientMixin.java} (96%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/{MixinEntity.java => EntityMixin.java} (97%) delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/item/stack/MixinItemStack.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/{MixinMinecraftServer.java => MinecraftServerMixin.java} (94%) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index 03b635cde1..d2739e7239 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -23,7 +23,10 @@ qslModule { entrypoints { events { - values = ["org.quiltmc.qsl.component.impl.event.ServerTickEventListener"] + values = [ + "org.quiltmc.qsl.component.impl.event.ServerTickEventListener", + "org.quiltmc.qsl.component.impl.event.ServerWorldTickEventListener" + ] } init { @@ -38,26 +41,30 @@ qslModule { accessWidener() injectedInterface("net/minecraft/class_2586") { // BlockEntity - values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } injectedInterface("net/minecraft/class_1297") { // Entity - values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } injectedInterface("net/minecraft/class_2791") { // Chunk - values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } injectedInterface("net/minecraft/class_1799") { // ItemStack - values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } injectedInterface("net/minecraft/class_310") { // MinecraftClient - values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } injectedInterface("net/minecraft/server/MinecraftServer") { // MinecraftServer - values = ["org/quiltmc/qsl/component/api/ComponentProvider"] + values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] + } + + injectedInterface("net/minecraft/class_1937") { // World + values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 1600404cc4..74db04ef55 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -21,6 +21,7 @@ import net.minecraft.util.registry.RegistryKey; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; @@ -38,8 +39,8 @@ public final class Components { public static final RegistryKey>> REGISTRY_KEY = ComponentsImpl.REGISTRY_KEY; public static final Registry> REGISTRY = ComponentsImpl.REGISTRY; - public static void inject(CachedInjectionPredicate predicate, ComponentType type) { - ComponentsImpl.inject(predicate, new ComponentEntry<>(type)); + public static void inject(InjectionPredicate predicate, ComponentEntry entry) { + ComponentsImpl.inject(predicate, entry); } public static void inject(Class clazz, ComponentType type) { @@ -59,7 +60,6 @@ public static void injectRedirected(Class mainClass, Co } public static void injectDynamic(Class

clazz, ComponentType type, Predicate

predicate) { - // TODO: Fix evil hack if possible ComponentsImpl.inject(new DynamicClassInjectionPredicate<>(clazz, predicate), new ComponentEntry<>(type)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java index ea2ade771b..d0a1abfd76 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java @@ -17,12 +17,13 @@ package org.quiltmc.qsl.component.api.components; import com.mojang.serialization.Codec; +import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtNull; import net.minecraft.nbt.NbtOps; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.impl.ComponentsImpl; -public class GenericComponent implements NbtComponent { +public class GenericComponent implements NbtComponent { protected final Codec codec; @Nullable private final Runnable saveOperation; @@ -47,14 +48,22 @@ public byte nbtType() { } @Override - public void read(E nbt) { - NbtOps.INSTANCE.withParser(this.codec).apply(nbt).result().ifPresent(t -> this.value = t); + public void read(NbtCompound nbt) { + this.codec.parse(NbtOps.INSTANCE, nbt.get("Value")) + .resultOrPartial(ComponentsImpl.LOGGER::error) + .ifPresent(this::setValue); } - @SuppressWarnings("unchecked") @Override - public E write() { // TODO: Make sure this doesn't cause problems. - return (E) NbtOps.INSTANCE.withEncoder(this.codec).apply(this.value).result().orElse(NbtNull.INSTANCE); + public NbtCompound write() { + var ret = new NbtCompound(); + if (this.value != null) { + this.codec.encodeStart(NbtOps.INSTANCE, this.value) + .result() + .ifPresent(nbtElement -> ret.put("Value", nbtElement)); + } + + return ret; } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java index 1ef0b12266..72638416ac 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java @@ -22,9 +22,10 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtList; import net.minecraft.util.collection.DefaultedList; -public interface InventoryComponent extends NbtComponent, Inventory { +public interface InventoryComponent extends NbtComponent, Inventory { @Override default int size() { return this.getStacks().size(); @@ -83,13 +84,20 @@ default byte nbtType() { } @Override - default void read(NbtCompound nbt) { - Inventories.readNbt(nbt, this.getStacks()); + default void read(NbtList nbt) { + for (int i = 0; i < nbt.size(); i++) { + this.setStack(i, ItemStack.fromNbt(nbt.getCompound(i))); + } } @Override - default NbtCompound write() { - return Inventories.writeNbt(new NbtCompound(), this.getStacks()); + default NbtList write() { + var nbt = new NbtList(); + for (int i = 0; i < this.getStacks().size(); i++) { + nbt.add(this.getStack(i).writeNbt(new NbtCompound())); + } + + return nbt; } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java index 5b06c5c2ef..24bff3aa02 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java @@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; -public class SyncedGenericComponent extends GenericComponent implements SyncedComponent { +public class SyncedGenericComponent extends GenericComponent implements SyncedComponent { private final NetworkCodec networkCodec; @Nullable private final Runnable syncOperation; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/DynamicInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/DynamicInjectionPredicate.java similarity index 85% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/DynamicInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/DynamicInjectionPredicate.java index d47abddee8..6b86d16d4e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/DynamicInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/DynamicInjectionPredicate.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api; +package org.quiltmc.qsl.component.api.predicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -public interface DynamicInjectionPredicate extends CachedInjectionPredicate { +public interface DynamicInjectionPredicate extends InjectionPredicate { boolean canInject(ComponentProvider provider); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/CachedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/InjectionPredicate.java similarity index 87% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/CachedInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/InjectionPredicate.java index 1a79d87e06..adfaf5934b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/CachedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/InjectionPredicate.java @@ -14,8 +14,8 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api; +package org.quiltmc.qsl.component.api.predicate; -public interface CachedInjectionPredicate { +public interface InjectionPredicate { boolean isClassValid(Class clazz); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java index 1afc065ec6..447aadbd9c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java @@ -28,6 +28,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.impl.container.AbstractComponentContainer; @InjectedInterface({ Entity.class, @@ -38,7 +39,9 @@ MinecraftClient.class }) public interface ComponentProvider { - ComponentContainer getComponentContainer(); + default ComponentContainer getComponentContainer() { + throw new AbstractMethodError("You need to implement the getComponentContainer method on your provider!"); + } default Maybe expose(ComponentType id) { return Components.expose(id, this); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index d9a005207d..2f2da78fdc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -23,6 +23,8 @@ import net.minecraft.util.registry.SimpleRegistry; import org.jetbrains.annotations.ApiStatus; import org.quiltmc.qsl.component.api.*; +import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; +import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.cached.CachedInjectionManager; @@ -46,7 +48,7 @@ public class ComponentsImpl { public static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); - public static void inject(CachedInjectionPredicate predicate, ComponentEntry componentEntry) { + public static void inject(InjectionPredicate predicate, ComponentEntry componentEntry) { if (predicate instanceof DynamicInjectionPredicate dynamicPredicate) { DYNAMIC_MANAGER.inject(dynamicPredicate, componentEntry); } else { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java index b9d435e089..b595c89198 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java @@ -19,8 +19,10 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; +import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; public final class ClientResolution { @@ -35,4 +37,8 @@ public static Entity getEntity(int id) { public static Chunk getChunk(ChunkPos pos) { return MinecraftClient.getInstance().world.getChunk(pos.x, pos.z); } + + public static World getWorld(Identifier identifier) { + return MinecraftClient.getInstance().world; + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java index 449abf0c04..e1acd16434 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java @@ -20,6 +20,7 @@ import org.quiltmc.qsl.base.api.event.ListenerPhase; import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.quiltmc.qsl.lifecycle.api.event.ServerTickEvents; +import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; @ListenerPhase( callbackTarget = ServerTickEvents.End.class, @@ -29,5 +30,8 @@ public class ServerTickEventListener implements ServerTickEvents.End { @Override public void endServerTick(MinecraftServer server) { server.getComponentContainer().tick(server); + server.getWorlds().forEach(world -> { + // Add world ticking! + }); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java new file mode 100644 index 0000000000..288c47f9b2 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java @@ -0,0 +1,19 @@ +package org.quiltmc.qsl.component.impl.event; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import org.quiltmc.qsl.base.api.event.ListenerPhase; +import org.quiltmc.qsl.component.impl.CommonInitializer; +import org.quiltmc.qsl.component.impl.util.ComponentProviderState; +import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; + +@ListenerPhase( + callbackTarget = ServerWorldTickEvents.End.class, + namespace = CommonInitializer.MODID, path = "tick_world_container" +) +public class ServerWorldTickEventListener implements ServerWorldTickEvents.End { + @Override + public void endWorldTick(MinecraftServer server, ServerWorld world) { + ComponentProviderState.get(world).getComponentContainer().tick(world); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java index d9706aad05..573181bd6b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java @@ -19,6 +19,7 @@ import net.minecraft.util.Util; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.*; +import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; @@ -26,7 +27,7 @@ import java.util.*; import java.util.stream.Stream; -public abstract class InjectionManager

{ +public abstract class InjectionManager

{ private final Map>> injections = new HashMap<>(); private final Map, List> cache = new IdentityHashMap<>(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java index 385e3be8fc..6ceb1d5fae 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java @@ -16,7 +16,7 @@ package org.quiltmc.qsl.component.impl.injection.manager.cached; -import org.quiltmc.qsl.component.api.CachedInjectionPredicate; +import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.InjectionManager; @@ -24,7 +24,7 @@ import java.util.List; import java.util.Objects; -public class CachedInjectionManager extends InjectionManager> { +public class CachedInjectionManager extends InjectionManager> { @Override public List> getInjections(ComponentProvider provider) { Class providerClass = provider.getClass(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java index 8bdf35981b..28a16a4f8a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java @@ -17,7 +17,7 @@ package org.quiltmc.qsl.component.impl.injection.manager.dynamic; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.api.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.InjectionManager; import org.quiltmc.qsl.base.api.util.Maybe; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java index 791e21b082..c1709ce590 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java @@ -16,14 +16,14 @@ package org.quiltmc.qsl.component.impl.injection.predicate.cached; -import org.quiltmc.qsl.component.api.CachedInjectionPredicate; +import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import java.util.Arrays; import java.util.Objects; -public class ClassInjectionPredicate implements CachedInjectionPredicate { +public class ClassInjectionPredicate implements InjectionPredicate { protected final Class clazz; public ClassInjectionPredicate(Class clazz) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java index e227061e05..99ba7ce343 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java @@ -47,6 +47,6 @@ public String toString() { @Override public boolean isClassValid(Class clazz) { - return !this.exceptions.contains(clazz) && this.clazz == clazz || (clazz != null && this.isClassValid(clazz.getSuperclass())); + return super.isClassValid(clazz) && !this.exceptions.contains(clazz); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java index 83fad5bb81..95c5f6735d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java @@ -16,7 +16,7 @@ package org.quiltmc.qsl.component.impl.injection.predicate.dynamic; -import org.quiltmc.qsl.component.api.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java new file mode 100644 index 0000000000..04312ae3fc --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java @@ -0,0 +1,27 @@ +package org.quiltmc.qsl.component.impl.injection.predicate.dynamic; + +import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; +import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; + +import java.util.function.Predicate; + +public class DynamicWrappedPredicate

implements DynamicInjectionPredicate { + private final InjectionPredicate wrapped; + private final Predicate

predicate; + + public DynamicWrappedPredicate(InjectionPredicate wrapped, Predicate

predicate) { + this.wrapped = wrapped; + this.predicate = predicate; + } + + @Override + public boolean isClassValid(Class clazz) { + return this.wrapped.isClassValid(clazz); + } + + @Override + public boolean canInject(ComponentProvider provider) { + return this.predicate.test((P) provider); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java index f9b580fc8d..1db28cab31 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java @@ -18,6 +18,7 @@ import com.mojang.datafixers.util.Pair; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; @@ -26,6 +27,7 @@ import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; @@ -39,6 +41,7 @@ import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.IntFunction; +import java.util.function.Supplier; public record NetworkCodec(BiConsumer encoder, Function decoder) { @@ -83,12 +86,7 @@ public record NetworkCodec(BiConsumer encoder, ); public static final NetworkCodec> INVENTORY = list(ITEM_STACK, size -> DefaultedList.ofSize(size, ItemStack.EMPTY)); - public static final NetworkCodec BLOCK_ENTITY = - BLOCK_POS.map(BlockEntity::getPos, ClientResolution::getBlockEntity); - public static final NetworkCodec ENTITY = - INT.map(Entity::getId, ClientResolution::getEntity); - public static final NetworkCodec CHUNK = - CHUNK_POS.map(Chunk::getPos, ClientResolution::getChunk); + public static > NetworkCodec list(NetworkCodec entryCodec, IntFunction listFactory) { return new NetworkCodec<>( @@ -137,6 +135,13 @@ public static NetworkCodec> pair(NetworkCodec keyCodec, Net ); } + public static NetworkCodec empty(Supplier instanceProvider) { + return new NetworkCodec<>( + (buf, t) -> {}, + buf -> instanceProvider.get() + ); + } + public void encode(PacketByteBuf buf, T t) { this.encoder.accept(buf, t); } @@ -151,7 +156,4 @@ public NetworkCodec map(Function decoder, Function encoder) { buf -> encoder.apply(this.decoder.apply(buf)) ); } - - public record Thingy(Identifier id, String idString, int twelve) { - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java index cf38f20848..e61eaf4f9b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -25,10 +25,12 @@ import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.SimpleRegistry; +import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.CommonInitializer; +import org.quiltmc.qsl.component.impl.client.ClientResolution; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import org.quiltmc.qsl.networking.api.PacketByteBufs; @@ -44,22 +46,35 @@ public record SyncPacketHeader

(NetworkCodec

code public static final NetworkCodec> NETWORK_CODEC = NetworkCodec.INT.map(REGISTRY::getRawId, ClientSyncHandler.getInstance()::getHeader); - // The default implemented types, that can sync. - public static final SyncPacketHeader BLOCK_ENTITY = new SyncPacketHeader<>(NetworkCodec.BLOCK_ENTITY); - public static final SyncPacketHeader ENTITY = new SyncPacketHeader<>(NetworkCodec.ENTITY); - public static final SyncPacketHeader CHUNK = new SyncPacketHeader<>(NetworkCodec.CHUNK); - private static final NetworkCodec LEVEL_CODEC = new NetworkCodec<>( - (buf, provider) -> { - }, - buf -> MinecraftClient.getInstance() - ); - public static final SyncPacketHeader SAVE = new SyncPacketHeader<>(LEVEL_CODEC); + // BlockEntity + public static final NetworkCodec BLOCK_ENTITY_CODEC = + NetworkCodec.BLOCK_POS.map(BlockEntity::getPos, ClientResolution::getBlockEntity); + public static final SyncPacketHeader BLOCK_ENTITY = new SyncPacketHeader<>(BLOCK_ENTITY_CODEC); + + // Entity + public static final NetworkCodec ENTITY_CODEC = + NetworkCodec.INT.map(Entity::getId, ClientResolution::getEntity); + public static final SyncPacketHeader ENTITY = new SyncPacketHeader<>(ENTITY_CODEC); + + // Chunk + public static final NetworkCodec CHUNK_CODEC = + NetworkCodec.CHUNK_POS.map(Chunk::getPos, ClientResolution::getChunk); + public static final SyncPacketHeader CHUNK = new SyncPacketHeader<>(CHUNK_CODEC); + + // World + public static final NetworkCodec WORLD_CODEC = NetworkCodec.empty(() -> MinecraftClient.getInstance().world); + public static final SyncPacketHeader WORLD = new SyncPacketHeader<>(WORLD_CODEC); + + // Level aka Save + private static final NetworkCodec LEVEL_CODEC = NetworkCodec.empty(MinecraftClient::getInstance); + public static final SyncPacketHeader LEVEL = new SyncPacketHeader<>(LEVEL_CODEC); public static void registerDefaults() { register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); register(CommonInitializer.id("entity"), ENTITY); register(CommonInitializer.id("chunk"), CHUNK); - register(CommonInitializer.id("level"), SAVE); + register(CommonInitializer.id("world"), WORLD); + register(CommonInitializer.id("level"), LEVEL); } public static

void register(Identifier id, SyncPacketHeader

header) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java index a11ed7686f..3602506cad 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java @@ -80,7 +80,7 @@ private LazyComponentContainer initContainer(ServerWorld world) { return ComponentContainer.builder(this) .unwrap() .saving(this::markDirty) - .syncing(SyncPacketHeader.SAVE, world::getPlayers) + .syncing(SyncPacketHeader.LEVEL, world::getPlayers) .ticking() .build(LazyComponentContainer.FACTORY); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinBlockEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinBlockEntity.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java index f50c0f76ff..662014104b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinBlockEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java @@ -34,7 +34,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(BlockEntity.class) -public abstract class MixinBlockEntity implements ComponentProvider { +public abstract class BlockEntityMixin implements ComponentProvider { private ComponentContainer qsl$container; @Shadow diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinDirectBlockEntityTickInvoker.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinDirectBlockEntityTickInvoker.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java index db95321d32..c0814eaa61 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/MixinDirectBlockEntityTickInvoker.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java @@ -29,7 +29,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(WorldChunk.DirectBlockEntityTickInvoker.class) -public class MixinDirectBlockEntityTickInvoker { +public class DirectBlockEntityTickInvokerMixin { @Shadow @Final private T blockEntity; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunk.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java index 877c61fb7b..d1439413da 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java @@ -36,7 +36,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Chunk.class) -public abstract class MixinChunk implements ComponentProvider { +public abstract class ChunkMixin implements ComponentProvider { private ComponentContainer qsl$container; @Shadow diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunkSerializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkSerializerMixin.java similarity index 98% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunkSerializer.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkSerializerMixin.java index 679049a22a..7bb52b090c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinChunkSerializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkSerializerMixin.java @@ -30,7 +30,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ChunkSerializer.class) -public class MixinChunkSerializer { +public class ChunkSerializerMixin { @Inject(method = "deserialize", at = @At("RETURN"), cancellable = true) private static void deserializeComponents(ServerWorld world, PointOfInterestStorage poiStorage, ChunkPos pos, NbtCompound nbt, CallbackInfoReturnable cir) { var ret = cir.getReturnValue(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/MixinServerWorld.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ServerWorldMixin.java similarity index 75% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/MixinServerWorld.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ServerWorldMixin.java index 60d96986f6..32527f4216 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/MixinServerWorld.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ServerWorldMixin.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.mixin.world; +package org.quiltmc.qsl.component.mixin.chunk; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Holder; @@ -24,9 +24,7 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.dimension.DimensionType; -import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -35,18 +33,13 @@ import java.util.function.Supplier; @Mixin(ServerWorld.class) -public abstract class MixinServerWorld extends World implements ComponentProvider { - protected MixinServerWorld(MutableWorldProperties mutableWorldProperties, RegistryKey registryKey, Holder holder, Supplier supplier, boolean bl, boolean bl2, long l, int i) { +public abstract class ServerWorldMixin extends World implements ComponentProvider { + protected ServerWorldMixin(MutableWorldProperties mutableWorldProperties, RegistryKey registryKey, Holder holder, Supplier supplier, boolean bl, boolean bl2, long l, int i) { super(mutableWorldProperties, registryKey, holder, supplier, bl, bl2, l, i); } - @Override - public ComponentContainer getComponentContainer() { - return ComponentProviderState.get(this).getComponentContainer(); - } - @Inject(method = "tickChunk", at = @At("TAIL")) - private void tickContainer(WorldChunk chunk, int randomTickSpeed, CallbackInfo ci) { + private void tickChunkContainers(WorldChunk chunk, int randomTickSpeed, CallbackInfo ci) { chunk.getComponentContainer().tick(chunk); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinThreadedChunkStorage.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinThreadedChunkStorage.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java index 53ff9cf2a0..cf34e27a64 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinThreadedChunkStorage.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java @@ -27,7 +27,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ThreadedAnvilChunkStorage.class) -public abstract class MixinThreadedChunkStorage { +public abstract class ThreadedChunkStorageMixin { @Inject( method = "sendChunkDataPackets", diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinWorldChunk.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java similarity index 94% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinWorldChunk.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java index 9ac4d9951d..28a23c819c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/MixinWorldChunk.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java @@ -32,8 +32,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(WorldChunk.class) -public abstract class MixinWorldChunk extends Chunk implements ComponentProvider { - public MixinWorldChunk(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, @Nullable ChunkSection[] chunkSections, @Nullable BlendingData blendingData) { +public abstract class WorldChunkMixin extends Chunk implements ComponentProvider { + public WorldChunkMixin(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, @Nullable ChunkSection[] chunkSections, @Nullable BlendingData blendingData) { super(chunkPos, upgradeData, heightLimitView, registry, l, chunkSections, blendingData); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MixinMinecraftClient.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MinecraftClientMixin.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MixinMinecraftClient.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MinecraftClientMixin.java index b675aa746c..6b1f4ae9e6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MixinMinecraftClient.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MinecraftClientMixin.java @@ -27,7 +27,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(MinecraftClient.class) -public class MixinMinecraftClient implements ComponentProvider { +public class MinecraftClientMixin implements ComponentProvider { private ComponentContainer qsl$container; @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/MixinEntity.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/MixinEntity.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java index c7c8e31e09..ee86c030f2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/MixinEntity.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java @@ -32,7 +32,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Entity.class) -public abstract class MixinEntity implements ComponentProvider { +public abstract class EntityMixin implements ComponentProvider { private ComponentContainer qsl$container; @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/item/stack/MixinItemStack.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/item/stack/MixinItemStack.java deleted file mode 100644 index cc2d5b2f43..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/item/stack/MixinItemStack.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.mixin.item.stack; - -import net.minecraft.entity.Entity; -import net.minecraft.item.ItemConvertible; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.world.World; -import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.container.ComponentContainer; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@SuppressWarnings("ConstantConditions") -@Deprecated -@Mixin(ItemStack.class) -public abstract class MixinItemStack implements ComponentProvider { // TODO: Make sure nothing else may be broken before final PR. - @Shadow - private @Nullable NbtCompound nbt; - private LazyComponentContainer qsl$container; - - @Shadow - public abstract NbtCompound getOrCreateNbt(); - - @Override - public ComponentContainer getComponentContainer() { - return this.qsl$container; - } - - @Inject(method = "(Lnet/minecraft/item/ItemConvertible;I)V", at = @At("TAIL")) - private void initContainer(ItemConvertible itemConvertible, int i, CallbackInfo ci) { - this.qsl$container = ComponentContainer.builder(this) - .unwrap() - .saving(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) - .ticking() - .build(LazyComponentContainer.FACTORY); - } - - @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;)V", at = @At("TAIL")) - private void readContainer(NbtCompound nbtCompound, CallbackInfo ci) { - this.qsl$container = ComponentContainer.builder(this) - .unwrap() - .saving(() -> this.qsl$container.writeNbt(this.getOrCreateNbt())) - .ticking() - .build(LazyComponentContainer.FACTORY); - - if (this.nbt != null) { - this.qsl$container.readNbt(this.nbt); - } - } - - @Inject(method = "setNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;postProcessNbt(Lnet/minecraft/nbt/NbtCompound;)V")) - private void readContainerAgain(NbtCompound nbt, CallbackInfo ci) { - if (this.qsl$container != null) { - this.qsl$container.readNbt(this.nbt); - } - } - - @Inject(method = "copy", at = @At(value = "RETURN", ordinal = 1)) - private void deserializeContainer(CallbackInfoReturnable cir) { - ItemStack copiedStack = cir.getReturnValue(); - NbtCompound nbt = copiedStack.getNbt(); - if (nbt != null) { - copiedStack.getComponentContainer().readNbt(nbt); - } - } - - @Inject(method = "inventoryTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;inventoryTick(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;IZ)V")) - private void tickContainer(World world, Entity entity, int slot, boolean selected, CallbackInfo ci) { - this.qsl$container.tick(this); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MixinMinecraftServer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java similarity index 94% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MixinMinecraftServer.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java index e7c0f39be3..14af2189c4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MixinMinecraftServer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java @@ -23,7 +23,7 @@ import org.spongepowered.asm.mixin.Mixin; @Mixin(MinecraftServer.class) -public abstract class MixinMinecraftServer implements ComponentProvider { +public abstract class MinecraftServerMixin implements ComponentProvider { @Override public ComponentContainer getComponentContainer() { return ComponentProviderState.getGlobal(this).getComponentContainer(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java new file mode 100644 index 0000000000..37b825d2e5 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java @@ -0,0 +1,15 @@ +package org.quiltmc.qsl.component.mixin.world; + +import net.minecraft.world.World; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.util.ComponentProviderState; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(World.class) +public class WorldMixin implements ComponentProvider { + @Override + public ComponentContainer getComponentContainer() { + return ComponentProviderState.get(this).getComponentContainer(); + } +} diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index 75ae4e96a7..46e449da60 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -3,19 +3,19 @@ "package": "org.quiltmc.qsl.component.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "block.entity.MixinBlockEntity", - "chunk.MixinChunk", - "chunk.MixinChunkSerializer", - "block.entity.MixinDirectBlockEntityTickInvoker", - "entity.MixinEntity", - "item.stack.MixinItemStack", - "level.MixinMinecraftServer", - "world.MixinServerWorld", - "chunk.MixinThreadedChunkStorage", - "chunk.MixinWorldChunk" + "block.entity.BlockEntityMixin", + "block.entity.DirectBlockEntityTickInvokerMixin", + "chunk.ChunkMixin", + "chunk.ChunkSerializerMixin", + "chunk.ServerWorldMixin", + "chunk.ThreadedChunkStorageMixin", + "chunk.WorldChunkMixin", + "entity.EntityMixin", + "level.MinecraftServerMixin", + "world.WorldMixin" ], "client": [ - "client.level.MixinMinecraftClient" + "client.level.MinecraftClientMixin" ], "injectors": { "defaultRequire": 1 diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index c08a9cf822..f2435f4ead 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -25,10 +25,8 @@ import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.nbt.NbtLongArray; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; @@ -38,7 +36,6 @@ import net.minecraft.util.dynamic.Codecs; import net.minecraft.util.registry.Registry; import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.level.LevelProperties; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.block.entity.api.QuiltBlockEntityTypeBuilder; @@ -102,7 +99,7 @@ public class ComponentTestMod implements ModInitializer { new Identifier(ComponentTestMod.MODID, "test_be_int"), DefaultIntegerComponent::new ); - public static final ComponentType> UUID_THING = Components.register( + public static final ComponentType> UUID_THING = Components.register( new Identifier(MODID, "uuid_thing"), (saveOperation, syncOperation) -> new GenericComponent<>(saveOperation, Codecs.UUID) ); @@ -162,14 +159,12 @@ public void onInitialize(ModContainer mod) { Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); -// Components.inject(LevelProperties.class, SAVE_FLOAT); - Components.injectInheritage(ServerPlayerEntity.class, PLAYER_TICK); Components.inject(MinecraftServer.class, SERVER_TICK); + Components.injectInheritage(ServerPlayerEntity.class, PLAYER_TICK); Components.inject(ServerPlayerEntity.class, UUID_THING); - Components.inject(ComponentProviderState.class, SAVE_FLOAT); // FIXME + Components.inject(ComponentProviderState.class, SAVE_FLOAT); // Dynamic Injection - Components.injectDynamic(PlayerEntity.class, SAVE_FLOAT, player -> player.world.isClient); } public static final BlockEntityType TEST_BE_TYPE = From aefd5bf82e34cfb0c7dd164dd0a58079af81d41e Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 12 Jul 2022 22:27:05 +0300 Subject: [PATCH 52/70] Cleaned up networking code. --- .../component/impl/sync/SyncPlayerList.java | 5 ++++ .../impl/sync/codec/NetworkCodec.java | 21 +++++++-------- .../impl/sync/header/SyncPacketHeader.java | 27 ++++++++++--------- .../impl/sync/packet/SyncPacket.java | 8 +++--- .../impl/util/ComponentProviderState.java | 24 ++++++++++++----- 5 files changed, 51 insertions(+), 34 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java index 2e83cd9539..ca13c092be 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java @@ -28,6 +28,7 @@ import java.util.Collection; import java.util.List; import java.util.Objects; +import java.util.function.Supplier; public final class SyncPlayerList { public static Collection create(World world, BlockPos pos) { @@ -49,4 +50,8 @@ public static Collection create(WorldChunk chunk) { public static Collection create(ServerWorld world) { return PlayerLookup.world(world); } + + public static Collection create(World world) { + return world.isClient ? List.of() : PlayerLookup.world((ServerWorld) world); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java index 1db28cab31..41cb16a817 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java @@ -17,9 +17,6 @@ package org.quiltmc.qsl.component.impl.sync.codec; import com.mojang.datafixers.util.Pair; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; @@ -27,13 +24,8 @@ import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.impl.client.ClientResolution; -import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; +import org.quiltmc.qsl.component.impl.ComponentsImpl; import java.util.List; import java.util.Map; @@ -87,7 +79,6 @@ public record NetworkCodec(BiConsumer encoder, public static final NetworkCodec> INVENTORY = list(ITEM_STACK, size -> DefaultedList.ofSize(size, ItemStack.EMPTY)); - public static > NetworkCodec list(NetworkCodec entryCodec, IntFunction listFactory) { return new NetworkCodec<>( (buf, os) -> { @@ -137,7 +128,8 @@ public static NetworkCodec> pair(NetworkCodec keyCodec, Net public static NetworkCodec empty(Supplier instanceProvider) { return new NetworkCodec<>( - (buf, t) -> {}, + (buf, t) -> { + }, buf -> instanceProvider.get() ); } @@ -147,7 +139,12 @@ public void encode(PacketByteBuf buf, T t) { } public Maybe decode(PacketByteBuf buf) { - return Maybe.wrap(this.decoder.apply(buf)); + try { + return Maybe.just(this.decoder.apply(buf)); + } catch (IndexOutOfBoundsException e) { // An IOOB exception is thrown if the memory is either + ComponentsImpl.LOGGER.warn(e.getMessage()); + return Maybe.nothing(); + } } public NetworkCodec map(Function decoder, Function encoder) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java index e61eaf4f9b..84e6191735 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java @@ -49,46 +49,49 @@ public record SyncPacketHeader

(NetworkCodec

code // BlockEntity public static final NetworkCodec BLOCK_ENTITY_CODEC = NetworkCodec.BLOCK_POS.map(BlockEntity::getPos, ClientResolution::getBlockEntity); - public static final SyncPacketHeader BLOCK_ENTITY = new SyncPacketHeader<>(BLOCK_ENTITY_CODEC); + public static final SyncPacketHeader BLOCK_ENTITY = register("block_entity", BLOCK_ENTITY_CODEC); + // Entity public static final NetworkCodec ENTITY_CODEC = NetworkCodec.INT.map(Entity::getId, ClientResolution::getEntity); - public static final SyncPacketHeader ENTITY = new SyncPacketHeader<>(ENTITY_CODEC); + public static final SyncPacketHeader ENTITY = register("entity", ENTITY_CODEC); // Chunk public static final NetworkCodec CHUNK_CODEC = NetworkCodec.CHUNK_POS.map(Chunk::getPos, ClientResolution::getChunk); - public static final SyncPacketHeader CHUNK = new SyncPacketHeader<>(CHUNK_CODEC); + public static final SyncPacketHeader CHUNK = register("chunk", CHUNK_CODEC); // World public static final NetworkCodec WORLD_CODEC = NetworkCodec.empty(() -> MinecraftClient.getInstance().world); - public static final SyncPacketHeader WORLD = new SyncPacketHeader<>(WORLD_CODEC); + public static final SyncPacketHeader WORLD = register("world", WORLD_CODEC); // Level aka Save private static final NetworkCodec LEVEL_CODEC = NetworkCodec.empty(MinecraftClient::getInstance); - public static final SyncPacketHeader LEVEL = new SyncPacketHeader<>(LEVEL_CODEC); + public static final SyncPacketHeader LEVEL = register("level", LEVEL_CODEC); public static void registerDefaults() { - register(CommonInitializer.id("block_entity"), BLOCK_ENTITY); - register(CommonInitializer.id("entity"), ENTITY); - register(CommonInitializer.id("chunk"), CHUNK); - register(CommonInitializer.id("world"), WORLD); - register(CommonInitializer.id("level"), LEVEL); + // Only exists to make sure these fields are classloaded before registries are frozen. + } + + private static

SyncPacketHeader

register(String id, NetworkCodec

codec) { + SyncPacketHeader

header = new SyncPacketHeader<>(codec); + register(CommonInitializer.id(id), header); + return header; } public static

void register(Identifier id, SyncPacketHeader

header) { Registry.register(REGISTRY, id, header); } - public static Maybe toProvider(PacketByteBuf buf) { + public static Maybe fromBuffer(PacketByteBuf buf) { return NETWORK_CODEC.decode(buf) .map(SyncPacketHeader::codec) .filterMap(networkCodec -> networkCodec.decode(buf)); } @SuppressWarnings("unchecked") - public PacketByteBuf start(ComponentProvider provider) { + public PacketByteBuf toBuffer(ComponentProvider provider) { var buf = PacketByteBufs.create(); buf.writeInt(REGISTRY.getRawId(this)); // the person calling is responsible to make sure we get a valid provider instance! diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index bd4aa8b03e..2e1ecddae3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -39,10 +39,10 @@ public class SyncPacket { * */ public static void handle(PacketByteBuf buf, MinecraftClient client) { - buf.retain(); + buf.retain(); // We need the buffer to exist until the client next pulls tasks on the main thread! client.execute(() -> { - SyncPacketHeader.toProvider(buf).ifJust(provider -> { + SyncPacketHeader.fromBuffer(buf).ifJust(provider -> { var size = buf.readInt(); for (int i = 0; i < size; i++) { @@ -53,7 +53,7 @@ public static void handle(PacketByteBuf buf, MinecraftClient client) { } }); - buf.release(); + buf.release(); // Make sure the buffer is cleared! }); } @@ -73,7 +73,7 @@ public static void syncFromQueue( return; } - PacketByteBuf buf = context.header().start(provider); + PacketByteBuf buf = context.header().toBuffer(provider); buf.writeInt(pendingSync.size()); while (!pendingSync.isEmpty()) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java index 3602506cad..26a9145e9d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java @@ -20,9 +20,11 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; import net.minecraft.world.PersistentState; +import net.minecraft.world.World; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; +import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; public class ComponentProviderState extends PersistentState implements ComponentProvider { @@ -31,23 +33,24 @@ public class ComponentProviderState extends PersistentState implements Component private final ComponentContainer container; - public ComponentProviderState(ServerWorld world) { - this.container = this.initContainer(world); + public ComponentProviderState(ServerWorld world, boolean level) { + this.container = this.initLevelContainer(world); } public ComponentProviderState(NbtCompound rootQslNbt, ServerWorld world) { - this.container = this.initContainer(world); + this.container = this.initLevelContainer(world); this.container.readNbt(rootQslNbt); } public static ComponentProviderState get(Object obj) { + // TODO: Client world treatment! if (!(obj instanceof ServerWorld world)) { throw ErrorUtil.illegalArgument("A ServerWorld instance needs to be provided to initialize a container!").get(); } return world.getPersistentStateManager().getOrCreate( nbtCompound -> new ComponentProviderState(nbtCompound, world), - () -> new ComponentProviderState(world), + () -> new ComponentProviderState(world, false), ID ); } @@ -60,7 +63,7 @@ public static ComponentProviderState getGlobal(Object obj) { ServerWorld overworld = server.getOverworld(); return overworld.getPersistentStateManager().getOrCreate( nbtCompound -> new ComponentProviderState(nbtCompound, overworld), - () -> new ComponentProviderState(overworld), + () -> new ComponentProviderState(overworld, true), GLOBAL_ID ); } @@ -76,7 +79,7 @@ public ComponentContainer getComponentContainer() { return this.container; } - private LazyComponentContainer initContainer(ServerWorld world) { + private LazyComponentContainer initLevelContainer(ServerWorld world) { return ComponentContainer.builder(this) .unwrap() .saving(this::markDirty) @@ -84,4 +87,13 @@ private LazyComponentContainer initContainer(ServerWorld world) { .ticking() .build(LazyComponentContainer.FACTORY); } + + private LazyComponentContainer initWorldContainer(World world) { + return ComponentContainer.builder(this) + .unwrap() + .saving(this::markDirty) + .syncing(SyncPacketHeader.LEVEL, () -> SyncPlayerList.create(world)) + .ticking() + .build(LazyComponentContainer.FACTORY); + } } From cf29d509eba34179d323091a2fa75dfc08112da2 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 12 Jul 2022 22:30:15 +0300 Subject: [PATCH 53/70] Reverted small mistake. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eebca9f8b3..fc3fbf4357 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -234,7 +234,7 @@ the actual name of the variable and the namespace. `@Unique` fields must be prefixed with `quilt$`, but `@Unique` methods don't need prefixes. In the case of a pseudo-local variable (a field used briefly to pass around a local variable of a method between 2 -componentEntries of said method), the field should be named with the namespace first, then the name of the injected method, +injections of said method), the field should be named with the namespace first, then the name of the injected method, and finally the name of the local (`quilt$injectedMethod$localName`). ## Gradle Conventions From ee09df53d2dd409cca8cb358de367285a6db7a0e Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 14 Jul 2022 22:05:42 +0300 Subject: [PATCH 54/70] Applied changes requested by EnnuiL --- .../org/quiltmc/qsl/base/api/util/Maybe.java | 3 +- library/data/component/build.gradle | 4 +-- .../qsl/component/api/ComponentType.java | 6 ++-- .../quiltmc/qsl/component/api/Components.java | 2 +- .../GenericComponent.java | 2 +- .../InventoryComponent.java | 2 +- .../NbtComponent.java | 8 ++--- .../SyncedComponent.java | 6 +--- .../SyncedGenericComponent.java | 2 +- .../TickingComponent.java | 2 +- .../api/components/FloatComponent.java | 26 ----------------- .../api/components/IntegerComponent.java | 29 ------------------- .../api/provider/ComponentProvider.java | 13 ++++----- .../qsl/component/impl/CommonInitializer.java | 4 +-- .../qsl/component/impl/ComponentsImpl.java | 2 +- .../components/DefaultFloatComponent.java | 7 ++--- .../components/DefaultIntegerComponent.java | 11 ++----- .../components/DefaultInventoryComponent.java | 4 +-- .../container/AbstractComponentContainer.java | 10 +++---- .../container/EmptyComponentContainer.java | 4 +-- .../container/LazyComponentContainer.java | 4 +-- .../event/ServerWorldTickEventListener.java | 3 +- .../impl/sync/packet/SyncPacket.java | 2 +- .../component/impl/util/StringConstants.java | 3 +- .../qsl/component/test/ComponentTestMod.java | 10 +++---- .../qsl/component/test/TestBlockEntity.java | 2 +- ...erer.java => TestBlockEntityRenderer.java} | 2 +- .../test/component/SaveFloatComponent.java | 2 +- .../MixinBlockEntityRendererFactories.java | 4 +-- .../test/mixin/client/MixinInGameHud.java | 4 +-- .../quilt_component_test.mixins.json | 1 - 31 files changed, 53 insertions(+), 131 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{components => component}/GenericComponent.java (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{components => component}/InventoryComponent.java (98%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{components => component}/NbtComponent.java (90%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{components => component}/SyncedComponent.java (83%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{components => component}/SyncedGenericComponent.java (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{components => component}/TickingComponent.java (94%) delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java rename library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/{TestBeRenderer.java => TestBlockEntityRenderer.java} (95%) diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java index f4ba765bff..0589f38a08 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java @@ -286,8 +286,7 @@ public static final class Nothing extends Maybe { */ private static final Nothing INSTANCE = new Nothing<>(); - private Nothing() { - } + private Nothing() { } /** * @see Maybe#map diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index d2739e7239..bbdeca361b 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -3,10 +3,10 @@ plugins { } qslModule { - name = "Quilt Component Attachment API" + name = "Quilt Component API" moduleName = "component" id = "quilt_component" - description = "API allowing attachment and querying of an ECS-like interface for entities, block-entities, chunks, etc." + description = "API allowing attachment and querying of an ECS-like interface to entities, block-entities, chunks, etc." library = "data" moduleDependencies { core { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 5e8ae5f13d..df67bfa3c5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -50,12 +50,10 @@ public T create(Runnable saveOperation, Runnable syncOperation) { public static class Static { private final Map, Component> staticInstances = new IdentityHashMap<>(); - private Static() { - - } + private Static() { } @SuppressWarnings("unchecked") - C getOrCreate(ComponentType type, Runnable saveOperation, Runnable syncOperation) { + public C getOrCreate(ComponentType type, Runnable saveOperation, Runnable syncOperation) { if (this.staticInstances.containsKey(type)) { return (C) this.staticInstances.get(type); } else { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 74db04ef55..905a3c3376 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -20,7 +20,7 @@ import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.ComponentsImpl; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java index d0a1abfd76..9ae0bfe93a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/GenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components; +package org.quiltmc.qsl.component.api.component; import com.mojang.serialization.Codec; import net.minecraft.nbt.NbtCompound; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java similarity index 98% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java index 72638416ac..3c78009b57 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components; +package org.quiltmc.qsl.component.api.component; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.Inventories; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java similarity index 90% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java index 9dd11218f2..e7d4af6737 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components; +package org.quiltmc.qsl.component.api.component; import net.minecraft.nbt.*; import net.minecraft.util.Identifier; @@ -33,14 +33,12 @@ static void readFrom(NbtComponent nbtComponent, Identifier id, NbtCompound ro case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); - case NbtElement.BYTE_ARRAY_TYPE -> - ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); + case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); case NbtElement.INT_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtIntArray) nbtTarget); - case NbtElement.LONG_ARRAY_TYPE -> - ((NbtComponent) nbtComponent).read((NbtLongArray) nbtTarget); + case NbtElement.LONG_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtLongArray) nbtTarget); default -> // We throw if we ever find a non-vanilla type trying to be used for component serialization! throw ErrorUtil.runtime( "The nbt data type with id %D is not vanilla!", diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java similarity index 83% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java index 65c52f1505..ff293d0222 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java @@ -14,15 +14,11 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components; +package org.quiltmc.qsl.component.api.component; import net.minecraft.network.PacketByteBuf; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; - -import java.util.function.Consumer; public interface SyncedComponent extends Component { void writeToBuf(PacketByteBuf buf); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java index 24bff3aa02..f8613a0f6b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/SyncedGenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components; +package org.quiltmc.qsl.component.api.component; import com.mojang.serialization.Codec; import net.minecraft.nbt.NbtElement; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/TickingComponent.java similarity index 94% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/TickingComponent.java index fb57049c5c..977c5f1f10 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/TickingComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/TickingComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.components; +package org.quiltmc.qsl.component.api.component; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.provider.ComponentProvider; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java deleted file mode 100644 index ccc6e2a6ce..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/FloatComponent.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.api.components; - -import org.quiltmc.qsl.component.api.Component; - - -public interface FloatComponent extends Component { - float get(); - - void set(float value); -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java deleted file mode 100644 index 8302e87f65..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/components/IntegerComponent.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.api.components; - -import org.quiltmc.qsl.component.api.Component; - -public interface IntegerComponent extends Component { - void increment(); - - void decrement(); - - void set(int value); - - int get(); -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java index 447aadbd9c..ef20aaa74b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java @@ -28,15 +28,14 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.impl.container.AbstractComponentContainer; @InjectedInterface({ - Entity.class, - BlockEntity.class, - Chunk.class, - ItemStack.class, - MinecraftServer.class, - MinecraftClient.class + Entity.class, + BlockEntity.class, + Chunk.class, + ItemStack.class, + MinecraftServer.class, + MinecraftClient.class }) public interface ComponentProvider { default ComponentContainer getComponentContainer() { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 4f7a8ad9ae..3d1d34a378 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -27,10 +27,10 @@ @ApiStatus.Internal public final class CommonInitializer implements ModInitializer { - public static final String MODID = "quilt_component"; + public static final String MOD_ID = "quilt_component"; public static Identifier id(String id) { - return new Identifier(MODID, id); + return new Identifier(MOD_ID, id); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 2f2da78fdc..d0719ced9d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -46,7 +46,7 @@ public class ComponentsImpl { public static final CachedInjectionManager CACHED_MANAGER = new CachedInjectionManager(); public static final DynamicInjectionManager DYNAMIC_MANAGER = new DynamicInjectionManager(); - public static final Logger LOGGER = LoggerFactory.getLogger("QSL/Components"); + public static final Logger LOGGER = LoggerFactory.getLogger("Quilt Component"); public static void inject(InjectionPredicate predicate, ComponentEntry componentEntry) { if (predicate instanceof DynamicInjectionPredicate dynamicPredicate) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java index 2c81977d36..1a7567d3b0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java @@ -19,10 +19,9 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtFloat; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.components.FloatComponent; -import org.quiltmc.qsl.component.api.components.NbtComponent; +import org.quiltmc.qsl.component.api.component.NbtComponent; -public class DefaultFloatComponent implements FloatComponent, NbtComponent { +public class DefaultFloatComponent implements NbtComponent { private float value; @Nullable private final Runnable saveOperation; @@ -36,12 +35,10 @@ public DefaultFloatComponent(@Nullable Runnable saveOperation, float initialValu this.saveOperation = saveOperation; } - @Override public float get() { return this.value; } - @Override public void set(float value) { this.value = value; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java index b2d54ca954..c2af551b71 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java @@ -20,11 +20,10 @@ import net.minecraft.nbt.NbtInt; import net.minecraft.network.PacketByteBuf; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.components.IntegerComponent; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.components.SyncedComponent; +import org.quiltmc.qsl.component.api.component.NbtComponent; +import org.quiltmc.qsl.component.api.component.SyncedComponent; -public class DefaultIntegerComponent implements IntegerComponent, NbtComponent, SyncedComponent { +public class DefaultIntegerComponent implements NbtComponent, SyncedComponent { private int value; @Nullable private final Runnable saveOperation; @@ -41,22 +40,18 @@ public DefaultIntegerComponent(@Nullable Runnable saveOperation, @Nullable Runna this.syncOperation = syncOperation; } - @Override public void increment() { this.value++; } - @Override public void decrement() { this.value--; } - @Override public void set(int value) { this.value = value; } - @Override public int get() { return this.value; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java index 45ea522943..44478f7b4c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java @@ -20,8 +20,8 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.util.collection.DefaultedList; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.components.InventoryComponent; -import org.quiltmc.qsl.component.api.components.SyncedComponent; +import org.quiltmc.qsl.component.api.component.InventoryComponent; +import org.quiltmc.qsl.component.api.component.SyncedComponent; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import java.util.Objects; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index 02990fa384..627b422e83 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -5,9 +5,9 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.*; -import org.quiltmc.qsl.component.api.components.NbtComponent; -import org.quiltmc.qsl.component.api.components.SyncedComponent; -import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.api.component.NbtComponent; +import org.quiltmc.qsl.component.api.component.SyncedComponent; +import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; @@ -113,7 +113,5 @@ protected COMP initializeComponent(ComponentEntry return component; } - public record ContainerOperations(Runnable saveOperation, - Function, Runnable> syncOperationFactory) { - } + public record ContainerOperations(Runnable saveOperation, Function, Runnable> syncOperationFactory) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java index 9a2e6e7666..c3af65dd38 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java @@ -29,9 +29,7 @@ public final class EmptyComponentContainer implements ComponentContainer { public static final ComponentContainer.Factory FACTORY = (provider, injections, saveOperation, ticking, syncContext) -> INSTANCE; - private EmptyComponentContainer() { - - } + private EmptyComponentContainer() { } @Override public Maybe expose(ComponentType type) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 71aeb10c00..be44bca596 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -68,9 +68,7 @@ public Maybe expose(ComponentType id) { } @Override - protected void addComponent(ComponentType type, Component component) { - - } + protected void addComponent(ComponentType type, Component component) { } private IdentityHashMap, Lazy> initializeComponents(ComponentProvider provider) { var map = new IdentityHashMap, Lazy>(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java index 288c47f9b2..217d078319 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java @@ -7,9 +7,10 @@ import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; +@SuppressWarnings("unused") @ListenerPhase( callbackTarget = ServerWorldTickEvents.End.class, - namespace = CommonInitializer.MODID, path = "tick_world_container" + namespace = CommonInitializer.MOD_ID, path = "tick_world_container" ) public class ServerWorldTickEventListener implements ServerWorldTickEvents.End { @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index 2e1ecddae3..cbaf0d3c39 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -21,7 +21,7 @@ import net.minecraft.server.network.ServerPlayerEntity; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.components.SyncedComponent; +import org.quiltmc.qsl.component.api.component.SyncedComponent; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.networking.api.ServerPlayNetworking; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java index 3a5e1e17f4..12b1039996 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java @@ -17,5 +17,6 @@ package org.quiltmc.qsl.component.impl.util; public final class StringConstants { - public static final String COMPONENT_ROOT = "QslComponentRoot"; + // TODO: Check about this key! + public static final String COMPONENT_ROOT = "QuiltComponentRoot"; } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index f2435f4ead..60dc098103 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -41,10 +41,10 @@ import org.quiltmc.qsl.block.entity.api.QuiltBlockEntityTypeBuilder; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.components.FloatComponent; -import org.quiltmc.qsl.component.api.components.GenericComponent; -import org.quiltmc.qsl.component.api.components.InventoryComponent; -import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.api.component.GenericComponent; +import org.quiltmc.qsl.component.api.component.InventoryComponent; +import org.quiltmc.qsl.component.api.component.TickingComponent; +import org.quiltmc.qsl.component.impl.components.DefaultFloatComponent; import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; import org.quiltmc.qsl.component.impl.components.DefaultInventoryComponent; import org.quiltmc.qsl.component.impl.util.ComponentProviderState; @@ -115,7 +115,7 @@ public class ComponentTestMod implements ModInitializer { var props = player.getWorld().getServer().getSaveProperties(); if (props instanceof MinecraftServer levelProperties && player.getWorld().getTime() % 100 == 0) { player.sendMessage(Text.literal( - levelProperties.expose(SAVE_FLOAT).map(FloatComponent::get).unwrapOr(0f).toString() + levelProperties.expose(SAVE_FLOAT).map(DefaultFloatComponent::get).unwrapOr(0f).toString() ), false); } player.expose(UUID_THING).ifJust(uuidGenericComponent -> { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index c5cc629903..0616db8dc9 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -31,7 +31,7 @@ import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.components.InventoryComponent; +import org.quiltmc.qsl.component.api.component.InventoryComponent; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java similarity index 95% rename from library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java index d3b05781b0..68185a5823 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBeRenderer.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java @@ -29,7 +29,7 @@ import java.util.function.Predicate; -public class TestBeRenderer implements BlockEntityRenderer { +public class TestBlockEntityRenderer implements BlockEntityRenderer { @Override public void render(TestBlockEntity entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { entity.expose(ComponentTestMod.CHUNK_INVENTORY) diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java index fb72284016..0b33ed5a27 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java @@ -18,7 +18,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.api.components.TickingComponent; +import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.impl.components.DefaultFloatComponent; public class SaveFloatComponent extends DefaultFloatComponent implements TickingComponent { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java index ec28c99872..71dc8c7d26 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java @@ -22,7 +22,7 @@ import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.test.ComponentTestMod; -import org.quiltmc.qsl.component.test.client.TestBeRenderer; +import org.quiltmc.qsl.component.test.client.TestBlockEntityRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -38,6 +38,6 @@ private static void register(BlockEntityType", at = @At("TAIL")) private static void registerCustom(CallbackInfo ci) { - register(ComponentTestMod.TEST_BE_TYPE, context -> new TestBeRenderer()); + register(ComponentTestMod.TEST_BE_TYPE, context -> new TestBlockEntityRenderer()); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index 0ae222e918..a9a08592d7 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -23,7 +23,7 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.util.math.ChunkPos; -import org.quiltmc.qsl.component.api.components.IntegerComponent; +import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; import org.quiltmc.qsl.component.test.ComponentTestMod; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -46,7 +46,7 @@ public abstract class MixinInGameHud { private void renderCustom(MatrixStack matrices, float tickDelta, CallbackInfo ci) { Entity entity = MinecraftClient.getInstance().targetedEntity; if (entity != null) { - entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).map(IntegerComponent::get).ifJust(integer -> { + entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).map(DefaultIntegerComponent::get).ifJust(integer -> { this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa); }); } diff --git a/library/data/component/src/testmod/resources/quilt_component_test.mixins.json b/library/data/component/src/testmod/resources/quilt_component_test.mixins.json index 2e67077741..eecf5ebf3e 100644 --- a/library/data/component/src/testmod/resources/quilt_component_test.mixins.json +++ b/library/data/component/src/testmod/resources/quilt_component_test.mixins.json @@ -2,7 +2,6 @@ "required": true, "package": "org.quiltmc.qsl.component.test.mixin", "compatibilityLevel": "JAVA_17", - "minVersion": "0.8", "mixins": [ ], "client": [ From b3904014dd290ec0b6d0fe0f8037b26577863973 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Fri, 15 Jul 2022 18:21:35 +0300 Subject: [PATCH 55/70] Applied suggestions Leo40Git --- .../org/quiltmc/qsl/base/api/util/Lazy.java | 324 ++++++++++++++++++ .../org/quiltmc/qsl/base/api/util/Maybe.java | 33 +- .../api/container/ComponentContainer.java | 2 +- .../container/SingleComponentContainer.java | 92 +++++ .../component/mixin/entity/EntityMixin.java | 2 +- 5 files changed, 447 insertions(+), 6 deletions(-) create mode 100644 library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java new file mode 100644 index 0000000000..cb496c9069 --- /dev/null +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java @@ -0,0 +1,324 @@ +package org.quiltmc.qsl.base.api.util; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * Represents a value that is only initialized once it's needed.
+ * Similar to {@link com.google.common.base.Suppliers#memoize}. + * + * @param The type of the value this {@link Lazy} represents. + */ +public sealed abstract class Lazy implements Supplier permits Lazy.Filled, Lazy.OfSupplier { + /** + * Wraps the provided {@link Supplier} into a {@link OfSupplier} instance. + * @param supplier The {@link Supplier} to a value. + * @return A new {@link OfSupplier} instance. + * @param The type of the wrapped value. + */ + public static Lazy of(Supplier supplier) { + return new OfSupplier<>(supplier); + } + + + + /** + * Returns an {@link Filled} instance wrapping the provided {@link T} value. + * + * @param value The value to wrap. + * @return A new {@link Filled} instance. + * @param The type of the wrapped value. + */ + public static Lazy filled(T value) { + return new Filled<>(value); + } + + /** + * Creates a new {@link Lazy} containing the current value mapped using the provided {@link Function}.
+ * This does not initialize the contained value! + * + * @param mapper + * @return + * @param The new contained type. + */ + public abstract Lazy map(Function mapper); + + /** + * If we contain a value, we instantly return the transformed version, using the {@link Function} provided.
+ * Otherwise, we return a new {@link Lazy} containing the value of the result of the mapper {@link Function}.
+ * This does not initialize the contained value! + * + * @param mapper The {@link Function} to use. + * @return The mapped {@link Lazy} value. + * @param The new contained type. + */ + public abstract Lazy flatMap(Function> mapper); + + /** + * Initializes the current {@link Lazy} and returns the result of applying the provided {@link Function} to the value.
+ * This initializes the contained value. + * + * @param function The {@link Function} to use. + * @return The {@link M} value produced from the application of the provided {@link Function}}. + * @param The return type. + */ + public M mapUnwrap(Function function) { + return function.apply(this.unwrap()); + } + + /** + * Whether the current {@link Lazy} has initialized its value. + * @return Whether the current {@link Lazy} contains an initialized value. + */ + public abstract boolean isFilled(); + + /** + * Applies the provided {@link Consumer} on the current value, if it is initialized. + * + * @param action The {@link Consumer} to apply the value to. + * @return This instance(for chaining). + */ + public abstract Lazy ifFilled(Consumer action); + + /** + * Runs the provided {@link Runnable}, if our value is not initialized.
+ * + * @param action The {@link Runnable} to run. + * @return This instance(for chaining). + */ + public abstract Lazy ifEmpty(Runnable action); + + /** + * Whether the current instance has an initialized value. + * + * @return Whether there is a value in this {@link Lazy} that is initialized. + */ + public abstract boolean isEmpty(); + + /** + * Initializes the current value and applies it to the provided {@link Consumer}.
+ * This initializes the contained value. + * + * @param action The {@link Consumer} to accept the current value. + * @return This instance(for chaining). + */ + public Lazy compute(Consumer action) { + action.accept(this.get()); + return this; + } + + /** + * @see Lazy#get + */ + public T unwrap() { + return this.get(); + } + + /** + * Returns the contained value if it is initialized, otherwise the provided {@link T} instance. + * This does not initialize the contained value. + * + * @param defaultValue The default {@link T} instance to return. + * @return The contained value or the provided {@link T}. + */ + public abstract T unwrapOr(T defaultValue); + + /** + * Works like {@link Lazy#unwrapOr} except the default {@link T} value is provided lazily. + * + * @param defaultSupplier A provider of a {@link T} instance. + * @return Either the contained value or the result of {@link Supplier#get} when called on the provided {@link Supplier}. + */ + public abstract T unwrapOrGet(Supplier defaultSupplier); + + /** + * A {@link Lazy} with an already initialized value.
+ * + * This class can either be created using the {@link Lazy#filled} method or by mapping a {@link Lazy} with an initialized value.
+ * A {@link Lazy} cannot be converted by itself into a {@link Filled}. + * @param The contained type. + */ + public static final class Filled extends Lazy { + private final T value; + + /** + * @param value The contained value. + */ + private Filled(T value) { + this.value = value; + } + + /** + * @see Lazy#get + */ + @Override + public T get() { + return this.value; + } + + /** + * @see Lazy#map + */ + @Override + public Lazy map(Function mapper) { + return filled(mapper.apply(this.value)); + } + + /** + * @see Lazy#flatMap + */ + @Override + public Lazy flatMap(Function> mapper) { + return mapper.apply(this.get()); + } + + /** + * @see Lazy#isFilled + */ + @Override + public boolean isFilled() { + return true; + } + + /** + * @see Lazy#ifFilled + */ + @Override + public Lazy ifFilled(Consumer action) { + action.accept(this.get()); + return this; + } + + /** + * @see Lazy#ifEmpty + */ + @Override + public Lazy ifEmpty(Runnable action) { + return this; + } + + /** + * @see Lazy#isEmpty + */ + @Override + public boolean isEmpty() { + return false; + } + + + /** + * @see Lazy#unwrapOr + */ + @Override + public T unwrapOr(T defaultValue) { + return this.value; + } + + /** + * @see Lazy#unwrapOrGet + */ + @Override + public T unwrapOrGet(Supplier defaultSupplier) { + return this.value; + } + } + + /** + * A {@link Lazy} with either an initialized value or not. + * @param + */ + public static final class OfSupplier extends Lazy { + private Supplier supplier; + // There is no overhead to using a Maybe here since Maybe has statically evaluated returns for Nothing instances.. + private Maybe value; + + /** + * @param supplier The {@link Supplier} used to initialize the value. + */ + private OfSupplier(Supplier supplier) { + this.supplier = supplier; + this.value = Maybe.nothing(); + } + + /** + * @see Lazy#get + */ + @Override + public T get() { + if (this.value.isNothing()) { + this.value = Maybe.just(this.supplier.get()); + this.supplier = null; + } + + return this.value.unwrap(); + } + + /** + * @see Lazy#map + */ + @Override + public Lazy map(Function mapper) { + return this.value.isJust() ? filled(mapper.apply(this.get())) : of(() -> mapper.apply(this.supplier.get())); + } + + /** + * @see Lazy#flatMap + */ + @Override + public Lazy flatMap(Function> mapper) { + return this.value.isJust() ? mapper.apply(this.get()) : of(() -> mapper.apply(this.get()).get()); + } + + /** + * @see Lazy#isFilled + */ + @Override + public boolean isFilled() { + return this.value.isJust(); + } + + /** + * @see Lazy#ifFilled + */ + @Override + public Lazy ifFilled(Consumer action) { + this.value.ifJust(action); + return this; + } + + /** + * @see Lazy#ifEmpty + */ + @Override + public Lazy ifEmpty(Runnable action) { + this.value.ifNothing(action); + return this; + } + + + /** + * @see Lazy#isEmpty + */ + @Override + public boolean isEmpty() { + return this.value.isNothing(); + } + + /** + * @see Lazy#unwrapOr + */ + @Override + public T unwrapOr(T defaultValue) { + return this.value.unwrapOr(defaultValue); + } + + /** + * @see Lazy#unwrapOrGet + */ + @Override + public T unwrapOrGet(Supplier defaultSupplier) { + return this.value.unwrapOrGet(defaultSupplier); + } + } +} diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java index 0589f38a08..d54843a4c3 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java @@ -31,7 +31,7 @@ * * Can either be {@link Just} or {@link Nothing}.
* {@link Just} instances contain a value of type {@link T}.
- * {@link Nothing} instance all reference the {@link Nothing} singleton and contain no data.
+ * {@link Nothing} instances all contain no data.
* * @param The type of the wrapped object * @author 0xJoeMama @@ -44,7 +44,7 @@ public sealed abstract class Maybe permits Maybe.Just, Maybe.Nothing { * @param value A {@link Nullable} value that will be wrapped into a {@link Maybe}. * @param The type of object the {@link Maybe} instance will hold. * @return An instance of {@link Just} if the provided value is not null,
- * otherwise the singleton {@link Nothing} instance. + * otherwise a {@link Nothing} instance. * @see Optional#ofNullable */ public static Maybe wrap(@Nullable T value) { @@ -68,7 +68,7 @@ public static Maybe just(T value) { * Similar function to {@link Optional#empty()}. * * @param The type the {@link Nothing} instance will take the form of. - * @return the singleton {@link Nothing} instance after casting it to the proper type. + * @return A {@link Nothing} instance after casting it to the proper type. * @see Optional#empty() */ @SuppressWarnings("unchecked") // Nothing doesn't contain a value, so we can freely cast it! @@ -258,7 +258,7 @@ public static Maybe fromOptional(Optional opt) { public abstract T unwrapOr(T defaultValue); /** - * Works like {@link Maybe#unwrapOr} except that it lazily evaluated the return value using the provided {@link Supplier}. + * Works like {@link Maybe#unwrapOr} except that it lazily evaluates the return value using the provided {@link Supplier}. * * @param supplier A {@link Supplier} that will create the {@link T} value to be returns if the current instance is {@link Nothing}. * @return The current {@link T} value if the current instance if {@link Just}, @@ -267,6 +267,15 @@ public static Maybe fromOptional(Optional opt) { */ public abstract T unwrapOrGet(Supplier supplier); + /** + * Works like {@link Maybe#unwrap} except it throws the provided {@link Throwable} and not the default one. + * + * @param throwableSupplier The {@link Throwable} to throw. + * @return The contained value, if it exists. + * @throws Throwable A customizable throwable. + */ + public abstract T unwrapOrThrow(Supplier throwableSupplier) throws Throwable; + /** * Turns the current {@link Maybe} instance into an {@link Optional}, for inter-operability. * @@ -385,6 +394,14 @@ public T unwrapOrGet(Supplier supplier) { return supplier.get(); } + /** + * @see Maybe#unwrapOrThrow + */ + @Override + public T unwrapOrThrow(Supplier throwableSupplier) throws Throwable { + throw throwableSupplier.get(); + } + /** * @see Maybe#toOptional */ @@ -504,6 +521,14 @@ public T unwrapOrGet(Supplier supplier) { return this.unwrap(); } + /** + * @see Maybe#unwrapOrThrow + */ + @Override + public T unwrapOrThrow(Supplier throwableSupplier) throws Throwable { + return this.unwrap(); + } + /** * @see Maybe#toOptional */ diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index 911edc8e3f..680e9c69a7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -19,6 +19,7 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.server.network.ServerPlayerEntity; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; @@ -27,7 +28,6 @@ import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; -import org.quiltmc.qsl.component.impl.util.Lazy; import java.util.ArrayList; import java.util.Collection; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java new file mode 100644 index 0000000000..c835290a3b --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java @@ -0,0 +1,92 @@ +package org.quiltmc.qsl.component.impl.container; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.base.api.util.Lazy; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.component.NbtComponent; +import org.quiltmc.qsl.component.api.component.SyncedComponent; +import org.quiltmc.qsl.component.api.component.TickingComponent; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; + +import java.util.function.Supplier; + +public class SingleComponentContainer implements ComponentContainer { + private final ComponentType type; + private final Maybe syncContext; + private final boolean ticking; + private Lazy entry; + private boolean shouldSync = false; + + private SingleComponentContainer(ComponentType type, boolean ticking, @Nullable SyncPacket.SyncContext syncContext) { + this.type = type; + this.ticking = ticking; + this.syncContext = Maybe.wrap(syncContext); + } + + private void setLazy(Supplier supplier) { + this.entry = Lazy.of(supplier); + } + + public static ComponentContainer.Factory> createFactory(ComponentEntry entry) { + return (provider, ignored, saveOperation, ticking, syncContext) -> { + ComponentType type = entry.type(); + var container = new SingleComponentContainer<>(type, ticking, syncContext); + container.setLazy(() -> entry.apply(saveOperation, () -> container.shouldSync = true)); + + return container; + }; + } + + @Override + public Maybe expose(ComponentType type) { + return type == this.type ? Maybe.just(this.entry.get()) : Maybe.nothing(); + } + + @Override + public void writeNbt(NbtCompound providerRootNbt) { + this.entry.ifFilled(c -> { + if (c instanceof NbtComponent nbtComponent) { + NbtComponent.writeTo(providerRootNbt, nbtComponent, this.type.id()); + } + }); + } + + @Override + public void readNbt(NbtCompound providerRootNbt) { + String idString = this.type.id().toString(); + if (providerRootNbt.getKeys().contains(idString)) { + this.expose(this.type) + .map(it -> ((NbtComponent) it)) + .ifJust(nbtComponent -> NbtComponent.readFrom(nbtComponent, this.type.id(), providerRootNbt)); + } + } + + @Override + public void tick(ComponentProvider provider) { + if (this.ticking) { + this.expose(this.type) + .map(it -> ((TickingComponent) it)) + .ifJust(tickingComponent -> tickingComponent.tick(provider)); + } + } + + @Override + public void sync(ComponentProvider provider) { + if (this.shouldSync) { + this.syncContext.ifJust(ctx -> { + PacketByteBuf buf = ctx.header().toBuffer(provider); + buf.writeInt(1); + ComponentType.NETWORK_CODEC.encode(buf, this.type); + ((SyncedComponent) this.entry.get()).writeToBuf(buf); + SyncPacket.send(ctx, buf); + }); + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java index ee86c030f2..03bf984779 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java @@ -62,6 +62,6 @@ private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { @Inject(method = "tick", at = @At("TAIL")) private void tickContainer(CallbackInfo ci) { - this.getComponentContainer().tick(this); + this.qsl$container.tick(this); } } From 436f55d2cec4ca2c16c1a72830d1b89d64f53170 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sat, 16 Jul 2022 16:05:10 +0300 Subject: [PATCH 56/70] Applied Leo40Git's suggestions + other minor changes. --- .../org/quiltmc/qsl/base/api/util/Maybe.java | 6 +- .../DefaultFloatComponent.java | 2 +- .../DefaultIntegerComponent.java | 2 +- .../DefaultInventoryComponent.java | 2 +- .../container/LazyComponentContainer.java | 4 +- .../quiltmc/qsl/component/impl/util/Lazy.java | 84 ------------------- .../qsl/component/test/ComponentTestMod.java | 6 +- .../test/component/SaveFloatComponent.java | 2 +- .../test/mixin/client/MixinInGameHud.java | 2 +- 9 files changed, 13 insertions(+), 97 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/{components => component}/DefaultFloatComponent.java (96%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/{components => component}/DefaultIntegerComponent.java (97%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/{components => component}/DefaultInventoryComponent.java (98%) delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java index d54843a4c3..ec2ca9e3c5 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java @@ -274,7 +274,7 @@ public static Maybe fromOptional(Optional opt) { * @return The contained value, if it exists. * @throws Throwable A customizable throwable. */ - public abstract T unwrapOrThrow(Supplier throwableSupplier) throws Throwable; + public abstract T unwrapOrThrow(Supplier throwableSupplier) throws E; /** * Turns the current {@link Maybe} instance into an {@link Optional}, for inter-operability. @@ -398,7 +398,7 @@ public T unwrapOrGet(Supplier supplier) { * @see Maybe#unwrapOrThrow */ @Override - public T unwrapOrThrow(Supplier throwableSupplier) throws Throwable { + public T unwrapOrThrow(Supplier throwableSupplier) throws E { throw throwableSupplier.get(); } @@ -525,7 +525,7 @@ public T unwrapOrGet(Supplier supplier) { * @see Maybe#unwrapOrThrow */ @Override - public T unwrapOrThrow(Supplier throwableSupplier) throws Throwable { + public T unwrapOrThrow(Supplier throwableSupplier) throws E { return this.unwrap(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java index 1a7567d3b0..551a09c0b5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.components; +package org.quiltmc.qsl.component.impl.component; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtFloat; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java index c2af551b71..9efa7f5327 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.components; +package org.quiltmc.qsl.component.impl.component; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtInt; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java similarity index 98% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java index 44478f7b4c..96709a42a3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/components/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.components; +package org.quiltmc.qsl.component.impl.component; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index be44bca596..8a6acf3bb7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -17,6 +17,7 @@ package org.quiltmc.qsl.component.impl.container; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.container.ComponentContainer; @@ -25,7 +26,6 @@ import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; -import org.quiltmc.qsl.component.impl.util.Lazy; import java.util.IdentityHashMap; import java.util.List; @@ -48,7 +48,7 @@ protected LazyComponentContainer( } public static void move(LazyComponentContainer from, LazyComponentContainer into) { - from.components.forEach((id, componentLazy) -> componentLazy.ifPresent(component -> { + from.components.forEach((id, componentLazy) -> componentLazy.ifFilled(component -> { into.components.put(id, componentLazy); // Directly overriding our value. })); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java deleted file mode 100644 index ee8f6bb636..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/Lazy.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.impl.util; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -public class Lazy { - @NotNull - private final Supplier sup; - @Nullable - private T value; - - private Lazy(@NotNull Supplier sup) { - this.sup = sup; - this.value = null; - } - - private Lazy(@NotNull T value) { - this.value = value; - this.sup = () -> value; - } - - @NotNull - public static Lazy filled(@NotNull T value) { - return new Lazy<>(value); - } - - @NotNull - public static Lazy of(@NotNull Supplier sup) { - return new Lazy<>(sup); - } - - @NotNull - public Supplier getSupplier() { - return sup; - } - - @NotNull - public Lazy map(@NotNull Function func) { - return Lazy.of(() -> func.apply(this.get())); - } - - @NotNull - public T get() { - if (value == null) { - this.value = sup.get(); - } - - return value; - } - - public void ifPresent(@NotNull Consumer action) { - if (!this.isEmpty()) { - action.accept(this.get()); - } - } - - public boolean isEmpty() { - return this.value == null; - } - - public void compute(@NotNull Consumer action) { - action.accept(this.get()); - } -} diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 60dc098103..a308a0f682 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -44,9 +44,9 @@ import org.quiltmc.qsl.component.api.component.GenericComponent; import org.quiltmc.qsl.component.api.component.InventoryComponent; import org.quiltmc.qsl.component.api.component.TickingComponent; -import org.quiltmc.qsl.component.impl.components.DefaultFloatComponent; -import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; -import org.quiltmc.qsl.component.impl.components.DefaultInventoryComponent; +import org.quiltmc.qsl.component.impl.component.DefaultFloatComponent; +import org.quiltmc.qsl.component.impl.component.DefaultIntegerComponent; +import org.quiltmc.qsl.component.impl.component.DefaultInventoryComponent; import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.quiltmc.qsl.component.test.component.SaveFloatComponent; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java index 0b33ed5a27..f680bc65a3 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java @@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.component.TickingComponent; -import org.quiltmc.qsl.component.impl.components.DefaultFloatComponent; +import org.quiltmc.qsl.component.impl.component.DefaultFloatComponent; public class SaveFloatComponent extends DefaultFloatComponent implements TickingComponent { public SaveFloatComponent(@Nullable Runnable saveOperation, @Nullable Runnable ignored) { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index a9a08592d7..5d378085c1 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -23,7 +23,7 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.util.math.ChunkPos; -import org.quiltmc.qsl.component.impl.components.DefaultIntegerComponent; +import org.quiltmc.qsl.component.impl.component.DefaultIntegerComponent; import org.quiltmc.qsl.component.test.ComponentTestMod; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; From 21444390e76d54eed0e3e3809aeb7635cefac0cf Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 18 Jul 2022 20:04:49 +0300 Subject: [PATCH 57/70] Major Rewrite + Docs(doesn't function right now) --- .../org/quiltmc/qsl/base/api/util/Lazy.java | 6 +- .../org/quiltmc/qsl/base/api/util/Maybe.java | 4 +- .../qsl/base/api/util/TwoWayFunction.java | 23 ++++ library/data/component/build.gradle | 6 +- .../quiltmc/qsl/component/api/Component.java | 53 +++++++- .../qsl/component/api/ComponentType.java | 66 +++++++++- .../quiltmc/qsl/component/api/Components.java | 121 +++++++++++++++++- .../api/component/GenericComponent.java | 9 +- .../api/component/InventoryComponent.java | 18 +-- .../api/component/SyncedComponent.java | 2 +- .../api/component/SyncedGenericComponent.java | 15 +-- .../api/container/ComponentContainer.java | 40 ++++-- .../qsl/component/api/package-info.java | 112 ++++++++++++++++ .../qsl/component/impl/CommonInitializer.java | 4 +- .../qsl/component/impl/ComponentsImpl.java | 6 - .../impl/client/ClientInitializer.java | 3 +- .../client/{ => sync}/ClientResolution.java | 5 +- .../impl/client/sync/ClientSyncHandler.java | 24 ++-- .../impl/component/DefaultFloatComponent.java | 9 +- .../component/DefaultIntegerComponent.java | 31 +---- .../component/DefaultInventoryComponent.java | 37 +----- .../container/AbstractComponentContainer.java | 41 +++--- .../CompositeComponentContainer.java | 48 +++++++ .../container/EmptyComponentContainer.java | 2 +- .../container/LazyComponentContainer.java | 15 +-- .../container/OnAccessComponentContainer.java | 54 ++++---- .../container/SimpleComponentContainer.java | 9 +- .../container/SingleComponentContainer.java | 43 ++++--- .../impl/event/ServerTickEventListener.java | 5 - .../event/ServerWorldTickEventListener.java | 3 +- .../impl/injection/ComponentEntry.java | 7 +- .../dynamic/DynamicInjectionManager.java | 3 +- .../DynamicClassInjectionPredicate.java | 2 + .../dynamic/DynamicWrappedPredicate.java | 1 + .../impl/sync/ServerSyncHandler.java | 11 +- .../qsl/component/impl/sync/SyncChannel.java | 98 ++++++++++++++ .../component/impl/sync/SyncPlayerList.java | 57 --------- .../impl/sync/codec/NetworkCodec.java | 2 +- .../impl/sync/header/SyncPacketHeader.java | 101 --------------- .../component/impl/sync/packet/PacketIds.java | 7 +- .../impl/sync/packet/RegistryPacket.java | 12 +- .../impl/sync/packet/SyncPacket.java | 84 +++++------- .../impl/util/ComponentProviderState.java | 72 ++++++----- .../component/impl/util/StringConstants.java | 1 - .../mixin/block/entity/BlockEntityMixin.java | 9 +- .../qsl/component/mixin/chunk/ChunkMixin.java | 10 +- .../chunk/ThreadedChunkStorageMixin.java | 3 +- .../client/level/MinecraftClientMixin.java | 42 ------ .../component/mixin/entity/EntityMixin.java | 9 +- .../mixin/level/MinecraftServerMixin.java | 3 +- .../level/client/MinecraftClientMixin.java | 26 ++++ .../qsl/component/mixin/world/WorldMixin.java | 3 +- .../resources/quilt_component.mixins.json | 2 +- .../qsl/component/test/ComponentTestMod.java | 26 ++-- .../component/test/ServerTickListener.java | 27 +--- .../qsl/component/test/TestBlockEntity.java | 31 +---- .../test/client/ComponentTestModClient.java | 1 + .../test/component/SaveFloatComponent.java | 31 ++++- .../test/mixin/client/MixinInGameHud.java | 13 +- 59 files changed, 894 insertions(+), 614 deletions(-) create mode 100644 library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/{ => sync}/ClientResolution.java (90%) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MinecraftClientMixin.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java index cb496c9069..91337ca062 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java @@ -21,8 +21,6 @@ public static Lazy of(Supplier supplier) { return new OfSupplier<>(supplier); } - - /** * Returns an {@link Filled} instance wrapping the provided {@link T} value. * @@ -38,8 +36,8 @@ public static Lazy filled(T value) { * Creates a new {@link Lazy} containing the current value mapped using the provided {@link Function}.
* This does not initialize the contained value! * - * @param mapper - * @return + * @param mapper The function to apply to the contained value. + * @return A new {@link Lazy} instance, that may or may not be initialized that contains the mapped value. * @param The new contained type. */ public abstract Lazy map(Function mapper); diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java index ec2ca9e3c5..db00ff6eca 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java @@ -272,7 +272,7 @@ public static Maybe fromOptional(Optional opt) { * * @param throwableSupplier The {@link Throwable} to throw. * @return The contained value, if it exists. - * @throws Throwable A customizable throwable. + * @throws E A customizable throwable. */ public abstract T unwrapOrThrow(Supplier throwableSupplier) throws E; @@ -525,7 +525,7 @@ public T unwrapOrGet(Supplier supplier) { * @see Maybe#unwrapOrThrow */ @Override - public T unwrapOrThrow(Supplier throwableSupplier) throws E { + public T unwrapOrThrow(Supplier throwableSupplier) { return this.unwrap(); } diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java new file mode 100644 index 0000000000..68683cb941 --- /dev/null +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java @@ -0,0 +1,23 @@ +package org.quiltmc.qsl.base.api.util; + +/** + * Represents an object that can trasmute between 2 types of objects provided it has one of them available. + * + * @param The first object type + * @param The second object type + */ +public interface TwoWayFunction { + /** + * Transform a {@link U} instance into a {@link T} instance. + * @param u The {@link U} instance to transform. + * @return The produced {@link T} instance + */ + T to(U u); + + /** + * Transform a {@link T} instance into a {@link U} instance. + * @param t The {@link T} instance to transform. + * @return The produced {@link T} instance. + */ + U from(T t); +} diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index bbdeca361b..da70659ab8 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -52,9 +52,9 @@ qslModule { values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } - injectedInterface("net/minecraft/class_1799") { // ItemStack - values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] - } +// injectedInterface("net/minecraft/class_1799") { // ItemStack +// values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] +// } injectedInterface("net/minecraft/class_310") { // MinecraftClient values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java index 7ac60904a4..354534c765 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java @@ -16,9 +16,60 @@ package org.quiltmc.qsl.component.api; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +/** + * Marks a type as a container for data and/or behaviour. + * + * @author 0xJoeMama + */ public interface Component { + /** + * Class meant to provide a component using the provided {@link Operations} argument. + * + * @param The type of the returned {@link Component}. + * @author 0xJoeMama + */ @FunctionalInterface interface Factory { - T create(Runnable saveOperation, Runnable syncOperation); + /** + * @param operations The {@link Operations} that the {@link Component} may use. + * @return A {@link T} instance. + */ + T create(Component.Operations operations); + } + + /** + * A list of method a {@link Component} may call when needed to interact with outside factors.
+ * The outside factors statement refers to things like the {@link org.quiltmc.qsl.component.api.container.ComponentContainer} + * or the {@link org.quiltmc.qsl.component.api.provider.ComponentProvider} this {@link Component} belongs to. + * + * @author 0xJoeMama + */ + @SuppressWarnings("ClassCanBeRecord") // we want the class to be extendable to people can create their own Operations + class Operations { + private final @Nullable Runnable saveOperation; + private final @Nullable Runnable syncOperation; + + /** + * Both of these parameters may be null, depending on the container this {@link Component} belongs to. + * + * @param saveOperation The action performed to cause an {@link org.quiltmc.qsl.component.api.component.NbtComponent} to issue a save to its {@linkplain org.quiltmc.qsl.component.api.provider.ComponentProvider provider}. + * @param syncOperation The action performed to cause a {@link org.quiltmc.qsl.component.api.component.SyncedComponent} to issue a sync to its {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer container}. + */ + public Operations(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation) { + this.saveOperation = saveOperation; + this.syncOperation = syncOperation; + } + + public @Nullable Runnable saveOperation() { + return this.saveOperation; + } + + public @Nullable Runnable syncOperation() { + return this.syncOperation; + } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index df67bfa3c5..16fc76d842 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -24,12 +24,39 @@ import java.util.IdentityHashMap; import java.util.Map; +/** + * A global identifier for a specific type of {@linkplain Component components}.
+ * This class must always exist as singleton instances, which have to be registered under the {@linkplain Components#REGISTRY registry}. + * + * @param id The {@link Identifier} the type is registered with(it's here just for accesibility, however you may also get access to it using the {@linkplain Components#REGISTRY registry} and a {@link ComponentType} instance). + * @param defaultFactory A factory to a default {@link Component} instance, that this type may produce, + * if no specific factory is defined under the container {@link org.quiltmc.qsl.component.impl.injection.ComponentEntry}.
+ * Used only during component injections or creation of {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer containers}. + * @param isStatic Whether this {@linkplain ComponentType type} works as a static type. + * @param isInstant Whether this {@linkplain ComponentType type} will be instantly initialized when put in a container. Useful for {@link org.quiltmc.qsl.component.api.component.TickingComponent}s or componens you want to initialize on {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer container} creation. + * @param The generic type of {@link Component} this type will provide. Most of the time, you would want this to be an interface providing all the needed API you may use to interact with a {@link Component} of this {@linkplain ComponentType type}. + * @author 0xJoeMama + */ public record ComponentType(Identifier id, Component.Factory defaultFactory, boolean isStatic, boolean isInstant) implements Component.Factory { + /** + * We provide a {@link NetworkCodec} to be used with manual registry sync, until the registry sync API is merged. + */ public static final NetworkCodec> NETWORK_CODEC = NetworkCodec.INT.map(Components.REGISTRY::getRawId, ClientSyncHandler.getInstance()::getType); + /** + * @see Static + */ private static final Static STATIC_CACHE = new Static(); + /** + * Performed an unchecked unsafe cast on the provided component.
+ * Used to attempt to translate any {@linkplain Component normal component} into a specific type. + * + * @param component The {@link Component} the cast is to be performed on. + * @return Instead of letting the {@link ClassCastException} be thrown on invalid casts, we catch it and return {@link Maybe#nothing()} if the component cannot be cast. + * Otherwise, we just wrap the cast result into a {@link Maybe}. + */ @SuppressWarnings("unchecked") public Maybe cast(Component component) { try { @@ -39,25 +66,52 @@ public Maybe cast(Component component) { } } + /** + * A {@linkplain ComponentType type} functions as its own {@link Component.Factory} using the provided {@link ComponentType#defaultFactory}. + * + * @param operations The {@link Component.Operations} that the {@link Component} may use. + * @return A {@link Component} of type {@link T}. + */ @Override - public T create(Runnable saveOperation, Runnable syncOperation) { - if (this.isStatic) { - return STATIC_CACHE.getOrCreate(this, saveOperation, syncOperation); + public T create(Component.Operations operations) { + if (this.isStatic) { // First check for static components + return STATIC_CACHE.getOrCreate(this, operations); } - return this.defaultFactory.create(saveOperation, syncOperation); + + // Otherwise just create a new one. + return this.defaultFactory.create(operations); } + /** + * Static components are singleton components, created only once during runtime.
+ * Most of the time this is useful for components that only provide behavior.
+ * Other use-cases may be quite rare.
+ * + * @author 0xJoeMama + * @see ComponentType + */ public static class Static { + /** + * We store singleton instances in an {@link IdentityHashMap} as is common practice when using {@link ComponentType}s as keys. + */ private final Map, Component> staticInstances = new IdentityHashMap<>(); private Static() { } + /** + * Performs simple lazy initialization on the provided {@link ComponentType static type} + * using the provided {@link org.quiltmc.qsl.component.api.Component.Operations} as initialization arguments. + * @param type The type of the component to be created. + * @param operations The operations to use as initialization arguments. + * @return A singleton {@link C} instance. + * @param The type of {@linkplain Component component} to be created. + */ @SuppressWarnings("unchecked") - public C getOrCreate(ComponentType type, Runnable saveOperation, Runnable syncOperation) { + public C getOrCreate(ComponentType type, Component.Operations operations) { if (this.staticInstances.containsKey(type)) { return (C) this.staticInstances.get(type); } else { - C singleton = type.defaultFactory.create(saveOperation, syncOperation); + C singleton = type.defaultFactory.create(operations); this.staticInstances.put(type, singleton); return singleton; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 905a3c3376..9d6c3ec163 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -19,6 +19,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; +import org.jetbrains.annotations.ApiStatus; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; @@ -35,46 +36,141 @@ import java.util.Set; import java.util.function.Predicate; +/** + * The external version of the component API, meant to be used by modders.
+ * Use this and not {@link ComponentsImpl}.
+ * + * For usage docs, check {@link package-info.java} + * + * @author 0xJoeMama + */ +@ApiStatus.Experimental public final class Components { + // begin registry + /** + * The registry used for {@link ComponentType}s. + */ public static final RegistryKey>> REGISTRY_KEY = ComponentsImpl.REGISTRY_KEY; public static final Registry> REGISTRY = ComponentsImpl.REGISTRY; - + // end registry + + // begin injection methods + /** + * The most manual method of injection.
+ * Callers can provide custom {@link InjectionPredicate}s and also custom {@linkplain ComponentEntry entries} + * @param predicate The {@linkplain InjectionPredicate predicate} used for the injection + * @param entry The {@linkplain ComponentEntry entry} used for the injection. + * @param The type of the injected component. + * @see InjectionPredicate + * @see ComponentEntry + */ public static void inject(InjectionPredicate predicate, ComponentEntry entry) { ComponentsImpl.inject(predicate, entry); } + /** + * The simplest method of injection.
+ * Injects the provided {@link ComponentType} into all direct instances of the provided {@link Class}. + * + * @param clazz The target class(must implement {@link ComponentProvider}). + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param The type held by the injected type. + * @see ClassInjectionPredicate + */ public static void inject(Class clazz, ComponentType type) { ComponentsImpl.inject(new ClassInjectionPredicate(clazz), new ComponentEntry<>(type)); } + /** + * Similar to {@link Components#inject(Class, ComponentType)} except it injects into all subclasses and indirect instances of the provided class. + * @param clazz The highest class in the hierarchy that will be injected. + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param The type held by the injected type. + * @see InheritedInjectionPredicate + */ public static void injectInheritage(Class clazz, ComponentType type) { ComponentsImpl.inject(new InheritedInjectionPredicate(clazz), new ComponentEntry<>(type)); } + /** + * Similar to {@link Components#injectInheritage(Class, ComponentType)}, except it skips the provided classes in the hierarchy. + * + * @param clazz The highest class in the hierarchy that will be injected. + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param exceptions The classes to avoid injecting into. + * @param The type help by the provided type. + * @see FilteredInheritedInjectionPredicate + */ public static void injectInheritanceExcept(Class clazz, ComponentType type, Class... exceptions) { ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), new ComponentEntry<>(type)); } + /** + * TODO: This is supposed to be merged with {@link Components#inject(Class, ComponentType)} and a mapping to redirections is to be created. + */ public static void injectRedirected(Class mainClass, ComponentType type, Class... others) { ComponentsImpl.inject(new RedirectedInjectionPredicate(mainClass, Set.of(others)), new ComponentEntry<>(type)); } + /** + * Dynamically injects into the provided {@link Class} using the provided predicate.
+ * For more info on dynamic injection check {@link org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate}; + * + * @param clazz The target class(must implement {@link ComponentProvider}). + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param predicate The predicate used to determine if injection is possible. + * @param The type of component that will be injected. + * @param

The type of the provider that the dynamic injection targets. + */ public static void injectDynamic(Class

clazz, ComponentType type, Predicate

predicate) { ComponentsImpl.inject(new DynamicClassInjectionPredicate<>(clazz, predicate), new ComponentEntry<>(type)); } - + // end injection methods + + // begin registration methods + /** + * The proper way to expose component instances.
+ * This does type-checking and also makes sure a {@link ComponentProvider} is given.
+ * This should be used where interface injection cannot apply(in other words custom implementations of {@link ComponentProvider}).
+ * + * @param id The {@link ComponentType} to expose. + * @param obj Any object will work. If it does not implement {@link ComponentProvider} an empty will be instantly returned. + * @return Either {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the result of expose called on the provider's container + * or {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided object is not a {@link ComponentProvider}. + * @param The type of component held by the {@link ComponentType}. + * @param The object to attempt to expose the component on. + * @see ComponentProvider#expose + * @see org.quiltmc.qsl.component.api.container.ComponentContainer#expose + */ public static Maybe expose(ComponentType id, S obj) { if (obj instanceof ComponentProvider provider) { - return provider.getComponentContainer().expose(id).filterMap(id::cast); + return provider.getComponentContainer().expose(id) + .filterMap(id::cast); // mapping with cast will make sure we get the correct type back. } return Maybe.nothing(); } + /** + * Register a manually created {@link ComponentType}. + * + * @param id The id to register the type with. + * @param type The type to register. + * @return The registered version of the component type. + * @param The type of component held by the type. + */ public static ComponentType register(Identifier id, ComponentType type) { return ComponentsImpl.register(id, type); } + /** + * Register a normal {@link ComponentType} using the provided {@linkplain Component.Factory default factory}. + * + * @param id The id to register the type with. + * @param factory The default {@link Component.Factory} of the type. + * @return A new {@link ComponentType} of {@link C} components. + * @param The type of component held by the type. + */ public static ComponentType register(Identifier id, Component.Factory factory) { if (factory instanceof ComponentType) { throw ErrorUtil.illegalArgument("Do NOT register ComponentTypes as factories, use the correct method").get(); @@ -82,11 +178,28 @@ public static ComponentType register(Identifier id, Com return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, false)); } + /** + * Register a {@linkplain ComponentType.Static static} {@linkplain ComponentType type} using the provided factory. + * @param id THe id to register the type with. + * @param factory The default {@link Component.Factory} of the type. + * @return A new static {@link ComponentType}. + * @param The type of component held by the type. + */ public static ComponentType registerStatic(Identifier id, Component.Factory factory) { return ComponentsImpl.register(id, new ComponentType<>(id, factory, true, false)); } - public static ComponentType registerTicking(Identifier id, Component.Factory factory) { + /** + * Register an instance {@link ComponentType}.
+ * For more info check the {@linkplain ComponentType relevant docs}. + * + * @param id The id to register the type with. + * @param factory The default {@link Component.Factory} of the type. + * @return A new instant {@link ComponentType}. + * @param The type of component held by the type. + */ + public static ComponentType registerInstant(Identifier id, Component.Factory factory) { return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, true)); } + // end registration method } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java index 9ae0bfe93a..609079edee 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java @@ -21,6 +21,7 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtOps; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.impl.ComponentsImpl; public class GenericComponent implements NbtComponent { @@ -29,8 +30,8 @@ public class GenericComponent implements NbtComponent { private final Runnable saveOperation; protected T value; - public GenericComponent(@Nullable Runnable saveOperation, Codec codec) { - this.saveOperation = saveOperation; + public GenericComponent(Component.Operations ops, Codec codec) { + this.saveOperation = ops.saveOperation(); this.codec = codec; } @@ -50,7 +51,7 @@ public byte nbtType() { @Override public void read(NbtCompound nbt) { this.codec.parse(NbtOps.INSTANCE, nbt.get("Value")) - .resultOrPartial(ComponentsImpl.LOGGER::error) + .result() .ifPresent(this::setValue); } @@ -59,7 +60,7 @@ public NbtCompound write() { var ret = new NbtCompound(); if (this.value != null) { this.codec.encodeStart(NbtOps.INSTANCE, this.value) - .result() + .resultOrPartial(ComponentsImpl.LOGGER::error) .ifPresent(nbtElement -> ret.put("Value", nbtElement)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java index 3c78009b57..c123924f4c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java @@ -22,10 +22,9 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtList; import net.minecraft.util.collection.DefaultedList; -public interface InventoryComponent extends NbtComponent, Inventory { +public interface InventoryComponent extends NbtComponent, Inventory { @Override default int size() { return this.getStacks().size(); @@ -84,20 +83,13 @@ default byte nbtType() { } @Override - default void read(NbtList nbt) { - for (int i = 0; i < nbt.size(); i++) { - this.setStack(i, ItemStack.fromNbt(nbt.getCompound(i))); - } + default void read(NbtCompound nbt) { + Inventories.readNbt(nbt, this.getStacks()); } @Override - default NbtList write() { - var nbt = new NbtList(); - for (int i = 0; i < this.getStacks().size(); i++) { - nbt.add(this.getStack(i).writeNbt(new NbtCompound())); - } - - return nbt; + default NbtCompound write() { + return Inventories.writeNbt(new NbtCompound(), this.getStacks()); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java index ff293d0222..d2895b8405 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java @@ -23,7 +23,7 @@ public interface SyncedComponent extends Component { void writeToBuf(PacketByteBuf buf); - void readFromBuf(PacketByteBuf buf); // Investigate what happens when the server doesn't send correct data?! + void readFromBuf(PacketByteBuf buf); @Nullable Runnable getSyncOperation(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java index f8613a0f6b..db64473950 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java @@ -17,31 +17,30 @@ package org.quiltmc.qsl.component.api.component; import com.mojang.serialization.Codec; -import net.minecraft.nbt.NbtElement; import net.minecraft.network.PacketByteBuf; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; -public class SyncedGenericComponent extends GenericComponent implements SyncedComponent { +public class SyncedGenericComponent extends GenericComponent implements SyncedComponent { private final NetworkCodec networkCodec; @Nullable private final Runnable syncOperation; - protected SyncedGenericComponent( - @Nullable Runnable saveOperation, @Nullable Runnable syncOperation, Codec codec, NetworkCodec networkCodec) { - super(saveOperation, codec); - this.syncOperation = syncOperation; + protected SyncedGenericComponent(Component.Operations ops, Codec codec, NetworkCodec networkCodec) { + super(ops, codec); + this.syncOperation = ops.syncOperation(); this.networkCodec = networkCodec; } @Override public void writeToBuf(PacketByteBuf buf) { - this.networkCodec.encode(buf, this.value); + this.networkCodec.encode(buf, this.getValue()); } @Override public void readFromBuf(PacketByteBuf buf) { - this.networkCodec.decode(buf).ifJust(t -> this.value = t); + this.networkCodec.decode(buf).ifJust(this::setValue); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index 680e9c69a7..cb0d33990f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -17,28 +17,40 @@ package org.quiltmc.qsl.component.api.container; import net.minecraft.nbt.NbtCompound; -import net.minecraft.server.network.ServerPlayerEntity; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.EmptyComponentContainer; +import org.quiltmc.qsl.component.impl.container.*; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.function.Supplier; public interface ComponentContainer { ComponentContainer EMPTY = EmptyComponentContainer.INSTANCE; + ComponentContainer.Factory EMPTY_FACTORY = EmptyComponentContainer.FACTORY; + ComponentContainer.Factory SIMPLE_FACTORY = SimpleComponentContainer.FACTORY; + ComponentContainer.Factory LAZY_FACTORY = LazyComponentContainer.FACTORY; + ComponentContainer.Factory ON_ACCESS_FACTORY = OnAccessComponentContainer.FACTORY; - static Maybe builder(Object obj) { - return obj instanceof ComponentProvider provider ? Maybe.just(new Builder(provider)) : Maybe.nothing(); + static ComponentContainer.Factory> createSingleFactory(ComponentType type) { + return SingleComponentContainer.createFactory(new ComponentEntry<>(type)); + } + + static ComponentContainer.Factory> createSingleFactory(ComponentEntry entry) { + return SingleComponentContainer.createFactory(entry); + } + + static Builder builder(Object obj) { + if (!(obj instanceof ComponentProvider provider)) { + throw new UnsupportedOperationException("Cannot create a container for a non-provider object"); + } + + return new Builder(provider); } Maybe expose(ComponentType type); @@ -57,7 +69,7 @@ T generate(ComponentProvider provider, Lazy>> injections, @Nullable Runnable saveOperation, boolean ticking, - SyncPacket.SyncContext syncContext); + @Nullable SyncChannel syncChannel); } class Builder { @@ -67,13 +79,13 @@ class Builder { @Nullable private Runnable saveOperation; @Nullable - private SyncPacket.SyncContext syncContext; + private SyncChannel syncChannel; private Builder(ComponentProvider provider) { this.provider = provider; this.injections = Lazy.of(ArrayList::new); this.saveOperation = null; - this.syncContext = null; + this.syncChannel = null; } public Builder saving(Runnable saveOperation) { @@ -86,8 +98,8 @@ public Builder ticking() { return this; } - public Builder syncing(SyncPacketHeader header, Supplier> playerGenerator) { - this.syncContext = new SyncPacket.SyncContext(header, playerGenerator); + public Builder syncing(SyncChannel syncChannel) { + this.syncChannel = syncChannel; return this; } @@ -115,7 +127,7 @@ public Builder add(ComponentType... types) { } public T build(ComponentContainer.Factory factory) { - return factory.generate(this.provider, this.injections, this.saveOperation, this.ticking, this.syncContext); + return factory.generate(this.provider, this.injections, this.saveOperation, this.ticking, this.syncChannel); } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java new file mode 100644 index 0000000000..93977a26e0 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java @@ -0,0 +1,112 @@ +/** + *

Quilt Component API

+ * An QSL library module, allowing the attachment/querying of arbitrary data and/or behaviour to various game objects. + *

+ * + *

Getting Started

+ * The simplest thing you can do using this module is create a {@link org.quiltmc.qsl.component.api.ComponentType}. + * It works as an identifier for components of a specific type.
+ * To create one simply follow this: + *
{@code
+ * public class MainClass implements ModInitializer {
+ *    // ...
+ *    public static final ComponentType A_COMPONENT = Components.register(
+ *    	new Identifier("modid", "a_component"), // The identifier used for registration
+ *    	DefaultAComponent::new // the default factory of this type
+ *    );
+ * }
+ * }
+ *

+ * Java is now gonna complain since we need 2 more things: the AComponent interface as well as the ADefaultComponent default class. + * Creating them is as simple as this: + *

{@code
+ * public interface AComponent extends Component {
+ *     void doSomething();
+ *
+ *     String getStringData();
+ * }
+ *
+ * public class ADefaultComponent implements AComponent {
+ *	   private final String stringData;
+ *
+ *     public ADefaultComponent(Component.Operations ignored) {
+ *         this.stringData = "Hello there";
+ *     }
+ *
+ *     public void doSomething() {
+ *         System.out.println(this.getStringData());
+ *     }
+ *
+ *     public String getStringData() {
+ *         return this.stringData;
+ *     }
+ * }
+ * }
+ *

+ * The AComponent interface provides the API for AComponent instances.
+ * The ADefaultComponent class provides a default implementation of the AComponent interface. + * The data contained by ADefaultComponent is not saved or synced. If you want to learn how to save or sync data,
+ * visit the {@linkplain org.quiltmc.qsl.component.api.component.NbtComponent NbtComponent} and {@linkplain org.quiltmc.qsl.component.api.component.SyncedComponent SyncedComponent} documentation. + *

+ *

Component Injection

+ * The {@link org.quiltmc.qsl.component.api.ComponentType} we have created does exist, but nothing actually exposes it's interface.
+ * For that to happen we need to inject our type into game objects. + *

+ * Game Objects that can have {@linkplain org.quiltmc.qsl.component.api.Component components} injected to them are by convention called {@link org.quiltmc.qsl.component.api.provider.ComponentProvider}s.
+ * The {@linkplain org.quiltmc.qsl.component.api.provider.ComponentProvider providers} implemented by default are the following: + *

    + *
  • BlockEntity
  • + *
  • Entity
  • + *
  • Chunk
  • + *
  • World
  • + *
  • Level(meaning a game save)
  • + *
+ * For more info on {@linkplain org.quiltmc.qsl.component.api.provider.ComponentProvider providers} check the {@linkplain org.quiltmc.qsl.component.api.provider.ComponentProvider relevant documentation}. + *

+ * + * Choose one of those and then you are 1 step away from getting a functioning component injected to it.
+ * On the below example, I have chosen BlockEntity as the target of my injection. + *

{@code
+ * public class MainClass implements ModInitializer {
+ *     // ...
+ * 	   @Override
+ * 	   public void onInitialize(ModContainer mod) {
+ * 	   	   // ...
+ * 	       Components.inject(ChestBlockEntity.class, A_COMPONENT);
+ * 	       // ...
+ * 	   }
+ * }
+ * }
+ * + * Now all chests should have A_COMPONENT injected into them, when they are created. + *

+ *

Accessing Components

+ * For any {@link org.quiltmc.qsl.component.api.provider.ComponentProvider} that has components injected into it, accessing them follows pretty much the same pattern.
+ * You need an instance of the {@link org.quiltmc.qsl.component.api.provider.ComponentProvider} that your component is injected into.
+ * After that you can do this: + *
{@code
+ * //...
+ * // consider pos and world to be an arguments
+ * // passed into the current method.
+ * var blockEntity = world.getBlockEntity(pos);
+ * // The expose method returns a Maybe instance.
+ * // ifJust just unwraps that instance if it exists and gives it to us.
+ * blockEntity.expose(MainClass.A_COMPONENT).ifJust(AComponent::doSomething);
+ * // notice how we can basically avoid casting the block entity into a chest block entity.
+ * //...
+ * }
+ *

+ * + * Keep in mind that when exposing component instances: + *

    + *
  1. You always get back the type that matches your {@link org.quiltmc.qsl.component.api.ComponentType}. In this case that would be an AComponent instance.
  2. + *
  3. + * You always get back a {@link org.quiltmc.qsl.base.api.util.Maybe} instance. You need to use its methods to perform actions on the component. + * Furthermore it's not recommended to attempt to {@linkplain org.quiltmc.qsl.base.api.util.Maybe#unwrap() unwrap} the instance, because in the + * case the injection failed(for whatever reason), this will crash the game instance. + *
  4. + *
+ * + * @author 0xJoeMama + */ +package org.quiltmc.qsl.component.api; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 3d1d34a378..63d05708f3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -21,7 +21,6 @@ import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.impl.sync.ServerSyncHandler; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.lifecycle.api.event.ServerLifecycleEvents; import org.quiltmc.qsl.networking.api.ServerLoginConnectionEvents; @@ -35,13 +34,12 @@ public static Identifier id(String id) { @Override public void onInitialize(ModContainer mod) { - SyncPacketHeader.registerDefaults(); ServerSyncHandler.getInstance().registerPackets(); ServerLoginConnectionEvents.QUERY_START.register(id("component_sync"), ServerSyncHandler.getInstance()); ServerLifecycleEvents.STARTING.register( id("freeze_component_registries"), - server -> ComponentsImpl.freezeRegistries() + server -> ComponentsImpl.REGISTRY.freeze() ); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index d0719ced9d..9a4e30d7d6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -29,7 +29,6 @@ import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.cached.CachedInjectionManager; import org.quiltmc.qsl.component.impl.injection.manager.dynamic.DynamicInjectionManager; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,9 +65,4 @@ public static List> getInjections(ComponentProvider provider) public static ComponentType register(Identifier id, ComponentType type) { return Registry.register(REGISTRY, id, type); } - - public static void freezeRegistries() { - REGISTRY.freeze(); - SyncPacketHeader.REGISTRY.freeze(); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java index 706731ac54..3207695523 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java @@ -21,6 +21,7 @@ import org.quiltmc.qsl.component.impl.CommonInitializer; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import org.quiltmc.qsl.lifecycle.api.client.event.ClientLifecycleEvents; public class ClientInitializer implements ClientModInitializer { @@ -30,7 +31,7 @@ public void onInitializeClient(ModContainer mod) { ClientLifecycleEvents.READY.register( CommonInitializer.id("freeze_component_registies"), - client -> ComponentsImpl.freezeRegistries() + client -> ComponentsImpl.REGISTRY.freeze() ); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java similarity index 90% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java index b595c89198..7f2d2830aa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientResolution.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java @@ -14,12 +14,11 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.client; +package org.quiltmc.qsl.component.impl.client.sync; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; -import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; @@ -38,7 +37,7 @@ public static Chunk getChunk(ChunkPos pos) { return MinecraftClient.getInstance().world.getChunk(pos.x, pos.z); } - public static World getWorld(Identifier identifier) { + public static World getWorld() { return MinecraftClient.getInstance().world; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java index 8cfb0afea7..b4b05e187f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -19,7 +19,8 @@ import net.minecraft.util.collection.IdList; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.networking.api.client.ClientLoginNetworking; @@ -30,7 +31,7 @@ public class ClientSyncHandler { private IdList> componentList = null; - private IdList> headerList = null; + private ClientSyncHandler() { } public static ClientSyncHandler getInstance() { if (INSTANCE == null) { @@ -40,22 +41,19 @@ public static ClientSyncHandler getInstance() { return INSTANCE; } + public

void registerChannel(SyncChannel

channel) { + ClientPlayNetworking.registerGlobalReceiver(channel.channelId(), (client, handler, buf, responseSender) -> { + ComponentProvider provider = channel.to(buf); + SyncPacket.handle(client, provider, buf); + }); + } + public void registerPackets() { ClientLoginNetworking.registerGlobalReceiver(PacketIds.TYPES, (client, handler, buf, listenerAdder) -> ClientRegistryPacket.handleRegistryPacket(buf, Components.REGISTRY, list -> this.componentList = list) ); - ClientLoginNetworking.registerGlobalReceiver(PacketIds.HEADERS, (client, handler, buf, listenerAdder) -> - ClientRegistryPacket.handleRegistryPacket(buf, SyncPacketHeader.REGISTRY, list -> this.headerList = list) - ); - - ClientPlayNetworking.registerGlobalReceiver(PacketIds.SYNC, (client, handler, buf, responseSender) -> - SyncPacket.handle(buf, client) - ); - } - - public SyncPacketHeader getHeader(int rawId) { - return this.headerList.get(rawId); + SyncChannel.createPacketChannels(this::registerChannel); } public ComponentType getType(int rawId) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java index 551a09c0b5..2c087d8a75 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java @@ -19,6 +19,7 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtFloat; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.component.NbtComponent; public class DefaultFloatComponent implements NbtComponent { @@ -26,13 +27,13 @@ public class DefaultFloatComponent implements NbtComponent { @Nullable private final Runnable saveOperation; - public DefaultFloatComponent(@Nullable Runnable saveOperation) { - this(saveOperation, 0); + public DefaultFloatComponent(Component.Operations ops) { + this(ops, 0); } - public DefaultFloatComponent(@Nullable Runnable saveOperation, float initialValue) { + public DefaultFloatComponent(Component.Operations ops, float initialValue) { this.value = initialValue; - this.saveOperation = saveOperation; + this.saveOperation = ops.saveOperation(); } public float get() { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java index 9efa7f5327..69bb7c5737 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java @@ -18,26 +18,22 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtInt; -import net.minecraft.network.PacketByteBuf; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.component.NbtComponent; -import org.quiltmc.qsl.component.api.component.SyncedComponent; -public class DefaultIntegerComponent implements NbtComponent, SyncedComponent { +public class DefaultIntegerComponent implements NbtComponent { private int value; @Nullable private final Runnable saveOperation; - @Nullable - private final Runnable syncOperation; - public DefaultIntegerComponent(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation) { - this(saveOperation, syncOperation, 0); + public DefaultIntegerComponent(Component.Operations ops) { + this(ops, 0); } - public DefaultIntegerComponent(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation, int defaultValue) { + public DefaultIntegerComponent(Component.Operations ops, int defaultValue) { this.value = defaultValue; - this.saveOperation = saveOperation; - this.syncOperation = syncOperation; + this.saveOperation = ops.saveOperation(); } public void increment() { @@ -75,19 +71,4 @@ public NbtInt write() { public @Nullable Runnable getSaveOperation() { return this.saveOperation; } - - @Override - public void writeToBuf(PacketByteBuf buf) { - buf.writeInt(this.value); - } - - @Override - public void readFromBuf(PacketByteBuf buf) { - this.value = buf.readInt(); - } - - @Override - public @Nullable Runnable getSyncOperation() { - return this.syncOperation; - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java index 96709a42a3..bc431f4df1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java @@ -17,33 +17,27 @@ package org.quiltmc.qsl.component.impl.component; import net.minecraft.item.ItemStack; -import net.minecraft.network.PacketByteBuf; import net.minecraft.util.collection.DefaultedList; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.component.InventoryComponent; -import org.quiltmc.qsl.component.api.component.SyncedComponent; -import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; import java.util.Objects; import java.util.function.Supplier; -public class DefaultInventoryComponent implements InventoryComponent, SyncedComponent { +public class DefaultInventoryComponent implements InventoryComponent { private final DefaultedList stacks; @Nullable private final Runnable saveOperation; - @Nullable - private final Runnable syncOperation; - public DefaultInventoryComponent(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation, int size) { + public DefaultInventoryComponent(Component.Operations ops, int size) { this.stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); - this.saveOperation = saveOperation; - this.syncOperation = syncOperation; + this.saveOperation = ops.saveOperation(); } - public DefaultInventoryComponent(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation, Supplier> stacks) { - this.syncOperation = syncOperation; + public DefaultInventoryComponent(Component.Operations ops, Supplier> stacks) { this.stacks = stacks.get(); - this.saveOperation = saveOperation; + this.saveOperation = ops.saveOperation(); } @Override @@ -56,11 +50,6 @@ public DefaultedList getStacks() { return this.saveOperation; } - @Override - public @Nullable Runnable getSyncOperation() { - return this.syncOperation; - } - @Override public int hashCode() { return Objects.hash(stacks); @@ -72,18 +61,4 @@ public boolean equals(Object o) { if (!(o instanceof DefaultInventoryComponent that)) return false; return stacks.equals(that.stacks); } - - @Override - public void writeToBuf(PacketByteBuf buf) { - NetworkCodec.INVENTORY.encode(buf, this.stacks); - } - - @Override - public void readFromBuf(PacketByteBuf buf) { - NetworkCodec.INVENTORY.decode(buf).ifJust(itemStacks -> { - for (int i = 0; i < itemStacks.size(); i++) { - this.stacks.set(i, itemStacks.get(i)); - } - }); - } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index 627b422e83..763fd50d40 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -11,6 +11,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; @@ -23,24 +24,24 @@ public abstract class AbstractComponentContainer implements ComponentContainer { protected final List> nbtComponents; protected final Maybe>> ticking; protected final Maybe>> pendingSync; - protected final Maybe syncContext; + protected final Maybe> syncContext; - public AbstractComponentContainer(Runnable saveOperation, + public AbstractComponentContainer(@Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncPacket.SyncContext syncContext) { + @Nullable SyncChannel syncChannel) { this.ticking = ticking ? Maybe.just(new ArrayList<>()) : Maybe.nothing(); this.nbtComponents = new ArrayList<>(); - this.syncContext = Maybe.wrap(syncContext); + this.syncContext = Maybe.wrap(syncChannel); this.pendingSync = this.syncContext.map(it -> new ArrayDeque<>()); this.operations = new ContainerOperations( - saveOperation, - type -> () -> this.pendingSync.ifJust(pending -> pending.add(type)) + saveOperation, + type -> () -> this.pendingSync.ifJust(pending -> pending.add(type)) ); } @Override public void writeNbt(NbtCompound providerRootNbt) { - var rootQslNbt = new NbtCompound(); + var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); this.nbtComponents.forEach(type -> this.expose(type) .map(it -> ((NbtComponent) it)) .ifJust(nbtComponent -> NbtComponent.writeTo(rootQslNbt, nbtComponent, type.id())) @@ -56,12 +57,18 @@ public void readNbt(NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); rootQslNbt.getKeys().stream() - .map(Identifier::new) + .map(Identifier::new) // All encoded component types *must* strictly be identifiers .map(Components.REGISTRY::get) .filter(Objects::nonNull) .forEach(type -> this.expose(type) .map(component -> ((NbtComponent) component)) - .ifJust(component -> NbtComponent.readFrom(component, type.id(), rootQslNbt)) + .ifJust(component -> { + NbtComponent.readFrom(component, type.id(), rootQslNbt); + + if (component instanceof SyncedComponent synced) { + synced.sync(); + } + }) ); } @@ -69,8 +76,8 @@ public void readNbt(NbtCompound providerRootNbt) { public void tick(ComponentProvider provider) { this.ticking.ifJust(componentTypes -> componentTypes.forEach(type -> this.expose(type) - .map(it -> ((TickingComponent) it)) - .ifJust(tickingComponent -> tickingComponent.tick(provider))) + .map(it -> ((TickingComponent) it)) + .ifJust(tickingComponent -> tickingComponent.tick(provider))) ).ifNothing(() -> { throw ErrorUtil.illegalState("Attempted to tick a non-ticking container").get(); }); @@ -80,10 +87,10 @@ public void tick(ComponentProvider provider) { @Override public void sync(ComponentProvider provider) { - this.syncContext.ifJust(ctx -> SyncPacket.syncFromQueue( + this.syncContext.ifJust(channel -> SyncPacket.createFromQueue( this.pendingSync.unwrap(), - ctx, - type -> (SyncedComponent) this.expose(type).unwrap(), + channel, + type -> (SyncedComponent) this.expose(type).unwrap(), // We *need* to contain the provided type therefore it's definitely in here. provider )).ifNothing(() -> { throw ErrorUtil.illegalState("Attempted to sync a non-syncable container!").get(); @@ -94,7 +101,9 @@ public void sync(ComponentProvider provider) { protected COMP initializeComponent(ComponentEntry componentEntry) { ComponentType type = componentEntry.type(); - Runnable syncOperation = this.operations.syncOperationFactory().apply(type); + + Function, Runnable> factory = this.operations.syncOperationFactory(); + Runnable syncOperation = factory != null ? factory.apply(type) : null; COMP component = componentEntry.apply(this.operations.saveOperation(), syncOperation); @@ -113,5 +122,5 @@ protected COMP initializeComponent(ComponentEntry return component; } - public record ContainerOperations(Runnable saveOperation, Function, Runnable> syncOperationFactory) { } + public record ContainerOperations(@Nullable Runnable saveOperation, @Nullable Function, Runnable> syncOperationFactory) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java new file mode 100644 index 0000000000..bfa763afa4 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java @@ -0,0 +1,48 @@ +package org.quiltmc.qsl.component.impl.container; + +import net.minecraft.nbt.NbtCompound; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; + +// TODO: Make this work!!! +public class CompositeComponentContainer implements ComponentContainer { + private final ComponentContainer main; + private final ComponentContainer fallback; + + public CompositeComponentContainer(ComponentContainer main, ComponentContainer fallback) { + this.main = main; + this.fallback = fallback; + } + + @Override + public Maybe expose(ComponentType type) { + return this.main.expose(type).or(() -> this.fallback.expose(type)); + } + + @Override + public void writeNbt(NbtCompound providerRootNbt) { + this.main.writeNbt(providerRootNbt); + this.fallback.writeNbt(providerRootNbt); + } + + @Override + public void readNbt(NbtCompound providerRootNbt) { + this.main.readNbt(providerRootNbt); + this.fallback.readNbt(providerRootNbt); + } + + @Override + public void tick(ComponentProvider provider) { + this.main.tick(provider); + this.fallback.tick(provider); + } + + @Override + public void sync(ComponentProvider provider) { + this.main.sync(provider); + this.fallback.sync(provider); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java index c3af65dd38..5d303138f4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java @@ -27,7 +27,7 @@ public final class EmptyComponentContainer implements ComponentContainer { public static final EmptyComponentContainer INSTANCE = new EmptyComponentContainer(); public static final ComponentContainer.Factory FACTORY = - (provider, injections, saveOperation, ticking, syncContext) -> INSTANCE; + (provider, injections, saveOperation, ticking, syncChannel) -> INSTANCE; private EmptyComponentContainer() { } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 8a6acf3bb7..916020bfb7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -25,7 +25,7 @@ import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import java.util.IdentityHashMap; import java.util.List; @@ -33,18 +33,18 @@ public class LazyComponentContainer extends AbstractComponentContainer { public static final ComponentContainer.Factory FACTORY = - (provider, injections, saveOperation, ticking, syncContext) -> - new LazyComponentContainer(provider, saveOperation, ticking, syncContext); + (provider, injections, saveOperation, ticking, syncChannel) -> + new LazyComponentContainer(provider, saveOperation, ticking, syncChannel); private final IdentityHashMap, Lazy> components; protected LazyComponentContainer( ComponentProvider provider, @Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncPacket.SyncContext syncContext + @Nullable SyncChannel syncChannel ) { - super(saveOperation, ticking, syncContext); - this.components = this.initializeComponents(provider); + super(saveOperation, ticking, syncChannel); + this.components = this.createLazyMap(provider); } public static void move(LazyComponentContainer from, LazyComponentContainer into) { @@ -70,7 +70,7 @@ public Maybe expose(ComponentType id) { @Override protected void addComponent(ComponentType type, Component component) { } - private IdentityHashMap, Lazy> initializeComponents(ComponentProvider provider) { + private IdentityHashMap, Lazy> createLazyMap(ComponentProvider provider) { var map = new IdentityHashMap, Lazy>(); ComponentsImpl.getInjections(provider).forEach(injection -> map.put(injection.type(), this.createLazy(injection))); return map; @@ -81,7 +81,6 @@ private Lazy createLazy(ComponentEntry compo if (type.isStatic() || type.isInstant()) { var component = this.initializeComponent(componentEntry); - return Lazy.filled(component); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index 41b68db5a4..7610d11db6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -16,52 +16,62 @@ package org.quiltmc.qsl.component.impl.container; +import com.mojang.datafixers.util.Either; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; -import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; import java.util.Map; // Suggestion from Technici4n from fabric. May help improve performance and memory footprint once done. public class OnAccessComponentContainer extends AbstractComponentContainer { - private final Map, Component> components; + public static final Factory FACTORY = + (provider, injections, saveOperation, ticking, syncChannel) -> + new OnAccessComponentContainer(provider, saveOperation, ticking, syncChannel); + private final Map, Either, Component>> components; - private OnAccessComponentContainer(ComponentProvider provider, + protected OnAccessComponentContainer(ComponentProvider provider, @Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncPacket.SyncContext syncContext) { - super(saveOperation, ticking, syncContext); - this.components = this.getInitialComponents(provider); + @Nullable SyncChannel syncChannel) { + super(saveOperation, ticking, syncChannel); + this.components = this.createComponents(provider); + } + + private Map, Either, Component>> createComponents(ComponentProvider provider) { + List> injections = ComponentsImpl.getInjections(provider); + var map = new IdentityHashMap, Either, Component>>(); + injections.forEach(entry -> { + ComponentType type = entry.type(); + if (type.isStatic() || type.isInstant()) { + this.initializeComponent(entry); + } else { + map.put(type, Either.left(entry)); + } + }); + + return map; } @Override public Maybe expose(ComponentType type) { - return Maybe.wrap(this.components.get(type)) - .or(() -> this.supports(type) ? Maybe.just(this.initializeComponent(this.getInjection(type))) : Maybe.nothing()); + return Maybe.fromOptional(this.components.get(type).right()) + .or(() -> this.supports(type) ? Maybe.just(this.initializeComponent(this.components.get(type).left().orElseThrow())) : Maybe.nothing()); } @Override protected void addComponent(ComponentType type, Component component) { - this.components.put(type, component); - } - - private ComponentEntry getInjection(ComponentType type) { - throw new UnsupportedOperationException("TODO: NOT IMPLEMENTED"); + this.components.put(type, Either.right(component)); } private boolean supports(ComponentType type) { - throw new UnsupportedOperationException("TODO: NOT IMPLEMENTED"); - } - - private Map, Component> getInitialComponents(ComponentProvider provider) { -// return this.supportedTypes.stream() // TODO: We can cache this value. -// .filter(((Predicate>) ComponentType::isStatic).or(ComponentType::isInstant)) -// .collect(IdentityHashMap::new, (map, type) -> map.put(type, this.createComponent(type)), Map::putAll); - return new HashMap<>(); + return this.components.containsKey(type); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 18d343ebf6..a3d8ccc6e3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -22,6 +22,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.component.impl.util.ErrorUtil; @@ -31,14 +32,14 @@ public class SimpleComponentContainer extends AbstractComponentContainer { public static final ComponentContainer.Factory FACTORY = - (provider, injections, saveOperation, ticking, syncContext) -> new SimpleComponentContainer( - saveOperation, ticking, syncContext, injections.get().stream() + (provider, injections, saveOperation, ticking, syncChannel) -> new SimpleComponentContainer( + saveOperation, ticking, syncChannel, injections.get().stream() ); private final Map, Component> components; - protected SimpleComponentContainer(Runnable saveOperation, + protected SimpleComponentContainer(@Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncPacket.SyncContext syncContext, + @Nullable SyncChannel syncContext, Stream> types) { super(saveOperation, ticking, syncContext); this.components = new IdentityHashMap<>(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java index c835290a3b..60c40a0a63 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java @@ -1,7 +1,6 @@ package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; @@ -13,32 +12,28 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import java.util.function.Supplier; public class SingleComponentContainer implements ComponentContainer { private final ComponentType type; - private final Maybe syncContext; + private final Maybe> syncChannel; private final boolean ticking; private Lazy entry; private boolean shouldSync = false; - private SingleComponentContainer(ComponentType type, boolean ticking, @Nullable SyncPacket.SyncContext syncContext) { + protected SingleComponentContainer(ComponentType type, boolean ticking, @Nullable SyncChannel syncChannel) { this.type = type; this.ticking = ticking; - this.syncContext = Maybe.wrap(syncContext); - } - - private void setLazy(Supplier supplier) { - this.entry = Lazy.of(supplier); + this.syncChannel = Maybe.wrap(syncChannel); } public static ComponentContainer.Factory> createFactory(ComponentEntry entry) { - return (provider, ignored, saveOperation, ticking, syncContext) -> { + return (provider, ignored, saveOperation, ticking, syncChannel) -> { ComponentType type = entry.type(); - var container = new SingleComponentContainer<>(type, ticking, syncContext); - container.setLazy(() -> entry.apply(saveOperation, () -> container.shouldSync = true)); + var container = new SingleComponentContainer<>(type, ticking, syncChannel); + container.setEntry(() -> entry.apply(saveOperation, () -> container.shouldSync = true)); return container; }; @@ -64,7 +59,13 @@ public void readNbt(NbtCompound providerRootNbt) { if (providerRootNbt.getKeys().contains(idString)) { this.expose(this.type) .map(it -> ((NbtComponent) it)) - .ifJust(nbtComponent -> NbtComponent.readFrom(nbtComponent, this.type.id(), providerRootNbt)); + .ifJust(nbtComponent -> { + NbtComponent.readFrom(nbtComponent, this.type.id(), providerRootNbt); + + if (this.syncChannel.isJust()) { + ((SyncedComponent) nbtComponent).sync(); + } + }); } } @@ -80,13 +81,15 @@ public void tick(ComponentProvider provider) { @Override public void sync(ComponentProvider provider) { if (this.shouldSync) { - this.syncContext.ifJust(ctx -> { - PacketByteBuf buf = ctx.header().toBuffer(provider); - buf.writeInt(1); - ComponentType.NETWORK_CODEC.encode(buf, this.type); - ((SyncedComponent) this.entry.get()).writeToBuf(buf); - SyncPacket.send(ctx, buf); - }); + this.syncChannel.ifJust(channel -> channel.send(provider, buf -> { + buf.writeInt(1); // size will always be one in this case. + ComponentType.NETWORK_CODEC.encode(buf, this.type); // append the type rawId + ((SyncedComponent) this.entry.get()).writeToBuf(buf); // append component data + })); } } + + private void setEntry(Supplier supplier) { + this.entry = Lazy.of(supplier); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java index e1acd16434..3643adc45a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java @@ -18,9 +18,7 @@ import net.minecraft.server.MinecraftServer; import org.quiltmc.qsl.base.api.event.ListenerPhase; -import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.quiltmc.qsl.lifecycle.api.event.ServerTickEvents; -import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; @ListenerPhase( callbackTarget = ServerTickEvents.End.class, @@ -30,8 +28,5 @@ public class ServerTickEventListener implements ServerTickEvents.End { @Override public void endServerTick(MinecraftServer server) { server.getComponentContainer().tick(server); - server.getWorlds().forEach(world -> { - // Add world ticking! - }); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java index 217d078319..81fecaa9cf 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java @@ -4,7 +4,6 @@ import net.minecraft.server.world.ServerWorld; import org.quiltmc.qsl.base.api.event.ListenerPhase; import org.quiltmc.qsl.component.impl.CommonInitializer; -import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; @SuppressWarnings("unused") @@ -15,6 +14,6 @@ public class ServerWorldTickEventListener implements ServerWorldTickEvents.End { @Override public void endWorldTick(MinecraftServer server, ServerWorld world) { - ComponentProviderState.get(world).getComponentContainer().tick(world); + world.getComponentContainer().tick(world); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java index b189c88109..69d045c259 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java @@ -16,15 +16,16 @@ package org.quiltmc.qsl.component.impl.injection; +import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; public record ComponentEntry(ComponentType type, Component.Factory factory) { public ComponentEntry(ComponentType type) { - this(type, type); + this(type, type.defaultFactory()); } - public C apply(Runnable saveOperation, Runnable syncOperation) { - return this.factory.create(saveOperation, syncOperation); + public C apply(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation) { + return this.factory.create(new Component.Operations(saveOperation, syncOperation)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java index 28a16a4f8a..f7c6b8dd73 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java @@ -31,12 +31,13 @@ public class DynamicInjectionManager extends InjectionManager> getInjections(ComponentProvider provider) { Class providerClass = provider.getClass(); + // First check the cached side return this.getCache(providerClass).or(() -> { var injections = this.initInjections(providerClass); this.record(providerClass, injections); return Maybe.just(injections); }).unwrap().stream() - .map(dynamicInjection -> dynamicInjection.test(provider) ? dynamicInjection.componentEntries() : null) + .map(dynamicInjection -> dynamicInjection.test(provider) ? dynamicInjection.componentEntries() : null) // After check the dynamic side .filter(Objects::nonNull) .flatMap(List::stream) .collect(Collectors.toList()); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java index 95c5f6735d..b58bf78e01 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java @@ -30,8 +30,10 @@ public DynamicClassInjectionPredicate(Class

clazz, Predicate

predicate) { this.predicate = predicate; } + @SuppressWarnings("unchecked") @Override public boolean canInject(ComponentProvider provider) { + // The class will be checked first so the provider will most definitely match the target type. return this.predicate.test((P) provider); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java index 04312ae3fc..a5f6eb4602 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java @@ -20,6 +20,7 @@ public boolean isClassValid(Class clazz) { return this.wrapped.isClassValid(clazz); } + @SuppressWarnings("unchecked") // Whoever hands us the provider should make sure it's valid! @Override public boolean canInject(ComponentProvider provider) { return this.predicate.test((P) provider); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java index e2d17e4968..0c6bea86c6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java @@ -19,7 +19,6 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerLoginNetworkHandler; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; import org.quiltmc.qsl.component.impl.sync.packet.RegistryPacket; import org.quiltmc.qsl.networking.api.PacketSender; @@ -29,9 +28,7 @@ public final class ServerSyncHandler implements ServerLoginConnectionEvents.QueryStart { private static ServerSyncHandler INSTANCE = null; - private ServerSyncHandler() { - - } + private ServerSyncHandler() { } public static ServerSyncHandler getInstance() { if (INSTANCE == null) { @@ -43,10 +40,7 @@ public static ServerSyncHandler getInstance() { public void registerPackets() { ServerLoginNetworking.registerGlobalReceiver(PacketIds.TYPES, (server, handler, understood, buf, sync, sender) -> - RegistryPacket.handleRegistryResponse(buf, handler, "Component with id %s was not found in the client!") - ); - ServerLoginNetworking.registerGlobalReceiver(PacketIds.HEADERS, (server, handler, understood, buf, synchronizer, sender) -> - RegistryPacket.handleRegistryResponse(buf, handler, "Header with id %s was not found in the client!") + RegistryPacket.handleRegistryResponse(buf, handler, "Component with id %s was not found in the client!") ); } @@ -54,6 +48,5 @@ public void registerPackets() { public void onLoginStart(ServerLoginNetworkHandler handler, MinecraftServer server, PacketSender sender, ServerLoginNetworking.LoginSynchronizer synchronizer) { // TODO: Maybe use regitry sync for this?! sender.sendPacket(PacketIds.TYPES, RegistryPacket.createRegistryPacket(Components.REGISTRY)); - sender.sendPacket(PacketIds.HEADERS, RegistryPacket.createRegistryPacket(SyncPacketHeader.REGISTRY)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java new file mode 100644 index 0000000000..a7d878759c --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java @@ -0,0 +1,98 @@ +package org.quiltmc.qsl.component.impl.sync; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.WorldChunk; +import org.quiltmc.qsl.base.api.util.TwoWayFunction; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.client.sync.ClientResolution; +import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; +import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; +import org.quiltmc.qsl.networking.api.PacketByteBufs; +import org.quiltmc.qsl.networking.api.PlayerLookup; +import org.quiltmc.qsl.networking.api.ServerPlayNetworking; + +import java.util.Collection; +import java.util.function.Consumer; +import java.util.function.Function; + +public record SyncChannel

(Identifier channelId, + NetworkCodec

codec, + Function> playerProvider) + implements TwoWayFunction { + // BlockEntity + private static final NetworkCodec BLOCK_ENTITY_CODEC = + NetworkCodec.BLOCK_POS.map(BlockEntity::getPos, ClientResolution::getBlockEntity); + public static final SyncChannel BLOCK_ENTITY = + new SyncChannel<>(PacketIds.BLOCK_ENTITY_SYNC, BLOCK_ENTITY_CODEC, PlayerLookup::tracking); + + // Entity + private static final NetworkCodec ENTITY_CODEC = + NetworkCodec.INT.map(Entity::getId, ClientResolution::getEntity); + public static final SyncChannel ENTITY = + new SyncChannel<>(PacketIds.ENTITY_SYNC, ENTITY_CODEC, PlayerLookup::tracking); + + // Chunk + private static final NetworkCodec CHUNK_CODEC = + NetworkCodec.CHUNK_POS.map(Chunk::getPos, ClientResolution::getChunk); + public static final SyncChannel CHUNK = // **Careful**: This only works with WorldChunks not other chunk types! + new SyncChannel<>(PacketIds.CHUNK_SYNC, CHUNK_CODEC, + chunk -> PlayerLookup.tracking((ServerWorld) ((WorldChunk) chunk).getWorld(), chunk.getPos())); + + // World + private static final NetworkCodec WORLD_CODEC = + NetworkCodec.empty(ClientResolution::getWorld); + public static final SyncChannel WORLD = + new SyncChannel<>(PacketIds.WORLD_SYNC, WORLD_CODEC, + world -> PlayerLookup.world(((ServerWorld) world))); + + // Level + private static final NetworkCodec LEVEL_CODEC = + NetworkCodec.empty(MinecraftClient::getInstance); + public static final SyncChannel LEVEL = + new SyncChannel<>(PacketIds.LEVEL_SYNC, LEVEL_CODEC, + provider -> PlayerLookup.all(((MinecraftServer) provider))); + + public static void createPacketChannels(Consumer> register) { + register.accept(BLOCK_ENTITY); + register.accept(ENTITY); + register.accept(CHUNK); + register.accept(WORLD); + register.accept(LEVEL); + } + + @Override + public P to(PacketByteBuf buf) { + return this.codec.decode(buf).unwrap(); // we throw in case we cannot find the target component provider. + } + + @Override + public PacketByteBuf from(P p) { + var buf = PacketByteBufs.create(); + this.codec.encode(buf, p); + return buf; + } + + @SuppressWarnings("unchecked") + public void send(ComponentProvider provider, BufferFiller bufferFiller) { + // The casting to P should never fail, since the provider and + // the channel type *must* match for the implementation to be correct anyway + P providerAsP = (P) provider; + var buf = this.from(providerAsP); // append provider data + bufferFiller.fill(buf); // append all the container data + ServerPlayNetworking.send(this.playerProvider.apply(providerAsP), this.channelId, buf); + } + + @FunctionalInterface + public interface BufferFiller { + void fill(PacketByteBuf buf); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java deleted file mode 100644 index ca13c092be..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncPlayerList.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.impl.sync; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.Entity; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.chunk.WorldChunk; -import org.quiltmc.qsl.networking.api.PlayerLookup; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.function.Supplier; - -public final class SyncPlayerList { - public static Collection create(World world, BlockPos pos) { - return world.isClient ? List.of() : PlayerLookup.tracking((ServerWorld) world, pos); - } - - public static Collection create(Entity entity) { - return entity.getWorld().isClient ? List.of() : PlayerLookup.tracking(entity); - } - - public static Collection create(BlockEntity blockEntity) { - return Objects.requireNonNull(blockEntity.getWorld()).isClient ? List.of() : PlayerLookup.tracking(blockEntity); - } - - public static Collection create(WorldChunk chunk) { - return chunk.getWorld().isClient ? List.of() : PlayerLookup.tracking((ServerWorld) chunk.getWorld(), chunk.getPos()); - } - - public static Collection create(ServerWorld world) { - return PlayerLookup.world(world); - } - - public static Collection create(World world) { - return world.isClient ? List.of() : PlayerLookup.world((ServerWorld) world); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java index 41cb16a817..940fa107fd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java @@ -141,7 +141,7 @@ public void encode(PacketByteBuf buf, T t) { public Maybe decode(PacketByteBuf buf) { try { return Maybe.just(this.decoder.apply(buf)); - } catch (IndexOutOfBoundsException e) { // An IOOB exception is thrown if the memory is either + } catch (IndexOutOfBoundsException e) { // An IOOB exception is thrown if we try to read invalid memory ComponentsImpl.LOGGER.warn(e.getMessage()); return Maybe.nothing(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java deleted file mode 100644 index 84e6191735..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/header/SyncPacketHeader.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.impl.sync.header; - -import com.mojang.serialization.Lifecycle; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.Entity; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryKey; -import net.minecraft.util.registry.SimpleRegistry; -import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; -import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.CommonInitializer; -import org.quiltmc.qsl.component.impl.client.ClientResolution; -import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; -import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; -import org.quiltmc.qsl.networking.api.PacketByteBufs; - -public record SyncPacketHeader

(NetworkCodec

codec) { - // Registry TODO: Maybe register this?! - public static final RegistryKey>> REGISTRY_KEY = - RegistryKey.ofRegistry(CommonInitializer.id("sync_headers")); - public static final Registry> REGISTRY = - new SimpleRegistry<>(REGISTRY_KEY, Lifecycle.experimental(), null); - - // Codec - public static final NetworkCodec> NETWORK_CODEC = - NetworkCodec.INT.map(REGISTRY::getRawId, ClientSyncHandler.getInstance()::getHeader); - - // BlockEntity - public static final NetworkCodec BLOCK_ENTITY_CODEC = - NetworkCodec.BLOCK_POS.map(BlockEntity::getPos, ClientResolution::getBlockEntity); - public static final SyncPacketHeader BLOCK_ENTITY = register("block_entity", BLOCK_ENTITY_CODEC); - - - // Entity - public static final NetworkCodec ENTITY_CODEC = - NetworkCodec.INT.map(Entity::getId, ClientResolution::getEntity); - public static final SyncPacketHeader ENTITY = register("entity", ENTITY_CODEC); - - // Chunk - public static final NetworkCodec CHUNK_CODEC = - NetworkCodec.CHUNK_POS.map(Chunk::getPos, ClientResolution::getChunk); - public static final SyncPacketHeader CHUNK = register("chunk", CHUNK_CODEC); - - // World - public static final NetworkCodec WORLD_CODEC = NetworkCodec.empty(() -> MinecraftClient.getInstance().world); - public static final SyncPacketHeader WORLD = register("world", WORLD_CODEC); - - // Level aka Save - private static final NetworkCodec LEVEL_CODEC = NetworkCodec.empty(MinecraftClient::getInstance); - public static final SyncPacketHeader LEVEL = register("level", LEVEL_CODEC); - - public static void registerDefaults() { - // Only exists to make sure these fields are classloaded before registries are frozen. - } - - private static

SyncPacketHeader

register(String id, NetworkCodec

codec) { - SyncPacketHeader

header = new SyncPacketHeader<>(codec); - register(CommonInitializer.id(id), header); - return header; - } - - public static

void register(Identifier id, SyncPacketHeader

header) { - Registry.register(REGISTRY, id, header); - } - - public static Maybe fromBuffer(PacketByteBuf buf) { - return NETWORK_CODEC.decode(buf) - .map(SyncPacketHeader::codec) - .filterMap(networkCodec -> networkCodec.decode(buf)); - } - - @SuppressWarnings("unchecked") - public PacketByteBuf toBuffer(ComponentProvider provider) { - var buf = PacketByteBufs.create(); - buf.writeInt(REGISTRY.getRawId(this)); - // the person calling is responsible to make sure we get a valid provider instance! - this.codec.encode(buf, (P) provider); - return buf; - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java index ba3032a7f4..c685effe89 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java @@ -20,7 +20,10 @@ import org.quiltmc.qsl.component.impl.CommonInitializer; public final class PacketIds { - public static final Identifier HEADERS = CommonInitializer.id("headers"); public static final Identifier TYPES = CommonInitializer.id("types"); - public static final Identifier SYNC = CommonInitializer.id("sync"); + public static final Identifier BLOCK_ENTITY_SYNC = CommonInitializer.id("block_entity"); + public static final Identifier ENTITY_SYNC = CommonInitializer.id("entity"); + public static final Identifier CHUNK_SYNC = CommonInitializer.id("chunk"); + public static final Identifier WORLD_SYNC = CommonInitializer.id("world"); + public static final Identifier LEVEL_SYNC = CommonInitializer.id("level"); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java index c90faaa745..dae21ef397 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java @@ -24,15 +24,16 @@ import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.networking.api.PacketByteBufs; -public final class RegistryPacket { // TODO: Fix this with registry sync maybe?! +public final class RegistryPacket { public static PacketByteBuf createRegistryPacket(Registry registry) { var buf = PacketByteBufs.create(); - buf.writeInt(registry.size()); + buf.writeInt(registry.size()); // append size + registry.forEach(t -> { var id = registry.getId(t); var rawId = registry.getRawId(t); - buf.writeIdentifier(id).writeInt(rawId); + buf.writeIdentifier(id).writeInt(rawId); // append id and rawId }); return buf; @@ -41,9 +42,10 @@ public static PacketByteBuf createRegistryPacket(Registry registry) { public static void handleRegistryResponse(PacketByteBuf buf, ServerLoginNetworkHandler handler, String msg) { String retString = buf.readString(); - if (!retString.equals("Ok")) { - Identifier id = Identifier.tryParse(retString); + if (!retString.equals("Ok")) { // a handled packet should return 'Ok' + Identifier id = Identifier.tryParse(retString); // a failed one should return the id that caused a desync + // In case we failed, we disconnect the client since we cannot validly sync components with it handler.disconnect(Text.literal(msg.formatted(id))); ComponentsImpl.LOGGER.warn(msg.formatted(id)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java index cbaf0d3c39..db5fe0d1da 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java @@ -16,56 +16,28 @@ package org.quiltmc.qsl.component.impl.sync.packet; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.network.PacketByteBuf; -import net.minecraft.server.network.ServerPlayerEntity; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.component.SyncedComponent; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; -import org.quiltmc.qsl.networking.api.ServerPlayNetworking; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; -import java.util.Collection; import java.util.Queue; import java.util.function.Function; -import java.util.function.Supplier; +/** + *

+ *         PROVIDER_DATA  SIZE [TYPE DATA]
+ *             var		  32bit	   var
+ * 
+ */ public class SyncPacket { - /** - *
- *     		Handled by SyncPacketHeader		The data we add
-	 *        HEADER_ID PROVIDER_DATA       SIZE [TYPE DATA]
-	 *        	32bit		var				32bit	 var
-	 * 
- */ - public static void handle(PacketByteBuf buf, MinecraftClient client) { - buf.retain(); // We need the buffer to exist until the client next pulls tasks on the main thread! - - client.execute(() -> { - SyncPacketHeader.fromBuffer(buf).ifJust(provider -> { - var size = buf.readInt(); - - for (int i = 0; i < size; i++) { - ComponentType.NETWORK_CODEC.decode(buf) - .filterMap(provider::expose) - .map(it -> ((SyncedComponent) it)) - .ifJust(synced -> synced.readFromBuf(buf)); - } - }); - - buf.release(); // Make sure the buffer is cleared! - }); - } - - public static void send(SyncContext context, PacketByteBuf packet) { - context.playerGenerator().get().forEach(serverPlayer -> - ServerPlayNetworking.send(serverPlayer, PacketIds.SYNC, packet) - ); - } - - public static void syncFromQueue( + public static

void createFromQueue( Queue> pendingSync, - SyncPacket.SyncContext context, + SyncChannel

channel, Function, SyncedComponent> mapper, ComponentProvider provider ) { @@ -73,18 +45,32 @@ public static void syncFromQueue( return; } - PacketByteBuf buf = context.header().toBuffer(provider); - buf.writeInt(pendingSync.size()); - - while (!pendingSync.isEmpty()) { - var currentType = pendingSync.poll(); - ComponentType.NETWORK_CODEC.encode(buf, currentType); - mapper.apply(currentType).writeToBuf(buf); - } + channel.send(provider, buf -> { + buf.writeInt(pendingSync.size()); // append size - SyncPacket.send(context, buf); + while (!pendingSync.isEmpty()) { + var currentType = pendingSync.poll(); + ComponentType.NETWORK_CODEC.encode(buf, currentType); // append type rawId + mapper.apply(currentType).writeToBuf(buf); // append component data + } + }); } - public record SyncContext(SyncPacketHeader header, Supplier> playerGenerator) { + @Environment(EnvType.CLIENT) + public static void handle(MinecraftClient client, ComponentProvider provider, PacketByteBuf buf) { + buf.retain(); // hold the buffer in memory + + client.execute(() -> { + int size = buf.readInt(); // consume size + + for (int i = 0; i < size; i++) { + ComponentType.NETWORK_CODEC.decode(buf) // consume type rawId + .filterMap(provider::expose) + .map(it -> ((SyncedComponent) it)) + .ifJust(syncedComponent -> syncedComponent.readFromBuf(buf)); // consume data + } + + buf.release(); // make sure the buffer is freed now that we don't need it + }); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java index 26a9145e9d..c99773e18d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java @@ -19,14 +19,18 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.PersistentState; import net.minecraft.world.World; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import java.util.HashMap; +import java.util.Map; + +// TODO: Fix this public class ComponentProviderState extends PersistentState implements ComponentProvider { public static final String ID = "components"; public static final String GLOBAL_ID = "save_components"; @@ -34,32 +38,23 @@ public class ComponentProviderState extends PersistentState implements Component private final ComponentContainer container; public ComponentProviderState(ServerWorld world, boolean level) { - this.container = this.initLevelContainer(world); + this.container = level ? this.initLevelContainer(world.getServer()) : this.initWorldContainer(world); } public ComponentProviderState(NbtCompound rootQslNbt, ServerWorld world) { - this.container = this.initLevelContainer(world); + this.container = this.initWorldContainer(world); this.container.readNbt(rootQslNbt); } - public static ComponentProviderState get(Object obj) { - // TODO: Client world treatment! - if (!(obj instanceof ServerWorld world)) { - throw ErrorUtil.illegalArgument("A ServerWorld instance needs to be provided to initialize a container!").get(); - } - - return world.getPersistentStateManager().getOrCreate( - nbtCompound -> new ComponentProviderState(nbtCompound, world), - () -> new ComponentProviderState(world, false), + public static ComponentProvider get(World world) { + return !world.isClient ? ((ServerWorld) world).getPersistentStateManager().getOrCreate( + nbtCompound -> new ComponentProviderState(nbtCompound, (ServerWorld) world), + () -> new ComponentProviderState((ServerWorld) world, false), ID - ); + ) : ClientComponentProviderState.getOrCreate(world); } - public static ComponentProviderState getGlobal(Object obj) { - if (!(obj instanceof MinecraftServer server)) { - throw ErrorUtil.illegalArgument("A MinecraftServer instance needs to be provided to initialize a container!").get(); - } - + public static ComponentProvider getGlobal(MinecraftServer server) { ServerWorld overworld = server.getOverworld(); return overworld.getPersistentStateManager().getOrCreate( nbtCompound -> new ComponentProviderState(nbtCompound, overworld), @@ -79,21 +74,40 @@ public ComponentContainer getComponentContainer() { return this.container; } - private LazyComponentContainer initLevelContainer(ServerWorld world) { - return ComponentContainer.builder(this) - .unwrap() + private LazyComponentContainer initLevelContainer(MinecraftServer server) { + return ComponentContainer.builder(server) .saving(this::markDirty) - .syncing(SyncPacketHeader.LEVEL, world::getPlayers) + .syncing(SyncChannel.LEVEL) .ticking() - .build(LazyComponentContainer.FACTORY); + .build(ComponentContainer.LAZY_FACTORY); } - private LazyComponentContainer initWorldContainer(World world) { - return ComponentContainer.builder(this) - .unwrap() + private LazyComponentContainer initWorldContainer(ServerWorld world) { + return ComponentContainer.builder(world) .saving(this::markDirty) - .syncing(SyncPacketHeader.LEVEL, () -> SyncPlayerList.create(world)) + .syncing(SyncChannel.WORLD) .ticking() - .build(LazyComponentContainer.FACTORY); + .build(ComponentContainer.LAZY_FACTORY); + } + + public static class ClientComponentProviderState implements ComponentProvider { + private static final Map, ComponentProvider> cachedValue = new HashMap<>(); + private final ComponentContainer container; + + private static ComponentProvider getOrCreate(World world) { + return cachedValue.computeIfAbsent( + world.getRegistryKey(), + worldRegistryKey -> new ClientComponentProviderState(world) + ); + } + + private ClientComponentProviderState(World world) { + this.container = ComponentContainer.builder(world).build(ComponentContainer.LAZY_FACTORY); + } + + @Override + public ComponentContainer getComponentContainer() { + return this.container; + } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java index 12b1039996..e415660987 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/StringConstants.java @@ -17,6 +17,5 @@ package org.quiltmc.qsl.component.impl.util; public final class StringConstants { - // TODO: Check about this key! public static final String COMPONENT_ROOT = "QuiltComponentRoot"; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java index 662014104b..5ae5d81591 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java @@ -24,8 +24,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -50,15 +49,13 @@ private void onReadNbt(NbtCompound nbt, CallbackInfo ci) { this.qsl$container.readNbt(nbt); } - @SuppressWarnings("ConstantConditions") @Inject(method = "", at = @At("RETURN")) private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { this.qsl$container = ComponentContainer.builder(this) - .unwrap() .saving(this::markDirty) .ticking() - .syncing(SyncPacketHeader.BLOCK_ENTITY, () -> SyncPlayerList.create((BlockEntity) (Object) this)) - .build(LazyComponentContainer.FACTORY); + .syncing(SyncChannel.BLOCK_ENTITY) + .build(ComponentContainer.LAZY_FACTORY); } @Inject(method = "toNbt", at = @At("TAIL")) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java index d1439413da..3db77a2795 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java @@ -27,8 +27,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -51,13 +50,12 @@ public ComponentContainer getComponentContainer() { @Inject(method = "", at = @At("RETURN")) private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { LazyComponentContainer.Builder builder = ComponentContainer.builder(this) - .unwrap() .saving(() -> this.setNeedsSaving(true)); - if ((Chunk) (Object) this instanceof WorldChunk worldChunk) { - builder.syncing(SyncPacketHeader.CHUNK, () -> SyncPlayerList.create(worldChunk)).ticking(); + if ((Chunk) (Object) this instanceof WorldChunk) { + builder.syncing(SyncChannel.CHUNK).ticking(); } - this.qsl$container = builder.build(LazyComponentContainer.FACTORY); + this.qsl$container = builder.build(ComponentContainer.LAZY_FACTORY); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java index cf34e27a64..1310896235 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java @@ -28,7 +28,6 @@ @Mixin(ThreadedAnvilChunkStorage.class) public abstract class ThreadedChunkStorageMixin { - @Inject( method = "sendChunkDataPackets", at = @At( @@ -38,6 +37,6 @@ public abstract class ThreadedChunkStorageMixin { ) ) private void syncChunkContainer(ServerPlayerEntity player, MutableObject mutableObject, WorldChunk chunk, CallbackInfo ci) { - // FIXME: Make this work + chunk.getComponentContainer().sync(chunk); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MinecraftClientMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MinecraftClientMixin.java deleted file mode 100644 index 6b1f4ae9e6..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/client/level/MinecraftClientMixin.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.mixin.client.level; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.RunArgs; -import org.quiltmc.qsl.component.api.container.ComponentContainer; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(MinecraftClient.class) -public class MinecraftClientMixin implements ComponentProvider { - private ComponentContainer qsl$container; - - @Override - public ComponentContainer getComponentContainer() { - return this.qsl$container; - } - - @Inject(method = "", at = @At("TAIL")) - private void initContainer(RunArgs runArgs, CallbackInfo ci) { - this.qsl$container = ComponentContainer.builder(this).unwrap().build(LazyComponentContainer.FACTORY); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java index 03bf984779..044832683e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java @@ -23,8 +23,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -40,14 +39,12 @@ public ComponentContainer getComponentContainer() { return this.qsl$container; } - @SuppressWarnings("ConstantConditions") @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { this.qsl$container = ComponentContainer.builder(this) - .unwrap() .ticking() - .syncing(SyncPacketHeader.ENTITY, () -> SyncPlayerList.create((Entity) (Object) this)) - .build(LazyComponentContainer.FACTORY); + .syncing(SyncChannel.ENTITY) + .build(ComponentContainer.LAZY_FACTORY); } @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java index 14af2189c4..78524559d8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java @@ -24,8 +24,9 @@ @Mixin(MinecraftServer.class) public abstract class MinecraftServerMixin implements ComponentProvider { + @SuppressWarnings("ConstantConditions") @Override public ComponentContainer getComponentContainer() { - return ComponentProviderState.getGlobal(this).getComponentContainer(); + return ComponentProviderState.getGlobal((MinecraftServer) (Object)this).getComponentContainer(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java new file mode 100644 index 0000000000..5cb6e80adc --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java @@ -0,0 +1,26 @@ +package org.quiltmc.qsl.component.mixin.level.client; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.RunArgs; +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public abstract class MinecraftClientMixin implements ComponentProvider { + private ComponentContainer qsl$container; + + @Inject(method = "", at = @At("TAIL")) + private void initContainer(RunArgs runArgs, CallbackInfo ci) { + this.qsl$container = ComponentContainer.builder(this).build(ComponentContainer.LAZY_FACTORY); + } + + @Override + public ComponentContainer getComponentContainer() { + return this.qsl$container; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java index 37b825d2e5..8bda6dc2e3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java @@ -8,8 +8,9 @@ @Mixin(World.class) public class WorldMixin implements ComponentProvider { + @SuppressWarnings("ConstantConditions") @Override public ComponentContainer getComponentContainer() { - return ComponentProviderState.get(this).getComponentContainer(); + return ComponentProviderState.get((World)(Object)this).getComponentContainer(); } } diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index 46e449da60..bc33348aa8 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -15,7 +15,7 @@ "world.WorldMixin" ], "client": [ - "client.level.MinecraftClientMixin" + "level.client.MinecraftClientMixin" ], "injectors": { "defaultRequire": 1 diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index a308a0f682..c40d0e9098 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -35,6 +35,7 @@ import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.dynamic.Codecs; import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; @@ -47,7 +48,6 @@ import org.quiltmc.qsl.component.impl.component.DefaultFloatComponent; import org.quiltmc.qsl.component.impl.component.DefaultIntegerComponent; import org.quiltmc.qsl.component.impl.component.DefaultInventoryComponent; -import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.quiltmc.qsl.component.test.component.SaveFloatComponent; import java.util.UUID; @@ -57,11 +57,11 @@ public class ComponentTestMod implements ModInitializer { public static final ComponentType COW_INVENTORY = Components.register( new Identifier(MODID, "cow_inventory"), - (saveOp, syncOp) -> new DefaultInventoryComponent(saveOp, syncOp, () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64))) + operations -> new DefaultInventoryComponent(operations, () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64))) ); public static final ComponentType CREEPER_EXPLODE_TIME = Components.register( new Identifier(MODID, "creeper_explode_time"), - (saveOp, syncOp) -> new DefaultIntegerComponent(saveOp, syncOp, 200) + operations -> new DefaultIntegerComponent(operations, 200) ); public static final ComponentType HOSTILE_EXPLODE_TIME = Components.register( new Identifier(MODID, "hostile_explode_time"), @@ -69,19 +69,19 @@ public class ComponentTestMod implements ModInitializer { ); public static final ComponentType CHEST_NUMBER = Components.register( new Identifier(MODID, "chest_number"), - (saveOp, syncOp) -> new DefaultIntegerComponent(saveOp, syncOp, 200) + operations -> new DefaultIntegerComponent(operations, 200) ); public static final ComponentType CHUNK_INVENTORY = Components.register( new Identifier(MODID, "chunk_inventory"), - (saveOp, syncOp) -> new DefaultInventoryComponent(saveOp, syncOp, 1) + operations -> new DefaultInventoryComponent(operations, 1) ); - public static final ComponentType SAVE_FLOAT = Components.registerTicking( + public static final ComponentType SAVE_FLOAT = Components.registerInstant( new Identifier(MODID, "save_float"), SaveFloatComponent::new ); - public static final ComponentType SERVER_TICK = Components.registerTicking( + public static final ComponentType SERVER_TICK = Components.registerInstant( new Identifier(MODID, "level_tick"), - (saveOp, syncOP) -> provider -> { + (ops) -> provider -> { if (provider instanceof MinecraftServer properties) { properties.expose(SAVE_FLOAT).ifJust(floatComponent -> { floatComponent.set(floatComponent.get() + 0.5f); @@ -101,11 +101,11 @@ public class ComponentTestMod implements ModInitializer { ); public static final ComponentType> UUID_THING = Components.register( new Identifier(MODID, "uuid_thing"), - (saveOperation, syncOperation) -> new GenericComponent<>(saveOperation, Codecs.UUID) + (ops) -> new GenericComponent<>(ops, Codecs.UUID) ); - public static final ComponentType PLAYER_TICK = Components.registerTicking( + public static final ComponentType PLAYER_TICK = Components.registerInstant( new Identifier(MODID, "player_tick"), - (saveOP, syncOp) -> provider -> { + (ops) -> provider -> { if (provider instanceof ServerPlayerEntity player) { ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); if (stackInHand.isOf(Items.WHEAT)) { @@ -159,10 +159,10 @@ public void onInitialize(ModContainer mod) { Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); - Components.inject(MinecraftServer.class, SERVER_TICK); +// Components.inject(MinecraftServer.class, SERVER_TICK); Components.injectInheritage(ServerPlayerEntity.class, PLAYER_TICK); Components.inject(ServerPlayerEntity.class, UUID_THING); - Components.inject(ComponentProviderState.class, SAVE_FLOAT); + Components.injectInheritage(World.class, SAVE_FLOAT); // Dynamic Injection } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 700b510831..116c006764 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -21,12 +21,10 @@ import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; -import net.minecraft.util.Hand; import net.minecraft.util.TypeFilter; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.explosion.Explosion; @@ -48,27 +46,12 @@ public void endWorldTick(MinecraftServer server, ServerWorld world) { return; } Chunk chunk = world.getChunk(player.getBlockPos()); - ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); cowTick(world); creeperTick(world); hostileTick(world); currentChunkBETick(world, chunk); currentChunkTick(player, chunk); - stackInHandTick(player, stackInHand); - } - - private void stackInHandTick(ServerPlayerEntity player, ItemStack stackInHand) { - if (!stackInHand.isEmpty() && stackInHand.isOf(Items.BOOKSHELF)) { - stackInHand.expose(ComponentTestMod.ITEMSTACK_INT).ifJust(integerComponent -> { - integerComponent.increment(); - integerComponent.save(); - - if (integerComponent.get() >= 200) { - player.setStackInHand(Hand.MAIN_HAND, new ItemStack(Items.BOOK, 12)); - } - }); - } } private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { @@ -87,10 +70,10 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { if (ItemStack.canCombine(stack, playerStack)) { stack.increment(1); playerStack.decrement(1); - stack.expose(ComponentTestMod.ITEMSTACK_INT).ifJust(defaultIntegerComponent -> { - defaultIntegerComponent.increment(); - defaultIntegerComponent.save(); - }); +// stack.expose(ComponentTestMod.ITEMSTACK_INT).ifJust(defaultIntegerComponent -> { +// defaultIntegerComponent.increment(); +// defaultIntegerComponent.save(); +// }); inventory.save(); inventory.sync(); } @@ -120,7 +103,7 @@ private void hostileTick(ServerWorld world) { if (explodeTime.get() <= 200) { explodeTime.increment(); explodeTime.save(); -// explodeTime.sync(); Causes mucho lag!! + explodeTime.sync(); // Causes mucho lag!! } else { hostile.getWorld().createExplosion( null, diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 0616db8dc9..61ebf39ad3 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -27,14 +27,11 @@ import net.minecraft.util.math.Direction; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.container.ComponentContainer; -import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.component.InventoryComponent; +import org.quiltmc.qsl.component.impl.container.CompositeComponentContainer; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; -import org.quiltmc.qsl.component.impl.sync.SyncPlayerList; -import org.quiltmc.qsl.component.impl.sync.header.SyncPacketHeader; +import org.quiltmc.qsl.component.impl.sync.SyncChannel; import java.util.Arrays; import java.util.HashSet; @@ -43,11 +40,12 @@ public class TestBlockEntity extends BlockEntity { private final ComponentContainer container = ComponentContainer.builder(this) - .unwrap() .saving(this::markDirty) + .ticking() .add(ComponentTestMod.TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) - .syncing(SyncPacketHeader.BLOCK_ENTITY, () -> SyncPlayerList.create(this)) + .syncing(SyncChannel.BLOCK_ENTITY) .build(SimpleComponentContainer.FACTORY); + private final ComponentContainer composite = new CompositeComponentContainer(this.container, super.getComponentContainer()); public TestBlockEntity(BlockPos blockPos, BlockState blockState) { super(ComponentTestMod.TEST_BE_TYPE, blockPos, blockState); @@ -87,18 +85,7 @@ private static void expand(BlockPos initialPos, BlockPos pos, World world, Set Maybe expose(ComponentType id) { - return super.expose(id).or(() -> this.container.expose(id).filterMap(id::cast)); - } - - @Override - public void readNbt(NbtCompound nbt) { - super.readNbt(nbt); - this.container.readNbt(nbt); + return this.composite; } @Nullable @@ -111,10 +98,4 @@ public Packet toUpdatePacket() { public NbtCompound toInitialChunkDataNbt() { return this.toNbt(); } - - @Override - protected void writeNbt(NbtCompound nbt) { - super.writeNbt(nbt); - this.container.writeNbt(nbt); - } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java index 6a3dba5c51..14bc5f72ce 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java @@ -25,5 +25,6 @@ public class ComponentTestModClient implements ClientModInitializer { @Override public void onInitializeClient(ModContainer mod) { +// Components.inject(MinecraftClient.class, ComponentTestMod.SAVE_FLOAT); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java index f680bc65a3..51cc32b190 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java @@ -16,19 +16,42 @@ package org.quiltmc.qsl.component.test.component; +import net.minecraft.network.PacketByteBuf; import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.component.SyncedComponent; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.impl.component.DefaultFloatComponent; +import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; -public class SaveFloatComponent extends DefaultFloatComponent implements TickingComponent { - public SaveFloatComponent(@Nullable Runnable saveOperation, @Nullable Runnable ignored) { - super(saveOperation); +public class SaveFloatComponent extends DefaultFloatComponent implements TickingComponent, SyncedComponent { + private final Runnable syncOperation; + + public SaveFloatComponent(Component.Operations ops) { + super(ops); + this.syncOperation = ops.syncOperation(); } @Override public void tick(ComponentProvider provider) { - this.set(this.get() + 0.5f); + this.set(this.get() + 50); this.save(); + this.sync(); + } + + @Override + public void writeToBuf(PacketByteBuf buf) { + NetworkCodec.FLOAT.encode(buf, this.get()); + } + + @Override + public void readFromBuf(PacketByteBuf buf) { + this.set(NetworkCodec.FLOAT.decode(buf).unwrapOr(0f)); + } + + @Override + public @Nullable Runnable getSyncOperation() { + return this.syncOperation; } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index 5d378085c1..f2d230f8d6 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -25,6 +25,7 @@ import net.minecraft.util.math.ChunkPos; import org.quiltmc.qsl.component.impl.component.DefaultIntegerComponent; import org.quiltmc.qsl.component.test.ComponentTestMod; +import org.quiltmc.qsl.component.test.component.SaveFloatComponent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -44,11 +45,17 @@ public abstract class MixinInGameHud { @Inject(method = "render", at = @At("TAIL")) private void renderCustom(MatrixStack matrices, float tickDelta, CallbackInfo ci) { + MinecraftClient.getInstance().world + .expose(ComponentTestMod.SAVE_FLOAT) + .map(SaveFloatComponent::get) + .map(String::valueOf) + .ifJust(saveFloat -> this.getTextRenderer().draw(matrices, saveFloat, 10, 20, 0xfafafa)); + Entity entity = MinecraftClient.getInstance().targetedEntity; if (entity != null) { - entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).map(DefaultIntegerComponent::get).ifJust(integer -> { - this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa); - }); + entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME) + .map(DefaultIntegerComponent::get) + .ifJust(integer -> this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa)); } ChunkPos chunkPos = MinecraftClient.getInstance().player.getChunkPos(); MinecraftClient.getInstance().world.getChunk(chunkPos.x, chunkPos.z).expose(ComponentTestMod.CHUNK_INVENTORY) From 664c0d1dc51373143b011bae8e4ccb793f7e85da Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 18 Jul 2022 21:46:37 +0300 Subject: [PATCH 58/70] Cleared up some code. --- .../org/quiltmc/qsl/base/api/util/Lazy.java | 16 ++++++++++ .../qsl/base/api/util/TwoWayFunction.java | 16 ++++++++++ .../qsl/component/api/ComponentType.java | 2 +- .../client/sync/ClientRegistryPacket.java | 4 +-- .../container/AbstractComponentContainer.java | 16 ++++++++++ .../CompositeComponentContainer.java | 16 ++++++++++ .../container/SingleComponentContainer.java | 16 ++++++++++ .../event/ServerWorldTickEventListener.java | 16 ++++++++++ .../dynamic/DynamicWrappedPredicate.java | 16 ++++++++++ .../qsl/component/impl/sync/SyncChannel.java | 29 +++++++++++++++---- .../impl/sync/codec/NetworkCodec.java | 17 +++++++---- .../impl/sync/packet/RegistryPacket.java | 2 +- .../mixin/block/entity/BlockEntityMixin.java | 1 - .../chunk/ThreadedChunkStorageMixin.java | 3 +- .../level/client/MinecraftClientMixin.java | 16 ++++++++++ .../qsl/component/mixin/world/WorldMixin.java | 16 ++++++++++ .../component/test/ServerTickListener.java | 6 ++-- .../quiltmc/qsl/component/test/TestBlock.java | 2 +- 18 files changed, 189 insertions(+), 21 deletions(-) diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java index 91337ca062..f5af338817 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.base.api.util; import java.util.function.Consumer; diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java index 68683cb941..f010d299bc 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.base.api.util; /** diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 16fc76d842..e5d3e59db6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -43,7 +43,7 @@ public record ComponentType(Identifier id, Component.Factor * We provide a {@link NetworkCodec} to be used with manual registry sync, until the registry sync API is merged. */ public static final NetworkCodec> NETWORK_CODEC = - NetworkCodec.INT.map(Components.REGISTRY::getRawId, ClientSyncHandler.getInstance()::getType); + NetworkCodec.VAR_INT.map(Components.REGISTRY::getRawId, ClientSyncHandler.getInstance()::getType); /** * @see Static */ diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java index a7a9a17f60..0c880e9f9a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java @@ -44,8 +44,8 @@ public static Either, Identifier> createIdList(PacketByteBuf buf, IdList ret = new IdList<>(size); // size is dropped for (int i = 0; i < size; i++) { - Identifier id = buf.readIdentifier(); - int rawId = buf.readInt(); // a whole entry is dropped + Identifier id = buf.readIdentifier(); // consume identifier + int rawId = buf.readVarInt(); // consumer rawId Maybe type = Maybe.fromOptional(targetRegistry.getOrEmpty(id)); if (type.isNothing()) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index 763fd50d40..fa1bef3b20 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java index bfa763afa4..b6cfc7e05c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java index 60c40a0a63..31eda13dfa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.container; import net.minecraft.nbt.NbtCompound; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java index 81fecaa9cf..fb652a1e6c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.event; import net.minecraft.server.MinecraftServer; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java index a5f6eb4602..6b3622550d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.injection.predicate.dynamic; import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java index a7d878759c..e5e1f25c79 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.sync; import net.minecraft.block.entity.BlockEntity; @@ -24,39 +40,42 @@ import java.util.function.Consumer; import java.util.function.Function; +// ClientResolution.* all reference client-only classes, +// so we need to just make sure we use lambdas so no attempt at class loading non-existent classes +@SuppressWarnings("Convert2MethodRef") public record SyncChannel

(Identifier channelId, NetworkCodec

codec, Function> playerProvider) implements TwoWayFunction { // BlockEntity private static final NetworkCodec BLOCK_ENTITY_CODEC = - NetworkCodec.BLOCK_POS.map(BlockEntity::getPos, ClientResolution::getBlockEntity); + NetworkCodec.BLOCK_POS.map(BlockEntity::getPos, blockPos -> ClientResolution.getBlockEntity(blockPos)); public static final SyncChannel BLOCK_ENTITY = new SyncChannel<>(PacketIds.BLOCK_ENTITY_SYNC, BLOCK_ENTITY_CODEC, PlayerLookup::tracking); // Entity private static final NetworkCodec ENTITY_CODEC = - NetworkCodec.INT.map(Entity::getId, ClientResolution::getEntity); + NetworkCodec.INT.map(Entity::getId, rawId -> ClientResolution.getEntity(rawId)); public static final SyncChannel ENTITY = new SyncChannel<>(PacketIds.ENTITY_SYNC, ENTITY_CODEC, PlayerLookup::tracking); // Chunk private static final NetworkCodec CHUNK_CODEC = - NetworkCodec.CHUNK_POS.map(Chunk::getPos, ClientResolution::getChunk); + NetworkCodec.CHUNK_POS.map(Chunk::getPos, chunkPos -> ClientResolution.getChunk(chunkPos)); public static final SyncChannel CHUNK = // **Careful**: This only works with WorldChunks not other chunk types! new SyncChannel<>(PacketIds.CHUNK_SYNC, CHUNK_CODEC, chunk -> PlayerLookup.tracking((ServerWorld) ((WorldChunk) chunk).getWorld(), chunk.getPos())); // World private static final NetworkCodec WORLD_CODEC = - NetworkCodec.empty(ClientResolution::getWorld); + NetworkCodec.empty(() -> ClientResolution.getWorld()); public static final SyncChannel WORLD = new SyncChannel<>(PacketIds.WORLD_SYNC, WORLD_CODEC, world -> PlayerLookup.world(((ServerWorld) world))); // Level private static final NetworkCodec LEVEL_CODEC = - NetworkCodec.empty(MinecraftClient::getInstance); + NetworkCodec.empty(() -> MinecraftClient.getInstance()); public static final SyncChannel LEVEL = new SyncChannel<>(PacketIds.LEVEL_SYNC, LEVEL_CODEC, provider -> PlayerLookup.all(((MinecraftServer) provider))); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java index 940fa107fd..cff4d7fbc1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java @@ -35,20 +35,25 @@ import java.util.function.IntFunction; import java.util.function.Supplier; -public record NetworkCodec(BiConsumer encoder, - Function decoder) { +public record NetworkCodec(BiConsumer encoder, Function decoder) { public static final NetworkCodec BYTE = new NetworkCodec<>( (buf, aByte) -> buf.writeByte(aByte), PacketByteBuf::readByte ); public static final NetworkCodec INT = new NetworkCodec<>( PacketByteBuf::writeInt, PacketByteBuf::readInt ); + public static final NetworkCodec VAR_INT = new NetworkCodec<>( + PacketByteBuf::writeVarInt, PacketByteBuf::readVarInt + ); public static final NetworkCodec SHORT = new NetworkCodec<>( (buf, aShort) -> buf.writeShort(aShort), PacketByteBuf::readShort ); public static final NetworkCodec LONG = new NetworkCodec<>( PacketByteBuf::writeLong, PacketByteBuf::readLong ); + public static final NetworkCodec VAR_LONG = new NetworkCodec<>( + PacketByteBuf::writeVarLong, PacketByteBuf::readVarLong + ); public static final NetworkCodec FLOAT = new NetworkCodec<>( PacketByteBuf::writeFloat, PacketByteBuf::readFloat ); @@ -82,11 +87,11 @@ public record NetworkCodec(BiConsumer encoder, public static > NetworkCodec list(NetworkCodec entryCodec, IntFunction listFactory) { return new NetworkCodec<>( (buf, os) -> { - INT.encode(buf, os.size()); + VAR_INT.encode(buf, os.size()); os.forEach(o -> entryCodec.encode(buf, o)); }, buf -> { - int size = INT.decode(buf).unwrap(); + int size = VAR_INT.decode(buf).unwrap(); L newList = listFactory.apply(size); for (int i = 0; i < size; i++) { @@ -101,11 +106,11 @@ public static > NetworkCodec list(NetworkCodec entryC public static > NetworkCodec map(NetworkCodec> entryCodec, IntFunction mapFactory) { return new NetworkCodec<>( (buf, m) -> { - INT.encode(buf, m.size()); + VAR_INT.encode(buf, m.size()); m.forEach((key, value) -> entryCodec.encode(buf, Pair.of(key, value))); }, buf -> { - int size = INT.decode(buf).unwrap(); + int size = VAR_INT.decode(buf).unwrap(); var map = mapFactory.apply(size); for (int i = 0; i < size; i++) { entryCodec.decode(buf).ifJust(ovPair -> map.put(ovPair.getFirst(), ovPair.getSecond())); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java index dae21ef397..6ff78fb9ce 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java @@ -33,7 +33,7 @@ public static PacketByteBuf createRegistryPacket(Registry registry) { var id = registry.getId(t); var rawId = registry.getRawId(t); - buf.writeIdentifier(id).writeInt(rawId); // append id and rawId + buf.writeIdentifier(id).writeVarInt(rawId); // append id and rawId }); return buf; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java index 5ae5d81591..c85c55fc08 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java @@ -23,7 +23,6 @@ import net.minecraft.util.math.BlockPos; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.quiltmc.qsl.component.impl.sync.SyncChannel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java index 1310896235..8ea28e505a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java @@ -37,6 +37,7 @@ public abstract class ThreadedChunkStorageMixin { ) ) private void syncChunkContainer(ServerPlayerEntity player, MutableObject mutableObject, WorldChunk chunk, CallbackInfo ci) { - chunk.getComponentContainer().sync(chunk); + chunk.getComponentContainer().sync(chunk); // Handles initial chunk sync + chunk.getBlockEntities().forEach((blockPos, blockEntity) -> blockEntity.getComponentContainer().sync(blockEntity)); // Handles initial block entity sync } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java index 5cb6e80adc..d1ea3045cc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin.level.client; import net.minecraft.client.MinecraftClient; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java index 8bda6dc2e3..cca01a078d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin.world; import net.minecraft.world.World; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 116c006764..3c53f89ad9 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -64,7 +64,7 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { newStack.setCount(1); inventory.setStack(0, newStack); inventory.save(); - inventory.sync(); + // inventory.sync(); playerStack.decrement(1); } else { if (ItemStack.canCombine(stack, playerStack)) { @@ -75,7 +75,7 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { // defaultIntegerComponent.save(); // }); inventory.save(); - inventory.sync(); + // inventory.sync(); } } } @@ -103,7 +103,7 @@ private void hostileTick(ServerWorld world) { if (explodeTime.get() <= 200) { explodeTime.increment(); explodeTime.save(); - explodeTime.sync(); // Causes mucho lag!! + // explodeTime.sync(); // Causes mucho lag!! } else { hostile.getWorld().createExplosion( null, diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index 7b5cf9a791..38a424a40c 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -70,7 +70,7 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt copied.setCount(1); inventoryComponent.setStack(0, copied); inventoryComponent.save(); - inventoryComponent.sync(); + // inventoryComponent.sync(); ret[0] = ActionResult.SUCCESS; } else { if (ItemStack.canCombine(stack, handStack)) { From 93c72f075c2811bf3af6c58a573bdfc28fe6a679 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 21 Jul 2022 15:05:34 +0300 Subject: [PATCH 59/70] Rewrite of syncing: * Implemented initial sync. * Implemented sync requests. This is the last feature commit. From now on only improvements, until the initial release. --- .../qsl/base/api/util/TwoWayFunction.java | 39 --- library/data/component/build.gradle | 12 +- .../quiltmc/qsl/component/api/Component.java | 2 - .../qsl/component/api/ComponentType.java | 4 +- .../api/component/SyncedGenericComponent.java | 4 +- .../api/container/ComponentContainer.java | 172 +++++++++- .../qsl/component/api/package-info.java | 10 +- .../api/provider/ComponentProvider.java | 56 +++- .../qsl/component/api/sync/SyncChannel.java | 293 ++++++++++++++++++ .../sync/codec/NetworkCodec.java | 66 ++-- .../qsl/component/impl/CommonInitializer.java | 24 +- .../impl/client/ClientInitializer.java | 29 +- .../client/sync/ClientRegistryPacket.java | 3 + .../impl/client/sync/ClientResolution.java | 41 ++- .../impl/client/sync/ClientSyncHandler.java | 53 +++- .../container/AbstractComponentContainer.java | 39 +-- .../CompositeComponentContainer.java | 9 +- .../container/EmptyComponentContainer.java | 21 +- .../container/LazyComponentContainer.java | 29 +- .../container/OnAccessComponentContainer.java | 10 +- .../container/SimpleComponentContainer.java | 11 +- .../container/SingleComponentContainer.java | 40 +-- .../impl/event/ClientEventListener.java | 38 +++ .../impl/event/CommonEventListener.java | 29 ++ .../impl/event/ComponentEventPhases.java | 14 + .../impl/event/ServerTickEventListener.java | 32 -- .../event/ServerWorldTickEventListener.java | 35 --- .../impl/sync/ServerSyncHandler.java | 25 +- .../qsl/component/impl/sync/SyncChannel.java | 117 ------- .../impl/sync/packet/RegistryPacket.java | 1 + .../impl/sync/packet/SyncPacket.java | 76 ----- .../impl/util/ComponentProviderState.java | 2 +- .../mixin/block/entity/BlockEntityMixin.java | 6 +- .../DirectBlockEntityTickInvokerMixin.java | 20 +- .../qsl/component/mixin/chunk/ChunkMixin.java | 2 +- .../chunk/ThreadedChunkStorageMixin.java | 43 --- .../component/mixin/entity/EntityMixin.java | 9 +- .../mixin/level/MinecraftServerMixin.java | 1 + .../level/client/MinecraftClientMixin.java | 1 - .../sync/ClientPlayNetworkHandlerMixin.java | 24 ++ .../component/mixin/sync/WorldChunkMixin.java | 19 ++ .../resources/quilt_component.mixins.json | 5 +- .../qsl/component/test/ComponentTestMod.java | 9 +- .../component/test/ServerTickListener.java | 6 +- .../quiltmc/qsl/component/test/TestBlock.java | 12 +- .../qsl/component/test/TestBlockEntity.java | 5 +- .../component/ChunkInventoryComponent.java | 52 ++++ .../test/component/SaveFloatComponent.java | 9 +- 48 files changed, 1011 insertions(+), 548 deletions(-) delete mode 100644 library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api}/sync/codec/NetworkCodec.java (72%) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java create mode 100644 library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java deleted file mode 100644 index f010d299bc..0000000000 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/TwoWayFunction.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.base.api.util; - -/** - * Represents an object that can trasmute between 2 types of objects provided it has one of them available. - * - * @param The first object type - * @param The second object type - */ -public interface TwoWayFunction { - /** - * Transform a {@link U} instance into a {@link T} instance. - * @param u The {@link U} instance to transform. - * @return The produced {@link T} instance - */ - T to(U u); - - /** - * Transform a {@link T} instance into a {@link U} instance. - * @param t The {@link T} instance to transform. - * @return The produced {@link T} instance. - */ - U from(T t); -} diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index da70659ab8..cccc46cf07 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -22,12 +22,12 @@ qslModule { } entrypoints { - events { - values = [ - "org.quiltmc.qsl.component.impl.event.ServerTickEventListener", - "org.quiltmc.qsl.component.impl.event.ServerWorldTickEventListener" - ] - } +// events { +// values = [ +// "org.quiltmc.qsl.component.impl.event.ServerTickEventListener", +// "org.quiltmc.qsl.component.impl.event.ServerWorldTickEventListener" +// ] +// } init { values = ["org.quiltmc.qsl.component.impl.CommonInitializer"] diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java index 354534c765..ca6b6310ec 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java @@ -18,8 +18,6 @@ import org.jetbrains.annotations.Nullable; -import java.util.Objects; - /** * Marks a type as a container for data and/or behaviour. * diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index e5d3e59db6..2ec4f4bb4d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -19,7 +19,7 @@ import net.minecraft.util.Identifier; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; -import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; +import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; import java.util.IdentityHashMap; import java.util.Map; @@ -43,7 +43,7 @@ public record ComponentType(Identifier id, Component.Factor * We provide a {@link NetworkCodec} to be used with manual registry sync, until the registry sync API is merged. */ public static final NetworkCodec> NETWORK_CODEC = - NetworkCodec.VAR_INT.map(Components.REGISTRY::getRawId, ClientSyncHandler.getInstance()::getType); + NetworkCodec.VAR_INT.map(Components.REGISTRY::getRawId, rawId -> ClientSyncHandler.getInstance().getType(rawId)); /** * @see Static */ diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java index db64473950..437eafbe3f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java @@ -20,7 +20,7 @@ import net.minecraft.network.PacketByteBuf; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; +import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; public class SyncedGenericComponent extends GenericComponent implements SyncedComponent { private final NetworkCodec networkCodec; @@ -40,7 +40,7 @@ public void writeToBuf(PacketByteBuf buf) { @Override public void readFromBuf(PacketByteBuf buf) { - this.networkCodec.decode(buf).ifJust(this::setValue); + this.setValue(this.networkCodec.decode(buf)); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index cb0d33990f..ca1920b232 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -17,6 +17,7 @@ package org.quiltmc.qsl.component.api.container; import net.minecraft.nbt.NbtCompound; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; @@ -25,26 +26,118 @@ import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.*; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import java.util.ArrayList; import java.util.List; +import java.util.Queue; +import java.util.function.BiConsumer; +/** + * A base container for all {@link Component}s that a {@link ComponentProvider} contains. + * The implementation of this, needs to not take up too much runtime, since the methods in here may be called really often. + *

+ * There are default implementations used internally in the API implementation, but they are also usable outside of internals. + * These include: + *

    + *
  1. {@link EmptyComponentContainer}: usable through the {@link ComponentContainer#EMPTY} instance or the {@link ComponentContainer#EMPTY_FACTORY} instance.
  2. + *
  3. {@link SimpleComponentContainer}: usable through the {@link ComponentContainer#SIMPLE_FACTORY} instance.
  4. + *
  5. {@link LazyComponentContainer}: usable through the {@link ComponentContainer#LAZY_FACTORY} instance.
  6. + *
  7. {@link OnAccessComponentContainer}: usable through the {@link ComponentContainer#ON_ACCESS_FACTORY} instance.
  8. + *
  9. {@link SingleComponentContainer}: usable through the {@link ComponentContainer#createSingleFactory} method.
  10. + *
  11. {@link CompositeComponentContainer}: usable through the {@link ComponentContainer#createComposite} method.
  12. + *
+ * + * To create a container, most of the time, you should use the {@link Builder} class.
+ * You are also free to extend it and create a custom {@link Builder} implementation to suit your needs. + * + * @see ComponentProvider + * @see ComponentType + * @see Component + * @author 0xJoeMama + */ public interface ComponentContainer { + /** + * A {@link ComponentContainer} that holds no components. + */ ComponentContainer EMPTY = EmptyComponentContainer.INSTANCE; + /** + * A {@link Factory} to the aforementioned {@link EmptyComponentContainer}.
+ * This will always return the same instance. + */ ComponentContainer.Factory EMPTY_FACTORY = EmptyComponentContainer.FACTORY; + /** + * A {@link Factory} to a {@link SimpleComponentContainer}.
+ * A {@link SimpleComponentContainer} instantly initializes all of its components, disregarding the + * {@link ComponentType#isInstant()} value for their types.
+ * + * The advantage of this {@linkplain ComponentContainer container} is that by initializing all of its components right off the bat, + * it can have a faster runtime. However, that does sacrifice on memory and also on disc space, + * since all {@link org.quiltmc.qsl.component.api.component.NbtComponent}s, even if their value hasn't been modified, will be saved. + */ ComponentContainer.Factory SIMPLE_FACTORY = SimpleComponentContainer.FACTORY; + /** + * A {@link Factory} to a {@link LazyComponentContainer}.
+ * A {@link LazyComponentContainer} lazily initializes its components. + * This saves on memory and disc space, since non-initialized components, will not be written to disc.
+ * The runtime hit of using this {@linkplain ComponentContainer container} is minimal, since it mostly consists of work that would also be done at runtime by a {@link SimpleComponentContainer}.
+ * The only functional difference is that this container will pull injections targetting its provider. + * This container is used as the default for all type at the moment. + */ ComponentContainer.Factory LAZY_FACTORY = LazyComponentContainer.FACTORY; + /** + * A {@link Factory} to a {@link OnAccessComponentContainer}.
+ * An {@link OnAccessComponentContainer} is similar to a {@link LazyComponentContainer} in that it lazily initializes its components. + * However, it does so in a different way. Instead of storing {@link Lazy} instances, + * it stores {@link com.mojang.datafixers.util.Either} instances that it attempts to access and/or initialize on expose. + * This currently leads to extra object creation, hence it's considered {@linkplain org.jetbrains.annotations.ApiStatus.Experimental experimental}.
+ * + * May be used as the default container for our implementations in the future. + * + * @deprecated Experimental + */ + @ApiStatus.Experimental ComponentContainer.Factory ON_ACCESS_FACTORY = OnAccessComponentContainer.FACTORY; + /** + * Creates a {@link Factory} to a {@link SingleComponentContainer}.
+ * + * A {@link SingleComponentContainer} is identical to a {@link LazyComponentContainer}, except it can only store 1 component. + * + * @param type The {@link ComponentType} to store. The default factory of the type is used for initialization. + * @return A new {@link Factory} for {@link SingleComponentContainer} holding the provided {@link ComponentType}. + * @param The type of component that is contained by the container. + */ static ComponentContainer.Factory> createSingleFactory(ComponentType type) { return SingleComponentContainer.createFactory(new ComponentEntry<>(type)); } - static ComponentContainer.Factory> createSingleFactory(ComponentEntry entry) { - return SingleComponentContainer.createFactory(entry); + /** + * Identical to {@link ComponentContainer#createSingleFactory(ComponentType)}, except that it allows the caller to specify the {@link Component.Factory} used. + * @see ComponentContainer#createSingleFactory(ComponentType) + */ + static ComponentContainer.Factory> createSingleFactory(ComponentType type, Component.Factory factory) { + return SingleComponentContainer.createFactory(new ComponentEntry<>(type, factory)); } + /** + * Creates a {@link CompositeComponentContainer} using the 2 {@linkplain ComponentContainer containers} provided. + * + * @param main The main container. + * @param fallback The secondary container. + * @return A {@link CompositeComponentContainer} which basically just wraos the other two containers and functions as their union. + */ + static ComponentContainer createComposite(ComponentContainer main, ComponentContainer fallback) { + return new CompositeComponentContainer(main, fallback); + } + + /** + * Creates an {@link Builder} targetting the provided object as its provider. + * + * @param obj The object that the {@link Builder} will target. + * @return A new {@link Builder} instance. + * @throws UnsupportedOperationException If the provided object does not implement {@link ComponentProvider}. + */ static Builder builder(Object obj) { if (!(obj instanceof ComponentProvider provider)) { throw new UnsupportedOperationException("Cannot create a container for a non-provider object"); @@ -53,25 +146,89 @@ static Builder builder(Object obj) { return new Builder(provider); } + /** + * The deepest level implementation of {@link org.quiltmc.qsl.component.api.Components#expose}.
+ * This takes in a wildcarded type and only returns a {@link Component} without casting it.
+ * This is type-unsafe and if not implemented correctly, may lead to crashes with {@link ClassCastException}s.
+ * + * This method is called really often, so it is advised you make it have a really fast runtime. + * + * @param type The type to expose. + * @return Should return {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided {@link ComponentType} is not contained in the current container. + * Otherwise, should always return {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the contained {@link Component} instance. + */ Maybe expose(ComponentType type); + /** + * Serializes the {@link org.quiltmc.qsl.component.api.component.NbtComponent}s this {@linkplain ComponentContainer container} contains, into the provided nbt tag. + * + * @param providerRootNbt The root nbt tag of the provider containing this {@link ComponentContainer}. + */ void writeNbt(NbtCompound providerRootNbt); + /** + * Deserializes the {@link org.quiltmc.qsl.component.api.component.NbtComponent}s this {@link ComponentContainer container} contains, from the provided nbt tag.
+ * + * @implNote There is no guarantee that the provided tag will contain exactly the same components as the container. + * It may contain less or more. Keep that in mind when creating custom implementations. + * + * @param providerRootNbt The root nbt tag of the provider containing this {@link ComponentContainer}. + */ void readNbt(NbtCompound providerRootNbt); + /** + * Ticks all {@link org.quiltmc.qsl.component.api.component.TickingComponent}s contained in this {@link ComponentContainer}. + * + * @param provider The provider is passed in so that {@link org.quiltmc.qsl.component.api.component.TickingComponent}s can use it. + */ void tick(ComponentProvider provider); + /** + * Syncs all {@link org.quiltmc.qsl.component.api.component.SyncedComponent}s contained in this {@link ComponentContainer}, provided they need syncing. + * Most of the time this method is invoked by {@link ComponentContainer#tick}.
+ * + * @param provider The provider is passed in so that {@link SyncChannel#syncFromQueue} can use it, when creating a packet to sync data to the client. + * @implNote The best way to sync components at the moment is using {@link SyncChannel#syncFromQueue}, which takes in a {@link Queue} of components that need syncing. + */ void sync(ComponentProvider provider); + /** + * Runs the specified action over all entries of this container.
+ * + * @apiNote May be slow, so use sparingly! + */ + void forEach(BiConsumer, ? super Component> action); + + /** + * An interface representing the way to create a new {@link ComponentContainer}. + * + * @param The type of container created by calling {@link Factory#generate}. + * @author 0xJoeMama + */ @FunctionalInterface interface Factory { + /** + * Creates a {@link ComponentContainer} using the specified arguments. + * + * @param provider The {@link ComponentProvider} that will contain the created {@link ComponentContainer}. + * @param entries A {@link List} containing all the entries that were manually added by the {@link Builder}. + * @param saveOperation The operation to be run by the contained {@link Component}s to mark the {@linkplain ComponentProvider provider} as needing to save. + * @param ticking Whether this container can tick. + * @param syncChannel The {@link SyncChannel} representing the {@link ComponentProvider} that contains the created {@link ComponentContainer}. + * @return A {@link ComponentContainer} created using the specified parameters. + */ T generate(ComponentProvider provider, - Lazy>> injections, + Lazy>> entries, @Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncChannel syncChannel); + @Nullable SyncChannel syncChannel); } + /** + * Base {@link Builder} class to create {@link ComponentContainer}s. + * + * @apiNote You may create custom implementations of this class, if it is needed. + */ class Builder { private final ComponentProvider provider; private final Lazy>> injections; @@ -79,7 +236,7 @@ class Builder { @Nullable private Runnable saveOperation; @Nullable - private SyncChannel syncChannel; + private SyncChannel syncChannel; private Builder(ComponentProvider provider) { this.provider = provider; @@ -98,7 +255,7 @@ public Builder ticking() { return this; } - public Builder syncing(SyncChannel syncChannel) { + public Builder syncing(SyncChannel syncChannel) { this.syncChannel = syncChannel; return this; } @@ -127,6 +284,7 @@ public Builder add(ComponentType... types) { } public T build(ComponentContainer.Factory factory) { + // TODO: See if we can cache the builder at some stage to reduce object creation. return factory.generate(this.provider, this.injections, this.saveOperation, this.ticking, this.syncChannel); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java index 93977a26e0..53a53e8f24 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java @@ -43,9 +43,9 @@ * } * } *

- * The AComponent interface provides the API for AComponent instances.
- * The ADefaultComponent class provides a default implementation of the AComponent interface. - * The data contained by ADefaultComponent is not saved or synced. If you want to learn how to save or sync data,
+ * The {@code AComponent} interface provides the API for {@code AComponent} instances.
+ * The {@code ADefaultComponent} class provides a default implementation of the {@code AComponent} interface. + * The data contained by {@code ADefaultComponent} is not saved or synced. If you want to learn how to save or sync data,
* visit the {@linkplain org.quiltmc.qsl.component.api.component.NbtComponent NbtComponent} and {@linkplain org.quiltmc.qsl.component.api.component.SyncedComponent SyncedComponent} documentation. *

*

Component Injection

@@ -78,7 +78,7 @@ * } * } * - * Now all chests should have A_COMPONENT injected into them, when they are created. + * Now all chests should have {@code AComponent} injected into them, when they are created. *

*

Accessing Components

* For any {@link org.quiltmc.qsl.component.api.provider.ComponentProvider} that has components injected into it, accessing them follows pretty much the same pattern.
@@ -86,7 +86,7 @@ * After that you can do this: *
{@code
  * //...
- * // consider pos and world to be an arguments
+ * // consider pos and world to be arguments
  * // passed into the current method.
  * var blockEntity = world.getBlockEntity(pos);
  * // The expose method returns a Maybe instance.
diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java
index ef20aaa74b..811ff47f2e 100644
--- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java
+++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java
@@ -19,8 +19,8 @@
 import net.minecraft.block.entity.BlockEntity;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.entity.Entity;
-import net.minecraft.item.ItemStack;
 import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.World;
 import net.minecraft.world.chunk.Chunk;
 import org.quiltmc.qsl.base.api.util.InjectedInterface;
 import org.quiltmc.qsl.base.api.util.Maybe;
@@ -29,20 +29,62 @@
 import org.quiltmc.qsl.component.api.ComponentType;
 import org.quiltmc.qsl.component.api.Components;
 
-@InjectedInterface({
+/**
+ * Any object that wishes to allow {@link Component components} to be attached to and queried from it,
+ * needs to implement this interface.
+ * + * Currectly it consists of the {@link ComponentProvider#getComponentContainer()} method, which is the abstract one, + * as well as the {@link ComponentProvider#expose(ComponentType)} method, which is just a utility method.
+ * In the future, more methods may be added, but for now this is all the API we need to expose on game objects.
+ * You may create custom implementations of this interface. However, to do so, I would suggest looking at + * {@link ComponentContainer} beforehand. + *

+ * + * By default, QSL provides the following, interface injected {@linkplain ComponentProvider providers}: + *

    + *
  • BlockEntity
  • + *
  • Entity
  • + *
  • Chunk
  • + *
  • World
  • + *
  • Level(in other words a world save)
  • + *
+ * + * Furthermore, all of them support component saving and syncing.
+ * + * Note: You shouldn't have to use the {@link ComponentProvider#getComponentContainer()} method that often, + * if ever, because it's needed for implementations not for using the API. + * + * @see ComponentContainer + * @see Components + * @author 0xJoeMama + */ +@InjectedInterface({ // We inject this inteface, so that modders don't need to use the methods in Components directly with our default implementations. Entity.class, BlockEntity.class, Chunk.class, - ItemStack.class, - MinecraftServer.class, - MinecraftClient.class + MinecraftServer.class, // MinecraftServer and MinecraftClient contain Level components + MinecraftClient.class, + World.class }) public interface ComponentProvider { + /** + * Every {@linkplain ComponentProvider provider} must provide a {@link ComponentContainer}, + * so that it can store the components targetting or that are manually added to it. + * + * @return An instance of {@link ComponentContainer} with a valid implementation of its interface. + */ default ComponentContainer getComponentContainer() { throw new AbstractMethodError("You need to implement the getComponentContainer method on your provider!"); } - default Maybe expose(ComponentType id) { - return Components.expose(id, this); + /** + * Utility method to call {@link Components#expose(ComponentType, Object)} on the actual provider. + * + * @param type The {@linkplain ComponentType type} we want to query. + * @return A {@link Maybe} instance following the rules defined in {@link Components#expose(ComponentType, Object)}. + * @param The type of the held component. + */ + default Maybe expose(ComponentType type) { + return Components.expose(type, this); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java new file mode 100644 index 0000000000..194fb583b1 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java @@ -0,0 +1,293 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.api.sync; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.Unit; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.WorldChunk; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.component.SyncedComponent; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; +import org.quiltmc.qsl.component.impl.client.sync.ClientResolution; +import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; +import org.quiltmc.qsl.networking.api.PacketByteBufs; +import org.quiltmc.qsl.networking.api.PlayerLookup; +import org.quiltmc.qsl.networking.api.ServerPlayNetworking; +import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking; + +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; + +// ClientResolution.* all reference client-only classes, +// so we need to just make sure we use lambdas so no attempt at class loading non-existent classes +@SuppressWarnings("Convert2MethodRef") +public class SyncChannel

{ + + // BlockEntity + public static final SyncChannel BLOCK_ENTITY = new SyncChannel<>( + PacketIds.BLOCK_ENTITY_SYNC, + NetworkCodec.BLOCK_POS, + BlockEntity::getPos, + blockPos -> ClientResolution.blockEntity(blockPos), + (serverPlayer, blockPos) -> serverPlayer.getWorld().getBlockEntity(blockPos), + PlayerLookup::tracking + ); + + // Entity + public static final SyncChannel ENTITY = new SyncChannel<>( + PacketIds.ENTITY_SYNC, + NetworkCodec.VAR_INT, + Entity::getId, + id -> ClientResolution.entity(id), + (serverPlayer, id) -> serverPlayer.getWorld().getEntityById(id), + PlayerLookup::tracking + ); + + // Chunk + public static final SyncChannel CHUNK = new SyncChannel<>( + PacketIds.CHUNK_SYNC, + NetworkCodec.CHUNK_POS, + Chunk::getPos, + chunkPos -> ClientResolution.chunk(chunkPos), + (serverPlayer, chunkPos) -> serverPlayer.getWorld().getChunk(chunkPos.x, chunkPos.z), + chunk -> PlayerLookup.tracking(((ServerWorld) ((WorldChunk) chunk).getWorld()), chunk.getPos()) // only called server side so the cast is safe + ); // **Careful**: This only works with WorldChunks not other chunk types! + + // World + public static final SyncChannel WORLD = new SyncChannel<>( + PacketIds.WORLD_SYNC, + NetworkCodec.EMPTY, + world -> Unit.INSTANCE, + unit -> ClientResolution.world(), + (serverPlayer, unit) -> serverPlayer.getWorld(), + world -> PlayerLookup.world((ServerWorld) world)// only called server side so the cast is safe + ); + + // Level + public static final SyncChannel LEVEL = new SyncChannel<>( + PacketIds.LEVEL_SYNC, + NetworkCodec.EMPTY, + provider -> Unit.INSTANCE, + unit -> ClientResolution.level(), + (serverPlayer, unit) -> serverPlayer.getServer(), + provider -> PlayerLookup.all((MinecraftServer) provider) // only called server side so the cast is safe + ); + + // TODO: Do we need accessors for these fields? + protected final Identifier channelId; + protected final NetworkCodec codec; + protected final Function identifyingDataTransformer; + protected final Function clientLocator; + protected final BiFunction serverLocator; + protected final Function> playerProvider; + @Environment(EnvType.CLIENT) + protected final Queue requestQueue = new ArrayDeque<>(); + protected final NetworkCodec> queueCodec; + + public SyncChannel(Identifier channelId, NetworkCodec codec, Function identifyingDataTransformer, + Function clientLocator, BiFunction serverLocator, + Function> playerProvider) { + this.channelId = channelId; + this.codec = codec; + this.identifyingDataTransformer = identifyingDataTransformer; + this.clientLocator = clientLocator; + this.serverLocator = serverLocator; + this.playerProvider = playerProvider; + this.queueCodec = NetworkCodec.queue(this.codec, ArrayDeque::new); + } + + public static void createPacketChannels(Consumer> register) { + register.accept(BLOCK_ENTITY); + register.accept(ENTITY); + register.accept(CHUNK); + register.accept(WORLD); + register.accept(LEVEL); + } + + @Environment(EnvType.CLIENT) + public P toClientProvider(PacketByteBuf buf) { + return this.clientLocator.apply(this.codec.decode(buf)); + } + + public PacketByteBuf toClientBuffer(P p) { + var buf = PacketByteBufs.create(); + this.codec.encode(buf, this.identifyingDataTransformer.apply(p)); + return buf; + } + + @SuppressWarnings("unchecked") + public void send(Collection players, ComponentProvider provider, BufferFiller filler) { + // The casting to P should never fail, since the provider and + // the channel type *must* match for the implementation to be correct anyway + P providerAsP = (P) provider; + var buf = this.toClientBuffer(providerAsP); // append provider data + filler.fill(buf); // append all the container data + ServerPlayNetworking.send(players.isEmpty() ? this.playerProvider.apply(providerAsP) : players, this.channelId, buf); + } + + public void syncFromQueue(Queue> pendingSync, Function, SyncedComponent> mapper, ComponentProvider provider) { + this.syncFromQueue(pendingSync, mapper, provider, List.of()); + } + + public void syncFromQueue(Queue> pendingSync, Function, SyncedComponent> mapper, ComponentProvider provider, Collection players) { + if (pendingSync.isEmpty()) { + return; + } + + this.send(players, provider, buf -> { // calling 'send' appends the provider data + buf.writeInt(pendingSync.size()); // append size + + while (!pendingSync.isEmpty()) { + var currentType = pendingSync.poll(); + ComponentType.NETWORK_CODEC.encode(buf, currentType); // append type rawId + mapper.apply(currentType).writeToBuf(buf); // append component data + } + }); + } + + @Environment(EnvType.CLIENT) + public void handleServerPushedSync(MinecraftClient client, PacketByteBuf buf) { + buf.retain(); // hold the buffer in memory + client.execute(() -> { + // provider data is consumed by SyncChannel#toClientProvider + ComponentProvider provider = this.toClientProvider(buf); + + int size = buf.readInt(); // consume size + + for (int i = 0; i < size; i++) { + ComponentType type = ComponentType.NETWORK_CODEC.decode(buf); // consume rawId + provider.expose(type).ifJust(component -> ((SyncedComponent) component).readFromBuf(buf)); // consume component data + } + + buf.release(); // make sure the buffer is properly freed + }); + } + + public void handleClientSyncRequest(MinecraftServer server, ServerPlayerEntity sender, PacketByteBuf buf) { + buf.retain(); + server.execute(() -> { + Queue queued = this.queueCodec.decode(buf); + + while (!queued.isEmpty()) { + var identifyingData = queued.poll(); + + ComponentProvider provider = this.serverLocator.apply(sender, identifyingData); + if (provider == null) { + return; + } + + this.forceSync(provider, sender); + } + + buf.release(); + }); + } + + /** + * Forcibly syncs all syncable components. + * Currently, used only for initial sync! + * + * @param provider The provider to force the sync on. + * @param sender The client that requested the sync. + * @apiNote Avoid using this to sync components. Sync should be initiated from the server, unless specifically needed. + */ + public void forceSync(ComponentProvider provider, ServerPlayerEntity sender) { + // TODO: Is there a way to avoid object creation here? + var queue = new ArrayDeque>(); + + provider.getComponentContainer().forEach((type, component) -> { + if (component instanceof SyncedComponent) { + queue.add(type); + } + }); + + this.syncFromQueue(queue, type -> ((SyncedComponent) provider.expose(type).unwrap()), provider, Collections.singletonList(sender)); + } + + @Environment(EnvType.CLIENT) + public void requestSync(P p) { + this.requestQueue.add(this.identifyingDataTransformer.apply(p)); + } + + @Environment(EnvType.CLIENT) + public void requestSync(U identifyingData) { + this.requestQueue.add(identifyingData); + } + + @Environment(EnvType.CLIENT) + public void sendMassRequests() { + if (this.requestQueue.isEmpty()) { + return; + } + + var buf = PacketByteBufs.create(); + this.queueCodec.encode(buf, this.requestQueue); + this.requestQueue.clear(); + + ClientPlayNetworking.send(this.channelId, buf); + } + + public Identifier getChannelId() { + return channelId; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (!(obj instanceof SyncChannel that)) return false; + return Stream.of( + Objects.equals(this.channelId, that.channelId), + Objects.equals(this.codec, that.codec), + Objects.equals(this.identifyingDataTransformer, that.identifyingDataTransformer), + Objects.equals(this.clientLocator, that.clientLocator), + Objects.equals(this.serverLocator, that.serverLocator), + Objects.equals(this.playerProvider, that.playerProvider) + ).reduce(Boolean::logicalAnd).orElse(false); + } + + @Override + public int hashCode() { + return Objects.hash(channelId, codec, identifyingDataTransformer, clientLocator, serverLocator, playerProvider); + } + + @Override + public String toString() { + return "SyncChannel[" + this.channelId + "]"; + } + + @FunctionalInterface + public interface BufferFiller { + void fill(PacketByteBuf buf); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/codec/NetworkCodec.java similarity index 72% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/codec/NetworkCodec.java index cff4d7fbc1..7f70b77ec9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/codec/NetworkCodec.java @@ -14,21 +14,23 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.sync.codec; +package org.quiltmc.qsl.component.api.sync.codec; import com.mojang.datafixers.util.Pair; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; -import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.Unit; +import net.minecraft.util.collection.IndexedIterable; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; -import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.impl.ComponentsImpl; import java.util.List; import java.util.Map; +import java.util.Queue; import java.util.UUID; import java.util.function.BiConsumer; import java.util.function.Function; @@ -81,8 +83,7 @@ public record NetworkCodec(BiConsumer encoder, Function ITEM_STACK = new NetworkCodec<>( PacketByteBuf::writeItemStack, PacketByteBuf::readItemStack ); - public static final NetworkCodec> INVENTORY = - list(ITEM_STACK, size -> DefaultedList.ofSize(size, ItemStack.EMPTY)); + public static final NetworkCodec EMPTY = new NetworkCodec<>((buf, unit) -> { }, buf -> Unit.INSTANCE); public static > NetworkCodec list(NetworkCodec entryCodec, IntFunction listFactory) { return new NetworkCodec<>( @@ -91,11 +92,11 @@ public static > NetworkCodec list(NetworkCodec entryC os.forEach(o -> entryCodec.encode(buf, o)); }, buf -> { - int size = VAR_INT.decode(buf).unwrap(); + int size = VAR_INT.decode(buf); L newList = listFactory.apply(size); for (int i = 0; i < size; i++) { - newList.set(i, entryCodec.decode(buf).unwrap()); + newList.set(i, entryCodec.decode(buf)); } return newList; @@ -103,17 +104,40 @@ public static > NetworkCodec list(NetworkCodec entryC ); } - public static > NetworkCodec map(NetworkCodec> entryCodec, IntFunction mapFactory) { + public static > NetworkCodec queue(NetworkCodec elementCodec, IntFunction queueFactory) { return new NetworkCodec<>( - (buf, m) -> { - VAR_INT.encode(buf, m.size()); - m.forEach((key, value) -> entryCodec.encode(buf, Pair.of(key, value))); + (buf, os) -> { + VAR_INT.encode(buf, os.size()); + os.forEach(o -> elementCodec.encode(buf, o)); + }, + buf -> { + int size = VAR_INT.decode(buf); + var queue = queueFactory.apply(size); + + for (int i = 0; i < size; i++) { + queue.add(elementCodec.decode(buf)); + } + + return queue; + } + ); + } + + public static > NetworkCodec map(NetworkCodec keyCodec, NetworkCodec valueCodec, IntFunction mapFactory) { + return new NetworkCodec<>( + (buf, map) -> { + VAR_INT.encode(buf, map.size()); // append size + map.forEach((o, v) -> { + keyCodec.encode(buf, o); // append key + valueCodec.encode(buf, v); // append value + }); }, buf -> { - int size = VAR_INT.decode(buf).unwrap(); + int size = VAR_INT.decode(buf); // consume size var map = mapFactory.apply(size); + for (int i = 0; i < size; i++) { - entryCodec.decode(buf).ifJust(ovPair -> map.put(ovPair.getFirst(), ovPair.getSecond())); + map.put(keyCodec.decode(buf), valueCodec.decode(buf)); // consume key-value pair } return map; @@ -131,7 +155,11 @@ public static NetworkCodec> pair(NetworkCodec keyCodec, Net ); } - public static NetworkCodec empty(Supplier instanceProvider) { + public static NetworkCodec idIndexed(IndexedIterable idList) { + return NetworkCodec.VAR_INT.map(idList::getRawId, idList::get); + } + + public static NetworkCodec defaultReturn(Supplier instanceProvider) { return new NetworkCodec<>( (buf, t) -> { }, @@ -143,12 +171,12 @@ public void encode(PacketByteBuf buf, T t) { this.encoder.accept(buf, t); } - public Maybe decode(PacketByteBuf buf) { + public T decode(PacketByteBuf buf) { try { - return Maybe.just(this.decoder.apply(buf)); + return this.decoder.apply(buf); } catch (IndexOutOfBoundsException e) { // An IOOB exception is thrown if we try to read invalid memory - ComponentsImpl.LOGGER.warn(e.getMessage()); - return Maybe.nothing(); + CrashReport report = new CrashReport("Attempted to read invalid memory!", e); + throw new CrashException(report); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 63d05708f3..9c177bece8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -20,8 +20,12 @@ import org.jetbrains.annotations.ApiStatus; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; +import org.quiltmc.qsl.component.impl.event.CommonEventListener; +import org.quiltmc.qsl.component.impl.event.ComponentEventPhases; import org.quiltmc.qsl.component.impl.sync.ServerSyncHandler; import org.quiltmc.qsl.lifecycle.api.event.ServerLifecycleEvents; +import org.quiltmc.qsl.lifecycle.api.event.ServerTickEvents; +import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; import org.quiltmc.qsl.networking.api.ServerLoginConnectionEvents; @ApiStatus.Internal @@ -35,11 +39,25 @@ public static Identifier id(String id) { @Override public void onInitialize(ModContainer mod) { ServerSyncHandler.getInstance().registerPackets(); - ServerLoginConnectionEvents.QUERY_START.register(id("component_sync"), ServerSyncHandler.getInstance()); + + ServerLoginConnectionEvents.QUERY_START.register( + ComponentEventPhases.SYNC_COMPONENT_REGISTRY, + CommonEventListener::onQueryStart + ); ServerLifecycleEvents.STARTING.register( - id("freeze_component_registries"), - server -> ComponentsImpl.REGISTRY.freeze() + ComponentEventPhases.FREEZE_COMPONENT_REGISTRIES, + CommonEventListener::onServerStart + ); + + ServerTickEvents.END.register( + ComponentEventPhases.TICK_LEVEL_CONTAINER, + CommonEventListener::onServerTick + ); + + ServerWorldTickEvents.END.register( + ComponentEventPhases.TICK_WORLD_CONTAINER, + CommonEventListener::onServerWorldTick ); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java index 3207695523..653edb6cf6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java @@ -16,22 +16,41 @@ package org.quiltmc.qsl.component.impl.client; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; -import org.quiltmc.qsl.component.impl.CommonInitializer; -import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.impl.event.ClientEventListener; +import org.quiltmc.qsl.component.impl.event.ComponentEventPhases; import org.quiltmc.qsl.lifecycle.api.client.event.ClientLifecycleEvents; +import org.quiltmc.qsl.lifecycle.api.client.event.ClientTickEvents; +import org.quiltmc.qsl.networking.api.client.ClientPlayConnectionEvents; +@Environment(EnvType.CLIENT) public class ClientInitializer implements ClientModInitializer { @Override public void onInitializeClient(ModContainer mod) { ClientSyncHandler.getInstance().registerPackets(); ClientLifecycleEvents.READY.register( - CommonInitializer.id("freeze_component_registies"), - client -> ComponentsImpl.REGISTRY.freeze() + ComponentEventPhases.FREEZE_COMPONENT_REGISTRIES, + ClientEventListener::onClientReady + ); + + ClientPlayConnectionEvents.JOIN.register( + ComponentEventPhases.UNFREEZE_COMPONENT_NETWORK, + ClientEventListener::onServerJoin + ); + + ClientPlayConnectionEvents.DISCONNECT.register( + ComponentEventPhases.FREEZE_COMPONENT_NETWORK, + ClientEventListener::onServerDisconnect + ); + + ClientTickEvents.END.register( + ComponentEventPhases.CLIENT_REQUEST_POLL, + ClientEventListener::onClientTick ); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java index 0c880e9f9a..bbedddabe8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java @@ -17,6 +17,8 @@ package org.quiltmc.qsl.component.impl.client.sync; import com.mojang.datafixers.util.Either; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; import net.minecraft.util.collection.IdList; @@ -27,6 +29,7 @@ import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; +@Environment(EnvType.CLIENT) public final class ClientRegistryPacket { public static CompletableFuture handleRegistryPacket(PacketByteBuf buf, Registry registry, Consumer> action) { return CompletableFuture.supplyAsync(() -> { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java index 7f2d2830aa..b2a4a4760a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java @@ -1,21 +1,7 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package org.quiltmc.qsl.component.impl.client.sync; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; @@ -23,21 +9,32 @@ import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +@SuppressWarnings("ConstantConditions") // all of these are called after the client joins a world, so no NPEs will be thrown +@Environment(EnvType.CLIENT) public final class ClientResolution { - public static BlockEntity getBlockEntity(BlockPos pos) { - return MinecraftClient.getInstance().world.getBlockEntity(pos); + public static Entity entity(int id) { + return MinecraftClient.getInstance().world.getEntityById(id); } - public static Entity getEntity(int id) { - return MinecraftClient.getInstance().world.getEntityById(id); + public static BlockEntity blockEntity(BlockPos pos) { + return MinecraftClient.getInstance().world.getBlockEntity(pos); } - public static Chunk getChunk(ChunkPos pos) { + public static Chunk chunk(ChunkPos pos) { return MinecraftClient.getInstance().world.getChunk(pos.x, pos.z); } - public static World getWorld() { + public static World world() { return MinecraftClient.getInstance().world; } + + public static ComponentProvider level() { + return MinecraftClient.getInstance(); + } + + public static Chunk chunk(int chunkX, int chunkZ) { + return MinecraftClient.getInstance().world.getChunk(chunkX, chunkZ); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java index b4b05e187f..a0a7b5dfa4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -16,20 +16,29 @@ package org.quiltmc.qsl.component.impl.client.sync; +import com.mojang.datafixers.util.Pair; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.PacketByteBuf; import net.minecraft.util.collection.IdList; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; import org.quiltmc.qsl.networking.api.client.ClientLoginNetworking; import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking; -public class ClientSyncHandler { - private static ClientSyncHandler INSTANCE = null; +import java.util.ArrayDeque; +import java.util.Queue; +@Environment(EnvType.CLIENT) +public final class ClientSyncHandler { + private static ClientSyncHandler INSTANCE = null; + private final Queue, PacketByteBuf>> queue = new ArrayDeque<>(); private IdList> componentList = null; + private boolean frozen = true; private ClientSyncHandler() { } @@ -41,10 +50,15 @@ public static ClientSyncHandler getInstance() { return INSTANCE; } - public

void registerChannel(SyncChannel

channel) { - ClientPlayNetworking.registerGlobalReceiver(channel.channelId(), (client, handler, buf, responseSender) -> { - ComponentProvider provider = channel.to(buf); - SyncPacket.handle(client, provider, buf); + public void registerChannel(SyncChannel channel) { + ComponentsImpl.LOGGER.info("Registering client-side component sync channel with id " + channel.getChannelId()); + ClientPlayNetworking.registerGlobalReceiver(channel.getChannelId(), (client, handler, buf, responseSender) -> { + if (this.frozen) { + buf.retain(); // we keep the buffer in memory + this.queue.add(Pair.of(channel, buf)); + } else { + channel.handleServerPushedSync(client, buf); + } }); } @@ -59,4 +73,25 @@ public void registerPackets() { public ComponentType getType(int rawId) { return this.componentList.get(rawId); } + + public void unfreeze() { + this.frozen = false; + } + + public void freeze() { + this.frozen = true; + } + + public void processQueued(MinecraftClient client) { + while (!this.queue.isEmpty()) { + Pair, PacketByteBuf> currentPair = this.queue.poll(); + + var channel = currentPair.getFirst(); + var buf = currentPair.getSecond(); + + channel.handleServerPushedSync(client, buf); + + buf.release(); // release it once we are done + } + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index fa1bef3b20..21cff50604 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -20,15 +20,16 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.*; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.component.NbtComponent; import org.quiltmc.qsl.component.api.component.SyncedComponent; import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; @@ -40,18 +41,18 @@ public abstract class AbstractComponentContainer implements ComponentContainer { protected final List> nbtComponents; protected final Maybe>> ticking; protected final Maybe>> pendingSync; - protected final Maybe> syncContext; + protected final Maybe> syncContext; public AbstractComponentContainer(@Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncChannel syncChannel) { + @Nullable SyncChannel syncChannel) { this.ticking = ticking ? Maybe.just(new ArrayList<>()) : Maybe.nothing(); this.nbtComponents = new ArrayList<>(); this.syncContext = Maybe.wrap(syncChannel); this.pendingSync = this.syncContext.map(it -> new ArrayDeque<>()); this.operations = new ContainerOperations( - saveOperation, - type -> () -> this.pendingSync.ifJust(pending -> pending.add(type)) + saveOperation, + type -> () -> this.pendingSync.ifJust(pending -> pending.add(type)) ); } @@ -78,22 +79,15 @@ public void readNbt(NbtCompound providerRootNbt) { .filter(Objects::nonNull) .forEach(type -> this.expose(type) .map(component -> ((NbtComponent) component)) - .ifJust(component -> { - NbtComponent.readFrom(component, type.id(), rootQslNbt); - - if (component instanceof SyncedComponent synced) { - synced.sync(); - } - }) + .ifJust(component -> NbtComponent.readFrom(component, type.id(), rootQslNbt)) ); } @Override public void tick(ComponentProvider provider) { - this.ticking.ifJust(componentTypes -> componentTypes.forEach(type -> - this.expose(type) - .map(it -> ((TickingComponent) it)) - .ifJust(tickingComponent -> tickingComponent.tick(provider))) + this.ticking.ifJust(componentTypes -> componentTypes.forEach(type -> this.expose(type) + .map(it -> ((TickingComponent) it)) + .ifJust(tickingComponent -> tickingComponent.tick(provider))) ).ifNothing(() -> { throw ErrorUtil.illegalState("Attempted to tick a non-ticking container").get(); }); @@ -103,10 +97,9 @@ public void tick(ComponentProvider provider) { @Override public void sync(ComponentProvider provider) { - this.syncContext.ifJust(channel -> SyncPacket.createFromQueue( + this.syncContext.ifJust(channel -> channel.syncFromQueue( this.pendingSync.unwrap(), - channel, - type -> (SyncedComponent) this.expose(type).unwrap(), // We *need* to contain the provided type therefore it's definitely in here. + type -> (SyncedComponent) this.expose(type).unwrap(), provider )).ifNothing(() -> { throw ErrorUtil.illegalState("Attempted to sync a non-syncable container!").get(); @@ -138,5 +131,7 @@ protected COMP initializeComponent(ComponentEntry return component; } - public record ContainerOperations(@Nullable Runnable saveOperation, @Nullable Function, Runnable> syncOperationFactory) { } + public record ContainerOperations(@Nullable Runnable saveOperation, + @Nullable Function, Runnable> syncOperationFactory) { + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java index b6cfc7e05c..f006ce3797 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java @@ -23,7 +23,8 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -// TODO: Make this work!!! +import java.util.function.BiConsumer; + public class CompositeComponentContainer implements ComponentContainer { private final ComponentContainer main; private final ComponentContainer fallback; @@ -61,4 +62,10 @@ public void sync(ComponentProvider provider) { this.main.sync(provider); this.fallback.sync(provider); } + + @Override + public void forEach(BiConsumer, ? super Component> action) { + this.main.forEach(action); + this.fallback.forEach(action); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java index 5d303138f4..f894b1c21d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java @@ -19,9 +19,11 @@ import net.minecraft.nbt.NbtCompound; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.api.ComponentType; + +import java.util.function.BiConsumer; public final class EmptyComponentContainer implements ComponentContainer { public static final EmptyComponentContainer INSTANCE = new EmptyComponentContainer(); @@ -37,22 +39,17 @@ public Maybe expose(ComponentType type) { } @Override - public void writeNbt(NbtCompound providerRootNbt) { - - } + public void writeNbt(NbtCompound providerRootNbt) { } @Override - public void readNbt(NbtCompound providerRootNbt) { - - } + public void readNbt(NbtCompound providerRootNbt) { } @Override - public void tick(ComponentProvider provider) { - - } + public void tick(ComponentProvider provider) { } @Override - public void sync(ComponentProvider provider) { + public void sync(ComponentProvider provider) { } - } + @Override + public void forEach(BiConsumer, ? super Component> action) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 916020bfb7..84c26db730 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -20,28 +20,30 @@ import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import java.util.IdentityHashMap; import java.util.List; +import java.util.Map; import java.util.Queue; +import java.util.function.BiConsumer; public class LazyComponentContainer extends AbstractComponentContainer { public static final ComponentContainer.Factory FACTORY = (provider, injections, saveOperation, ticking, syncChannel) -> new LazyComponentContainer(provider, saveOperation, ticking, syncChannel); - private final IdentityHashMap, Lazy> components; + private final Map, Lazy>> components; protected LazyComponentContainer( ComponentProvider provider, @Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncChannel syncChannel + @Nullable SyncChannel syncChannel ) { super(saveOperation, ticking, syncChannel); this.components = this.createLazyMap(provider); @@ -64,26 +66,33 @@ public static void move(LazyComponentContainer from, LazyComponentContainer into @Override public Maybe expose(ComponentType id) { - return Maybe.wrap(this.components.get(id)).map(Lazy::get); + return this.components.containsKey(id) ? this.components.get(id).get() : Maybe.nothing(); + } + + @Override + public void forEach(BiConsumer, ? super Component> action) { + // unwrap will work here since all Lazies are Just instances for this. + this.components.forEach((type, componentLazy) -> componentLazy.ifFilled(component -> action.accept(type, component.unwrap()))); } @Override protected void addComponent(ComponentType type, Component component) { } - private IdentityHashMap, Lazy> createLazyMap(ComponentProvider provider) { - var map = new IdentityHashMap, Lazy>(); + private Map, Lazy>> createLazyMap(ComponentProvider provider) { + // TODO: Consider adding a way to directly add components to the builder. + var map = new IdentityHashMap, Lazy>>(); ComponentsImpl.getInjections(provider).forEach(injection -> map.put(injection.type(), this.createLazy(injection))); return map; } - private Lazy createLazy(ComponentEntry componentEntry) { + private Lazy> createLazy(ComponentEntry componentEntry) { ComponentType type = componentEntry.type(); if (type.isStatic() || type.isInstant()) { var component = this.initializeComponent(componentEntry); - return Lazy.filled(component); + return Lazy.filled((Maybe.Just) Maybe.just(component)); // this cast will obviously never fail } - return Lazy.of(() -> this.initializeComponent(componentEntry)); + return Lazy.of(() -> ((Maybe.Just) Maybe.just(this.initializeComponent(componentEntry)))); // same here } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index 7610d11db6..c8b63d4f8a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -24,11 +24,12 @@ import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import java.util.function.BiConsumer; // Suggestion from Technici4n from fabric. May help improve performance and memory footprint once done. public class OnAccessComponentContainer extends AbstractComponentContainer { @@ -40,7 +41,7 @@ public class OnAccessComponentContainer extends AbstractComponentContainer { protected OnAccessComponentContainer(ComponentProvider provider, @Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncChannel syncChannel) { + @Nullable SyncChannel syncChannel) { super(saveOperation, ticking, syncChannel); this.components = this.createComponents(provider); } @@ -66,6 +67,11 @@ public Maybe expose(ComponentType type) { .or(() -> this.supports(type) ? Maybe.just(this.initializeComponent(this.components.get(type).left().orElseThrow())) : Maybe.nothing()); } + @Override + public void forEach(BiConsumer, ? super Component> action) { + this.components.forEach((type, either) -> either.ifRight(component -> action.accept(type, component))); + } + @Override protected void addComponent(ComponentType type, Component component) { this.components.put(type, Either.right(component)); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index a3d8ccc6e3..b5253f3387 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -22,12 +22,12 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.sync.packet.SyncPacket; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import java.util.IdentityHashMap; import java.util.Map; +import java.util.function.BiConsumer; import java.util.stream.Stream; public class SimpleComponentContainer extends AbstractComponentContainer { @@ -39,7 +39,7 @@ public class SimpleComponentContainer extends AbstractComponentContainer { protected SimpleComponentContainer(@Nullable Runnable saveOperation, boolean ticking, - @Nullable SyncChannel syncContext, + @Nullable SyncChannel syncContext, Stream> types) { super(saveOperation, ticking, syncContext); this.components = new IdentityHashMap<>(); @@ -52,6 +52,11 @@ public Maybe expose(ComponentType type) { return Maybe.wrap(this.components.get(type)); } + @Override + public void forEach(BiConsumer, ? super Component> action) { + this.components.forEach(action); + } + @Override protected void addComponent(ComponentType type, Component component) { Component result = this.components.put(type, component); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java index 31eda13dfa..1616298f06 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java @@ -28,18 +28,21 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; +import java.util.ArrayDeque; +import java.util.List; +import java.util.function.BiConsumer; import java.util.function.Supplier; public class SingleComponentContainer implements ComponentContainer { private final ComponentType type; - private final Maybe> syncChannel; + private final Maybe> syncChannel; private final boolean ticking; private Lazy entry; private boolean shouldSync = false; - protected SingleComponentContainer(ComponentType type, boolean ticking, @Nullable SyncChannel syncChannel) { + protected SingleComponentContainer(ComponentType type, boolean ticking, @Nullable SyncChannel syncChannel) { this.type = type; this.ticking = ticking; this.syncChannel = Maybe.wrap(syncChannel); @@ -74,14 +77,8 @@ public void readNbt(NbtCompound providerRootNbt) { String idString = this.type.id().toString(); if (providerRootNbt.getKeys().contains(idString)) { this.expose(this.type) - .map(it -> ((NbtComponent) it)) - .ifJust(nbtComponent -> { - NbtComponent.readFrom(nbtComponent, this.type.id(), providerRootNbt); - - if (this.syncChannel.isJust()) { - ((SyncedComponent) nbtComponent).sync(); - } - }); + .map(it -> ((NbtComponent) it)) + .ifJust(nbtComponent -> NbtComponent.readFrom(nbtComponent, this.type.id(), providerRootNbt)); } } @@ -89,19 +86,26 @@ public void readNbt(NbtCompound providerRootNbt) { public void tick(ComponentProvider provider) { if (this.ticking) { this.expose(this.type) - .map(it -> ((TickingComponent) it)) - .ifJust(tickingComponent -> tickingComponent.tick(provider)); + .map(it -> ((TickingComponent) it)) + .ifJust(tickingComponent -> tickingComponent.tick(provider)); } } @Override public void sync(ComponentProvider provider) { if (this.shouldSync) { - this.syncChannel.ifJust(channel -> channel.send(provider, buf -> { - buf.writeInt(1); // size will always be one in this case. - ComponentType.NETWORK_CODEC.encode(buf, this.type); // append the type rawId - ((SyncedComponent) this.entry.get()).writeToBuf(buf); // append component data - })); + this.syncChannel.ifJust(channel -> channel.syncFromQueue( + new ArrayDeque<>(List.of(this.type)), + type -> (SyncedComponent) this.entry.get(), + provider + )); + } + } + + @Override + public void forEach(BiConsumer, ? super Component> action) { + if (this.entry.isFilled()) { + action.accept(this.type, this.entry.get()); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java new file mode 100644 index 0000000000..d028f293f5 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java @@ -0,0 +1,38 @@ +package org.quiltmc.qsl.component.impl.event; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; +import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.quiltmc.qsl.networking.api.PacketSender; + +@Environment(EnvType.CLIENT) +public final class ClientEventListener { + public static void onClientReady(MinecraftClient ignored) { + Components.REGISTRY.freeze(); + } + + public static void onServerJoin(ClientPlayNetworkHandler ignoredHandler, PacketSender ignoredSender, MinecraftClient client) { + ClientSyncHandler.getInstance().unfreeze(); + ClientSyncHandler.getInstance().processQueued(client); + + // We also request sync for these two while we are at it. + SyncChannel.LEVEL.requestSync(client); + SyncChannel.WORLD.requestSync(client.world); + } + + public static void onServerDisconnect(ClientPlayNetworkHandler ignoredHandler, MinecraftClient ignoredClient) { + ClientSyncHandler.getInstance().freeze(); + } + + public static void onClientTick(MinecraftClient ignoredClient) { + SyncChannel.LEVEL.sendMassRequests(); + SyncChannel.WORLD.sendMassRequests(); + SyncChannel.CHUNK.sendMassRequests(); + SyncChannel.ENTITY.sendMassRequests(); + SyncChannel.BLOCK_ENTITY.sendMassRequests(); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java new file mode 100644 index 0000000000..5e4be3b5d8 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java @@ -0,0 +1,29 @@ +package org.quiltmc.qsl.component.impl.event; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerLoginNetworkHandler; +import net.minecraft.server.world.ServerWorld; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; +import org.quiltmc.qsl.component.impl.sync.packet.RegistryPacket; +import org.quiltmc.qsl.networking.api.PacketSender; +import org.quiltmc.qsl.networking.api.ServerLoginNetworking; + +public final class CommonEventListener { + public static void onQueryStart(ServerLoginNetworkHandler ignoredHandler, MinecraftServer ignoredServer, PacketSender sender, ServerLoginNetworking.LoginSynchronizer ignoredSyncer) { + sender.sendPacket(PacketIds.TYPES, RegistryPacket.createRegistryPacket(Components.REGISTRY)); + } + + public static void onServerStart(MinecraftServer ignored) { + ComponentsImpl.REGISTRY.freeze(); + } + + public static void onServerTick(MinecraftServer server) { + server.getComponentContainer().tick(server); + } + + public static void onServerWorldTick(MinecraftServer ignored, ServerWorld world) { + world.getComponentContainer().tick(world); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java new file mode 100644 index 0000000000..326dca8fa8 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java @@ -0,0 +1,14 @@ +package org.quiltmc.qsl.component.impl.event; + +import net.minecraft.util.Identifier; +import org.quiltmc.qsl.component.impl.CommonInitializer; + +public final class ComponentEventPhases { + public static final Identifier TICK_LEVEL_CONTAINER = CommonInitializer.id("level_container_tick"); + public static final Identifier TICK_WORLD_CONTAINER = CommonInitializer.id("world_container_tick"); + public static final Identifier CLIENT_REQUEST_POLL = CommonInitializer.id("poll_sync_requests"); + public static final Identifier FREEZE_COMPONENT_REGISTRIES = CommonInitializer.id("freeze_component_registries"); + public static final Identifier UNFREEZE_COMPONENT_NETWORK = CommonInitializer.id("unfreeze_component_network"); + public static final Identifier FREEZE_COMPONENT_NETWORK = CommonInitializer.id("freeze_component_network"); + public static final Identifier SYNC_COMPONENT_REGISTRY = CommonInitializer.id("component_registry_sync"); +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java deleted file mode 100644 index 3643adc45a..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerTickEventListener.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.impl.event; - -import net.minecraft.server.MinecraftServer; -import org.quiltmc.qsl.base.api.event.ListenerPhase; -import org.quiltmc.qsl.lifecycle.api.event.ServerTickEvents; - -@ListenerPhase( - callbackTarget = ServerTickEvents.End.class, - namespace = "quilt_component", path = "tick_level_container" -) -public class ServerTickEventListener implements ServerTickEvents.End { - @Override - public void endServerTick(MinecraftServer server) { - server.getComponentContainer().tick(server); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java deleted file mode 100644 index fb652a1e6c..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ServerWorldTickEventListener.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.impl.event; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerWorld; -import org.quiltmc.qsl.base.api.event.ListenerPhase; -import org.quiltmc.qsl.component.impl.CommonInitializer; -import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; - -@SuppressWarnings("unused") -@ListenerPhase( - callbackTarget = ServerWorldTickEvents.End.class, - namespace = CommonInitializer.MOD_ID, path = "tick_world_container" -) -public class ServerWorldTickEventListener implements ServerWorldTickEvents.End { - @Override - public void endWorldTick(MinecraftServer server, ServerWorld world) { - world.getComponentContainer().tick(world); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java index 0c6bea86c6..e2c707212e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/ServerSyncHandler.java @@ -16,16 +16,14 @@ package org.quiltmc.qsl.component.impl.sync; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginNetworkHandler; -import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; import org.quiltmc.qsl.component.impl.sync.packet.RegistryPacket; -import org.quiltmc.qsl.networking.api.PacketSender; -import org.quiltmc.qsl.networking.api.ServerLoginConnectionEvents; import org.quiltmc.qsl.networking.api.ServerLoginNetworking; +import org.quiltmc.qsl.networking.api.ServerPlayNetworking; -public final class ServerSyncHandler implements ServerLoginConnectionEvents.QueryStart { +public final class ServerSyncHandler { private static ServerSyncHandler INSTANCE = null; private ServerSyncHandler() { } @@ -38,15 +36,18 @@ public static ServerSyncHandler getInstance() { return INSTANCE; } + public void registerChannel(SyncChannel syncChannel) { + ComponentsImpl.LOGGER.info("Registering server-side component sync channel with id {}", syncChannel.getChannelId()); + ServerPlayNetworking.registerGlobalReceiver(syncChannel.getChannelId(), (server, sender, handler, buf, responseSender) -> + syncChannel.handleClientSyncRequest(server, sender, buf) + ); + } + public void registerPackets() { ServerLoginNetworking.registerGlobalReceiver(PacketIds.TYPES, (server, handler, understood, buf, sync, sender) -> - RegistryPacket.handleRegistryResponse(buf, handler, "Component with id %s was not found in the client!") + RegistryPacket.handleRegistryResponse(buf, handler, "Component with id %s was not found in the client!") ); - } - @Override - public void onLoginStart(ServerLoginNetworkHandler handler, MinecraftServer server, PacketSender sender, ServerLoginNetworking.LoginSynchronizer synchronizer) { - // TODO: Maybe use regitry sync for this?! - sender.sendPacket(PacketIds.TYPES, RegistryPacket.createRegistryPacket(Components.REGISTRY)); + SyncChannel.createPacketChannels(this::registerChannel); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java deleted file mode 100644 index e5e1f25c79..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/SyncChannel.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.impl.sync; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.Entity; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.Identifier; -import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.WorldChunk; -import org.quiltmc.qsl.base.api.util.TwoWayFunction; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.client.sync.ClientResolution; -import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; -import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; -import org.quiltmc.qsl.networking.api.PacketByteBufs; -import org.quiltmc.qsl.networking.api.PlayerLookup; -import org.quiltmc.qsl.networking.api.ServerPlayNetworking; - -import java.util.Collection; -import java.util.function.Consumer; -import java.util.function.Function; - -// ClientResolution.* all reference client-only classes, -// so we need to just make sure we use lambdas so no attempt at class loading non-existent classes -@SuppressWarnings("Convert2MethodRef") -public record SyncChannel

(Identifier channelId, - NetworkCodec

codec, - Function> playerProvider) - implements TwoWayFunction { - // BlockEntity - private static final NetworkCodec BLOCK_ENTITY_CODEC = - NetworkCodec.BLOCK_POS.map(BlockEntity::getPos, blockPos -> ClientResolution.getBlockEntity(blockPos)); - public static final SyncChannel BLOCK_ENTITY = - new SyncChannel<>(PacketIds.BLOCK_ENTITY_SYNC, BLOCK_ENTITY_CODEC, PlayerLookup::tracking); - - // Entity - private static final NetworkCodec ENTITY_CODEC = - NetworkCodec.INT.map(Entity::getId, rawId -> ClientResolution.getEntity(rawId)); - public static final SyncChannel ENTITY = - new SyncChannel<>(PacketIds.ENTITY_SYNC, ENTITY_CODEC, PlayerLookup::tracking); - - // Chunk - private static final NetworkCodec CHUNK_CODEC = - NetworkCodec.CHUNK_POS.map(Chunk::getPos, chunkPos -> ClientResolution.getChunk(chunkPos)); - public static final SyncChannel CHUNK = // **Careful**: This only works with WorldChunks not other chunk types! - new SyncChannel<>(PacketIds.CHUNK_SYNC, CHUNK_CODEC, - chunk -> PlayerLookup.tracking((ServerWorld) ((WorldChunk) chunk).getWorld(), chunk.getPos())); - - // World - private static final NetworkCodec WORLD_CODEC = - NetworkCodec.empty(() -> ClientResolution.getWorld()); - public static final SyncChannel WORLD = - new SyncChannel<>(PacketIds.WORLD_SYNC, WORLD_CODEC, - world -> PlayerLookup.world(((ServerWorld) world))); - - // Level - private static final NetworkCodec LEVEL_CODEC = - NetworkCodec.empty(() -> MinecraftClient.getInstance()); - public static final SyncChannel LEVEL = - new SyncChannel<>(PacketIds.LEVEL_SYNC, LEVEL_CODEC, - provider -> PlayerLookup.all(((MinecraftServer) provider))); - - public static void createPacketChannels(Consumer> register) { - register.accept(BLOCK_ENTITY); - register.accept(ENTITY); - register.accept(CHUNK); - register.accept(WORLD); - register.accept(LEVEL); - } - - @Override - public P to(PacketByteBuf buf) { - return this.codec.decode(buf).unwrap(); // we throw in case we cannot find the target component provider. - } - - @Override - public PacketByteBuf from(P p) { - var buf = PacketByteBufs.create(); - this.codec.encode(buf, p); - return buf; - } - - @SuppressWarnings("unchecked") - public void send(ComponentProvider provider, BufferFiller bufferFiller) { - // The casting to P should never fail, since the provider and - // the channel type *must* match for the implementation to be correct anyway - P providerAsP = (P) provider; - var buf = this.from(providerAsP); // append provider data - bufferFiller.fill(buf); // append all the container data - ServerPlayNetworking.send(this.playerProvider.apply(providerAsP), this.channelId, buf); - } - - @FunctionalInterface - public interface BufferFiller { - void fill(PacketByteBuf buf); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java index 6ff78fb9ce..dc73142ed8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java @@ -24,6 +24,7 @@ import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.networking.api.PacketByteBufs; +// TODO: This should eventually be replaced with registry sync! public final class RegistryPacket { public static PacketByteBuf createRegistryPacket(Registry registry) { var buf = PacketByteBufs.create(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java deleted file mode 100644 index db5fe0d1da..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/SyncPacket.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.impl.sync.packet; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.network.PacketByteBuf; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.component.SyncedComponent; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; - -import java.util.Queue; -import java.util.function.Function; - -/** - *

- *         PROVIDER_DATA  SIZE [TYPE DATA]
- *             var		  32bit	   var
- * 
- */ -public class SyncPacket { - public static

void createFromQueue( - Queue> pendingSync, - SyncChannel

channel, - Function, SyncedComponent> mapper, - ComponentProvider provider - ) { - if (pendingSync.isEmpty()) { - return; - } - - channel.send(provider, buf -> { - buf.writeInt(pendingSync.size()); // append size - - while (!pendingSync.isEmpty()) { - var currentType = pendingSync.poll(); - ComponentType.NETWORK_CODEC.encode(buf, currentType); // append type rawId - mapper.apply(currentType).writeToBuf(buf); // append component data - } - }); - } - - @Environment(EnvType.CLIENT) - public static void handle(MinecraftClient client, ComponentProvider provider, PacketByteBuf buf) { - buf.retain(); // hold the buffer in memory - - client.execute(() -> { - int size = buf.readInt(); // consume size - - for (int i = 0; i < size; i++) { - ComponentType.NETWORK_CODEC.decode(buf) // consume type rawId - .filterMap(provider::expose) - .map(it -> ((SyncedComponent) it)) - .ifJust(syncedComponent -> syncedComponent.readFromBuf(buf)); // consume data - } - - buf.release(); // make sure the buffer is freed now that we don't need it - }); - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java index c99773e18d..a267ad9428 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java @@ -25,7 +25,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import java.util.HashMap; import java.util.Map; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java index c85c55fc08..d5cf251791 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java @@ -23,7 +23,7 @@ import net.minecraft.util.math.BlockPos; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -45,7 +45,7 @@ public ComponentContainer getComponentContainer() { @Inject(method = "readNbt", at = @At("TAIL")) private void onReadNbt(NbtCompound nbt, CallbackInfo ci) { - this.qsl$container.readNbt(nbt); + this.getComponentContainer().readNbt(nbt); } @Inject(method = "", at = @At("RETURN")) @@ -59,6 +59,6 @@ private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, Block @Inject(method = "toNbt", at = @At("TAIL")) private void onWriteNbt(CallbackInfoReturnable cir) { - this.qsl$container.writeNbt(cir.getReturnValue()); + this.getComponentContainer().writeNbt(cir.getReturnValue()); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java index c0814eaa61..36975899df 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java @@ -16,17 +16,14 @@ package org.quiltmc.qsl.component.mixin.block.entity; -import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityTicker; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(WorldChunk.DirectBlockEntityTickInvoker.class) public class DirectBlockEntityTickInvokerMixin { @@ -34,9 +31,14 @@ public class DirectBlockEntityTickInvokerMixin { @Final private T blockEntity; - @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/entity/BlockEntity;)V")) - private void tickContainer(BlockEntityTicker instance, World world, BlockPos blockPos, BlockState blockState, T t) { - instance.tick(world, blockPos, blockState, t); - this.blockEntity.getComponentContainer().tick(this.blockEntity); + @SuppressWarnings("ConstantConditions") + @Inject( + method = "tick", + at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/entity/BlockEntity;)V") + ) + private void tickContainer(CallbackInfo ci) { + if (!this.blockEntity.getWorld().isClient) { // we know the block entity will have a world if it is contained in a ticker + this.blockEntity.getComponentContainer().tick(this.blockEntity); + } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java index 3db77a2795..787e1c4ee4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java @@ -27,7 +27,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java deleted file mode 100644 index 8ea28e505a..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ThreadedChunkStorageMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.mixin.chunk; - -import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ThreadedAnvilChunkStorage; -import net.minecraft.world.chunk.WorldChunk; -import org.apache.commons.lang3.mutable.MutableObject; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ThreadedAnvilChunkStorage.class) -public abstract class ThreadedChunkStorageMixin { - @Inject( - method = "sendChunkDataPackets", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/network/ServerPlayerEntity;sendInitialChunkPackets(Lnet/minecraft/util/math/ChunkPos;Lnet/minecraft/network/Packet;)V", - shift = At.Shift.AFTER - ) - ) - private void syncChunkContainer(ServerPlayerEntity player, MutableObject mutableObject, WorldChunk chunk, CallbackInfo ci) { - chunk.getComponentContainer().sync(chunk); // Handles initial chunk sync - chunk.getBlockEntities().forEach((blockPos, blockEntity) -> blockEntity.getComponentContainer().sync(blockEntity)); // Handles initial block entity sync - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java index 044832683e..e9fef27682 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java @@ -22,8 +22,7 @@ import net.minecraft.world.World; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -49,16 +48,16 @@ private void onEntityInit(EntityType entityType, World world, CallbackInfo ci @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void onSerialize(NbtCompound nbt, CallbackInfoReturnable cir) { - this.qsl$container.writeNbt(nbt); + this.getComponentContainer().writeNbt(nbt); } @Inject(method = "readNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;readCustomDataFromNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { - this.qsl$container.readNbt(nbt); + this.getComponentContainer().readNbt(nbt); } @Inject(method = "tick", at = @At("TAIL")) private void tickContainer(CallbackInfo ci) { - this.qsl$container.tick(this); + this.getComponentContainer().tick(this); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java index 78524559d8..2adffd496f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java @@ -22,6 +22,7 @@ import org.quiltmc.qsl.component.impl.util.ComponentProviderState; import org.spongepowered.asm.mixin.Mixin; +// FIXME: Fix level and world being weird with one another @Mixin(MinecraftServer.class) public abstract class MinecraftServerMixin implements ComponentProvider { @SuppressWarnings("ConstantConditions") diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java index d1ea3045cc..61d7a725d7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java @@ -20,7 +20,6 @@ import net.minecraft.client.RunArgs; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java new file mode 100644 index 0000000000..4e71e10466 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java @@ -0,0 +1,24 @@ +package org.quiltmc.qsl.component.mixin.sync; + +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; +import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; +import net.minecraft.util.math.ChunkPos; +import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class ClientPlayNetworkHandlerMixin { + @Inject(method = "onChunkData", at = @At("RETURN")) + private void initialChunkSync(ChunkDataS2CPacket packet, CallbackInfo ci) { + SyncChannel.CHUNK.requestSync(new ChunkPos(packet.chunkX(), packet.chunkZ())); + } + + @Inject(method = "onEntitySpawn", at = @At("RETURN")) + private void initialEntitySync(EntitySpawnS2CPacket packet, CallbackInfo ci) { + SyncChannel.ENTITY.requestSync(packet.getId()); + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java new file mode 100644 index 0000000000..359e740b7e --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java @@ -0,0 +1,19 @@ +package org.quiltmc.qsl.component.mixin.sync; + +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.WorldChunk; +import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(WorldChunk.class) +public class WorldChunkMixin { + @Inject(method = "method_31716", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V")) + private void initialBlockEntitySync(BlockPos blockPos, BlockEntityType blockEntityType, NbtCompound nbtCompound, CallbackInfo ci) { + SyncChannel.BLOCK_ENTITY.requestSync(blockPos); + } +} diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index bc33348aa8..ef1fe9460d 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -8,14 +8,15 @@ "chunk.ChunkMixin", "chunk.ChunkSerializerMixin", "chunk.ServerWorldMixin", - "chunk.ThreadedChunkStorageMixin", "chunk.WorldChunkMixin", "entity.EntityMixin", "level.MinecraftServerMixin", + "sync.WorldChunkMixin", "world.WorldMixin" ], "client": [ - "level.client.MinecraftClientMixin" + "level.client.MinecraftClientMixin", + "sync.ClientPlayNetworkHandlerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index c40d0e9098..7192cf7925 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -37,6 +37,7 @@ import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.WorldChunk; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.block.entity.api.QuiltBlockEntityTypeBuilder; @@ -48,6 +49,9 @@ import org.quiltmc.qsl.component.impl.component.DefaultFloatComponent; import org.quiltmc.qsl.component.impl.component.DefaultIntegerComponent; import org.quiltmc.qsl.component.impl.component.DefaultInventoryComponent; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; +import org.quiltmc.qsl.component.test.component.ChunkInventoryComponent; import org.quiltmc.qsl.component.test.component.SaveFloatComponent; import java.util.UUID; @@ -71,9 +75,9 @@ public class ComponentTestMod implements ModInitializer { new Identifier(MODID, "chest_number"), operations -> new DefaultIntegerComponent(operations, 200) ); - public static final ComponentType CHUNK_INVENTORY = Components.register( + public static final ComponentType CHUNK_INVENTORY = Components.register( new Identifier(MODID, "chunk_inventory"), - operations -> new DefaultInventoryComponent(operations, 1) + ChunkInventoryComponent::new ); public static final ComponentType SAVE_FLOAT = Components.registerInstant( new Identifier(MODID, "save_float"), @@ -159,6 +163,7 @@ public void onInitialize(ModContainer mod) { Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); + Components.inject(new ClassInjectionPredicate(WorldChunk.class), new ComponentEntry<>(CHUNK_INVENTORY, ChunkInventoryComponent::new)); // Components.inject(MinecraftServer.class, SERVER_TICK); Components.injectInheritage(ServerPlayerEntity.class, PLAYER_TICK); Components.inject(ServerPlayerEntity.class, UUID_THING); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 3c53f89ad9..86d1cea3b5 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -30,6 +30,8 @@ import net.minecraft.world.explosion.Explosion; import org.quiltmc.qsl.base.api.event.ListenerPhase; import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.component.SyncedComponent; +import org.quiltmc.qsl.component.impl.component.DefaultInventoryComponent; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; import java.util.Objects; @@ -64,7 +66,7 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { newStack.setCount(1); inventory.setStack(0, newStack); inventory.save(); - // inventory.sync(); + inventory.sync(); playerStack.decrement(1); } else { if (ItemStack.canCombine(stack, playerStack)) { @@ -75,7 +77,7 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { // defaultIntegerComponent.save(); // }); inventory.save(); - // inventory.sync(); + inventory.sync(); } } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index 38a424a40c..92ed2d780c 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -30,6 +30,7 @@ import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.apache.commons.lang3.mutable.MutableObject; import org.jetbrains.annotations.Nullable; public class TestBlock extends Block implements BlockEntityProvider { @@ -60,7 +61,7 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt ItemStack handStack = player.getStackInHand(hand); if (!handStack.isEmpty()) { - final ActionResult[] ret = new ActionResult[]{ActionResult.PASS}; + final MutableObject ret = new MutableObject<>(ActionResult.PASS); be.expose(ComponentTestMod.CHUNK_INVENTORY).ifJust(inventoryComponent -> { var stack = inventoryComponent.getStack(0); @@ -70,19 +71,20 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt copied.setCount(1); inventoryComponent.setStack(0, copied); inventoryComponent.save(); - // inventoryComponent.sync(); - ret[0] = ActionResult.SUCCESS; + inventoryComponent.sync(); + ret.setValue(ActionResult.SUCCESS); } else { if (ItemStack.canCombine(stack, handStack)) { stack.increment(1); handStack.decrement(1); inventoryComponent.save(); - ret[0] = ActionResult.SUCCESS; + inventoryComponent.sync(); + ret.setValue(ActionResult.SUCCESS); } } }); - return ret[0]; + return ret.getValue(); } return super.onUse(state, world, pos, player, hand, hit); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 61ebf39ad3..91c2d06050 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -29,9 +29,8 @@ import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.component.InventoryComponent; -import org.quiltmc.qsl.component.impl.container.CompositeComponentContainer; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; -import org.quiltmc.qsl.component.impl.sync.SyncChannel; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import java.util.Arrays; import java.util.HashSet; @@ -45,7 +44,7 @@ public class TestBlockEntity extends BlockEntity { .add(ComponentTestMod.TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) .syncing(SyncChannel.BLOCK_ENTITY) .build(SimpleComponentContainer.FACTORY); - private final ComponentContainer composite = new CompositeComponentContainer(this.container, super.getComponentContainer()); + private final ComponentContainer composite = ComponentContainer.createComposite(container, super.getComponentContainer()); public TestBlockEntity(BlockPos blockPos, BlockState blockState) { super(ComponentTestMod.TEST_BE_TYPE, blockPos, blockState); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java new file mode 100644 index 0000000000..c6d4a46e1c --- /dev/null +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java @@ -0,0 +1,52 @@ +package org.quiltmc.qsl.component.test.component; + +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.collection.DefaultedList; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.component.InventoryComponent; +import org.quiltmc.qsl.component.api.component.SyncedComponent; +import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; + +import java.util.List; + +public class ChunkInventoryComponent implements InventoryComponent, SyncedComponent { + public static final NetworkCodec> NETWORK_CODEC = + NetworkCodec.list(NetworkCodec.ITEM_STACK, value -> DefaultedList.ofSize(value, ItemStack.EMPTY)); + + private final DefaultedList stacks = DefaultedList.ofSize(1, ItemStack.EMPTY); + private final Operations ops; + + public ChunkInventoryComponent(Component.Operations ops) { + this.ops = ops; + } + + @Override + public DefaultedList getStacks() { + return this.stacks; + } + + @Override + public @Nullable Runnable getSaveOperation() { + return this.ops.saveOperation(); + } + + @Override + public void writeToBuf(PacketByteBuf buf) { + NETWORK_CODEC.encode(buf, this.stacks); + } + + @Override + public void readFromBuf(PacketByteBuf buf) { + List receivedStacks = NETWORK_CODEC.decode(buf); + for (int i = 0; i < receivedStacks.size(); i++) { + this.stacks.set(i, receivedStacks.get(i)); + } + } + + @Override + public @Nullable Runnable getSyncOperation() { + return this.ops.syncOperation(); + } +} diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java index 51cc32b190..ecf94d2108 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java @@ -17,13 +17,14 @@ package org.quiltmc.qsl.component.test.component; import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.world.ServerWorld; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.component.SyncedComponent; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.impl.component.DefaultFloatComponent; -import org.quiltmc.qsl.component.impl.sync.codec.NetworkCodec; +import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; public class SaveFloatComponent extends DefaultFloatComponent implements TickingComponent, SyncedComponent { private final Runnable syncOperation; @@ -37,7 +38,9 @@ public SaveFloatComponent(Component.Operations ops) { public void tick(ComponentProvider provider) { this.set(this.get() + 50); this.save(); - this.sync(); + if (((ServerWorld) provider).getTime() % 100 == 0) { + this.sync(); + } } @Override @@ -47,7 +50,7 @@ public void writeToBuf(PacketByteBuf buf) { @Override public void readFromBuf(PacketByteBuf buf) { - this.set(NetworkCodec.FLOAT.decode(buf).unwrapOr(0f)); + this.set(NetworkCodec.FLOAT.decode(buf)); } @Override From 07802ca3c6f58e7fd8b6aba02f6a3afc3707da14 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 21 Jul 2022 15:54:29 +0300 Subject: [PATCH 60/70] Reformat using Checkstyle --- .../qsl/component/api/ComponentType.java | 24 ++++--- .../quiltmc/qsl/component/api/Components.java | 71 +++++++++++-------- .../api/component/GenericComponent.java | 4 +- .../component/api/component/NbtComponent.java | 18 ++++- .../api/component/SyncedComponent.java | 4 +- .../api/component/SyncedGenericComponent.java | 4 +- .../api/container/ComponentContainer.java | 61 +++++++++------- .../qsl/component/api/package-info.java | 14 ++-- .../api/provider/ComponentProvider.java | 23 +++--- .../qsl/component/api/sync/SyncChannel.java | 34 +++++---- .../api/sync/codec/NetworkCodec.java | 19 ++--- .../qsl/component/impl/CommonInitializer.java | 4 +- .../qsl/component/impl/ComponentsImpl.java | 19 ++--- .../impl/client/ClientInitializer.java | 1 + .../client/sync/ClientRegistryPacket.java | 11 +-- .../impl/client/sync/ClientResolution.java | 5 +- .../impl/client/sync/ClientSyncHandler.java | 8 ++- .../container/AbstractComponentContainer.java | 27 +++---- .../CompositeComponentContainer.java | 5 +- .../container/EmptyComponentContainer.java | 5 +- .../container/LazyComponentContainer.java | 15 ++-- .../container/OnAccessComponentContainer.java | 23 +++--- .../container/SimpleComponentContainer.java | 21 +++--- .../container/SingleComponentContainer.java | 16 +++-- .../impl/event/ClientEventListener.java | 4 +- .../impl/event/CommonEventListener.java | 1 + .../impl/event/ComponentEventPhases.java | 1 + .../impl/injection/ComponentEntry.java | 1 + .../injection/manager/InjectionManager.java | 16 +++-- .../cached/CachedInjectionManager.java | 6 +- .../dynamic/DynamicInjectionManager.java | 22 +++--- .../cached/ClassInjectionPredicate.java | 17 ++--- .../FilteredInheritedInjectionPredicate.java | 4 +- .../cached/RedirectedInjectionPredicate.java | 6 +- .../DynamicClassInjectionPredicate.java | 4 +- .../dynamic/DynamicWrappedPredicate.java | 6 +- .../component/impl/sync/packet/PacketIds.java | 1 + .../impl/sync/packet/RegistryPacket.java | 1 + .../impl/util/ComponentProviderState.java | 17 ++--- .../mixin/block/entity/BlockEntityMixin.java | 14 ++-- .../DirectBlockEntityTickInvokerMixin.java | 5 +- .../qsl/component/mixin/chunk/ChunkMixin.java | 14 ++-- .../mixin/chunk/ChunkSerializerMixin.java | 9 +-- .../mixin/chunk/ServerWorldMixin.java | 14 ++-- .../mixin/chunk/WorldChunkMixin.java | 19 +++-- .../component/mixin/entity/EntityMixin.java | 12 ++-- .../mixin/level/MinecraftServerMixin.java | 6 +- .../level/client/MinecraftClientMixin.java | 10 +-- .../sync/ClientPlayNetworkHandlerMixin.java | 12 ++-- .../component/mixin/sync/WorldChunkMixin.java | 10 +-- .../qsl/component/mixin/world/WorldMixin.java | 6 +- .../qsl/component/test/ComponentTestMod.java | 17 +++-- .../component/test/ServerTickListener.java | 24 +++---- .../quiltmc/qsl/component/test/TestBlock.java | 6 +- .../qsl/component/test/TestBlockEntity.java | 20 +++--- .../test/client/ComponentTestModClient.java | 5 +- .../test/client/TestBlockEntityRenderer.java | 5 +- .../component/ChunkInventoryComponent.java | 9 +-- .../component/DefaultFloatComponent.java | 8 ++- .../component/DefaultIntegerComponent.java | 8 ++- .../component/DefaultInventoryComponent.java | 17 ++--- .../test}/component/InventoryComponent.java | 4 +- .../test/component/SaveFloatComponent.java | 7 +- .../MixinBlockEntityRendererFactories.java | 12 ++-- .../test/mixin/client/MixinInGameHud.java | 30 ++++---- 65 files changed, 497 insertions(+), 349 deletions(-) rename library/data/component/src/{main/java/org/quiltmc/qsl/component/impl => testmod/java/org/quiltmc/qsl/component/test}/component/DefaultFloatComponent.java (96%) rename library/data/component/src/{main/java/org/quiltmc/qsl/component/impl => testmod/java/org/quiltmc/qsl/component/test}/component/DefaultIntegerComponent.java (97%) rename library/data/component/src/{main/java/org/quiltmc/qsl/component/impl => testmod/java/org/quiltmc/qsl/component/test}/component/DefaultInventoryComponent.java (90%) rename library/data/component/src/{main/java/org/quiltmc/qsl/component/api => testmod/java/org/quiltmc/qsl/component/test}/component/InventoryComponent.java (95%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 2ec4f4bb4d..d16217c621 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -16,29 +16,30 @@ package org.quiltmc.qsl.component.api; +import java.util.IdentityHashMap; +import java.util.Map; + import net.minecraft.util.Identifier; + import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; - -import java.util.IdentityHashMap; -import java.util.Map; +import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; /** * A global identifier for a specific type of {@linkplain Component components}.
* This class must always exist as singleton instances, which have to be registered under the {@linkplain Components#REGISTRY registry}. * - * @param id The {@link Identifier} the type is registered with(it's here just for accesibility, however you may also get access to it using the {@linkplain Components#REGISTRY registry} and a {@link ComponentType} instance). + * @param id The {@link Identifier} the type is registered with(it's here just for accesibility, however you may also get access to it using the {@linkplain Components#REGISTRY registry} and a {@link ComponentType} instance). * @param defaultFactory A factory to a default {@link Component} instance, that this type may produce, * if no specific factory is defined under the container {@link org.quiltmc.qsl.component.impl.injection.ComponentEntry}.
* Used only during component injections or creation of {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer containers}. - * @param isStatic Whether this {@linkplain ComponentType type} works as a static type. - * @param isInstant Whether this {@linkplain ComponentType type} will be instantly initialized when put in a container. Useful for {@link org.quiltmc.qsl.component.api.component.TickingComponent}s or componens you want to initialize on {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer container} creation. - * @param The generic type of {@link Component} this type will provide. Most of the time, you would want this to be an interface providing all the needed API you may use to interact with a {@link Component} of this {@linkplain ComponentType type}. + * @param isStatic Whether this {@linkplain ComponentType type} works as a static type. + * @param isInstant Whether this {@linkplain ComponentType type} will be instantly initialized when put in a container. Useful for {@link org.quiltmc.qsl.component.api.component.TickingComponent}s or componens you want to initialize on {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer container} creation. + * @param The generic type of {@link Component} this type will provide. Most of the time, you would want this to be an interface providing all the needed API you may use to interact with a {@link Component} of this {@linkplain ComponentType type}. * @author 0xJoeMama */ public record ComponentType(Identifier id, Component.Factory defaultFactory, - boolean isStatic, boolean isInstant) implements Component.Factory { + boolean isStatic, boolean isInstant) implements Component.Factory { /** * We provide a {@link NetworkCodec} to be used with manual registry sync, until the registry sync API is merged. */ @@ -101,10 +102,11 @@ private Static() { } /** * Performs simple lazy initialization on the provided {@link ComponentType static type} * using the provided {@link org.quiltmc.qsl.component.api.Component.Operations} as initialization arguments. - * @param type The type of the component to be created. + * + * @param type The type of the component to be created. * @param operations The operations to use as initialization arguments. + * @param The type of {@linkplain Component component} to be created. * @return A singleton {@link C} instance. - * @param The type of {@linkplain Component component} to be created. */ @SuppressWarnings("unchecked") public C getOrCreate(ComponentType type, Component.Operations operations) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 9d6c3ec163..9d448a2999 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -16,10 +16,15 @@ package org.quiltmc.qsl.component.api; +import java.util.Set; +import java.util.function.Predicate; + +import org.jetbrains.annotations.ApiStatus; + import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; -import org.jetbrains.annotations.ApiStatus; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; @@ -33,14 +38,12 @@ import org.quiltmc.qsl.component.impl.injection.predicate.dynamic.DynamicClassInjectionPredicate; import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import java.util.Set; -import java.util.function.Predicate; - /** * The external version of the component API, meant to be used by modders.
* Use this and not {@link ComponentsImpl}.
* - * For usage docs, check {@link package-info.java} + *

+ * For usage docs, check package-info.java * * @author 0xJoeMama */ @@ -55,12 +58,14 @@ public final class Components { // end registry // begin injection methods + /** * The most manual method of injection.
* Callers can provide custom {@link InjectionPredicate}s and also custom {@linkplain ComponentEntry entries} + * * @param predicate The {@linkplain InjectionPredicate predicate} used for the injection - * @param entry The {@linkplain ComponentEntry entry} used for the injection. - * @param The type of the injected component. + * @param entry The {@linkplain ComponentEntry entry} used for the injection. + * @param The type of the injected component. * @see InjectionPredicate * @see ComponentEntry */ @@ -73,8 +78,8 @@ public static void inject(InjectionPredicate predicate, Co * Injects the provided {@link ComponentType} into all direct instances of the provided {@link Class}. * * @param clazz The target class(must implement {@link ComponentProvider}). - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). - * @param The type held by the injected type. + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param The type held by the injected type. * @see ClassInjectionPredicate */ public static void inject(Class clazz, ComponentType type) { @@ -83,9 +88,10 @@ public static void inject(Class clazz, ComponentType /** * Similar to {@link Components#inject(Class, ComponentType)} except it injects into all subclasses and indirect instances of the provided class. + * * @param clazz The highest class in the hierarchy that will be injected. - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). - * @param The type held by the injected type. + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param The type held by the injected type. * @see InheritedInjectionPredicate */ public static void injectInheritage(Class clazz, ComponentType type) { @@ -95,10 +101,10 @@ public static void injectInheritage(Class clazz, Compon /** * Similar to {@link Components#injectInheritage(Class, ComponentType)}, except it skips the provided classes in the hierarchy. * - * @param clazz The highest class in the hierarchy that will be injected. - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param clazz The highest class in the hierarchy that will be injected. + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). * @param exceptions The classes to avoid injecting into. - * @param The type help by the provided type. + * @param The type help by the provided type. * @see FilteredInheritedInjectionPredicate */ public static void injectInheritanceExcept(Class clazz, ComponentType type, Class... exceptions) { @@ -116,36 +122,38 @@ public static void injectRedirected(Class mainClass, Co * Dynamically injects into the provided {@link Class} using the provided predicate.
* For more info on dynamic injection check {@link org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate}; * - * @param clazz The target class(must implement {@link ComponentProvider}). - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param clazz The target class(must implement {@link ComponentProvider}). + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). * @param predicate The predicate used to determine if injection is possible. - * @param The type of component that will be injected. - * @param

The type of the provider that the dynamic injection targets. + * @param The type of component that will be injected. + * @param

The type of the provider that the dynamic injection targets. */ public static void injectDynamic(Class

clazz, ComponentType type, Predicate

predicate) { ComponentsImpl.inject(new DynamicClassInjectionPredicate<>(clazz, predicate), new ComponentEntry<>(type)); } + // end injection methods // begin registration methods + /** * The proper way to expose component instances.
* This does type-checking and also makes sure a {@link ComponentProvider} is given.
* This should be used where interface injection cannot apply(in other words custom implementations of {@link ComponentProvider}).
* - * @param id The {@link ComponentType} to expose. + * @param id The {@link ComponentType} to expose. * @param obj Any object will work. If it does not implement {@link ComponentProvider} an empty will be instantly returned. - * @return Either {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the result of expose called on the provider's container - * or {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided object is not a {@link ComponentProvider}. * @param The type of component held by the {@link ComponentType}. * @param The object to attempt to expose the component on. + * @return Either {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the result of expose called on the provider's container + * or {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided object is not a {@link ComponentProvider}. * @see ComponentProvider#expose * @see org.quiltmc.qsl.component.api.container.ComponentContainer#expose */ public static Maybe expose(ComponentType id, S obj) { if (obj instanceof ComponentProvider provider) { return provider.getComponentContainer().expose(id) - .filterMap(id::cast); // mapping with cast will make sure we get the correct type back. + .filterMap(id::cast); // mapping with cast will make sure we get the correct type back. } return Maybe.nothing(); @@ -154,10 +162,10 @@ public static Maybe expose(ComponentType id, S ob /** * Register a manually created {@link ComponentType}. * - * @param id The id to register the type with. + * @param id The id to register the type with. * @param type The type to register. + * @param The type of component held by the type. * @return The registered version of the component type. - * @param The type of component held by the type. */ public static ComponentType register(Identifier id, ComponentType type) { return ComponentsImpl.register(id, type); @@ -166,24 +174,26 @@ public static ComponentType register(Identifier id, Com /** * Register a normal {@link ComponentType} using the provided {@linkplain Component.Factory default factory}. * - * @param id The id to register the type with. + * @param id The id to register the type with. * @param factory The default {@link Component.Factory} of the type. + * @param The type of component held by the type. * @return A new {@link ComponentType} of {@link C} components. - * @param The type of component held by the type. */ public static ComponentType register(Identifier id, Component.Factory factory) { if (factory instanceof ComponentType) { throw ErrorUtil.illegalArgument("Do NOT register ComponentTypes as factories, use the correct method").get(); } + return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, false)); } /** * Register a {@linkplain ComponentType.Static static} {@linkplain ComponentType type} using the provided factory. - * @param id THe id to register the type with. + * + * @param id THe id to register the type with. * @param factory The default {@link Component.Factory} of the type. + * @param The type of component held by the type. * @return A new static {@link ComponentType}. - * @param The type of component held by the type. */ public static ComponentType registerStatic(Identifier id, Component.Factory factory) { return ComponentsImpl.register(id, new ComponentType<>(id, factory, true, false)); @@ -193,13 +203,14 @@ public static ComponentType registerStatic(Identifier i * Register an instance {@link ComponentType}.
* For more info check the {@linkplain ComponentType relevant docs}. * - * @param id The id to register the type with. + * @param id The id to register the type with. * @param factory The default {@link Component.Factory} of the type. + * @param The type of component held by the type. * @return A new instant {@link ComponentType}. - * @param The type of component held by the type. */ public static ComponentType registerInstant(Identifier id, Component.Factory factory) { return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, true)); } + // end registration method } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java index 609079edee..7b4829dee3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java @@ -17,10 +17,12 @@ package org.quiltmc.qsl.component.api.component; import com.mojang.serialization.Codec; +import org.jetbrains.annotations.Nullable; + import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtOps; -import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.impl.ComponentsImpl; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java index e7d4af6737..d405f62807 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java @@ -16,9 +16,23 @@ package org.quiltmc.qsl.component.api.component; -import net.minecraft.nbt.*; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; + +import net.minecraft.nbt.NbtByte; +import net.minecraft.nbt.NbtByteArray; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtDouble; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtFloat; +import net.minecraft.nbt.NbtInt; +import net.minecraft.nbt.NbtIntArray; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtLong; +import net.minecraft.nbt.NbtLongArray; +import net.minecraft.nbt.NbtShort; +import net.minecraft.nbt.NbtString; +import net.minecraft.util.Identifier; + import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.impl.util.ErrorUtil; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java index d2895b8405..33f754dc55 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java @@ -16,8 +16,10 @@ package org.quiltmc.qsl.component.api.component; -import net.minecraft.network.PacketByteBuf; import org.jetbrains.annotations.Nullable; + +import net.minecraft.network.PacketByteBuf; + import org.quiltmc.qsl.component.api.Component; public interface SyncedComponent extends Component { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java index 437eafbe3f..e0098b7567 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java @@ -17,8 +17,10 @@ package org.quiltmc.qsl.component.api.component; import com.mojang.serialization.Codec; -import net.minecraft.network.PacketByteBuf; import org.jetbrains.annotations.Nullable; + +import net.minecraft.network.PacketByteBuf; + import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index ca1920b232..f0db2ed08a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -16,22 +16,29 @@ package org.quiltmc.qsl.component.api.container; -import net.minecraft.nbt.NbtCompound; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.function.BiConsumer; + import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; + +import net.minecraft.nbt.NbtCompound; + import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.*; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.api.sync.SyncChannel; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.function.BiConsumer; +import org.quiltmc.qsl.component.impl.container.CompositeComponentContainer; +import org.quiltmc.qsl.component.impl.container.EmptyComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; +import org.quiltmc.qsl.component.impl.container.OnAccessComponentContainer; +import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; +import org.quiltmc.qsl.component.impl.container.SingleComponentContainer; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; /** * A base container for all {@link Component}s that a {@link ComponentProvider} contains. @@ -48,13 +55,14 @@ *

  • {@link CompositeComponentContainer}: usable through the {@link ComponentContainer#createComposite} method.
  • * * + *

    * To create a container, most of the time, you should use the {@link Builder} class.
    * You are also free to extend it and create a custom {@link Builder} implementation to suit your needs. * + * @author 0xJoeMama * @see ComponentProvider * @see ComponentType * @see Component - * @author 0xJoeMama */ public interface ComponentContainer { /** @@ -63,7 +71,7 @@ public interface ComponentContainer { ComponentContainer EMPTY = EmptyComponentContainer.INSTANCE; /** * A {@link Factory} to the aforementioned {@link EmptyComponentContainer}.
    - * This will always return the same instance. + * This will always return the same instance. */ ComponentContainer.Factory EMPTY_FACTORY = EmptyComponentContainer.FACTORY; /** @@ -71,6 +79,7 @@ public interface ComponentContainer { * A {@link SimpleComponentContainer} instantly initializes all of its components, disregarding the * {@link ComponentType#isInstant()} value for their types.
    * + *

    * The advantage of this {@linkplain ComponentContainer container} is that by initializing all of its components right off the bat, * it can have a faster runtime. However, that does sacrifice on memory and also on disc space, * since all {@link org.quiltmc.qsl.component.api.component.NbtComponent}s, even if their value hasn't been modified, will be saved. @@ -92,9 +101,10 @@ public interface ComponentContainer { * it stores {@link com.mojang.datafixers.util.Either} instances that it attempts to access and/or initialize on expose. * This currently leads to extra object creation, hence it's considered {@linkplain org.jetbrains.annotations.ApiStatus.Experimental experimental}.
    * + *

    * May be used as the default container for our implementations in the future. * - * @deprecated Experimental + * @deprecated Experimental */ @ApiStatus.Experimental ComponentContainer.Factory ON_ACCESS_FACTORY = OnAccessComponentContainer.FACTORY; @@ -102,11 +112,12 @@ public interface ComponentContainer { /** * Creates a {@link Factory} to a {@link SingleComponentContainer}.
    * + *

    * A {@link SingleComponentContainer} is identical to a {@link LazyComponentContainer}, except it can only store 1 component. * * @param type The {@link ComponentType} to store. The default factory of the type is used for initialization. + * @param The type of component that is contained by the container. * @return A new {@link Factory} for {@link SingleComponentContainer} holding the provided {@link ComponentType}. - * @param The type of component that is contained by the container. */ static ComponentContainer.Factory> createSingleFactory(ComponentType type) { return SingleComponentContainer.createFactory(new ComponentEntry<>(type)); @@ -114,6 +125,7 @@ static ComponentContainer.Factory ComponentContainer.Factory> createSingleFactory(ComponentType type, Component.Factory factory) { @@ -123,7 +135,7 @@ static ComponentContainer.Factory * This is type-unsafe and if not implemented correctly, may lead to crashes with {@link ClassCastException}s.
    * + *

    * This method is called really often, so it is advised you make it have a really fast runtime. * * @param type The type to expose. * @return Should return {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided {@link ComponentType} is not contained in the current container. - * Otherwise, should always return {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the contained {@link Component} instance. + * Otherwise, should always return {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the contained {@link Component} instance. */ Maybe expose(ComponentType type); @@ -169,10 +182,9 @@ static Builder builder(Object obj) { /** * Deserializes the {@link org.quiltmc.qsl.component.api.component.NbtComponent}s this {@link ComponentContainer container} contains, from the provided nbt tag.
    * + * @param providerRootNbt The root nbt tag of the provider containing this {@link ComponentContainer}. * @implNote There is no guarantee that the provided tag will contain exactly the same components as the container. * It may contain less or more. Keep that in mind when creating custom implementations. - * - * @param providerRootNbt The root nbt tag of the provider containing this {@link ComponentContainer}. */ void readNbt(NbtCompound providerRootNbt); @@ -210,18 +222,19 @@ interface Factory { /** * Creates a {@link ComponentContainer} using the specified arguments. * - * @param provider The {@link ComponentProvider} that will contain the created {@link ComponentContainer}. - * @param entries A {@link List} containing all the entries that were manually added by the {@link Builder}. + * @param provider The {@link ComponentProvider} that will contain the created {@link ComponentContainer}. + * @param entries A {@link List} containing all the entries that were manually added by the {@link Builder}. * @param saveOperation The operation to be run by the contained {@link Component}s to mark the {@linkplain ComponentProvider provider} as needing to save. - * @param ticking Whether this container can tick. - * @param syncChannel The {@link SyncChannel} representing the {@link ComponentProvider} that contains the created {@link ComponentContainer}. + * @param ticking Whether this container can tick. + * @param syncChannel The {@link SyncChannel} representing the {@link ComponentProvider} that contains the created {@link ComponentContainer}. * @return A {@link ComponentContainer} created using the specified parameters. */ T generate(ComponentProvider provider, - Lazy>> entries, - @Nullable Runnable saveOperation, - boolean ticking, - @Nullable SyncChannel syncChannel); + Lazy>> entries, + @Nullable Runnable saveOperation, + boolean ticking, + @Nullable SyncChannel syncChannel + ); } /** diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java index 53a53e8f24..133bbbee52 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java @@ -7,7 +7,7 @@ * The simplest thing you can do using this module is create a {@link org.quiltmc.qsl.component.api.ComponentType}. * It works as an identifier for components of a specific type.
    * To create one simply follow this: - *

    {@code
    + * 
    {@code
      * public class MainClass implements ModInitializer {
      *    // ...
      *    public static final ComponentType A_COMPONENT = Components.register(
    @@ -27,7 +27,7 @@
      * }
      *
      * public class ADefaultComponent implements AComponent {
    - *	   private final String stringData;
    + * 	   private final String stringData;
      *
      *     public ADefaultComponent(Component.Operations ignored) {
      *         this.stringData = "Hello there";
    @@ -64,20 +64,22 @@
      * For more info on {@linkplain org.quiltmc.qsl.component.api.provider.ComponentProvider providers} check the {@linkplain org.quiltmc.qsl.component.api.provider.ComponentProvider relevant documentation}.
      * 

    * + *

    * Choose one of those and then you are 1 step away from getting a functioning component injected to it.
    * On the below example, I have chosen BlockEntity as the target of my injection. *

    {@code
      * public class MainClass implements ModInitializer {
      *     // ...
    - * 	   @Override
    - * 	   public void onInitialize(ModContainer mod) {
    + *       @Override
    + *       public void onInitialize(ModContainer mod) {
      * 	   	   // ...
      * 	       Components.inject(ChestBlockEntity.class, A_COMPONENT);
      * 	       // ...
    - * 	   }
    + *       }
      * }
      * }
    * + *

    * Now all chests should have {@code AComponent} injected into them, when they are created. *

    *

    Accessing Components

    @@ -97,6 +99,7 @@ * }
    *

    * + *

    * Keep in mind that when exposing component instances: *

      *
    1. You always get back the type that matches your {@link org.quiltmc.qsl.component.api.ComponentType}. In this case that would be an AComponent instance.
    2. @@ -109,4 +112,5 @@ * * @author 0xJoeMama */ + package org.quiltmc.qsl.component.api; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java index 811ff47f2e..e11e6f6606 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java @@ -22,24 +22,26 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; + import org.quiltmc.qsl.base.api.util.InjectedInterface; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.container.ComponentContainer; /** * Any object that wishes to allow {@link Component components} to be attached to and queried from it, * needs to implement this interface.
      * + *

      * Currectly it consists of the {@link ComponentProvider#getComponentContainer()} method, which is the abstract one, * as well as the {@link ComponentProvider#expose(ComponentType)} method, which is just a utility method.
      * In the future, more methods may be added, but for now this is all the API we need to expose on game objects.
      * You may create custom implementations of this interface. However, to do so, I would suggest looking at * {@link ComponentContainer} beforehand. - *

      * + *

      * By default, QSL provides the following, interface injected {@linkplain ComponentProvider providers}: *

        *
      • BlockEntity
      • @@ -49,22 +51,23 @@ *
      • Level(in other words a world save)
      • *
      * + *

      * Furthermore, all of them support component saving and syncing.
      * * Note: You shouldn't have to use the {@link ComponentProvider#getComponentContainer()} method that often, * if ever, because it's needed for implementations not for using the API. * + * @author 0xJoeMama * @see ComponentContainer * @see Components - * @author 0xJoeMama */ @InjectedInterface({ // We inject this inteface, so that modders don't need to use the methods in Components directly with our default implementations. - Entity.class, - BlockEntity.class, - Chunk.class, - MinecraftServer.class, // MinecraftServer and MinecraftClient contain Level components - MinecraftClient.class, - World.class + Entity.class, + BlockEntity.class, + Chunk.class, + MinecraftServer.class, // MinecraftServer and MinecraftClient contain Level components + MinecraftClient.class, + World.class }) public interface ComponentProvider { /** @@ -81,8 +84,8 @@ default ComponentContainer getComponentContainer() { * Utility method to call {@link Components#expose(ComponentType, Object)} on the actual provider. * * @param type The {@linkplain ComponentType type} we want to query. + * @param The type of the held component. * @return A {@link Maybe} instance following the rules defined in {@link Components#expose(ComponentType, Object)}. - * @param The type of the held component. */ default Maybe expose(ComponentType type) { return Components.expose(type, this); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java index 194fb583b1..2fb23c3d70 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java @@ -16,8 +16,20 @@ package org.quiltmc.qsl.component.api.sync; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Queue; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; + import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; + import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; @@ -32,6 +44,7 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.WorldChunk; + import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.component.SyncedComponent; import org.quiltmc.qsl.component.api.provider.ComponentProvider; @@ -43,17 +56,10 @@ import org.quiltmc.qsl.networking.api.ServerPlayNetworking; import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking; -import java.util.*; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.stream.Stream; - // ClientResolution.* all reference client-only classes, // so we need to just make sure we use lambdas so no attempt at class loading non-existent classes @SuppressWarnings("Convert2MethodRef") public class SyncChannel

      { - // BlockEntity public static final SyncChannel BLOCK_ENTITY = new SyncChannel<>( PacketIds.BLOCK_ENTITY_SYNC, @@ -115,9 +121,10 @@ public class SyncChannel

      { protected final Queue requestQueue = new ArrayDeque<>(); protected final NetworkCodec> queueCodec; - public SyncChannel(Identifier channelId, NetworkCodec codec, Function identifyingDataTransformer, - Function clientLocator, BiFunction serverLocator, - Function> playerProvider) { + public SyncChannel(Identifier channelId, NetworkCodec codec, + Function identifyingDataTransformer, + Function clientLocator, BiFunction serverLocator, + Function> playerProvider) { this.channelId = channelId; this.codec = codec; this.identifyingDataTransformer = identifyingDataTransformer; @@ -197,7 +204,7 @@ public void handleServerPushedSync(MinecraftClient client, PacketByteBuf buf) { public void handleClientSyncRequest(MinecraftServer server, ServerPlayerEntity sender, PacketByteBuf buf) { buf.retain(); server.execute(() -> { - Queue queued = this.queueCodec.decode(buf); + Queue queued = this.queueCodec.decode(buf); // we retrive the queue of identifying data while (!queued.isEmpty()) { var identifyingData = queued.poll(); @@ -207,6 +214,7 @@ public void handleClientSyncRequest(MinecraftServer server, ServerPlayerEntity s return; } + // force sync the target container this.forceSync(provider, sender); } @@ -259,7 +267,7 @@ public void sendMassRequests() { } public Identifier getChannelId() { - return channelId; + return this.channelId; } @Override @@ -278,7 +286,7 @@ public boolean equals(Object obj) { @Override public int hashCode() { - return Objects.hash(channelId, codec, identifyingDataTransformer, clientLocator, serverLocator, playerProvider); + return Objects.hash(this.channelId, this.codec, this.identifyingDataTransformer, this.clientLocator, this.serverLocator, this.playerProvider); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/codec/NetworkCodec.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/codec/NetworkCodec.java index 7f70b77ec9..cb0a7926b7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/codec/NetworkCodec.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/codec/NetworkCodec.java @@ -16,7 +16,17 @@ package org.quiltmc.qsl.component.api.sync.codec; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.UUID; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.function.Supplier; + import com.mojang.datafixers.util.Pair; + import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; @@ -28,15 +38,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.UUID; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.IntFunction; -import java.util.function.Supplier; - public record NetworkCodec(BiConsumer encoder, Function decoder) { public static final NetworkCodec BYTE = new NetworkCodec<>( (buf, aByte) -> buf.writeByte(aByte), PacketByteBuf::readByte diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 9c177bece8..5e6040dcad 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -16,8 +16,10 @@ package org.quiltmc.qsl.component.impl; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.ApiStatus; + +import net.minecraft.util.Identifier; + import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.impl.event.CommonEventListener; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 9a4e30d7d6..c265a09a72 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -16,24 +16,27 @@ package org.quiltmc.qsl.component.impl; +import java.util.ArrayList; +import java.util.List; + import com.mojang.serialization.Lifecycle; +import org.jetbrains.annotations.ApiStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.SimpleRegistry; -import org.jetbrains.annotations.ApiStatus; -import org.quiltmc.qsl.component.api.*; -import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; + +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.cached.CachedInjectionManager; import org.quiltmc.qsl.component.impl.injection.manager.dynamic.DynamicInjectionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; @ApiStatus.Internal public class ComponentsImpl { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java index 653edb6cf6..5ac1bb541d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/ClientInitializer.java @@ -18,6 +18,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; + import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java index bbedddabe8..5649170086 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java @@ -16,21 +16,24 @@ package org.quiltmc.qsl.component.impl.client.sync; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + import com.mojang.datafixers.util.Either; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; + import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; import net.minecraft.util.collection.IdList; import net.minecraft.util.registry.Registry; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.networking.api.PacketByteBufs; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; - @Environment(EnvType.CLIENT) public final class ClientRegistryPacket { + @SuppressWarnings("OptionalGetWithoutIsPresent") public static CompletableFuture handleRegistryPacket(PacketByteBuf buf, Registry registry, Consumer> action) { return CompletableFuture.supplyAsync(() -> { var finalEither = createIdList(buf, registry) @@ -38,7 +41,7 @@ public static CompletableFuture handleRegistryPacket(PacketBy .mapLeft(clientHeaderList -> PacketByteBufs.create().writeString("Ok")) .mapRight(PacketByteBufs.create()::writeIdentifier); - return finalEither.left().isPresent() ? finalEither.left().get() : finalEither.right().get(); + return finalEither.left().isPresent() ? finalEither.left().get() : finalEither.right().get(); // if we don't have a left value we will definitely have a right one }); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java index b2a4a4760a..f92dd40b2d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java @@ -2,6 +2,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; + import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; @@ -9,9 +10,11 @@ import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; + import org.quiltmc.qsl.component.api.provider.ComponentProvider; -@SuppressWarnings("ConstantConditions") // all of these are called after the client joins a world, so no NPEs will be thrown +// all of these are called after the client joins a world, so no NPEs will be thrown +@SuppressWarnings("ConstantConditions") @Environment(EnvType.CLIENT) public final class ClientResolution { public static Entity entity(int id) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java index a0a7b5dfa4..5a3f4c9d1f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientSyncHandler.java @@ -16,12 +16,17 @@ package org.quiltmc.qsl.component.impl.client.sync; +import java.util.ArrayDeque; +import java.util.Queue; + import com.mojang.datafixers.util.Pair; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; + import net.minecraft.client.MinecraftClient; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.collection.IdList; + import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.sync.SyncChannel; @@ -30,9 +35,6 @@ import org.quiltmc.qsl.networking.api.client.ClientLoginNetworking; import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking; -import java.util.ArrayDeque; -import java.util.Queue; - @Environment(EnvType.CLIENT) public final class ClientSyncHandler { private static ClientSyncHandler INSTANCE = null; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index 21cff50604..6d6058868d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -16,9 +16,18 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Queue; +import java.util.function.Function; + +import org.jetbrains.annotations.Nullable; + import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; @@ -28,14 +37,11 @@ import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; -import java.util.*; -import java.util.function.Function; - public abstract class AbstractComponentContainer implements ComponentContainer { protected final ContainerOperations operations; protected final List> nbtComponents; @@ -44,8 +50,8 @@ public abstract class AbstractComponentContainer implements ComponentContainer { protected final Maybe> syncContext; public AbstractComponentContainer(@Nullable Runnable saveOperation, - boolean ticking, - @Nullable SyncChannel syncChannel) { + boolean ticking, + @Nullable SyncChannel syncChannel) { this.ticking = ticking ? Maybe.just(new ArrayList<>()) : Maybe.nothing(); this.nbtComponents = new ArrayList<>(); this.syncContext = Maybe.wrap(syncChannel); @@ -79,8 +85,7 @@ public void readNbt(NbtCompound providerRootNbt) { .filter(Objects::nonNull) .forEach(type -> this.expose(type) .map(component -> ((NbtComponent) component)) - .ifJust(component -> NbtComponent.readFrom(component, type.id(), rootQslNbt)) - ); + .ifJust(component -> NbtComponent.readFrom(component, type.id(), rootQslNbt))); } @Override @@ -131,7 +136,5 @@ protected COMP initializeComponent(ComponentEntry return component; } - public record ContainerOperations(@Nullable Runnable saveOperation, - @Nullable Function, Runnable> syncOperationFactory) { - } + public record ContainerOperations(@Nullable Runnable saveOperation, @Nullable Function, Runnable> syncOperationFactory) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java index f006ce3797..2661875633 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java @@ -16,15 +16,16 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.function.BiConsumer; + import net.minecraft.nbt.NbtCompound; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import java.util.function.BiConsumer; - public class CompositeComponentContainer implements ComponentContainer { private final ComponentContainer main; private final ComponentContainer fallback; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java index f894b1c21d..91b56c9d68 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java @@ -16,15 +16,16 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.function.BiConsumer; + import net.minecraft.nbt.NbtCompound; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import java.util.function.BiConsumer; - public final class EmptyComponentContainer implements ComponentContainer { public static final EmptyComponentContainer INSTANCE = new EmptyComponentContainer(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 84c26db730..3737bbd644 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -16,22 +16,23 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.function.BiConsumer; + import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.api.sync.SyncChannel; - -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.function.BiConsumer; public class LazyComponentContainer extends AbstractComponentContainer { public static final ComponentContainer.Factory FACTORY = diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index c8b63d4f8a..7876e881fd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -16,32 +16,33 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; + import com.mojang.datafixers.util.Either; import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.api.sync.SyncChannel; - -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; // Suggestion from Technici4n from fabric. May help improve performance and memory footprint once done. public class OnAccessComponentContainer extends AbstractComponentContainer { public static final Factory FACTORY = (provider, injections, saveOperation, ticking, syncChannel) -> - new OnAccessComponentContainer(provider, saveOperation, ticking, syncChannel); + new OnAccessComponentContainer(provider, saveOperation, ticking, syncChannel); private final Map, Either, Component>> components; protected OnAccessComponentContainer(ComponentProvider provider, - @Nullable Runnable saveOperation, - boolean ticking, - @Nullable SyncChannel syncChannel) { + @Nullable Runnable saveOperation, + boolean ticking, + @Nullable SyncChannel syncChannel) { super(saveOperation, ticking, syncChannel); this.components = this.createComponents(provider); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index b5253f3387..9ef6409646 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -16,20 +16,21 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.stream.Stream; + import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.stream.Stream; - public class SimpleComponentContainer extends AbstractComponentContainer { public static final ComponentContainer.Factory FACTORY = (provider, injections, saveOperation, ticking, syncChannel) -> new SimpleComponentContainer( @@ -38,9 +39,9 @@ public class SimpleComponentContainer extends AbstractComponentContainer { private final Map, Component> components; protected SimpleComponentContainer(@Nullable Runnable saveOperation, - boolean ticking, - @Nullable SyncChannel syncContext, - Stream> types) { + boolean ticking, + @Nullable SyncChannel syncContext, + Stream> types) { super(saveOperation, ticking, syncContext); this.components = new IdentityHashMap<>(); types.forEach(this::initializeComponent); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java index 1616298f06..34ae807e47 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java @@ -16,8 +16,15 @@ package org.quiltmc.qsl.component.impl.container; -import net.minecraft.nbt.NbtCompound; +import java.util.ArrayDeque; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + import org.jetbrains.annotations.Nullable; + +import net.minecraft.nbt.NbtCompound; + import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Component; @@ -27,13 +34,8 @@ import org.quiltmc.qsl.component.api.component.TickingComponent; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.api.sync.SyncChannel; - -import java.util.ArrayDeque; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Supplier; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; public class SingleComponentContainer implements ComponentContainer { private final ComponentType type; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java index d028f293f5..f962baab03 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java @@ -2,11 +2,13 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; + import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; + import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; import org.quiltmc.qsl.networking.api.PacketSender; @Environment(EnvType.CLIENT) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java index 5e4be3b5d8..278d9714fc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java @@ -3,6 +3,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerLoginNetworkHandler; import net.minecraft.server.world.ServerWorld; + import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.sync.packet.PacketIds; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java index 326dca8fa8..3ff843cf26 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java @@ -1,6 +1,7 @@ package org.quiltmc.qsl.component.impl.event; import net.minecraft.util.Identifier; + import org.quiltmc.qsl.component.impl.CommonInitializer; public final class ComponentEventPhases { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java index 69d045c259..6c5d04117d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java @@ -17,6 +17,7 @@ package org.quiltmc.qsl.component.impl.injection; import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java index 573181bd6b..28761b0af3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java @@ -16,17 +16,24 @@ package org.quiltmc.qsl.component.impl.injection.manager; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + import net.minecraft.util.Util; + import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.*; +import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import java.util.*; -import java.util.stream.Stream; - public abstract class InjectionManager

      { private final Map>> injections = new HashMap<>(); private final Map, List> cache = new IdentityHashMap<>(); @@ -50,6 +57,7 @@ public void inject(P predicate, ComponentEntry componen } else { this.injections.put(predicate, Util.make(new ArrayList<>(), injections -> injections.add(componentEntry))); } + this.cache.clear(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java index 6ceb1d5fae..860398a879 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java @@ -16,14 +16,14 @@ package org.quiltmc.qsl.component.impl.injection.manager.cached; +import java.util.List; +import java.util.Objects; + import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.InjectionManager; -import java.util.List; -import java.util.Objects; - public class CachedInjectionManager extends InjectionManager> { @Override public List> getInjections(ComponentProvider provider) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java index f7c6b8dd73..7351e351a0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java @@ -16,27 +16,27 @@ package org.quiltmc.qsl.component.impl.injection.manager.dynamic; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.injection.manager.InjectionManager; -import org.quiltmc.qsl.base.api.util.Maybe; - import java.util.List; import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Collectors; +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.impl.injection.manager.InjectionManager; + public class DynamicInjectionManager extends InjectionManager { @Override public List> getInjections(ComponentProvider provider) { Class providerClass = provider.getClass(); // First check the cached side return this.getCache(providerClass).or(() -> { - var injections = this.initInjections(providerClass); - this.record(providerClass, injections); - return Maybe.just(injections); - }).unwrap().stream() + var injections = this.initInjections(providerClass); + this.record(providerClass, injections); + return Maybe.just(injections); + }).unwrap().stream() .map(dynamicInjection -> dynamicInjection.test(provider) ? dynamicInjection.componentEntries() : null) // After check the dynamic side .filter(Objects::nonNull) .flatMap(List::stream) @@ -51,7 +51,7 @@ private List initInjections(Class clazz) { } public record DynamicInjection(DynamicInjectionPredicate predicate, - List> componentEntries) implements Predicate { + List> componentEntries) implements Predicate { @Override public boolean test(ComponentProvider provider) { return this.predicate.canInject(provider); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java index c1709ce590..19a6a5e0ff 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java @@ -16,13 +16,13 @@ package org.quiltmc.qsl.component.impl.injection.predicate.cached; +import java.util.Arrays; +import java.util.Objects; + import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import java.util.Arrays; -import java.util.Objects; - public class ClassInjectionPredicate implements InjectionPredicate { protected final Class clazz; @@ -37,8 +37,8 @@ public ClassInjectionPredicate(Class clazz) { } private static boolean implementsComponentProvider(Class clazz) { - return Arrays.stream(clazz.getInterfaces()).anyMatch(it -> it == ComponentProvider.class) || - (clazz.getSuperclass() != null && implementsComponentProvider(clazz.getSuperclass())); + return Arrays.stream(clazz.getInterfaces()).anyMatch(it -> it == ComponentProvider.class) + || (clazz.getSuperclass() != null && implementsComponentProvider(clazz.getSuperclass())); } @Override @@ -48,20 +48,21 @@ public boolean isClassValid(Class clazz) { @Override public int hashCode() { - return Objects.hash(clazz); + return Objects.hash(this.clazz); } @Override public boolean equals(Object o) { if (this == o) return true; if (o instanceof ClassInjectionPredicate that) { - return clazz.equals(that.clazz); + return this.clazz.equals(that.clazz); } + return false; } @Override public String toString() { - return "ClassInjectionPredicate{clazz=" + clazz + '}'; + return "ClassInjectionPredicate{clazz=" + this.clazz + '}'; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java index 99ba7ce343..b75fc13d53 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/FilteredInheritedInjectionPredicate.java @@ -37,12 +37,12 @@ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof FilteredInheritedInjectionPredicate that)) return false; if (!super.equals(o)) return false; - return exceptions.equals(that.exceptions); + return this.exceptions.equals(that.exceptions); } @Override public String toString() { - return "FilteredInheritedInjectionPredicate{clazz=" + clazz + ", exceptions=" + exceptions + '}'; + return "FilteredInheritedInjectionPredicate{clazz=" + this.clazz + ", exceptions=" + this.exceptions + '}'; } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/RedirectedInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/RedirectedInjectionPredicate.java index a96580d946..3dc132d670 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/RedirectedInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/RedirectedInjectionPredicate.java @@ -34,7 +34,7 @@ public boolean isClassValid(Class clazz) { @Override public String toString() { - return "RedirectedInjectionPredicate{redirections=" + redirections + ", clazz=" + clazz + '}'; + return "RedirectedInjectionPredicate{redirections=" + this.redirections + ", clazz=" + this.clazz + '}'; } @Override @@ -42,11 +42,11 @@ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof RedirectedInjectionPredicate that)) return false; if (!super.equals(o)) return false; - return redirections.equals(that.redirections); + return this.redirections.equals(that.redirections); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), redirections); + return Objects.hash(super.hashCode(), this.redirections); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java index b58bf78e01..25714e05e9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java @@ -16,12 +16,12 @@ package org.quiltmc.qsl.component.impl.injection.predicate.dynamic; +import java.util.function.Predicate; + import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; -import java.util.function.Predicate; - public class DynamicClassInjectionPredicate

      extends ClassInjectionPredicate implements DynamicInjectionPredicate { private final Predicate

      predicate; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java index 6b3622550d..685db1ec04 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java @@ -16,12 +16,12 @@ package org.quiltmc.qsl.component.impl.injection.predicate.dynamic; -import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; +import java.util.function.Predicate; + import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import java.util.function.Predicate; - public class DynamicWrappedPredicate

      implements DynamicInjectionPredicate { private final InjectionPredicate wrapped; private final Predicate

      predicate; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java index c685effe89..b882262eee 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/PacketIds.java @@ -17,6 +17,7 @@ package org.quiltmc.qsl.component.impl.sync.packet; import net.minecraft.util.Identifier; + import org.quiltmc.qsl.component.impl.CommonInitializer; public final class PacketIds { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java index dc73142ed8..e3e27f8371 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/sync/packet/RegistryPacket.java @@ -21,6 +21,7 @@ import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; + import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.networking.api.PacketByteBufs; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java index a267ad9428..b02be176fa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java @@ -16,19 +16,20 @@ package org.quiltmc.qsl.component.impl.util; +import java.util.HashMap; +import java.util.Map; + import net.minecraft.nbt.NbtCompound; import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.PersistentState; import net.minecraft.world.World; + import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.quiltmc.qsl.component.api.sync.SyncChannel; - -import java.util.HashMap; -import java.util.Map; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; // TODO: Fix this public class ComponentProviderState extends PersistentState implements ComponentProvider { @@ -94,6 +95,10 @@ public static class ClientComponentProviderState implements ComponentProvider { private static final Map, ComponentProvider> cachedValue = new HashMap<>(); private final ComponentContainer container; + private ClientComponentProviderState(World world) { + this.container = ComponentContainer.builder(world).build(ComponentContainer.LAZY_FACTORY); + } + private static ComponentProvider getOrCreate(World world) { return cachedValue.computeIfAbsent( world.getRegistryKey(), @@ -101,10 +106,6 @@ private static ComponentProvider getOrCreate(World world) { ); } - private ClientComponentProviderState(World world) { - this.container = ComponentContainer.builder(world).build(ComponentContainer.LAZY_FACTORY); - } - @Override public ComponentContainer getComponentContainer() { return this.container; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java index d5cf251791..0e58d0eaf7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java @@ -16,20 +16,22 @@ package org.quiltmc.qsl.component.mixin.block.entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.BlockPos; + import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(BlockEntity.class) public abstract class BlockEntityMixin implements ComponentProvider { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java index 36975899df..50666c2fec 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java @@ -16,8 +16,6 @@ package org.quiltmc.qsl.component.mixin.block.entity; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.world.chunk.WorldChunk; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -25,6 +23,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.world.chunk.WorldChunk; + @Mixin(WorldChunk.DirectBlockEntityTickInvoker.class) public class DirectBlockEntityTickInvokerMixin { @Shadow diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java index 787e1c4ee4..90bb7555eb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java @@ -16,6 +16,12 @@ package org.quiltmc.qsl.component.mixin.chunk; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.Registry; import net.minecraft.world.HeightLimitView; @@ -24,15 +30,11 @@ import net.minecraft.world.chunk.UpgradeData; import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.gen.chunk.BlendingData; + import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; @Mixin(Chunk.class) public abstract class ChunkMixin implements ComponentProvider { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkSerializerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkSerializerMixin.java index 7bb52b090c..73fa3e412d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkSerializerMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkSerializerMixin.java @@ -16,6 +16,11 @@ package org.quiltmc.qsl.component.mixin.chunk; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + import net.minecraft.nbt.NbtCompound; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.ChunkPos; @@ -24,10 +29,6 @@ import net.minecraft.world.chunk.ProtoChunk; import net.minecraft.world.chunk.ReadOnlyChunk; import net.minecraft.world.poi.PointOfInterestStorage; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ChunkSerializer.class) public class ChunkSerializerMixin { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ServerWorldMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ServerWorldMixin.java index 32527f4216..0b8d02779a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ServerWorldMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ServerWorldMixin.java @@ -16,6 +16,13 @@ package org.quiltmc.qsl.component.mixin.chunk; +import java.util.function.Supplier; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Holder; import net.minecraft.util.profiler.Profiler; @@ -24,13 +31,8 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.dimension.DimensionType; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.spongepowered.asm.mixin.Mixin; -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.function.Supplier; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; @Mixin(ServerWorld.class) public abstract class ServerWorldMixin extends World implements ComponentProvider { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java index 28a23c819c..3ef5db10cd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java @@ -16,20 +16,27 @@ package org.quiltmc.qsl.component.mixin.chunk; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.Registry; import net.minecraft.world.HeightLimitView; import net.minecraft.world.biome.Biome; -import net.minecraft.world.chunk.*; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraft.world.chunk.ProtoChunk; +import net.minecraft.world.chunk.ReadOnlyChunk; +import net.minecraft.world.chunk.UpgradeData; +import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.gen.chunk.BlendingData; -import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(WorldChunk.class) public abstract class WorldChunkMixin extends Chunk implements ComponentProvider { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java index e9fef27682..22618c6c50 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java @@ -16,18 +16,20 @@ package org.quiltmc.qsl.component.mixin.entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.nbt.NbtCompound; import net.minecraft.world.World; + import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Entity.class) public abstract class EntityMixin implements ComponentProvider { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java index 2adffd496f..2f1bfd3357 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/MinecraftServerMixin.java @@ -16,11 +16,13 @@ package org.quiltmc.qsl.component.mixin.level; +import org.spongepowered.asm.mixin.Mixin; + import net.minecraft.server.MinecraftServer; + import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.util.ComponentProviderState; -import org.spongepowered.asm.mixin.Mixin; // FIXME: Fix level and world being weird with one another @Mixin(MinecraftServer.class) @@ -28,6 +30,6 @@ public abstract class MinecraftServerMixin implements ComponentProvider { @SuppressWarnings("ConstantConditions") @Override public ComponentContainer getComponentContainer() { - return ComponentProviderState.getGlobal((MinecraftServer) (Object)this).getComponentContainer(); + return ComponentProviderState.getGlobal((MinecraftServer) (Object) this).getComponentContainer(); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java index 61d7a725d7..ce036f1467 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/level/client/MinecraftClientMixin.java @@ -16,15 +16,17 @@ package org.quiltmc.qsl.component.mixin.level.client; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.RunArgs; -import org.quiltmc.qsl.component.api.container.ComponentContainer; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.RunArgs; + +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; + @Mixin(MinecraftClient.class) public abstract class MinecraftClientMixin implements ComponentProvider { private ComponentContainer qsl$container; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java index 4e71e10466..0547113e11 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java @@ -1,20 +1,22 @@ package org.quiltmc.qsl.component.mixin.sync; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; import net.minecraft.util.math.ChunkPos; + import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ClientPlayNetworkHandler.class) public abstract class ClientPlayNetworkHandlerMixin { @Inject(method = "onChunkData", at = @At("RETURN")) private void initialChunkSync(ChunkDataS2CPacket packet, CallbackInfo ci) { - SyncChannel.CHUNK.requestSync(new ChunkPos(packet.chunkX(), packet.chunkZ())); + SyncChannel.CHUNK.requestSync(new ChunkPos(packet.chunkX(), packet.chunkZ())); } @Inject(method = "onEntitySpawn", at = @At("RETURN")) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java index 359e740b7e..b5aa065418 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java @@ -1,14 +1,16 @@ package org.quiltmc.qsl.component.mixin.sync; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + import net.minecraft.block.entity.BlockEntityType; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.WorldChunk; + import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(WorldChunk.class) public class WorldChunkMixin { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java index cca01a078d..9c1ac7e6d3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/world/WorldMixin.java @@ -16,17 +16,19 @@ package org.quiltmc.qsl.component.mixin.world; +import org.spongepowered.asm.mixin.Mixin; + import net.minecraft.world.World; + import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.util.ComponentProviderState; -import org.spongepowered.asm.mixin.Mixin; @Mixin(World.class) public class WorldMixin implements ComponentProvider { @SuppressWarnings("ConstantConditions") @Override public ComponentContainer getComponentContainer() { - return ComponentProviderState.get((World)(Object)this).getComponentContainer(); + return ComponentProviderState.get((World) (Object) this).getComponentContainer(); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 7192cf7925..aed20a5339 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -16,6 +16,8 @@ package org.quiltmc.qsl.component.test; +import java.util.UUID; + import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.Blocks; @@ -38,24 +40,23 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.WorldChunk; + import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.block.entity.api.QuiltBlockEntityTypeBuilder; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.component.GenericComponent; -import org.quiltmc.qsl.component.api.component.InventoryComponent; import org.quiltmc.qsl.component.api.component.TickingComponent; -import org.quiltmc.qsl.component.impl.component.DefaultFloatComponent; -import org.quiltmc.qsl.component.impl.component.DefaultIntegerComponent; -import org.quiltmc.qsl.component.impl.component.DefaultInventoryComponent; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; import org.quiltmc.qsl.component.test.component.ChunkInventoryComponent; +import org.quiltmc.qsl.component.test.component.DefaultFloatComponent; +import org.quiltmc.qsl.component.test.component.DefaultIntegerComponent; +import org.quiltmc.qsl.component.test.component.DefaultInventoryComponent; +import org.quiltmc.qsl.component.test.component.InventoryComponent; import org.quiltmc.qsl.component.test.component.SaveFloatComponent; -import java.util.UUID; - public class ComponentTestMod implements ModInitializer { public static final String MODID = "quilt_component_test"; @@ -116,12 +117,14 @@ public class ComponentTestMod implements ModInitializer { player.giveItemStack(new ItemStack(Items.WHEAT)); player.sendMessage(Text.literal("Prankt"), true); } + var props = player.getWorld().getServer().getSaveProperties(); if (props instanceof MinecraftServer levelProperties && player.getWorld().getTime() % 100 == 0) { player.sendMessage(Text.literal( levelProperties.expose(SAVE_FLOAT).map(DefaultFloatComponent::get).unwrapOr(0f).toString() ), false); } + player.expose(UUID_THING).ifJust(uuidGenericComponent -> { Entity vehicle = player.getVehicle(); @@ -164,7 +167,7 @@ public void onInitialize(ModContainer mod) { Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); Components.inject(new ClassInjectionPredicate(WorldChunk.class), new ComponentEntry<>(CHUNK_INVENTORY, ChunkInventoryComponent::new)); -// Components.inject(MinecraftServer.class, SERVER_TICK); + // Components.inject(MinecraftServer.class, SERVER_TICK); Components.injectInheritage(ServerPlayerEntity.class, PLAYER_TICK); Components.inject(ServerPlayerEntity.class, UUID_THING); Components.injectInheritage(World.class, SAVE_FLOAT); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 86d1cea3b5..01cd0fb0f8 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -16,6 +16,8 @@ package org.quiltmc.qsl.component.test; +import java.util.Objects; + import net.minecraft.block.Blocks; import net.minecraft.entity.EntityType; import net.minecraft.entity.mob.HostileEntity; @@ -28,14 +30,11 @@ import net.minecraft.util.TypeFilter; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.explosion.Explosion; + import org.quiltmc.qsl.base.api.event.ListenerPhase; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.component.SyncedComponent; -import org.quiltmc.qsl.component.impl.component.DefaultInventoryComponent; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; -import java.util.Objects; - @ListenerPhase( callbackTarget = ServerWorldTickEvents.End.class, namespace = ComponentTestMod.MODID, path = "component_test_tick" @@ -47,13 +46,14 @@ public void endWorldTick(MinecraftServer server, ServerWorld world) { if (player == null) { return; } + Chunk chunk = world.getChunk(player.getBlockPos()); - cowTick(world); - creeperTick(world); - hostileTick(world); - currentChunkBETick(world, chunk); - currentChunkTick(player, chunk); + this.cowTick(world); + this.creeperTick(world); + this.hostileTick(world); + this.currentChunkBETick(world, chunk); + this.currentChunkTick(player, chunk); } private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { @@ -72,15 +72,13 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { if (ItemStack.canCombine(stack, playerStack)) { stack.increment(1); playerStack.decrement(1); -// stack.expose(ComponentTestMod.ITEMSTACK_INT).ifJust(defaultIntegerComponent -> { -// defaultIntegerComponent.increment(); -// defaultIntegerComponent.save(); -// }); + inventory.save(); inventory.sync(); } } } + player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); }); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index 92ed2d780c..61fdfc9ea3 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -16,6 +16,9 @@ package org.quiltmc.qsl.component.test; +import org.apache.commons.lang3.mutable.MutableObject; +import org.jetbrains.annotations.Nullable; + import net.minecraft.block.Block; import net.minecraft.block.BlockEntityProvider; import net.minecraft.block.BlockRenderType; @@ -30,8 +33,6 @@ import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import org.apache.commons.lang3.mutable.MutableObject; -import org.jetbrains.annotations.Nullable; public class TestBlock extends Block implements BlockEntityProvider { public TestBlock(Settings settings) { @@ -86,6 +87,7 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt return ret.getValue(); } + return super.onUse(state, world, pos, player, hand, hit); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 91c2d06050..72cfeb7be6 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -16,6 +16,13 @@ package org.quiltmc.qsl.component.test; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.jetbrains.annotations.Nullable; + import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntity; @@ -26,16 +33,11 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.container.ComponentContainer; -import org.quiltmc.qsl.component.api.component.InventoryComponent; -import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; import org.quiltmc.qsl.component.api.sync.SyncChannel; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; +import org.quiltmc.qsl.component.test.component.InventoryComponent; public class TestBlockEntity extends BlockEntity { private final ComponentContainer container = ComponentContainer.builder(this) @@ -44,7 +46,7 @@ public class TestBlockEntity extends BlockEntity { .add(ComponentTestMod.TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) .syncing(SyncChannel.BLOCK_ENTITY) .build(SimpleComponentContainer.FACTORY); - private final ComponentContainer composite = ComponentContainer.createComposite(container, super.getComponentContainer()); + private final ComponentContainer composite = ComponentContainer.createComposite(this.container, super.getComponentContainer()); public TestBlockEntity(BlockPos blockPos, BlockState blockState) { super(ComponentTestMod.TEST_BE_TYPE, blockPos, blockState); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java index 14bc5f72ce..2d4bb47ae8 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/ComponentTestModClient.java @@ -18,13 +18,12 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; + import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; @Environment(EnvType.CLIENT) public class ComponentTestModClient implements ClientModInitializer { @Override - public void onInitializeClient(ModContainer mod) { -// Components.inject(MinecraftClient.class, ComponentTestMod.SAVE_FLOAT); - } + public void onInitializeClient(ModContainer mod) { } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java index 68185a5823..149cee0795 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java @@ -16,6 +16,8 @@ package org.quiltmc.qsl.component.test.client; +import java.util.function.Predicate; + import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.VertexConsumerProvider; @@ -24,11 +26,10 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Vec3f; + import org.quiltmc.qsl.component.test.ComponentTestMod; import org.quiltmc.qsl.component.test.TestBlockEntity; -import java.util.function.Predicate; - public class TestBlockEntityRenderer implements BlockEntityRenderer { @Override public void render(TestBlockEntity entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java index c6d4a46e1c..ae6e700cf7 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java @@ -1,16 +1,17 @@ package org.quiltmc.qsl.component.test.component; +import java.util.List; + +import org.jetbrains.annotations.Nullable; + import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.collection.DefaultedList; -import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.component.InventoryComponent; import org.quiltmc.qsl.component.api.component.SyncedComponent; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; -import java.util.List; - public class ChunkInventoryComponent implements InventoryComponent, SyncedComponent { public static final NetworkCodec> NETWORK_CODEC = NetworkCodec.list(NetworkCodec.ITEM_STACK, value -> DefaultedList.ofSize(value, ItemStack.EMPTY)); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultFloatComponent.java similarity index 96% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultFloatComponent.java index 2c087d8a75..67b6b24978 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultFloatComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultFloatComponent.java @@ -14,18 +14,20 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.component; +package org.quiltmc.qsl.component.test.component; + +import org.jetbrains.annotations.Nullable; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtFloat; -import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.component.NbtComponent; public class DefaultFloatComponent implements NbtComponent { - private float value; @Nullable private final Runnable saveOperation; + private float value; public DefaultFloatComponent(Component.Operations ops) { this(ops, 0); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultIntegerComponent.java similarity index 97% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultIntegerComponent.java index 69bb7c5737..6a926a1df6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultIntegerComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultIntegerComponent.java @@ -14,18 +14,20 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.component; +package org.quiltmc.qsl.component.test.component; + +import org.jetbrains.annotations.Nullable; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtInt; -import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.component.NbtComponent; public class DefaultIntegerComponent implements NbtComponent { - private int value; @Nullable private final Runnable saveOperation; + private int value; public DefaultIntegerComponent(Component.Operations ops) { this(ops, 0); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultInventoryComponent.java similarity index 90% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultInventoryComponent.java index bc431f4df1..5c6de28183 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/component/DefaultInventoryComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultInventoryComponent.java @@ -14,16 +14,17 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.component; +package org.quiltmc.qsl.component.test.component; + +import java.util.Objects; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; import net.minecraft.item.ItemStack; import net.minecraft.util.collection.DefaultedList; -import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.component.InventoryComponent; -import java.util.Objects; -import java.util.function.Supplier; +import org.quiltmc.qsl.component.api.Component; public class DefaultInventoryComponent implements InventoryComponent { private final DefaultedList stacks; @@ -52,13 +53,13 @@ public DefaultedList getStacks() { @Override public int hashCode() { - return Objects.hash(stacks); + return Objects.hash(this.stacks); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof DefaultInventoryComponent that)) return false; - return stacks.equals(that.stacks); + return this.stacks.equals(that.stacks); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/InventoryComponent.java similarity index 95% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/InventoryComponent.java index c123924f4c..c2c6cf99ed 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/InventoryComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/InventoryComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.component; +package org.quiltmc.qsl.component.test.component; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.Inventories; @@ -24,6 +24,8 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.util.collection.DefaultedList; +import org.quiltmc.qsl.component.api.component.NbtComponent; + public interface InventoryComponent extends NbtComponent, Inventory { @Override default int size() { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java index ecf94d2108..580aa9880a 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java @@ -16,14 +16,15 @@ package org.quiltmc.qsl.component.test.component; +import org.jetbrains.annotations.Nullable; + import net.minecraft.network.PacketByteBuf; import net.minecraft.server.world.ServerWorld; -import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.component.SyncedComponent; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.component.TickingComponent; -import org.quiltmc.qsl.component.impl.component.DefaultFloatComponent; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; public class SaveFloatComponent extends DefaultFloatComponent implements TickingComponent, SyncedComponent { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java index 71dc8c7d26..84c1e94174 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinBlockEntityRendererFactories.java @@ -16,18 +16,20 @@ package org.quiltmc.qsl.component.test.mixin.client; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.client.render.block.entity.BlockEntityRendererFactories; import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; + import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.test.ComponentTestMod; import org.quiltmc.qsl.component.test.client.TestBlockEntityRenderer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(BlockEntityRendererFactories.class) public abstract class MixinBlockEntityRendererFactories { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index f2d230f8d6..9822bb1e9f 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -16,6 +16,13 @@ package org.quiltmc.qsl.component.test.mixin.client; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.hud.InGameHud; @@ -23,19 +30,13 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.util.math.ChunkPos; -import org.quiltmc.qsl.component.impl.component.DefaultIntegerComponent; + import org.quiltmc.qsl.component.test.ComponentTestMod; +import org.quiltmc.qsl.component.test.component.DefaultIntegerComponent; import org.quiltmc.qsl.component.test.component.SaveFloatComponent; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(InGameHud.class) public abstract class MixinInGameHud { - @Shadow @Final private ItemRenderer itemRenderer; @@ -43,20 +44,21 @@ public abstract class MixinInGameHud { @Shadow public abstract TextRenderer getTextRenderer(); + @SuppressWarnings("ConstantConditions") @Inject(method = "render", at = @At("TAIL")) private void renderCustom(MatrixStack matrices, float tickDelta, CallbackInfo ci) { MinecraftClient.getInstance().world - .expose(ComponentTestMod.SAVE_FLOAT) - .map(SaveFloatComponent::get) - .map(String::valueOf) - .ifJust(saveFloat -> this.getTextRenderer().draw(matrices, saveFloat, 10, 20, 0xfafafa)); + .expose(ComponentTestMod.SAVE_FLOAT) + .map(SaveFloatComponent::get) + .map(String::valueOf).ifJust(saveFloat -> this.getTextRenderer().draw(matrices, saveFloat, 10, 20, 0xfafafa)); Entity entity = MinecraftClient.getInstance().targetedEntity; if (entity != null) { entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME) - .map(DefaultIntegerComponent::get) - .ifJust(integer -> this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa)); + .map(DefaultIntegerComponent::get) + .ifJust(integer -> this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa)); } + ChunkPos chunkPos = MinecraftClient.getInstance().player.getChunkPos(); MinecraftClient.getInstance().world.getChunk(chunkPos.x, chunkPos.z).expose(ComponentTestMod.CHUNK_INVENTORY) .map(defaultInventoryComponent -> defaultInventoryComponent.getStack(0)) From 8f566e21aeec32008b95e0391e509d6930d26080 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Thu, 21 Jul 2022 17:46:48 +0300 Subject: [PATCH 61/70] Run applyLicenses --- .../org/quiltmc/qsl/base/api/util/Lazy.java | 243 +++++++++--------- .../org/quiltmc/qsl/base/api/util/Maybe.java | 7 +- .../qsl/component/impl/CommonInitializer.java | 45 ++-- .../impl/client/sync/ClientResolution.java | 16 ++ .../impl/event/ClientEventListener.java | 16 ++ .../impl/event/CommonEventListener.java | 16 ++ .../impl/event/ComponentEventPhases.java | 16 ++ .../sync/ClientPlayNetworkHandlerMixin.java | 16 ++ .../component/mixin/sync/WorldChunkMixin.java | 16 ++ .../component/ChunkInventoryComponent.java | 16 ++ 10 files changed, 260 insertions(+), 147 deletions(-) diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java index f5af338817..24235d2ec2 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java @@ -26,37 +26,38 @@ * * @param The type of the value this {@link Lazy} represents. */ -public sealed abstract class Lazy implements Supplier permits Lazy.Filled, Lazy.OfSupplier { +public abstract sealed class Lazy implements Supplier permits Lazy.Filled, Lazy.OfSupplier { /** * Wraps the provided {@link Supplier} into a {@link OfSupplier} instance. + * * @param supplier The {@link Supplier} to a value. + * @param The type of the wrapped value. * @return A new {@link OfSupplier} instance. - * @param The type of the wrapped value. */ - public static Lazy of(Supplier supplier) { - return new OfSupplier<>(supplier); - } + public static Lazy of(Supplier supplier) { + return new OfSupplier<>(supplier); + } /** * Returns an {@link Filled} instance wrapping the provided {@link T} value. * * @param value The value to wrap. + * @param The type of the wrapped value. * @return A new {@link Filled} instance. - * @param The type of the wrapped value. */ - public static Lazy filled(T value) { - return new Filled<>(value); - } + public static Lazy filled(T value) { + return new Filled<>(value); + } /** * Creates a new {@link Lazy} containing the current value mapped using the provided {@link Function}.
      * This does not initialize the contained value! * * @param mapper The function to apply to the contained value. + * @param The new contained type. * @return A new {@link Lazy} instance, that may or may not be initialized that contains the mapped value. - * @param The new contained type. */ - public abstract Lazy map(Function mapper); + public abstract Lazy map(Function mapper); /** * If we contain a value, we instantly return the transformed version, using the {@link Function} provided.
      @@ -64,28 +65,29 @@ public static Lazy filled(T value) { * This does not initialize the contained value! * * @param mapper The {@link Function} to use. + * @param The new contained type. * @return The mapped {@link Lazy} value. - * @param The new contained type. */ - public abstract Lazy flatMap(Function> mapper); + public abstract Lazy flatMap(Function> mapper); /** * Initializes the current {@link Lazy} and returns the result of applying the provided {@link Function} to the value.
      * This initializes the contained value. * * @param function The {@link Function} to use. + * @param The return type. * @return The {@link M} value produced from the application of the provided {@link Function}}. - * @param The return type. */ - public M mapUnwrap(Function function) { - return function.apply(this.unwrap()); - } + public M mapUnwrap(Function function) { + return function.apply(this.unwrap()); + } /** * Whether the current {@link Lazy} has initialized its value. + * * @return Whether the current {@link Lazy} contains an initialized value. */ - public abstract boolean isFilled(); + public abstract boolean isFilled(); /** * Applies the provided {@link Consumer} on the current value, if it is initialized. @@ -93,7 +95,7 @@ public M mapUnwrap(Function function) { * @param action The {@link Consumer} to apply the value to. * @return This instance(for chaining). */ - public abstract Lazy ifFilled(Consumer action); + public abstract Lazy ifFilled(Consumer action); /** * Runs the provided {@link Runnable}, if our value is not initialized.
      @@ -101,14 +103,14 @@ public M mapUnwrap(Function function) { * @param action The {@link Runnable} to run. * @return This instance(for chaining). */ - public abstract Lazy ifEmpty(Runnable action); + public abstract Lazy ifEmpty(Runnable action); /** * Whether the current instance has an initialized value. * * @return Whether there is a value in this {@link Lazy} that is initialized. */ - public abstract boolean isEmpty(); + public abstract boolean isEmpty(); /** * Initializes the current value and applies it to the provided {@link Consumer}.
      @@ -117,17 +119,17 @@ public M mapUnwrap(Function function) { * @param action The {@link Consumer} to accept the current value. * @return This instance(for chaining). */ - public Lazy compute(Consumer action) { - action.accept(this.get()); - return this; - } + public Lazy compute(Consumer action) { + action.accept(this.get()); + return this; + } /** * @see Lazy#get */ - public T unwrap() { - return this.get(); - } + public T unwrap() { + return this.get(); + } /** * Returns the contained value if it is initialized, otherwise the provided {@link T} instance. @@ -149,190 +151,191 @@ public T unwrap() { /** * A {@link Lazy} with an already initialized value.
      * + *

      * This class can either be created using the {@link Lazy#filled} method or by mapping a {@link Lazy} with an initialized value.
      * A {@link Lazy} cannot be converted by itself into a {@link Filled}. + * * @param The contained type. */ - public static final class Filled extends Lazy { - private final T value; + public static final class Filled extends Lazy { + private final T value; /** * @param value The contained value. */ - private Filled(T value) { - this.value = value; - } + private Filled(T value) { + this.value = value; + } /** * @see Lazy#get */ - @Override - public T get() { - return this.value; - } + @Override + public T get() { + return this.value; + } /** * @see Lazy#map */ - @Override - public Lazy map(Function mapper) { - return filled(mapper.apply(this.value)); - } + @Override + public Lazy map(Function mapper) { + return filled(mapper.apply(this.value)); + } /** * @see Lazy#flatMap */ - @Override - public Lazy flatMap(Function> mapper) { - return mapper.apply(this.get()); - } + @Override + public Lazy flatMap(Function> mapper) { + return mapper.apply(this.get()); + } /** * @see Lazy#isFilled */ - @Override - public boolean isFilled() { - return true; - } + @Override + public boolean isFilled() { + return true; + } /** * @see Lazy#ifFilled */ - @Override - public Lazy ifFilled(Consumer action) { - action.accept(this.get()); - return this; - } + @Override + public Lazy ifFilled(Consumer action) { + action.accept(this.get()); + return this; + } /** * @see Lazy#ifEmpty */ @Override - public Lazy ifEmpty(Runnable action) { - return this; - } + public Lazy ifEmpty(Runnable action) { + return this; + } /** * @see Lazy#isEmpty */ @Override - public boolean isEmpty() { - return false; - } - + public boolean isEmpty() { + return false; + } /** * @see Lazy#unwrapOr */ @Override - public T unwrapOr(T defaultValue) { - return this.value; - } + public T unwrapOr(T defaultValue) { + return this.value; + } /** * @see Lazy#unwrapOrGet */ - @Override - public T unwrapOrGet(Supplier defaultSupplier) { - return this.value; - } - } + @Override + public T unwrapOrGet(Supplier defaultSupplier) { + return this.value; + } + } /** * A {@link Lazy} with either an initialized value or not. + * * @param */ - public static final class OfSupplier extends Lazy { - private Supplier supplier; + public static final class OfSupplier extends Lazy { + private Supplier supplier; // There is no overhead to using a Maybe here since Maybe has statically evaluated returns for Nothing instances.. - private Maybe value; + private Maybe value; /** * @param supplier The {@link Supplier} used to initialize the value. */ - private OfSupplier(Supplier supplier) { - this.supplier = supplier; - this.value = Maybe.nothing(); - } + private OfSupplier(Supplier supplier) { + this.supplier = supplier; + this.value = Maybe.nothing(); + } /** * @see Lazy#get */ - @Override - public T get() { - if (this.value.isNothing()) { - this.value = Maybe.just(this.supplier.get()); - this.supplier = null; - } + @Override + public T get() { + if (this.value.isNothing()) { + this.value = Maybe.just(this.supplier.get()); + this.supplier = null; + } - return this.value.unwrap(); - } + return this.value.unwrap(); + } /** * @see Lazy#map */ - @Override - public Lazy map(Function mapper) { - return this.value.isJust() ? filled(mapper.apply(this.get())) : of(() -> mapper.apply(this.supplier.get())); - } + @Override + public Lazy map(Function mapper) { + return this.value.isJust() ? filled(mapper.apply(this.get())) : of(() -> mapper.apply(this.supplier.get())); + } /** * @see Lazy#flatMap */ - @Override - public Lazy flatMap(Function> mapper) { - return this.value.isJust() ? mapper.apply(this.get()) : of(() -> mapper.apply(this.get()).get()); - } + @Override + public Lazy flatMap(Function> mapper) { + return this.value.isJust() ? mapper.apply(this.get()) : of(() -> mapper.apply(this.get()).get()); + } /** * @see Lazy#isFilled */ - @Override - public boolean isFilled() { - return this.value.isJust(); - } + @Override + public boolean isFilled() { + return this.value.isJust(); + } /** * @see Lazy#ifFilled */ - @Override - public Lazy ifFilled(Consumer action) { - this.value.ifJust(action); - return this; - } + @Override + public Lazy ifFilled(Consumer action) { + this.value.ifJust(action); + return this; + } /** * @see Lazy#ifEmpty */ - @Override - public Lazy ifEmpty(Runnable action) { - this.value.ifNothing(action); - return this; - } - + @Override + public Lazy ifEmpty(Runnable action) { + this.value.ifNothing(action); + return this; + } /** * @see Lazy#isEmpty */ - @Override - public boolean isEmpty() { - return this.value.isNothing(); - } + @Override + public boolean isEmpty() { + return this.value.isNothing(); + } /** * @see Lazy#unwrapOr */ - @Override - public T unwrapOr(T defaultValue) { - return this.value.unwrapOr(defaultValue); - } + @Override + public T unwrapOr(T defaultValue) { + return this.value.unwrapOr(defaultValue); + } /** * @see Lazy#unwrapOrGet */ - @Override - public T unwrapOrGet(Supplier defaultSupplier) { - return this.value.unwrapOrGet(defaultSupplier); - } - } + @Override + public T unwrapOrGet(Supplier defaultSupplier) { + return this.value.unwrapOrGet(defaultSupplier); + } + } } diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java index db00ff6eca..09aedf724b 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java @@ -16,19 +16,20 @@ package org.quiltmc.qsl.base.api.util; -import org.jetbrains.annotations.Nullable; - import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; +import org.jetbrains.annotations.Nullable; + /** * Represents a monad that can either contain a value or no value.
      * Similar to the {@link Optional} class but with some performance improvements * and quality of life changes.
      * + *

      * Can either be {@link Just} or {@link Nothing}.
      * {@link Just} instances contain a value of type {@link T}.
      * {@link Nothing} instances all contain no data.
      @@ -36,7 +37,7 @@ * @param The type of the wrapped object * @author 0xJoeMama */ -public sealed abstract class Maybe permits Maybe.Just, Maybe.Nothing { +public abstract sealed class Maybe permits Maybe.Just, Maybe.Nothing { /** * Similar function to {@link Optional#ofNullable} function.
      * Wraps a {@link T} value into an {@link Maybe}. diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 5e6040dcad..7b69e2f15e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -18,6 +18,7 @@ import org.jetbrains.annotations.ApiStatus; +import net.minecraft.client.gui.screen.ingame.HandledScreens; import net.minecraft.util.Identifier; import org.quiltmc.loader.api.ModContainer; @@ -32,34 +33,30 @@ @ApiStatus.Internal public final class CommonInitializer implements ModInitializer { - public static final String MOD_ID = "quilt_component"; + public static final String MOD_ID = "quilt_component"; - public static Identifier id(String id) { - return new Identifier(MOD_ID, id); - } + public static Identifier id(String id) { + return new Identifier(MOD_ID, id); + } - @Override - public void onInitialize(ModContainer mod) { - ServerSyncHandler.getInstance().registerPackets(); + @Override + public void onInitialize(ModContainer mod) { + ServerSyncHandler.getInstance().registerPackets(); - ServerLoginConnectionEvents.QUERY_START.register( - ComponentEventPhases.SYNC_COMPONENT_REGISTRY, - CommonEventListener::onQueryStart - ); + ServerLoginConnectionEvents.QUERY_START.register( + ComponentEventPhases.SYNC_COMPONENT_REGISTRY, + CommonEventListener::onQueryStart); - ServerLifecycleEvents.STARTING.register( - ComponentEventPhases.FREEZE_COMPONENT_REGISTRIES, - CommonEventListener::onServerStart - ); + ServerLifecycleEvents.STARTING.register( + ComponentEventPhases.FREEZE_COMPONENT_REGISTRIES, + CommonEventListener::onServerStart); - ServerTickEvents.END.register( - ComponentEventPhases.TICK_LEVEL_CONTAINER, - CommonEventListener::onServerTick - ); + ServerTickEvents.END.register( + ComponentEventPhases.TICK_LEVEL_CONTAINER, + CommonEventListener::onServerTick); - ServerWorldTickEvents.END.register( - ComponentEventPhases.TICK_WORLD_CONTAINER, - CommonEventListener::onServerWorldTick - ); - } + ServerWorldTickEvents.END.register( + ComponentEventPhases.TICK_WORLD_CONTAINER, + CommonEventListener::onServerWorldTick); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java index f92dd40b2d..1743109de8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientResolution.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.client.sync; import net.fabricmc.api.EnvType; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java index f962baab03..b32d95893f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ClientEventListener.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.event; import net.fabricmc.api.EnvType; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java index 278d9714fc..823b926f40 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/CommonEventListener.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.event; import net.minecraft.server.MinecraftServer; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java index 3ff843cf26..84f371a2a2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/event/ComponentEventPhases.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.event; import net.minecraft.util.Identifier; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java index 0547113e11..4393a51200 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/ClientPlayNetworkHandlerMixin.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin.sync; import org.spongepowered.asm.mixin.Mixin; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java index b5aa065418..c10135135f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.mixin.sync; import org.spongepowered.asm.mixin.Mixin; diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java index ae6e700cf7..0f48225cd4 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.test.component; import java.util.List; From 41af9653b8cd163d8cfd2fcc812ec0ceb19be60c Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sun, 24 Jul 2022 17:30:04 +0300 Subject: [PATCH 62/70] Removed the Component interface. --- .../org/quiltmc/qsl/base/api/util/Maybe.java | 42 +++++-- library/data/component/build.gradle | 17 +-- .../quiltmc/qsl/component/api/Component.java | 73 ----------- .../api/ComponentCreationContext.java | 40 ++++++ .../qsl/component/api/ComponentFactory.java | 16 +++ .../qsl/component/api/ComponentType.java | 58 +++++---- .../quiltmc/qsl/component/api/Components.java | 85 +++++++------ .../component/api/component/NbtComponent.java | 81 ------------ .../api/component/NbtSerializable.java | 62 +++++++++ .../{SyncedComponent.java => Syncable.java} | 7 +- .../{TickingComponent.java => Tickable.java} | 3 +- .../api/component/field/GenericField.java | 7 ++ .../GenericSerializableField.java} | 28 +++-- .../SyncedGenericSerializableField.java} | 21 +++- .../api/container/ComponentContainer.java | 118 ++++++++++-------- .../qsl/component/api/package-info.java | 2 +- .../api/provider/ComponentProvider.java | 7 +- .../qsl/component/api/sync/SyncChannel.java | 16 ++- .../qsl/component/impl/CommonInitializer.java | 61 ++++----- .../qsl/component/impl/ComponentsImpl.java | 19 ++- .../container/AbstractComponentContainer.java | 62 +++++---- .../CompositeComponentContainer.java | 5 +- .../container/EmptyComponentContainer.java | 10 +- .../container/LazyComponentContainer.java | 42 ++++--- .../container/OnAccessComponentContainer.java | 59 ++++----- .../container/SimpleComponentContainer.java | 30 +++-- .../container/SingleComponentContainer.java | 54 ++++---- .../impl/injection/ComponentEntry.java | 8 +- .../injection/manager/InjectionManager.java | 14 +-- .../DirectBlockEntityTickInvokerMixin.java | 9 +- .../component/mixin/entity/EntityMixin.java | 19 ++- .../qsl/component/test/ComponentTestMod.java | 110 ++++++++-------- .../component/test/ServerTickListener.java | 9 +- .../qsl/component/test/TestBlockEntity.java | 4 +- ...t.java => ChunkInventorySerializable.java} | 10 +- ...ent.java => DefaultFloatSerializable.java} | 10 +- ...t.java => DefaultIntegerSerializable.java} | 44 +++++-- ...java => DefaultInventorySerializable.java} | 10 +- ...ponent.java => InventorySerializable.java} | 4 +- ...ponent.java => SaveFloatSerializable.java} | 10 +- .../test/mixin/client/MixinInGameHud.java | 50 +++++--- .../src/testmod/resources/quilt.mod.json | 3 +- .../quilt_component_test.accesswidener} | 1 - 43 files changed, 704 insertions(+), 636 deletions(-) delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java delete mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtSerializable.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/{SyncedComponent.java => Syncable.java} (90%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/{TickingComponent.java => Tickable.java} (88%) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericField.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/{GenericComponent.java => field/GenericSerializableField.java} (68%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/{SyncedGenericComponent.java => field/SyncedGenericSerializableField.java} (61%) rename library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/{ChunkInventoryComponent.java => ChunkInventorySerializable.java} (85%) rename library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/{DefaultFloatComponent.java => DefaultFloatSerializable.java} (79%) rename library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/{DefaultIntegerComponent.java => DefaultIntegerSerializable.java} (58%) rename library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/{DefaultInventoryComponent.java => DefaultInventorySerializable.java} (78%) rename library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/{InventoryComponent.java => InventorySerializable.java} (93%) rename library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/{SaveFloatComponent.java => SaveFloatSerializable.java} (81%) rename library/data/component/src/{main/resources/quilt_component.accesswidener => testmod/resources/quilt_component_test.accesswidener} (74%) diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java index 09aedf724b..04a4b61d32 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java @@ -16,14 +16,14 @@ package org.quiltmc.qsl.base.api.util; +import org.jetbrains.annotations.Nullable; + import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; -import org.jetbrains.annotations.Nullable; - /** * Represents a monad that can either contain a value or no value.
      * Similar to the {@link Optional} class but with some performance improvements @@ -72,9 +72,8 @@ public static Maybe just(T value) { * @return A {@link Nothing} instance after casting it to the proper type. * @see Optional#empty() */ - @SuppressWarnings("unchecked") // Nothing doesn't contain a value, so we can freely cast it! public static Maybe nothing() { - return (Maybe) Nothing.INSTANCE; + return Nothing.INSTANCE.castUnchecked(); } /** @@ -113,11 +112,13 @@ public static Maybe fromOptional(Optional opt) { public abstract Maybe filter(Predicate predicate); /** - * Filters the current instance based on whether mapping it with the provided {@link Function} provides {@link Nothing} or {@link Just}. + * Filters the current instance based on whether mapping it with the provided {@link Function} provides + * {@link Nothing} or {@link Just}. * Can be used as {@link Optional#flatMap} or as the bind operation of this monad. * The table below explains in detail. * - * @param transform A {@link Function} returning a {@link Maybe} instance instead of directly returning the mapping value. + * @param transform A {@link Function} returning a {@link Maybe} instance instead of directly returning the + * mapping value. * @param The value the returned {@link Maybe} will contain. * @return * @@ -179,7 +180,8 @@ public static Maybe fromOptional(Optional opt) { public abstract Maybe ifNothing(Runnable runnable); /** - * Performs an operation similar to the boolean or operation on the current instance, using the one provided. + * Performs an operation similar to the boolean or operation on the current instance, using the one + * provided. * The table below describes the different return values. * * @param supplier A {@link Supplier} of a {@link Maybe}, be it {@link Just} or {@link Nothing}. @@ -210,7 +212,8 @@ public static Maybe fromOptional(Optional opt) { public abstract Maybe or(Supplier> supplier); /** - * Performs an operation similar to the boolean and operation on the current instance using the one provided. + * Performs an operation similar to the boolean and operation on the current instance using the one + * provided. * The table below describes the different return values. * * @param other A {@link Supplier} of a {@link Maybe} instance, be it {@link Nothing} or {@link Just}. @@ -253,15 +256,18 @@ public static Maybe fromOptional(Optional opt) { * In that case it returns the provided {@link T} value. * * @param defaultValue The value to get if the current instance if {@link Nothing}. - * @return The current {@link T} value if the current instance is {@link Just}, otherwise the provided {@link T} value. + * @return The current {@link T} value if the current instance is {@link Just}, otherwise the provided {@link T} + * value. * @see Optional#orElse */ public abstract T unwrapOr(T defaultValue); /** - * Works like {@link Maybe#unwrapOr} except that it lazily evaluates the return value using the provided {@link Supplier}. + * Works like {@link Maybe#unwrapOr} except that it lazily evaluates the return value using the provided + * {@link Supplier}. * - * @param supplier A {@link Supplier} that will create the {@link T} value to be returns if the current instance is {@link Nothing}. + * @param supplier A {@link Supplier} that will create the {@link T} value to be returns if the current instance + * is {@link Nothing}. * @return The current {@link T} value if the current instance if {@link Just}, * otherwise the value produces by calling {@link Supplier#get()} on the provided {@link Supplier}. * @see Optional#orElseGet @@ -285,6 +291,17 @@ public static Maybe fromOptional(Optional opt) { */ public abstract Optional toOptional(); + /** + * Attempts to perform and unchecked, unsafe cast on the current instance. + * + * @param The target type + * @return The cast instance. + */ + @SuppressWarnings("unchecked") + public Maybe castUnchecked() { + return (Maybe) this; + } + /** * The {@link Maybe} state representing the absence of a value. * @@ -292,7 +309,8 @@ public static Maybe fromOptional(Optional opt) { */ public static final class Nothing extends Maybe { /** - * A singleton instance is used for Nothing since it doesn't contain data and can therefore be cast to any Maybe type. + * A singleton instance is used for Nothing since it doesn't contain data and can therefore be cast to any + * Maybe type. */ private static final Nothing INSTANCE = new Nothing<>(); diff --git a/library/data/component/build.gradle b/library/data/component/build.gradle index cccc46cf07..4d8172c8cf 100644 --- a/library/data/component/build.gradle +++ b/library/data/component/build.gradle @@ -22,13 +22,6 @@ qslModule { } entrypoints { -// events { -// values = [ -// "org.quiltmc.qsl.component.impl.event.ServerTickEventListener", -// "org.quiltmc.qsl.component.impl.event.ServerWorldTickEventListener" -// ] -// } - init { values = ["org.quiltmc.qsl.component.impl.CommonInitializer"] } @@ -38,7 +31,7 @@ qslModule { } } - accessWidener() + // accessWidener() injectedInterface("net/minecraft/class_2586") { // BlockEntity values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] @@ -52,10 +45,6 @@ qslModule { values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } -// injectedInterface("net/minecraft/class_1799") { // ItemStack -// values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] -// } - injectedInterface("net/minecraft/class_310") { // MinecraftClient values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } @@ -68,3 +57,7 @@ qslModule { values = ["org/quiltmc/qsl/component/api/provider/ComponentProvider"] } } + +loom { + accessWidenerPath = file("src/testmod/resources/quilt_component_test.accesswidener") +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java deleted file mode 100644 index ca6b6310ec..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Component.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.api; - -import org.jetbrains.annotations.Nullable; - -/** - * Marks a type as a container for data and/or behaviour. - * - * @author 0xJoeMama - */ -public interface Component { - /** - * Class meant to provide a component using the provided {@link Operations} argument. - * - * @param The type of the returned {@link Component}. - * @author 0xJoeMama - */ - @FunctionalInterface - interface Factory { - /** - * @param operations The {@link Operations} that the {@link Component} may use. - * @return A {@link T} instance. - */ - T create(Component.Operations operations); - } - - /** - * A list of method a {@link Component} may call when needed to interact with outside factors.
      - * The outside factors statement refers to things like the {@link org.quiltmc.qsl.component.api.container.ComponentContainer} - * or the {@link org.quiltmc.qsl.component.api.provider.ComponentProvider} this {@link Component} belongs to. - * - * @author 0xJoeMama - */ - @SuppressWarnings("ClassCanBeRecord") // we want the class to be extendable to people can create their own Operations - class Operations { - private final @Nullable Runnable saveOperation; - private final @Nullable Runnable syncOperation; - - /** - * Both of these parameters may be null, depending on the container this {@link Component} belongs to. - * - * @param saveOperation The action performed to cause an {@link org.quiltmc.qsl.component.api.component.NbtComponent} to issue a save to its {@linkplain org.quiltmc.qsl.component.api.provider.ComponentProvider provider}. - * @param syncOperation The action performed to cause a {@link org.quiltmc.qsl.component.api.component.SyncedComponent} to issue a sync to its {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer container}. - */ - public Operations(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation) { - this.saveOperation = saveOperation; - this.syncOperation = syncOperation; - } - - public @Nullable Runnable saveOperation() { - return this.saveOperation; - } - - public @Nullable Runnable syncOperation() { - return this.syncOperation; - } - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java new file mode 100644 index 0000000000..0d68faeb25 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java @@ -0,0 +1,40 @@ +package org.quiltmc.qsl.component.api; + +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.component.NbtSerializable; +import org.quiltmc.qsl.component.api.component.Syncable; + +/** + * A list of methods a component may call when needed to interact with outside factors.
      + * The outside factors statement refers to things like the + * {@link org.quiltmc.qsl.component.api.container.ComponentContainer} + * or the {@link org.quiltmc.qsl.component.api.provider.ComponentProvider} this component belongs to. + * + * @author 0xJoeMama + */ +@SuppressWarnings("ClassCanBeRecord")// we want the class to be extendable to people can create their own Contexes +public class ComponentCreationContext { + private final @Nullable Runnable saveOperation; + private final @Nullable Runnable syncOperation; + + /** + * Both of these parameters may be null, depending on the container this component belongs to. + * + * @param saveOperation The action performed to cause an {@link NbtSerializable} to issue a save to its + * {@linkplain org.quiltmc.qsl.component.api.provider.ComponentProvider provider}. + * @param syncOperation The action performed to cause a {@link Syncable} to issue a sync to its + * {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer container}. + */ + public ComponentCreationContext(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation) { + this.saveOperation = saveOperation; + this.syncOperation = syncOperation; + } + + public @Nullable Runnable saveOperation() { + return this.saveOperation; + } + + public @Nullable Runnable syncOperation() { + return this.syncOperation; + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java new file mode 100644 index 0000000000..702ca3e751 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java @@ -0,0 +1,16 @@ +package org.quiltmc.qsl.component.api; + +/** + * Class meant to provide a component using the provided {@link ComponentCreationContext} argument. + * + * @param The type of the returned component. + * @author 0xJoeMama + */ +@FunctionalInterface +public interface ComponentFactory { + /** + * @param operations The {@link ComponentCreationContext} that the {@link Component} may use. + * @return A {@link T} instance. + */ + T create(ComponentCreationContext operations); +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index d16217c621..3548e96dd6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -16,35 +16,45 @@ package org.quiltmc.qsl.component.api; -import java.util.IdentityHashMap; -import java.util.Map; - import net.minecraft.util.Identifier; - import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; +import java.util.IdentityHashMap; +import java.util.Map; + /** * A global identifier for a specific type of {@linkplain Component components}.
      - * This class must always exist as singleton instances, which have to be registered under the {@linkplain Components#REGISTRY registry}. + * This class must always exist as singleton instances, which have to be registered under the + * {@linkplain Components#REGISTRY registry}. * - * @param id The {@link Identifier} the type is registered with(it's here just for accesibility, however you may also get access to it using the {@linkplain Components#REGISTRY registry} and a {@link ComponentType} instance). + * @param id The {@link Identifier} the type is registered with(it's here just for accesibility, however + * you may also get access to it using the {@linkplain Components#REGISTRY registry} and a + * {@link ComponentType} instance). * @param defaultFactory A factory to a default {@link Component} instance, that this type may produce, - * if no specific factory is defined under the container {@link org.quiltmc.qsl.component.impl.injection.ComponentEntry}.
      - * Used only during component injections or creation of {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer containers}. + * if no specific factory is defined under the container + * {@link org.quiltmc.qsl.component.impl.injection.ComponentEntry}.
      + * Used only during component injections or creation of + * {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer containers}. * @param isStatic Whether this {@linkplain ComponentType type} works as a static type. - * @param isInstant Whether this {@linkplain ComponentType type} will be instantly initialized when put in a container. Useful for {@link org.quiltmc.qsl.component.api.component.TickingComponent}s or componens you want to initialize on {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer container} creation. - * @param The generic type of {@link Component} this type will provide. Most of the time, you would want this to be an interface providing all the needed API you may use to interact with a {@link Component} of this {@linkplain ComponentType type}. + * @param isInstant Whether this {@linkplain ComponentType type} will be instantly initialized when put in a + * container. Useful for {@link Tickable}s or componens you want to initialize on + * {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer container} creation. + * @param The generic type of {@link Component} this type will provide. Most of the time, you would + * want this to be an interface providing all the needed API you may use to interact with a + * {@link Component} of this {@linkplain ComponentType type}. * @author 0xJoeMama */ -public record ComponentType(Identifier id, Component.Factory defaultFactory, - boolean isStatic, boolean isInstant) implements Component.Factory { +public record ComponentType(Identifier id, ComponentFactory defaultFactory, + boolean isStatic, boolean isInstant) implements ComponentFactory { /** * We provide a {@link NetworkCodec} to be used with manual registry sync, until the registry sync API is merged. */ public static final NetworkCodec> NETWORK_CODEC = - NetworkCodec.VAR_INT.map(Components.REGISTRY::getRawId, rawId -> ClientSyncHandler.getInstance().getType(rawId)); + NetworkCodec.VAR_INT.map( + Components.REGISTRY::getRawId, rawId -> ClientSyncHandler.getInstance().getType(rawId)); /** * @see Static */ @@ -55,11 +65,13 @@ public record ComponentType(Identifier id, Component.Factor * Used to attempt to translate any {@linkplain Component normal component} into a specific type. * * @param component The {@link Component} the cast is to be performed on. - * @return Instead of letting the {@link ClassCastException} be thrown on invalid casts, we catch it and return {@link Maybe#nothing()} if the component cannot be cast. + * @return Instead of letting the {@link ClassCastException} be thrown on invalid casts, we catch it and return + * {@link Maybe#nothing()} if the component cannot be cast. * Otherwise, we just wrap the cast result into a {@link Maybe}. */ @SuppressWarnings("unchecked") - public Maybe cast(Component component) { + public Maybe cast(Object component) { + // TODO: SUS try { return Maybe.just((T) component); } catch (ClassCastException ignored) { @@ -68,13 +80,14 @@ public Maybe cast(Component component) { } /** - * A {@linkplain ComponentType type} functions as its own {@link Component.Factory} using the provided {@link ComponentType#defaultFactory}. + * A {@linkplain ComponentType type} functions as its own {@link ComponentFactory} using the provided + * {@link ComponentType#defaultFactory}. * - * @param operations The {@link Component.Operations} that the {@link Component} may use. + * @param operations The {@link ComponentCreationContext} that the {@link Component} may use. * @return A {@link Component} of type {@link T}. */ @Override - public T create(Component.Operations operations) { + public T create(ComponentCreationContext operations) { if (this.isStatic) { // First check for static components return STATIC_CACHE.getOrCreate(this, operations); } @@ -93,15 +106,16 @@ public T create(Component.Operations operations) { */ public static class Static { /** - * We store singleton instances in an {@link IdentityHashMap} as is common practice when using {@link ComponentType}s as keys. + * We store singleton instances in an {@link IdentityHashMap} as is common practice when using + * {@link ComponentType}s as keys. */ - private final Map, Component> staticInstances = new IdentityHashMap<>(); + private final Map, Object> staticInstances = new IdentityHashMap<>(); private Static() { } /** * Performs simple lazy initialization on the provided {@link ComponentType static type} - * using the provided {@link org.quiltmc.qsl.component.api.Component.Operations} as initialization arguments. + * using the provided {@link ComponentCreationContext} as initialization arguments. * * @param type The type of the component to be created. * @param operations The operations to use as initialization arguments. @@ -109,7 +123,7 @@ private Static() { } * @return A singleton {@link C} instance. */ @SuppressWarnings("unchecked") - public C getOrCreate(ComponentType type, Component.Operations operations) { + public C getOrCreate(ComponentType type, ComponentCreationContext operations) { if (this.staticInstances.containsKey(type)) { return (C) this.staticInstances.get(type); } else { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 9d448a2999..5dc701f924 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -16,17 +16,12 @@ package org.quiltmc.qsl.component.api; -import java.util.Set; -import java.util.function.Predicate; - -import org.jetbrains.annotations.ApiStatus; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; - +import org.jetbrains.annotations.ApiStatus; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.component.TickingComponent; +import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.ComponentsImpl; @@ -38,6 +33,9 @@ import org.quiltmc.qsl.component.impl.injection.predicate.dynamic.DynamicClassInjectionPredicate; import org.quiltmc.qsl.component.impl.util.ErrorUtil; +import java.util.Set; +import java.util.function.Predicate; + /** * The external version of the component API, meant to be used by modders.
      * Use this and not {@link ComponentsImpl}.
      @@ -69,7 +67,7 @@ public final class Components { * @see InjectionPredicate * @see ComponentEntry */ - public static void inject(InjectionPredicate predicate, ComponentEntry entry) { + public static void inject(InjectionPredicate predicate, ComponentEntry entry) { ComponentsImpl.inject(predicate, entry); } @@ -78,57 +76,66 @@ public static void inject(InjectionPredicate predicate, Co * Injects the provided {@link ComponentType} into all direct instances of the provided {@link Class}. * * @param clazz The target class(must implement {@link ComponentProvider}). - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is + * used). * @param The type held by the injected type. * @see ClassInjectionPredicate */ - public static void inject(Class clazz, ComponentType type) { + public static void inject(Class clazz, ComponentType type) { ComponentsImpl.inject(new ClassInjectionPredicate(clazz), new ComponentEntry<>(type)); } /** - * Similar to {@link Components#inject(Class, ComponentType)} except it injects into all subclasses and indirect instances of the provided class. + * Similar to {@link Components#inject(Class, ComponentType)} except it injects into all subclasses and indirect + * instances of the provided class. * * @param clazz The highest class in the hierarchy that will be injected. - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is + * used). * @param The type held by the injected type. * @see InheritedInjectionPredicate */ - public static void injectInheritage(Class clazz, ComponentType type) { + public static void injectInheritage(Class clazz, ComponentType type) { ComponentsImpl.inject(new InheritedInjectionPredicate(clazz), new ComponentEntry<>(type)); } /** - * Similar to {@link Components#injectInheritage(Class, ComponentType)}, except it skips the provided classes in the hierarchy. + * Similar to {@link Components#injectInheritage(Class, ComponentType)}, except it skips the provided classes in + * the hierarchy. * * @param clazz The highest class in the hierarchy that will be injected. - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the + * type} is used). * @param exceptions The classes to avoid injecting into. * @param The type help by the provided type. * @see FilteredInheritedInjectionPredicate */ - public static void injectInheritanceExcept(Class clazz, ComponentType type, Class... exceptions) { + public static void injectInheritanceExcept(Class clazz, ComponentType type, Class... exceptions) { ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), new ComponentEntry<>(type)); } /** - * TODO: This is supposed to be merged with {@link Components#inject(Class, ComponentType)} and a mapping to redirections is to be created. + * TODO: This is supposed to be merged with {@link Components#inject(Class, ComponentType)} and a mapping to + * redirections is to be created. */ - public static void injectRedirected(Class mainClass, ComponentType type, Class... others) { + public static void injectRedirected(Class mainClass, ComponentType type, Class... others) { ComponentsImpl.inject(new RedirectedInjectionPredicate(mainClass, Set.of(others)), new ComponentEntry<>(type)); } /** * Dynamically injects into the provided {@link Class} using the provided predicate.
      - * For more info on dynamic injection check {@link org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate}; + * For more info on dynamic injection check + * {@link org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate}; * * @param clazz The target class(must implement {@link ComponentProvider}). - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is used). + * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} + * is used). * @param predicate The predicate used to determine if injection is possible. * @param The type of component that will be injected. * @param

      The type of the provider that the dynamic injection targets. */ - public static void injectDynamic(Class

      clazz, ComponentType type, Predicate

      predicate) { + public static void injectDynamic(Class

      clazz, ComponentType type, + Predicate

      predicate) { ComponentsImpl.inject(new DynamicClassInjectionPredicate<>(clazz, predicate), new ComponentEntry<>(type)); } @@ -139,21 +146,24 @@ public static void injectDyna /** * The proper way to expose component instances.
      * This does type-checking and also makes sure a {@link ComponentProvider} is given.
      - * This should be used where interface injection cannot apply(in other words custom implementations of {@link ComponentProvider}).
      + * This should be used where interface injection cannot apply(in other words custom implementations of + * {@link ComponentProvider}).
      * * @param id The {@link ComponentType} to expose. - * @param obj Any object will work. If it does not implement {@link ComponentProvider} an empty will be instantly returned. + * @param obj Any object will work. If it does not implement {@link ComponentProvider} an empty will be instantly + * returned. * @param The type of component held by the {@link ComponentType}. * @param The object to attempt to expose the component on. - * @return Either {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the result of expose called on the provider's container - * or {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided object is not a {@link ComponentProvider}. + * @return Either {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the result of expose called on the provider's + * container + * or {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided object is not a + * {@link ComponentProvider}. * @see ComponentProvider#expose * @see org.quiltmc.qsl.component.api.container.ComponentContainer#expose */ - public static Maybe expose(ComponentType id, S obj) { + public static Maybe expose(ComponentType id, S obj) { if (obj instanceof ComponentProvider provider) { - return provider.getComponentContainer().expose(id) - .filterMap(id::cast); // mapping with cast will make sure we get the correct type back. + return provider.getComponentContainer().expose(id); } return Maybe.nothing(); @@ -167,21 +177,22 @@ public static Maybe expose(ComponentType id, S ob * @param The type of component held by the type. * @return The registered version of the component type. */ - public static ComponentType register(Identifier id, ComponentType type) { + public static ComponentType register(Identifier id, ComponentType type) { return ComponentsImpl.register(id, type); } /** - * Register a normal {@link ComponentType} using the provided {@linkplain Component.Factory default factory}. + * Register a normal {@link ComponentType} using the provided {@linkplain ComponentFactory default factory}. * * @param id The id to register the type with. - * @param factory The default {@link Component.Factory} of the type. + * @param factory The default {@link ComponentFactory} of the type. * @param The type of component held by the type. * @return A new {@link ComponentType} of {@link C} components. */ - public static ComponentType register(Identifier id, Component.Factory factory) { + public static ComponentType register(Identifier id, ComponentFactory factory) { if (factory instanceof ComponentType) { - throw ErrorUtil.illegalArgument("Do NOT register ComponentTypes as factories, use the correct method").get(); + throw ErrorUtil.illegalArgument("Do NOT register ComponentTypes as factories, use the correct method") + .get(); } return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, false)); @@ -191,11 +202,11 @@ public static ComponentType register(Identifier id, Com * Register a {@linkplain ComponentType.Static static} {@linkplain ComponentType type} using the provided factory. * * @param id THe id to register the type with. - * @param factory The default {@link Component.Factory} of the type. + * @param factory The default {@link ComponentFactory} of the type. * @param The type of component held by the type. * @return A new static {@link ComponentType}. */ - public static ComponentType registerStatic(Identifier id, Component.Factory factory) { + public static ComponentType registerStatic(Identifier id, ComponentFactory factory) { return ComponentsImpl.register(id, new ComponentType<>(id, factory, true, false)); } @@ -204,11 +215,11 @@ public static ComponentType registerStatic(Identifier i * For more info check the {@linkplain ComponentType relevant docs}. * * @param id The id to register the type with. - * @param factory The default {@link Component.Factory} of the type. + * @param factory The default {@link ComponentFactory} of the type. * @param The type of component held by the type. * @return A new instant {@link ComponentType}. */ - public static ComponentType registerInstant(Identifier id, Component.Factory factory) { + public static ComponentType registerInstant(Identifier id, ComponentFactory factory) { return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, true)); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java deleted file mode 100644 index d405f62807..0000000000 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtComponent.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.component.api.component; - -import org.jetbrains.annotations.Nullable; - -import net.minecraft.nbt.NbtByte; -import net.minecraft.nbt.NbtByteArray; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtDouble; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtFloat; -import net.minecraft.nbt.NbtInt; -import net.minecraft.nbt.NbtIntArray; -import net.minecraft.nbt.NbtList; -import net.minecraft.nbt.NbtLong; -import net.minecraft.nbt.NbtLongArray; -import net.minecraft.nbt.NbtShort; -import net.minecraft.nbt.NbtString; -import net.minecraft.util.Identifier; - -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.impl.util.ErrorUtil; - -public interface NbtComponent extends Component { - @SuppressWarnings("unchecked") - static void readFrom(NbtComponent nbtComponent, Identifier id, NbtCompound root) { - NbtElement nbtTarget = root.get(id.toString()); - switch (nbtComponent.nbtType()) { - case NbtElement.BYTE_TYPE -> ((NbtComponent) nbtComponent).read((NbtByte) nbtTarget); - case NbtElement.SHORT_TYPE -> ((NbtComponent) nbtComponent).read((NbtShort) nbtTarget); - case NbtElement.INT_TYPE -> ((NbtComponent) nbtComponent).read((NbtInt) nbtTarget); - case NbtElement.LONG_TYPE -> ((NbtComponent) nbtComponent).read((NbtLong) nbtTarget); - case NbtElement.FLOAT_TYPE -> ((NbtComponent) nbtComponent).read((NbtFloat) nbtTarget); - case NbtElement.DOUBLE_TYPE -> ((NbtComponent) nbtComponent).read((NbtDouble) nbtTarget); - case NbtElement.BYTE_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtByteArray) nbtTarget); - case NbtElement.STRING_TYPE -> ((NbtComponent) nbtComponent).read((NbtString) nbtTarget); - case NbtElement.LIST_TYPE -> ((NbtComponent) nbtComponent).read((NbtList) nbtTarget); - case NbtElement.COMPOUND_TYPE -> ((NbtComponent) nbtComponent).read((NbtCompound) nbtTarget); - case NbtElement.INT_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtIntArray) nbtTarget); - case NbtElement.LONG_ARRAY_TYPE -> ((NbtComponent) nbtComponent).read((NbtLongArray) nbtTarget); - default -> // We throw if we ever find a non-vanilla type trying to be used for component serialization! - throw ErrorUtil.runtime( - "The nbt data type with id %D is not vanilla!", - nbtComponent.nbtType() - ).get(); - } - } - - static void writeTo(NbtCompound root, NbtComponent nbtComponent, Identifier id) { - root.put(id.toString(), nbtComponent.write()); - } - - byte nbtType(); - - void read(T nbt); - - T write(); - - default void save() { - if (this.getSaveOperation() != null) { - this.getSaveOperation().run(); - } - } - - @Nullable Runnable getSaveOperation(); -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtSerializable.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtSerializable.java new file mode 100644 index 0000000000..75e1aee212 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtSerializable.java @@ -0,0 +1,62 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.quiltmc.qsl.component.api.component; + +import net.minecraft.nbt.*; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; + +public interface NbtSerializable { + @SuppressWarnings("unchecked") + static void readFrom(NbtSerializable nbtSerializable, Identifier id, NbtCompound root) { + NbtElement nbtTarget = root.get(id.toString()); + switch (nbtSerializable.nbtType()) { + case NbtElement.BYTE_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtByte) nbtTarget); + case NbtElement.SHORT_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtShort) nbtTarget); + case NbtElement.INT_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtInt) nbtTarget); + case NbtElement.LONG_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtLong) nbtTarget); + case NbtElement.FLOAT_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtFloat) nbtTarget); + case NbtElement.DOUBLE_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtDouble) nbtTarget); + case NbtElement.BYTE_ARRAY_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtByteArray) nbtTarget); + case NbtElement.STRING_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtString) nbtTarget); + case NbtElement.LIST_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtList) nbtTarget); + case NbtElement.COMPOUND_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtCompound) nbtTarget); + case NbtElement.INT_ARRAY_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtIntArray) nbtTarget); + case NbtElement.LONG_ARRAY_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtLongArray) nbtTarget); + default -> throw ErrorUtil.runtime("The nbt data type with id %D is not vanilla!", nbtSerializable.nbtType()).get(); + } + } + + static void writeTo(NbtCompound root, NbtSerializable nbtSerializable, Identifier id) { + root.put(id.toString(), nbtSerializable.write()); + } + + byte nbtType(); + + void read(T nbt); + + T write(); + + default void save() { + if (this.getSaveOperation() != null) { + this.getSaveOperation().run(); + } + } + + @Nullable Runnable getSaveOperation(); +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/Syncable.java similarity index 90% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/Syncable.java index 33f754dc55..7a98f19e93 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/Syncable.java @@ -16,13 +16,10 @@ package org.quiltmc.qsl.component.api.component; -import org.jetbrains.annotations.Nullable; - import net.minecraft.network.PacketByteBuf; +import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.component.api.Component; - -public interface SyncedComponent extends Component { +public interface Syncable { void writeToBuf(PacketByteBuf buf); void readFromBuf(PacketByteBuf buf); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/TickingComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/Tickable.java similarity index 88% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/TickingComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/Tickable.java index 977c5f1f10..ad211a1eb6 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/TickingComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/Tickable.java @@ -16,9 +16,8 @@ package org.quiltmc.qsl.component.api.component; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -public interface TickingComponent extends Component { +public interface Tickable { void tick(ComponentProvider provider); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericField.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericField.java new file mode 100644 index 0000000000..1d92c97fcf --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericField.java @@ -0,0 +1,7 @@ +package org.quiltmc.qsl.component.api.component.field; + +public interface GenericField { + T getValue(); + + void setValue(T value); +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericSerializableField.java similarity index 68% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericSerializableField.java index 7b4829dee3..2f4a2726ac 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/GenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericSerializableField.java @@ -14,33 +14,39 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.component; +package org.quiltmc.qsl.component.api.component.field; import com.mojang.serialization.Codec; -import org.jetbrains.annotations.Nullable; - import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtOps; - -import org.quiltmc.qsl.component.api.Component; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.ComponentCreationContext; +import org.quiltmc.qsl.component.api.component.NbtSerializable; import org.quiltmc.qsl.component.impl.ComponentsImpl; -public class GenericComponent implements NbtComponent { +public class GenericSerializableField implements GenericField, NbtSerializable { protected final Codec codec; @Nullable private final Runnable saveOperation; protected T value; - public GenericComponent(Component.Operations ops, Codec codec) { + public GenericSerializableField(ComponentCreationContext ctx, Codec codec) { + this(ctx, codec, null); + } + + public GenericSerializableField(ComponentCreationContext ops, Codec codec, T defaultValue) { this.saveOperation = ops.saveOperation(); this.codec = codec; + this.value = defaultValue; } + @Override public T getValue() { return this.value; } + @Override public void setValue(T value) { this.value = value; } @@ -53,8 +59,8 @@ public byte nbtType() { @Override public void read(NbtCompound nbt) { this.codec.parse(NbtOps.INSTANCE, nbt.get("Value")) - .result() - .ifPresent(this::setValue); + .result() + .ifPresent(this::setValue); } @Override @@ -62,8 +68,8 @@ public NbtCompound write() { var ret = new NbtCompound(); if (this.value != null) { this.codec.encodeStart(NbtOps.INSTANCE, this.value) - .resultOrPartial(ComponentsImpl.LOGGER::error) - .ifPresent(nbtElement -> ret.put("Value", nbtElement)); + .resultOrPartial(ComponentsImpl.LOGGER::error) + .ifPresent(nbtElement -> ret.put("Value", nbtElement)); } return ret; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SyncedGenericSerializableField.java similarity index 61% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SyncedGenericSerializableField.java index e0098b7567..d2631fdae9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/SyncedGenericComponent.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SyncedGenericSerializableField.java @@ -14,30 +14,39 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.component; +package org.quiltmc.qsl.component.api.component.field; import com.mojang.serialization.Codec; import org.jetbrains.annotations.Nullable; import net.minecraft.network.PacketByteBuf; -import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentCreationContext; +import org.quiltmc.qsl.component.api.component.Syncable; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; -public class SyncedGenericComponent extends GenericComponent implements SyncedComponent { +public class SyncedGenericSerializableField extends GenericSerializableField implements Syncable { private final NetworkCodec networkCodec; @Nullable private final Runnable syncOperation; - protected SyncedGenericComponent(Component.Operations ops, Codec codec, NetworkCodec networkCodec) { - super(ops, codec); + public SyncedGenericSerializableField(ComponentCreationContext ctx, Codec codec, NetworkCodec networkCodec) { + super(ctx, codec); + this.networkCodec = networkCodec; + this.syncOperation = ctx.syncOperation(); + } + + public SyncedGenericSerializableField(ComponentCreationContext ops, Codec codec, NetworkCodec networkCodec, T defaultValue) { + super(ops, codec, defaultValue); this.syncOperation = ops.syncOperation(); this.networkCodec = networkCodec; } @Override public void writeToBuf(PacketByteBuf buf) { - this.networkCodec.encode(buf, this.getValue()); + if (this.getValue() != null) { + this.networkCodec.encode(buf, this.getValue()); + } } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index f0db2ed08a..f0b1da90d3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -16,43 +16,45 @@ package org.quiltmc.qsl.component.api.container; -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.function.BiConsumer; - +import net.minecraft.nbt.NbtCompound; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; - -import net.minecraft.nbt.NbtCompound; - import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentFactory; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.component.NbtSerializable; +import org.quiltmc.qsl.component.api.component.Syncable; +import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.container.CompositeComponentContainer; -import org.quiltmc.qsl.component.impl.container.EmptyComponentContainer; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; -import org.quiltmc.qsl.component.impl.container.OnAccessComponentContainer; -import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; -import org.quiltmc.qsl.component.impl.container.SingleComponentContainer; +import org.quiltmc.qsl.component.impl.container.*; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.function.BiConsumer; + /** * A base container for all {@link Component}s that a {@link ComponentProvider} contains. - * The implementation of this, needs to not take up too much runtime, since the methods in here may be called really often. + * The implementation of this, needs to not take up too much runtime, since the methods in here may be called really + * often. *

      - * There are default implementations used internally in the API implementation, but they are also usable outside of internals. + * There are default implementations used internally in the API implementation, but they are also usable outside of + * internals. * These include: *

        - *
      1. {@link EmptyComponentContainer}: usable through the {@link ComponentContainer#EMPTY} instance or the {@link ComponentContainer#EMPTY_FACTORY} instance.
      2. + *
      3. {@link EmptyComponentContainer}: usable through the {@link ComponentContainer#EMPTY} instance or the + * {@link ComponentContainer#EMPTY_FACTORY} instance.
      4. *
      5. {@link SimpleComponentContainer}: usable through the {@link ComponentContainer#SIMPLE_FACTORY} instance.
      6. *
      7. {@link LazyComponentContainer}: usable through the {@link ComponentContainer#LAZY_FACTORY} instance.
      8. - *
      9. {@link OnAccessComponentContainer}: usable through the {@link ComponentContainer#ON_ACCESS_FACTORY} instance.
      10. - *
      11. {@link SingleComponentContainer}: usable through the {@link ComponentContainer#createSingleFactory} method.
      12. - *
      13. {@link CompositeComponentContainer}: usable through the {@link ComponentContainer#createComposite} method.
      14. + *
      15. {@link OnAccessComponentContainer}: usable through the {@link ComponentContainer#ON_ACCESS_FACTORY} + * instance.
      16. + *
      17. {@link SingleComponentContainer}: usable through the {@link ComponentContainer#createSingleFactory} method + * .
      18. + *
      19. {@link CompositeComponentContainer}: usable through the {@link ComponentContainer#createComposite} method + * .
      20. *
      * *

      @@ -62,7 +64,6 @@ * @author 0xJoeMama * @see ComponentProvider * @see ComponentType - * @see Component */ public interface ComponentContainer { /** @@ -80,26 +81,31 @@ public interface ComponentContainer { * {@link ComponentType#isInstant()} value for their types.
      * *

      - * The advantage of this {@linkplain ComponentContainer container} is that by initializing all of its components right off the bat, + * The advantage of this {@linkplain ComponentContainer container} is that by initializing all of its components + * right off the bat, * it can have a faster runtime. However, that does sacrifice on memory and also on disc space, - * since all {@link org.quiltmc.qsl.component.api.component.NbtComponent}s, even if their value hasn't been modified, will be saved. + * since all {@link NbtSerializable}s, even if their value hasn't been modified, will be saved. */ ComponentContainer.Factory SIMPLE_FACTORY = SimpleComponentContainer.FACTORY; /** * A {@link Factory} to a {@link LazyComponentContainer}.
      * A {@link LazyComponentContainer} lazily initializes its components. * This saves on memory and disc space, since non-initialized components, will not be written to disc.
      - * The runtime hit of using this {@linkplain ComponentContainer container} is minimal, since it mostly consists of work that would also be done at runtime by a {@link SimpleComponentContainer}.
      + * The runtime hit of using this {@linkplain ComponentContainer container} is minimal, since it mostly consists of + * work that would also be done at runtime by a {@link SimpleComponentContainer}.
      * The only functional difference is that this container will pull injections targetting its provider. * This container is used as the default for all type at the moment. */ ComponentContainer.Factory LAZY_FACTORY = LazyComponentContainer.FACTORY; /** * A {@link Factory} to a {@link OnAccessComponentContainer}.
      - * An {@link OnAccessComponentContainer} is similar to a {@link LazyComponentContainer} in that it lazily initializes its components. + * An {@link OnAccessComponentContainer} is similar to a {@link LazyComponentContainer} in that it lazily + * initializes its components. * However, it does so in a different way. Instead of storing {@link Lazy} instances, - * it stores {@link com.mojang.datafixers.util.Either} instances that it attempts to access and/or initialize on expose. - * This currently leads to extra object creation, hence it's considered {@linkplain org.jetbrains.annotations.ApiStatus.Experimental experimental}.
      + * it stores {@link com.mojang.datafixers.util.Either} instances that it attempts to access and/or initialize on + * expose. + * This currently leads to extra object creation, hence it's considered + * {@linkplain org.jetbrains.annotations.ApiStatus.Experimental experimental}.
      * *

      * May be used as the default container for our implementations in the future. @@ -113,22 +119,24 @@ public interface ComponentContainer { * Creates a {@link Factory} to a {@link SingleComponentContainer}.
      * *

      - * A {@link SingleComponentContainer} is identical to a {@link LazyComponentContainer}, except it can only store 1 component. + * A {@link SingleComponentContainer} is identical to a {@link LazyComponentContainer}, except it can only + * store 1 component. * * @param type The {@link ComponentType} to store. The default factory of the type is used for initialization. * @param The type of component that is contained by the container. * @return A new {@link Factory} for {@link SingleComponentContainer} holding the provided {@link ComponentType}. */ - static ComponentContainer.Factory> createSingleFactory(ComponentType type) { + static ComponentContainer.Factory> createSingleFactory(ComponentType type) { return SingleComponentContainer.createFactory(new ComponentEntry<>(type)); } /** - * Identical to {@link ComponentContainer#createSingleFactory(ComponentType)}, except that it allows the caller to specify the {@link Component.Factory} used. + * Identical to {@link ComponentContainer#createSingleFactory(ComponentType)}, except that it allows the caller to + * specify the {@link ComponentFactory} used. * * @see ComponentContainer#createSingleFactory(ComponentType) */ - static ComponentContainer.Factory> createSingleFactory(ComponentType type, Component.Factory factory) { + static ComponentContainer.Factory> createSingleFactory(ComponentType type, ComponentFactory factory) { return SingleComponentContainer.createFactory(new ComponentEntry<>(type, factory)); } @@ -137,7 +145,8 @@ static ComponentContainer.Factoryreally often, so it is advised you make it have a really fast runtime. * * @param type The type to expose. - * @return Should return {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided {@link ComponentType} is not contained in the current container. - * Otherwise, should always return {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the contained {@link Component} instance. + * @return Should return {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided {@link ComponentType} + * is not contained in the current container. + * Otherwise, should always return {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the contained + * {@link Component} instance. */ - Maybe expose(ComponentType type); + Maybe expose(ComponentType type); /** - * Serializes the {@link org.quiltmc.qsl.component.api.component.NbtComponent}s this {@linkplain ComponentContainer container} contains, into the provided nbt tag. + * Serializes the {@link NbtSerializable}s this {@linkplain ComponentContainer container} contains, into the + * provided nbt tag. * * @param providerRootNbt The root nbt tag of the provider containing this {@link ComponentContainer}. */ void writeNbt(NbtCompound providerRootNbt); /** - * Deserializes the {@link org.quiltmc.qsl.component.api.component.NbtComponent}s this {@link ComponentContainer container} contains, from the provided nbt tag.
      + * Deserializes the {@link NbtSerializable}s this {@link ComponentContainer container} contains, from the provided + * nbt tag.
      * * @param providerRootNbt The root nbt tag of the provider containing this {@link ComponentContainer}. * @implNote There is no guarantee that the provided tag will contain exactly the same components as the container. @@ -189,18 +202,20 @@ static Builder builder(Object obj) { void readNbt(NbtCompound providerRootNbt); /** - * Ticks all {@link org.quiltmc.qsl.component.api.component.TickingComponent}s contained in this {@link ComponentContainer}. + * Ticks all {@link Tickable}s contained in this {@link ComponentContainer}. * - * @param provider The provider is passed in so that {@link org.quiltmc.qsl.component.api.component.TickingComponent}s can use it. + * @param provider The provider is passed in so that {@link Tickable}s can use it. */ void tick(ComponentProvider provider); /** - * Syncs all {@link org.quiltmc.qsl.component.api.component.SyncedComponent}s contained in this {@link ComponentContainer}, provided they need syncing. + * Syncs all {@link Syncable}s contained in this {@link ComponentContainer}, provided they need syncing. * Most of the time this method is invoked by {@link ComponentContainer#tick}.
      * - * @param provider The provider is passed in so that {@link SyncChannel#syncFromQueue} can use it, when creating a packet to sync data to the client. - * @implNote The best way to sync components at the moment is using {@link SyncChannel#syncFromQueue}, which takes in a {@link Queue} of components that need syncing. + * @param provider The provider is passed in so that {@link SyncChannel#syncFromQueue} can use it, when creating a + * packet to sync data to the client. + * @implNote The best way to sync components at the moment is using {@link SyncChannel#syncFromQueue}, which takes + * in a {@link Queue} of components that need syncing. */ void sync(ComponentProvider provider); @@ -209,7 +224,7 @@ static Builder builder(Object obj) { * * @apiNote May be slow, so use sparingly! */ - void forEach(BiConsumer, ? super Component> action); + void forEach(BiConsumer, ? super Object> action); /** * An interface representing the way to create a new {@link ComponentContainer}. @@ -223,10 +238,13 @@ interface Factory { * Creates a {@link ComponentContainer} using the specified arguments. * * @param provider The {@link ComponentProvider} that will contain the created {@link ComponentContainer}. - * @param entries A {@link List} containing all the entries that were manually added by the {@link Builder}. - * @param saveOperation The operation to be run by the contained {@link Component}s to mark the {@linkplain ComponentProvider provider} as needing to save. + * @param entries A {@link List} containing all the entries that were manually added by the + * {@link Builder}. + * @param saveOperation The operation to be run by the contained {@link Component}s to mark the + * {@linkplain ComponentProvider provider} as needing to save. * @param ticking Whether this container can tick. - * @param syncChannel The {@link SyncChannel} representing the {@link ComponentProvider} that contains the created {@link ComponentContainer}. + * @param syncChannel The {@link SyncChannel} representing the {@link ComponentProvider} that contains the + * created {@link ComponentContainer}. * @return A {@link ComponentContainer} created using the specified parameters. */ T generate(ComponentProvider provider, @@ -273,17 +291,17 @@ public Builder syncing(SyncChannel syncChannel) { return this; } - public Builder add(ComponentEntry componentEntry) { + public Builder add(ComponentEntry componentEntry) { this.injections.get().add(componentEntry); return this; } - public Builder add(ComponentType type) { + public Builder add(ComponentType type) { this.add(new ComponentEntry<>(type)); return this; } - public Builder add(ComponentType type, Component.Factory factory) { + public Builder add(ComponentType type, ComponentFactory factory) { this.add(new ComponentEntry<>(type, factory)); return this; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java index 133bbbee52..10474b0bf0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java @@ -46,7 +46,7 @@ * The {@code AComponent} interface provides the API for {@code AComponent} instances.
      * The {@code ADefaultComponent} class provides a default implementation of the {@code AComponent} interface. * The data contained by {@code ADefaultComponent} is not saved or synced. If you want to learn how to save or sync data,
      - * visit the {@linkplain org.quiltmc.qsl.component.api.component.NbtComponent NbtComponent} and {@linkplain org.quiltmc.qsl.component.api.component.SyncedComponent SyncedComponent} documentation. + * visit the {@linkplain org.quiltmc.qsl.component.api.component.NbtSerializable NbtComponent} and {@linkplain org.quiltmc.qsl.component.api.component.Syncable SyncedComponent} documentation. *

      *

      Component Injection

      * The {@link org.quiltmc.qsl.component.api.ComponentType} we have created does exist, but nothing actually exposes it's interface.
      diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java index e11e6f6606..fc009ecee1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java @@ -25,13 +25,12 @@ import org.quiltmc.qsl.base.api.util.InjectedInterface; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.container.ComponentContainer; /** - * Any object that wishes to allow {@link Component components} to be attached to and queried from it, + * Any object that wishes to allow components to be attached to and queried from it, * needs to implement this interface.
      * *

      @@ -87,7 +86,7 @@ default ComponentContainer getComponentContainer() { * @param The type of the held component. * @return A {@link Maybe} instance following the rules defined in {@link Components#expose(ComponentType, Object)}. */ - default Maybe expose(ComponentType type) { - return Components.expose(type, this); + default Maybe expose(ComponentType type) { + return this.getComponentContainer().expose(type); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java index 2fb23c3d70..ac04998acf 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java @@ -46,7 +46,7 @@ import net.minecraft.world.chunk.WorldChunk; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.component.SyncedComponent; +import org.quiltmc.qsl.component.api.component.Syncable; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; import org.quiltmc.qsl.component.impl.client.sync.ClientResolution; @@ -163,11 +163,11 @@ public void send(Collection players, ComponentProvider provi ServerPlayNetworking.send(players.isEmpty() ? this.playerProvider.apply(providerAsP) : players, this.channelId, buf); } - public void syncFromQueue(Queue> pendingSync, Function, SyncedComponent> mapper, ComponentProvider provider) { + public void syncFromQueue(Queue> pendingSync, Function, Syncable> mapper, ComponentProvider provider) { this.syncFromQueue(pendingSync, mapper, provider, List.of()); } - public void syncFromQueue(Queue> pendingSync, Function, SyncedComponent> mapper, ComponentProvider provider, Collection players) { + public void syncFromQueue(Queue> pendingSync, Function, Syncable> mapper, ComponentProvider provider, Collection players) { if (pendingSync.isEmpty()) { return; } @@ -192,9 +192,13 @@ public void handleServerPushedSync(MinecraftClient client, PacketByteBuf buf) { int size = buf.readInt(); // consume size + if (provider == null) { + return; + } + for (int i = 0; i < size; i++) { ComponentType type = ComponentType.NETWORK_CODEC.decode(buf); // consume rawId - provider.expose(type).ifJust(component -> ((SyncedComponent) component).readFromBuf(buf)); // consume component data + provider.expose(type).ifJust(component -> ((Syncable) component).readFromBuf(buf)); // consume component data } buf.release(); // make sure the buffer is properly freed @@ -235,12 +239,12 @@ public void forceSync(ComponentProvider provider, ServerPlayerEntity sender) { var queue = new ArrayDeque>(); provider.getComponentContainer().forEach((type, component) -> { - if (component instanceof SyncedComponent) { + if (component instanceof Syncable) { queue.add(type); } }); - this.syncFromQueue(queue, type -> ((SyncedComponent) provider.expose(type).unwrap()), provider, Collections.singletonList(sender)); + this.syncFromQueue(queue, type -> ((Syncable) provider.expose(type).unwrap()), provider, Collections.singletonList(sender)); } @Environment(EnvType.CLIENT) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 7b69e2f15e..9c177bece8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -16,11 +16,8 @@ package org.quiltmc.qsl.component.impl; -import org.jetbrains.annotations.ApiStatus; - -import net.minecraft.client.gui.screen.ingame.HandledScreens; import net.minecraft.util.Identifier; - +import org.jetbrains.annotations.ApiStatus; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.impl.event.CommonEventListener; @@ -33,30 +30,34 @@ @ApiStatus.Internal public final class CommonInitializer implements ModInitializer { - public static final String MOD_ID = "quilt_component"; - - public static Identifier id(String id) { - return new Identifier(MOD_ID, id); - } - - @Override - public void onInitialize(ModContainer mod) { - ServerSyncHandler.getInstance().registerPackets(); - - ServerLoginConnectionEvents.QUERY_START.register( - ComponentEventPhases.SYNC_COMPONENT_REGISTRY, - CommonEventListener::onQueryStart); - - ServerLifecycleEvents.STARTING.register( - ComponentEventPhases.FREEZE_COMPONENT_REGISTRIES, - CommonEventListener::onServerStart); - - ServerTickEvents.END.register( - ComponentEventPhases.TICK_LEVEL_CONTAINER, - CommonEventListener::onServerTick); - - ServerWorldTickEvents.END.register( - ComponentEventPhases.TICK_WORLD_CONTAINER, - CommonEventListener::onServerWorldTick); - } + public static final String MOD_ID = "quilt_component"; + + public static Identifier id(String id) { + return new Identifier(MOD_ID, id); + } + + @Override + public void onInitialize(ModContainer mod) { + ServerSyncHandler.getInstance().registerPackets(); + + ServerLoginConnectionEvents.QUERY_START.register( + ComponentEventPhases.SYNC_COMPONENT_REGISTRY, + CommonEventListener::onQueryStart + ); + + ServerLifecycleEvents.STARTING.register( + ComponentEventPhases.FREEZE_COMPONENT_REGISTRIES, + CommonEventListener::onServerStart + ); + + ServerTickEvents.END.register( + ComponentEventPhases.TICK_LEVEL_CONTAINER, + CommonEventListener::onServerTick + ); + + ServerWorldTickEvents.END.register( + ComponentEventPhases.TICK_WORLD_CONTAINER, + CommonEventListener::onServerWorldTick + ); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index c265a09a72..5fa48dcd15 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -16,20 +16,12 @@ package org.quiltmc.qsl.component.impl; -import java.util.ArrayList; -import java.util.List; - import com.mojang.serialization.Lifecycle; -import org.jetbrains.annotations.ApiStatus; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.SimpleRegistry; - -import org.quiltmc.qsl.component.api.Component; +import org.jetbrains.annotations.ApiStatus; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; @@ -37,6 +29,11 @@ import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.cached.CachedInjectionManager; import org.quiltmc.qsl.component.impl.injection.manager.dynamic.DynamicInjectionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; @ApiStatus.Internal public class ComponentsImpl { @@ -50,7 +47,7 @@ public class ComponentsImpl { public static final Logger LOGGER = LoggerFactory.getLogger("Quilt Component"); - public static void inject(InjectionPredicate predicate, ComponentEntry componentEntry) { + public static void inject(InjectionPredicate predicate, ComponentEntry componentEntry) { if (predicate instanceof DynamicInjectionPredicate dynamicPredicate) { DYNAMIC_MANAGER.inject(dynamicPredicate, componentEntry); } else { @@ -65,7 +62,7 @@ public static List> getInjections(ComponentProvider provider) return result; } - public static ComponentType register(Identifier id, ComponentType type) { + public static ComponentType register(Identifier id, ComponentType type) { return Registry.register(REGISTRY, id, type); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index 6d6058868d..c7ec05944f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -16,25 +16,15 @@ package org.quiltmc.qsl.component.impl.container; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Queue; -import java.util.function.Function; - -import org.jetbrains.annotations.Nullable; - import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; - +import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.component.NbtComponent; -import org.quiltmc.qsl.component.api.component.SyncedComponent; -import org.quiltmc.qsl.component.api.component.TickingComponent; +import org.quiltmc.qsl.component.api.component.NbtSerializable; +import org.quiltmc.qsl.component.api.component.Syncable; +import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; @@ -42,6 +32,9 @@ import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; +import java.util.*; +import java.util.function.Function; + public abstract class AbstractComponentContainer implements ComponentContainer { protected final ContainerOperations operations; protected final List> nbtComponents; @@ -50,8 +43,8 @@ public abstract class AbstractComponentContainer implements ComponentContainer { protected final Maybe> syncContext; public AbstractComponentContainer(@Nullable Runnable saveOperation, - boolean ticking, - @Nullable SyncChannel syncChannel) { + boolean ticking, + @Nullable SyncChannel syncChannel) { this.ticking = ticking ? Maybe.just(new ArrayList<>()) : Maybe.nothing(); this.nbtComponents = new ArrayList<>(); this.syncContext = Maybe.wrap(syncChannel); @@ -66,8 +59,9 @@ public AbstractComponentContainer(@Nullable Runnable saveOperation, public void writeNbt(NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); this.nbtComponents.forEach(type -> this.expose(type) - .map(it -> ((NbtComponent) it)) - .ifJust(nbtComponent -> NbtComponent.writeTo(rootQslNbt, nbtComponent, type.id())) + .map(it -> ((NbtSerializable) it)) + .ifJust(nbtComponent -> NbtSerializable.writeTo( + rootQslNbt, nbtComponent, type.id())) ); if (!rootQslNbt.isEmpty()) { @@ -80,19 +74,20 @@ public void readNbt(NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); rootQslNbt.getKeys().stream() - .map(Identifier::new) // All encoded component types *must* strictly be identifiers - .map(Components.REGISTRY::get) - .filter(Objects::nonNull) - .forEach(type -> this.expose(type) - .map(component -> ((NbtComponent) component)) - .ifJust(component -> NbtComponent.readFrom(component, type.id(), rootQslNbt))); + .map(Identifier::new) // All encoded component types *must* strictly be identifiers + .map(Components.REGISTRY::get) + .filter(Objects::nonNull) + .forEach(type -> this.expose(type) + .map(component -> ((NbtSerializable) component)) + .ifJust(component -> NbtSerializable.readFrom(component, type.id(), rootQslNbt))); } @Override public void tick(ComponentProvider provider) { this.ticking.ifJust(componentTypes -> componentTypes.forEach(type -> this.expose(type) - .map(it -> ((TickingComponent) it)) - .ifJust(tickingComponent -> tickingComponent.tick(provider))) + .map(it -> ((Tickable) it)) + .ifJust(tickingComponent -> tickingComponent.tick( + provider))) ).ifNothing(() -> { throw ErrorUtil.illegalState("Attempted to tick a non-ticking container").get(); }); @@ -104,29 +99,29 @@ public void tick(ComponentProvider provider) { public void sync(ComponentProvider provider) { this.syncContext.ifJust(channel -> channel.syncFromQueue( this.pendingSync.unwrap(), - type -> (SyncedComponent) this.expose(type).unwrap(), + type -> (Syncable) this.expose(type).unwrap(), provider )).ifNothing(() -> { throw ErrorUtil.illegalState("Attempted to sync a non-syncable container!").get(); }); } - protected abstract void addComponent(ComponentType type, Component component); + protected abstract void addComponent(ComponentType type, COMP component); - protected COMP initializeComponent(ComponentEntry componentEntry) { - ComponentType type = componentEntry.type(); + protected COMP initializeComponent(ComponentEntry componentEntry) { + ComponentType type = componentEntry.type(); Function, Runnable> factory = this.operations.syncOperationFactory(); Runnable syncOperation = factory != null ? factory.apply(type) : null; COMP component = componentEntry.apply(this.operations.saveOperation(), syncOperation); - if (component instanceof NbtComponent) { + if (component instanceof NbtSerializable) { this.nbtComponents.add(type); } this.ticking.ifJust(componentTypes -> { - if (component instanceof TickingComponent) { + if (component instanceof Tickable) { componentTypes.add(type); } }); @@ -136,5 +131,6 @@ protected COMP initializeComponent(ComponentEntry return component; } - public record ContainerOperations(@Nullable Runnable saveOperation, @Nullable Function, Runnable> syncOperationFactory) { } + public record ContainerOperations(@Nullable Runnable saveOperation, + @Nullable Function, Runnable> syncOperationFactory) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java index 2661875633..1dd2147adf 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java @@ -21,7 +21,6 @@ import net.minecraft.nbt.NbtCompound; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; @@ -36,7 +35,7 @@ public CompositeComponentContainer(ComponentContainer main, ComponentContainer f } @Override - public Maybe expose(ComponentType type) { + public Maybe expose(ComponentType type) { return this.main.expose(type).or(() -> this.fallback.expose(type)); } @@ -65,7 +64,7 @@ public void sync(ComponentProvider provider) { } @Override - public void forEach(BiConsumer, ? super Component> action) { + public void forEach(BiConsumer, ? super Object> action) { this.main.forEach(action); this.fallback.forEach(action); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java index 91b56c9d68..a79a4324f8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java @@ -16,16 +16,14 @@ package org.quiltmc.qsl.component.impl.container; -import java.util.function.BiConsumer; - import net.minecraft.nbt.NbtCompound; - import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import java.util.function.BiConsumer; + public final class EmptyComponentContainer implements ComponentContainer { public static final EmptyComponentContainer INSTANCE = new EmptyComponentContainer(); @@ -35,7 +33,7 @@ public final class EmptyComponentContainer implements ComponentContainer { private EmptyComponentContainer() { } @Override - public Maybe expose(ComponentType type) { + public Maybe expose(ComponentType type) { return Maybe.nothing(); } @@ -52,5 +50,5 @@ public void tick(ComponentProvider provider) { } public void sync(ComponentProvider provider) { } @Override - public void forEach(BiConsumer, ? super Component> action) { } + public void forEach(BiConsumer, ? super Object> action) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 3737bbd644..1ff04ed94b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -16,17 +16,9 @@ package org.quiltmc.qsl.component.impl.container; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.function.BiConsumer; - import org.jetbrains.annotations.Nullable; - import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; @@ -34,11 +26,17 @@ import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.function.BiConsumer; + public class LazyComponentContainer extends AbstractComponentContainer { public static final ComponentContainer.Factory FACTORY = (provider, injections, saveOperation, ticking, syncChannel) -> new LazyComponentContainer(provider, saveOperation, ticking, syncChannel); - private final Map, Lazy>> components; + private final Map, Lazy>> components; protected LazyComponentContainer( ComponentProvider provider, @@ -66,34 +64,38 @@ public static void move(LazyComponentContainer from, LazyComponentContainer into } @Override - public Maybe expose(ComponentType id) { - return this.components.containsKey(id) ? this.components.get(id).get() : Maybe.nothing(); + public Maybe expose(ComponentType type) { + return this.components.containsKey(type) ? this.components.get(type).unwrap().castUnchecked() : + Maybe.nothing(); } @Override - public void forEach(BiConsumer, ? super Component> action) { + public void forEach(BiConsumer, ? super Object> action) { // unwrap will work here since all Lazies are Just instances for this. - this.components.forEach((type, componentLazy) -> componentLazy.ifFilled(component -> action.accept(type, component.unwrap()))); + this.components.forEach( + (type, componentLazy) -> componentLazy.ifFilled(component -> action.accept(type, component.unwrap())) + ); } @Override - protected void addComponent(ComponentType type, Component component) { } + protected void addComponent(ComponentType type, COMP component) { } - private Map, Lazy>> createLazyMap(ComponentProvider provider) { + private Map, Lazy>> createLazyMap(ComponentProvider provider) { // TODO: Consider adding a way to directly add components to the builder. - var map = new IdentityHashMap, Lazy>>(); - ComponentsImpl.getInjections(provider).forEach(injection -> map.put(injection.type(), this.createLazy(injection))); + var map = new IdentityHashMap, Lazy>>(); + ComponentsImpl.getInjections(provider) + .forEach(injection -> map.put(injection.type(), this.createLazy(injection))); return map; } - private Lazy> createLazy(ComponentEntry componentEntry) { + private Lazy> createLazy(ComponentEntry componentEntry) { ComponentType type = componentEntry.type(); if (type.isStatic() || type.isInstant()) { var component = this.initializeComponent(componentEntry); - return Lazy.filled((Maybe.Just) Maybe.just(component)); // this cast will obviously never fail + return Lazy.filled(Maybe.just(component)); // this cast will obviously never fail } - return Lazy.of(() -> ((Maybe.Just) Maybe.just(this.initializeComponent(componentEntry)))); // same here + return Lazy.of(() -> (Maybe.just(this.initializeComponent(componentEntry)))); // same here } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index 7876e881fd..d59aa3ab52 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -16,40 +16,57 @@ package org.quiltmc.qsl.component.impl.container; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; - import com.mojang.datafixers.util.Either; import org.jetbrains.annotations.Nullable; - import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; + // Suggestion from Technici4n from fabric. May help improve performance and memory footprint once done. public class OnAccessComponentContainer extends AbstractComponentContainer { public static final Factory FACTORY = (provider, injections, saveOperation, ticking, syncChannel) -> new OnAccessComponentContainer(provider, saveOperation, ticking, syncChannel); - private final Map, Either, Component>> components; + private final Map, Either, Object>> components; protected OnAccessComponentContainer(ComponentProvider provider, - @Nullable Runnable saveOperation, - boolean ticking, - @Nullable SyncChannel syncChannel) { + @Nullable Runnable saveOperation, + boolean ticking, + @Nullable SyncChannel syncChannel) { super(saveOperation, ticking, syncChannel); this.components = this.createComponents(provider); } - private Map, Either, Component>> createComponents(ComponentProvider provider) { + @Override + public Maybe expose(ComponentType type) { + return Maybe.fromOptional(this.components.get(type).right()) + .or(() -> this.supports(type) ? + Maybe.just(this.initializeComponent(this.components.get(type).left().orElseThrow())) : + Maybe.nothing()) + .castUnchecked(); + } + + @Override + public void forEach(BiConsumer, ? super Object> action) { + this.components.forEach((type, either) -> either.ifRight(component -> action.accept(type, component))); + } + + @Override + protected void addComponent(ComponentType type, COMP component) { + this.components.put(type, Either.right(component)); + } + + private Map, Either, Object>> createComponents(ComponentProvider provider) { List> injections = ComponentsImpl.getInjections(provider); - var map = new IdentityHashMap, Either, Component>>(); + var map = new IdentityHashMap, Either, Object>>(); injections.forEach(entry -> { ComponentType type = entry.type(); if (type.isStatic() || type.isInstant()) { @@ -62,22 +79,6 @@ private Map, Either, Component>> createCompon return map; } - @Override - public Maybe expose(ComponentType type) { - return Maybe.fromOptional(this.components.get(type).right()) - .or(() -> this.supports(type) ? Maybe.just(this.initializeComponent(this.components.get(type).left().orElseThrow())) : Maybe.nothing()); - } - - @Override - public void forEach(BiConsumer, ? super Component> action) { - this.components.forEach((type, either) -> either.ifRight(component -> action.accept(type, component))); - } - - @Override - protected void addComponent(ComponentType type, Component component) { - this.components.put(type, Either.right(component)); - } - private boolean supports(ComponentType type) { return this.components.containsKey(type); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 9ef6409646..989e2f761d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -16,32 +16,30 @@ package org.quiltmc.qsl.component.impl.container; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.stream.Stream; - import org.jetbrains.annotations.Nullable; - import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.stream.Stream; + public class SimpleComponentContainer extends AbstractComponentContainer { public static final ComponentContainer.Factory FACTORY = (provider, injections, saveOperation, ticking, syncChannel) -> new SimpleComponentContainer( saveOperation, ticking, syncChannel, injections.get().stream() ); - private final Map, Component> components; + private final Map, Object> components; protected SimpleComponentContainer(@Nullable Runnable saveOperation, - boolean ticking, - @Nullable SyncChannel syncContext, - Stream> types) { + boolean ticking, + @Nullable SyncChannel syncContext, + Stream> types) { super(saveOperation, ticking, syncContext); this.components = new IdentityHashMap<>(); types.forEach(this::initializeComponent); @@ -49,18 +47,18 @@ protected SimpleComponentContainer(@Nullable Runnable saveOperation, } @Override - public Maybe expose(ComponentType type) { - return Maybe.wrap(this.components.get(type)); + public Maybe expose(ComponentType type) { + return Maybe.wrap(this.components.get(type)).castUnchecked(); } @Override - public void forEach(BiConsumer, ? super Component> action) { + public void forEach(BiConsumer, ? super Object> action) { this.components.forEach(action); } @Override - protected void addComponent(ComponentType type, Component component) { - Component result = this.components.put(type, component); + protected void addComponent(ComponentType type, COMP component) { + Object result = this.components.put(type, component); if (result != null) { throw ErrorUtil.illegalState("Attempted to override a component on a simple container!").get(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java index 34ae807e47..e32b088b47 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java @@ -16,41 +16,39 @@ package org.quiltmc.qsl.component.impl.container; -import java.util.ArrayDeque; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -import org.jetbrains.annotations.Nullable; - import net.minecraft.nbt.NbtCompound; - +import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.component.NbtComponent; -import org.quiltmc.qsl.component.api.component.SyncedComponent; -import org.quiltmc.qsl.component.api.component.TickingComponent; +import org.quiltmc.qsl.component.api.component.NbtSerializable; +import org.quiltmc.qsl.component.api.component.Syncable; +import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -public class SingleComponentContainer implements ComponentContainer { - private final ComponentType type; +import java.util.ArrayDeque; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +public class SingleComponentContainer implements ComponentContainer { + private final ComponentType type; private final Maybe> syncChannel; private final boolean ticking; - private Lazy entry; + private Lazy entry; private boolean shouldSync = false; - protected SingleComponentContainer(ComponentType type, boolean ticking, @Nullable SyncChannel syncChannel) { + protected SingleComponentContainer(ComponentType type, boolean ticking, + @Nullable SyncChannel syncChannel) { this.type = type; this.ticking = ticking; this.syncChannel = Maybe.wrap(syncChannel); } - public static ComponentContainer.Factory> createFactory(ComponentEntry entry) { + public static ComponentContainer.Factory> createFactory(ComponentEntry entry) { return (provider, ignored, saveOperation, ticking, syncChannel) -> { ComponentType type = entry.type(); var container = new SingleComponentContainer<>(type, ticking, syncChannel); @@ -61,15 +59,15 @@ public static ComponentContainer.Factory expose(ComponentType type) { - return type == this.type ? Maybe.just(this.entry.get()) : Maybe.nothing(); + public Maybe expose(ComponentType type) { + return (type == this.type ? Maybe.just(this.entry.get()) : Maybe.nothing()).castUnchecked(); } @Override public void writeNbt(NbtCompound providerRootNbt) { this.entry.ifFilled(c -> { - if (c instanceof NbtComponent nbtComponent) { - NbtComponent.writeTo(providerRootNbt, nbtComponent, this.type.id()); + if (c instanceof NbtSerializable nbtSerializable) { + NbtSerializable.writeTo(providerRootNbt, nbtSerializable, this.type.id()); } }); } @@ -79,8 +77,8 @@ public void readNbt(NbtCompound providerRootNbt) { String idString = this.type.id().toString(); if (providerRootNbt.getKeys().contains(idString)) { this.expose(this.type) - .map(it -> ((NbtComponent) it)) - .ifJust(nbtComponent -> NbtComponent.readFrom(nbtComponent, this.type.id(), providerRootNbt)); + .map(it -> ((NbtSerializable) it)) + .ifJust(nbtComponent -> NbtSerializable.readFrom(nbtComponent, this.type.id(), providerRootNbt)); } } @@ -88,8 +86,8 @@ public void readNbt(NbtCompound providerRootNbt) { public void tick(ComponentProvider provider) { if (this.ticking) { this.expose(this.type) - .map(it -> ((TickingComponent) it)) - .ifJust(tickingComponent -> tickingComponent.tick(provider)); + .map(it -> ((Tickable) it)) + .ifJust(tickingComponent -> tickingComponent.tick(provider)); } } @@ -98,20 +96,20 @@ public void sync(ComponentProvider provider) { if (this.shouldSync) { this.syncChannel.ifJust(channel -> channel.syncFromQueue( new ArrayDeque<>(List.of(this.type)), - type -> (SyncedComponent) this.entry.get(), + type -> (Syncable) this.entry.get(), provider )); } } @Override - public void forEach(BiConsumer, ? super Component> action) { + public void forEach(BiConsumer, ? super Object> action) { if (this.entry.isFilled()) { action.accept(this.type, this.entry.get()); } } - private void setEntry(Supplier supplier) { + private void setEntry(Supplier supplier) { this.entry = Lazy.of(supplier); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java index 6c5d04117d..4bc96c7925 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java @@ -17,16 +17,16 @@ package org.quiltmc.qsl.component.impl.injection; import org.jetbrains.annotations.Nullable; - -import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentCreationContext; +import org.quiltmc.qsl.component.api.ComponentFactory; import org.quiltmc.qsl.component.api.ComponentType; -public record ComponentEntry(ComponentType type, Component.Factory factory) { +public record ComponentEntry(ComponentType type, ComponentFactory factory) { public ComponentEntry(ComponentType type) { this(type, type.defaultFactory()); } public C apply(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation) { - return this.factory.create(new Component.Operations(saveOperation, syncOperation)); + return this.factory.create(new ComponentCreationContext(saveOperation, syncOperation)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java index 28761b0af3..2990a2ee59 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java @@ -16,17 +16,8 @@ package org.quiltmc.qsl.component.impl.injection.manager; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - import net.minecraft.util.Util; - import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.Component; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; @@ -34,11 +25,14 @@ import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; +import java.util.*; +import java.util.stream.Stream; + public abstract class InjectionManager

      { private final Map>> injections = new HashMap<>(); private final Map, List> cache = new IdentityHashMap<>(); - public void inject(P predicate, ComponentEntry componentEntry) { + public void inject(P predicate, ComponentEntry componentEntry) { ComponentType type = componentEntry.type(); if (Components.REGISTRY.get(type.id()) == null) { throw ErrorUtil.illegalArgument("The target id %s does not match any registered component", type).get(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java index 50666c2fec..6d033e6a81 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/DirectBlockEntityTickInvokerMixin.java @@ -24,9 +24,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.block.entity.BlockEntity; -import net.minecraft.world.chunk.WorldChunk; -@Mixin(WorldChunk.DirectBlockEntityTickInvoker.class) +@Mixin(targets = "net/minecraft/world/chunk/WorldChunk$DirectBlockEntityTickInvoker") public class DirectBlockEntityTickInvokerMixin { @Shadow @Final @@ -35,7 +34,11 @@ public class DirectBlockEntityTickInvokerMixin { @SuppressWarnings("ConstantConditions") @Inject( method = "tick", - at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/entity/BlockEntity;)V") + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/entity/BlockEntity;)V", + shift = At.Shift.AFTER + ) ) private void tickContainer(CallbackInfo ci) { if (!this.blockEntity.getWorld().isClient) { // we know the block entity will have a world if it is contained in a ticker diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java index 22618c6c50..3f9fda510e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java @@ -16,7 +16,9 @@ package org.quiltmc.qsl.component.mixin.entity; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -33,6 +35,8 @@ @Mixin(Entity.class) public abstract class EntityMixin implements ComponentProvider { + @Shadow + public World world; private ComponentContainer qsl$container; @Override @@ -42,10 +46,13 @@ public ComponentContainer getComponentContainer() { @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { - this.qsl$container = ComponentContainer.builder(this) - .ticking() - .syncing(SyncChannel.ENTITY) - .build(ComponentContainer.LAZY_FACTORY); + var builder = ComponentContainer.builder(this); + + if (!world.isClient) { + builder.syncing(SyncChannel.ENTITY).ticking(); + } + + this.qsl$container = builder.build(LazyComponentContainer.FACTORY); } @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) @@ -60,6 +67,8 @@ private void onDeserialize(NbtCompound nbt, CallbackInfo ci) { @Inject(method = "tick", at = @At("TAIL")) private void tickContainer(CallbackInfo ci) { - this.getComponentContainer().tick(this); + if (!this.world.isClient) { + this.getComponentContainer().tick(this); + } } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index aed20a5339..198cfd4681 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -16,8 +16,7 @@ package org.quiltmc.qsl.component.test; -import java.util.UUID; - +import com.mojang.serialization.Codec; import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.Blocks; @@ -27,6 +26,7 @@ import net.minecraft.entity.mob.CreeperEntity; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.CowEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.server.MinecraftServer; @@ -40,76 +40,60 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.WorldChunk; - import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.block.entity.api.QuiltBlockEntityTypeBuilder; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.component.GenericComponent; -import org.quiltmc.qsl.component.api.component.TickingComponent; +import org.quiltmc.qsl.component.api.component.Tickable; +import org.quiltmc.qsl.component.api.component.field.SyncedGenericSerializableField; +import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; -import org.quiltmc.qsl.component.test.component.ChunkInventoryComponent; -import org.quiltmc.qsl.component.test.component.DefaultFloatComponent; -import org.quiltmc.qsl.component.test.component.DefaultIntegerComponent; -import org.quiltmc.qsl.component.test.component.DefaultInventoryComponent; -import org.quiltmc.qsl.component.test.component.InventoryComponent; -import org.quiltmc.qsl.component.test.component.SaveFloatComponent; +import org.quiltmc.qsl.component.test.component.*; + +import java.util.UUID; public class ComponentTestMod implements ModInitializer { - public static final String MODID = "quilt_component_test"; + public static final String MOD_ID = "quilt_component_test"; - public static final ComponentType COW_INVENTORY = Components.register( - new Identifier(MODID, "cow_inventory"), - operations -> new DefaultInventoryComponent(operations, () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64))) + public static final ComponentType COW_INVENTORY = Components.register( + new Identifier(MOD_ID, "cow_inventory"), + operations -> new DefaultInventorySerializable( + operations, () -> DefaultedList.ofSize(1, new ItemStack(Items.COBBLESTONE, 64)) + ) ); - public static final ComponentType CREEPER_EXPLODE_TIME = Components.register( - new Identifier(MODID, "creeper_explode_time"), - operations -> new DefaultIntegerComponent(operations, 200) + public static final ComponentType CREEPER_EXPLODE_TIME = Components.register( + new Identifier(MOD_ID, "creeper_explode_time"), + operations -> new DefaultIntegerSerializable(operations, 200) ); - public static final ComponentType HOSTILE_EXPLODE_TIME = Components.register( - new Identifier(MODID, "hostile_explode_time"), - DefaultIntegerComponent::new + public static final ComponentType HOSTILE_EXPLODE_TIME = Components.register( + new Identifier(MOD_ID, "hostile_explode_time"), + DefaultIntegerSerializable::new ); - public static final ComponentType CHEST_NUMBER = Components.register( - new Identifier(MODID, "chest_number"), - operations -> new DefaultIntegerComponent(operations, 200) + public static final ComponentType> CHEST_NUMBER = Components.register( + new Identifier(MOD_ID, "chest_number"), + operations -> new SyncedGenericSerializableField<>(operations, Codec.INT, NetworkCodec.VAR_INT, 200) ); - public static final ComponentType CHUNK_INVENTORY = Components.register( - new Identifier(MODID, "chunk_inventory"), - ChunkInventoryComponent::new + public static final ComponentType CHUNK_INVENTORY = Components.register( + new Identifier(MOD_ID, "chunk_inventory"), + ChunkInventorySerializable::new ); - public static final ComponentType SAVE_FLOAT = Components.registerInstant( - new Identifier(MODID, "save_float"), - SaveFloatComponent::new - ); - public static final ComponentType SERVER_TICK = Components.registerInstant( - new Identifier(MODID, "level_tick"), - (ops) -> provider -> { - if (provider instanceof MinecraftServer properties) { - properties.expose(SAVE_FLOAT).ifJust(floatComponent -> { - floatComponent.set(floatComponent.get() + 0.5f); - floatComponent.save(); - }); - } - } + public static final ComponentType SAVE_FLOAT = Components.registerInstant( + new Identifier(MOD_ID, "save_float"), + SaveFloatSerializable::new ); public static final Block TEST_BLOCK = new TestBlock(AbstractBlock.Settings.copy(Blocks.STONE)); - public static final ComponentType ITEMSTACK_INT = Components.register( - new Identifier(MODID, "itemstack_int"), - DefaultIntegerComponent::new - ); - public static final ComponentType TEST_BE_INT = Components.register( - new Identifier(ComponentTestMod.MODID, "test_be_int"), - DefaultIntegerComponent::new + public static final ComponentType TEST_BE_INT = Components.register( + new Identifier(ComponentTestMod.MOD_ID, "test_be_int"), + DefaultIntegerSerializable::new ); - public static final ComponentType> UUID_THING = Components.register( - new Identifier(MODID, "uuid_thing"), - (ops) -> new GenericComponent<>(ops, Codecs.UUID) + public static final ComponentType> UUID_THING = Components.register( + new Identifier(MOD_ID, "uuid_thing"), + (ops) -> new SyncedGenericSerializableField<>(ops, Codecs.UUID, NetworkCodec.UUID) ); - public static final ComponentType PLAYER_TICK = Components.registerInstant( - new Identifier(MODID, "player_tick"), + public static final ComponentType PLAYER_TICK = Components.registerInstant( + new Identifier(MOD_ID, "player_tick"), (ops) -> provider -> { if (provider instanceof ServerPlayerEntity player) { ItemStack stackInHand = player.getStackInHand(Hand.MAIN_HAND); @@ -121,7 +105,10 @@ public class ComponentTestMod implements ModInitializer { var props = player.getWorld().getServer().getSaveProperties(); if (props instanceof MinecraftServer levelProperties && player.getWorld().getTime() % 100 == 0) { player.sendMessage(Text.literal( - levelProperties.expose(SAVE_FLOAT).map(DefaultFloatComponent::get).unwrapOr(0f).toString() + levelProperties.expose(SAVE_FLOAT) + .map(DefaultFloatSerializable::get) + .unwrapOr(0f) + .toString() ), false); } @@ -132,12 +119,14 @@ public class ComponentTestMod implements ModInitializer { if (uuidGenericComponent.getValue() == null) { uuidGenericComponent.setValue(vehicle.getUuid()); uuidGenericComponent.save(); + uuidGenericComponent.sync(); } else { Entity vehicle1 = player.getWorld().getEntity(uuidGenericComponent.getValue()); if (vehicle1 == null) { uuidGenericComponent.setValue(null); uuidGenericComponent.save(); + uuidGenericComponent.sync(); return; } @@ -148,6 +137,8 @@ public class ComponentTestMod implements ModInitializer { } } else { uuidGenericComponent.setValue(null); + uuidGenericComponent.save(); + uuidGenericComponent.sync(); } }); } @@ -156,8 +147,8 @@ public class ComponentTestMod implements ModInitializer { @Override public void onInitialize(ModContainer mod) { - Registry.register(Registry.BLOCK, new Identifier(MODID, "test_block"), TEST_BLOCK); - Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(MODID, "block_entity"), TEST_BE_TYPE); + Registry.register(Registry.BLOCK, new Identifier(MOD_ID, "test_block"), TEST_BLOCK); + Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(MOD_ID, "block_entity"), TEST_BE_TYPE); Block.STATE_IDS.add(TEST_BLOCK.getDefaultState()); // Cached Injection @@ -166,10 +157,13 @@ public void onInitialize(ModContainer mod) { Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); Components.inject(ChestBlockEntity.class, CHEST_NUMBER); Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); - Components.inject(new ClassInjectionPredicate(WorldChunk.class), new ComponentEntry<>(CHUNK_INVENTORY, ChunkInventoryComponent::new)); + Components.inject( + new ClassInjectionPredicate(WorldChunk.class), + new ComponentEntry<>(CHUNK_INVENTORY, ChunkInventorySerializable::new) + ); // Components.inject(MinecraftServer.class, SERVER_TICK); Components.injectInheritage(ServerPlayerEntity.class, PLAYER_TICK); - Components.inject(ServerPlayerEntity.class, UUID_THING); + Components.injectInheritage(PlayerEntity.class, UUID_THING); Components.injectInheritage(World.class, SAVE_FLOAT); // Dynamic Injection diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 01cd0fb0f8..d6d9f102fc 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -37,7 +37,7 @@ @ListenerPhase( callbackTarget = ServerWorldTickEvents.End.class, - namespace = ComponentTestMod.MODID, path = "component_test_tick" + namespace = ComponentTestMod.MOD_ID, path = "component_test_tick" ) public class ServerTickListener implements ServerWorldTickEvents.End { @Override @@ -88,10 +88,11 @@ private void currentChunkBETick(ServerWorld world, Chunk chunk) { .map(chunk::getBlockEntity) .filter(Objects::nonNull) .forEach(blockEntity -> blockEntity.expose(ComponentTestMod.CHEST_NUMBER).ifJust(integerComponent -> { - integerComponent.decrement(); + integerComponent.setValue(integerComponent.getValue() - 1); integerComponent.save(); + integerComponent.sync(); - if (integerComponent.get() <= 0) { + if (integerComponent.getValue() <= 0) { world.setBlockState(blockEntity.getPos(), Blocks.DIAMOND_BLOCK.getDefaultState()); } })); @@ -103,7 +104,7 @@ private void hostileTick(ServerWorld world) { if (explodeTime.get() <= 200) { explodeTime.increment(); explodeTime.save(); - // explodeTime.sync(); // Causes mucho lag!! + explodeTime.sync(); // Causes mucho lag!! } else { hostile.getWorld().createExplosion( null, diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 72cfeb7be6..cddeae52ef 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -37,7 +37,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; -import org.quiltmc.qsl.component.test.component.InventoryComponent; +import org.quiltmc.qsl.component.test.component.InventorySerializable; public class TestBlockEntity extends BlockEntity { private final ComponentContainer container = ComponentContainer.builder(this) @@ -57,7 +57,7 @@ public static void tick(World world, BlockPos pos, Block return; } - if (blockEntity.expose(ComponentTestMod.CHUNK_INVENTORY).map(InventoryComponent::isEmpty).unwrapOr(true)) { + if (blockEntity.expose(ComponentTestMod.CHUNK_INVENTORY).map(InventorySerializable::isEmpty).unwrapOr(true)) { blockEntity.expose(ComponentTestMod.TEST_BE_INT).ifJust(integerComponent -> { if (integerComponent.get() % 40 == 0) { HashSet set = new HashSet<>(List.of(pos)); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventorySerializable.java similarity index 85% rename from library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventorySerializable.java index 0f48225cd4..f0115ff53a 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventoryComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/ChunkInventorySerializable.java @@ -24,18 +24,18 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.util.collection.DefaultedList; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.component.SyncedComponent; +import org.quiltmc.qsl.component.api.ComponentCreationContext; +import org.quiltmc.qsl.component.api.component.Syncable; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; -public class ChunkInventoryComponent implements InventoryComponent, SyncedComponent { +public class ChunkInventorySerializable implements InventorySerializable, Syncable { public static final NetworkCodec> NETWORK_CODEC = NetworkCodec.list(NetworkCodec.ITEM_STACK, value -> DefaultedList.ofSize(value, ItemStack.EMPTY)); private final DefaultedList stacks = DefaultedList.ofSize(1, ItemStack.EMPTY); - private final Operations ops; + private final ComponentCreationContext ops; - public ChunkInventoryComponent(Component.Operations ops) { + public ChunkInventorySerializable(ComponentCreationContext ops) { this.ops = ops; } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultFloatComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultFloatSerializable.java similarity index 79% rename from library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultFloatComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultFloatSerializable.java index 67b6b24978..52be659c4a 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultFloatComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultFloatSerializable.java @@ -21,19 +21,19 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtFloat; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.component.NbtComponent; +import org.quiltmc.qsl.component.api.ComponentCreationContext; +import org.quiltmc.qsl.component.api.component.NbtSerializable; -public class DefaultFloatComponent implements NbtComponent { +public class DefaultFloatSerializable implements NbtSerializable { @Nullable private final Runnable saveOperation; private float value; - public DefaultFloatComponent(Component.Operations ops) { + public DefaultFloatSerializable(ComponentCreationContext ops) { this(ops, 0); } - public DefaultFloatComponent(Component.Operations ops, float initialValue) { + public DefaultFloatSerializable(ComponentCreationContext ops, float initialValue) { this.value = initialValue; this.saveOperation = ops.saveOperation(); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultIntegerComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultIntegerSerializable.java similarity index 58% rename from library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultIntegerComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultIntegerSerializable.java index 6a926a1df6..0539ff6443 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultIntegerComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultIntegerSerializable.java @@ -16,26 +16,25 @@ package org.quiltmc.qsl.component.test.component; -import org.jetbrains.annotations.Nullable; - import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtInt; +import net.minecraft.network.PacketByteBuf; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.qsl.component.api.ComponentCreationContext; +import org.quiltmc.qsl.component.api.component.NbtSerializable; +import org.quiltmc.qsl.component.api.component.Syncable; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.component.NbtComponent; - -public class DefaultIntegerComponent implements NbtComponent { - @Nullable - private final Runnable saveOperation; +public class DefaultIntegerSerializable implements NbtSerializable, Syncable { + private final ComponentCreationContext ops; private int value; - public DefaultIntegerComponent(Component.Operations ops) { + public DefaultIntegerSerializable(ComponentCreationContext ops) { this(ops, 0); } - public DefaultIntegerComponent(Component.Operations ops, int defaultValue) { + public DefaultIntegerSerializable(ComponentCreationContext ops, int defaultValue) { this.value = defaultValue; - this.saveOperation = ops.saveOperation(); + this.ops = ops; } public void increment() { @@ -71,6 +70,27 @@ public NbtInt write() { @Override public @Nullable Runnable getSaveOperation() { - return this.saveOperation; + return this.ops.saveOperation(); + } + + @Override + public void writeToBuf(PacketByteBuf buf) { + buf.writeVarInt(this.value); + } + + @Override + public void readFromBuf(PacketByteBuf buf) { + this.value = buf.readVarInt(); + } + + @Override + public @Nullable Runnable getSyncOperation() { + return this.ops.syncOperation(); + } + + @Override + public void save() { + NbtSerializable.super.save(); + this.sync(); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultInventoryComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultInventorySerializable.java similarity index 78% rename from library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultInventoryComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultInventorySerializable.java index 5c6de28183..90ea4d03a7 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultInventoryComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/DefaultInventorySerializable.java @@ -24,19 +24,19 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.collection.DefaultedList; -import org.quiltmc.qsl.component.api.Component; +import org.quiltmc.qsl.component.api.ComponentCreationContext; -public class DefaultInventoryComponent implements InventoryComponent { +public class DefaultInventorySerializable implements InventorySerializable { private final DefaultedList stacks; @Nullable private final Runnable saveOperation; - public DefaultInventoryComponent(Component.Operations ops, int size) { + public DefaultInventorySerializable(ComponentCreationContext ops, int size) { this.stacks = DefaultedList.ofSize(size, ItemStack.EMPTY); this.saveOperation = ops.saveOperation(); } - public DefaultInventoryComponent(Component.Operations ops, Supplier> stacks) { + public DefaultInventorySerializable(ComponentCreationContext ops, Supplier> stacks) { this.stacks = stacks.get(); this.saveOperation = ops.saveOperation(); } @@ -59,7 +59,7 @@ public int hashCode() { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof DefaultInventoryComponent that)) return false; + if (!(o instanceof DefaultInventorySerializable that)) return false; return this.stacks.equals(that.stacks); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/InventoryComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/InventorySerializable.java similarity index 93% rename from library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/InventoryComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/InventorySerializable.java index c2c6cf99ed..6402546318 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/InventoryComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/InventorySerializable.java @@ -24,9 +24,9 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.util.collection.DefaultedList; -import org.quiltmc.qsl.component.api.component.NbtComponent; +import org.quiltmc.qsl.component.api.component.NbtSerializable; -public interface InventoryComponent extends NbtComponent, Inventory { +public interface InventorySerializable extends NbtSerializable, Inventory { @Override default int size() { return this.getStacks().size(); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatSerializable.java similarity index 81% rename from library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java rename to library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatSerializable.java index 580aa9880a..645510ba24 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatComponent.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/component/SaveFloatSerializable.java @@ -21,16 +21,16 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.server.world.ServerWorld; -import org.quiltmc.qsl.component.api.Component; -import org.quiltmc.qsl.component.api.component.SyncedComponent; -import org.quiltmc.qsl.component.api.component.TickingComponent; +import org.quiltmc.qsl.component.api.ComponentCreationContext; +import org.quiltmc.qsl.component.api.component.Syncable; +import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; -public class SaveFloatComponent extends DefaultFloatComponent implements TickingComponent, SyncedComponent { +public class SaveFloatSerializable extends DefaultFloatSerializable implements Tickable, Syncable { private final Runnable syncOperation; - public SaveFloatComponent(Component.Operations ops) { + public SaveFloatSerializable(ComponentCreationContext ops) { super(ops); this.syncOperation = ops.syncOperation(); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index 9822bb1e9f..5489baf7ed 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -16,24 +16,25 @@ package org.quiltmc.qsl.component.test.mixin.client; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - +import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; - +import net.minecraft.util.math.Vec3d; import org.quiltmc.qsl.component.test.ComponentTestMod; -import org.quiltmc.qsl.component.test.component.DefaultIntegerComponent; -import org.quiltmc.qsl.component.test.component.SaveFloatComponent; +import org.quiltmc.qsl.component.test.component.DefaultIntegerSerializable; +import org.quiltmc.qsl.component.test.component.SaveFloatSerializable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(InGameHud.class) public abstract class MixinInGameHud { @@ -49,19 +50,36 @@ public abstract class MixinInGameHud { private void renderCustom(MatrixStack matrices, float tickDelta, CallbackInfo ci) { MinecraftClient.getInstance().world .expose(ComponentTestMod.SAVE_FLOAT) - .map(SaveFloatComponent::get) - .map(String::valueOf).ifJust(saveFloat -> this.getTextRenderer().draw(matrices, saveFloat, 10, 20, 0xfafafa)); + .map(SaveFloatSerializable::get) + .map(String::valueOf) + .ifJust(saveFloat -> this.getTextRenderer().draw(matrices, saveFloat, 10, 20, 0xfafafa)); Entity entity = MinecraftClient.getInstance().targetedEntity; if (entity != null) { entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME) - .map(DefaultIntegerComponent::get) - .ifJust(integer -> this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa)); + .map(DefaultIntegerSerializable::get) + .ifJust(integer -> this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa)); } ChunkPos chunkPos = MinecraftClient.getInstance().player.getChunkPos(); MinecraftClient.getInstance().world.getChunk(chunkPos.x, chunkPos.z).expose(ComponentTestMod.CHUNK_INVENTORY) - .map(defaultInventoryComponent -> defaultInventoryComponent.getStack(0)) - .ifJust(itemStack -> this.itemRenderer.renderInGui(itemStack, 10, 10)); + .map(defaultInventoryComponent -> defaultInventoryComponent.getStack(0)) + .ifJust(itemStack -> this.itemRenderer.renderInGui(itemStack, 10, 10)); + + MinecraftClient.getInstance().player.expose(ComponentTestMod.UUID_THING).ifJust(uuidField -> { + if (uuidField.getValue() == null) { + return; + } + var uuidString = uuidField.getValue().toString(); + MinecraftClient.getInstance().textRenderer.draw(matrices, uuidString, 10, 30, 0xFAFAFA); + }); + + Vec3d pos = MinecraftClient.getInstance().crosshairTarget.getPos(); + BlockPos lookAt = new BlockPos(pos); + BlockEntity blockEntity = MinecraftClient.getInstance().world.getBlockEntity(lookAt); + if (blockEntity != null) { + blockEntity.expose(ComponentTestMod.CHEST_NUMBER) + .ifJust(defaultIntegerSerializable -> System.out.println(defaultIntegerSerializable.getValue())); + } } } diff --git a/library/data/component/src/testmod/resources/quilt.mod.json b/library/data/component/src/testmod/resources/quilt.mod.json index 0572d5fa9c..4b12571a66 100644 --- a/library/data/component/src/testmod/resources/quilt.mod.json +++ b/library/data/component/src/testmod/resources/quilt.mod.json @@ -28,5 +28,6 @@ "quilt_block_entity" ] }, - "mixin": "quilt_component_test.mixins.json" + "mixin": "quilt_component_test.mixins.json", + "access_widener": "quilt_component_test.accesswidener" } diff --git a/library/data/component/src/main/resources/quilt_component.accesswidener b/library/data/component/src/testmod/resources/quilt_component_test.accesswidener similarity index 74% rename from library/data/component/src/main/resources/quilt_component.accesswidener rename to library/data/component/src/testmod/resources/quilt_component_test.accesswidener index 5d6895d1d7..dbb6ca20c2 100644 --- a/library/data/component/src/main/resources/quilt_component.accesswidener +++ b/library/data/component/src/testmod/resources/quilt_component_test.accesswidener @@ -1,4 +1,3 @@ accessWidener v2 named # Using this to make the default implementation of the BlockEntityTickInvoker interface accessible to mixin. -transitive-accessible class net/minecraft/world/chunk/WorldChunk$DirectBlockEntityTickInvoker transitive-extendable class net/minecraft/block/entity/BlockEntityType$BlockEntityFactory # TODO: Remove this when the issue is resolved. From a39fb1a64289fe2a847a5a0b76604e215ccc63c9 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sun, 24 Jul 2022 17:46:51 +0300 Subject: [PATCH 63/70] Fixed docs. --- .../qsl/component/api/ComponentFactory.java | 4 +- .../qsl/component/api/ComponentType.java | 47 ++++++------------- .../api/container/ComponentContainer.java | 19 ++++---- .../qsl/component/api/package-info.java | 4 +- 4 files changed, 28 insertions(+), 46 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java index 702ca3e751..737a37cc6e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java @@ -9,8 +9,8 @@ @FunctionalInterface public interface ComponentFactory { /** - * @param operations The {@link ComponentCreationContext} that the {@link Component} may use. + * @param ctx The {@link ComponentCreationContext} that can be used by the component. * @return A {@link T} instance. */ - T create(ComponentCreationContext operations); + T create(ComponentCreationContext ctx); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 3548e96dd6..6262a349db 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -17,7 +17,6 @@ package org.quiltmc.qsl.component.api; import net.minecraft.util.Identifier; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; @@ -26,14 +25,14 @@ import java.util.Map; /** - * A global identifier for a specific type of {@linkplain Component components}.
      + * A global identifier for a specific type of component.
      * This class must always exist as singleton instances, which have to be registered under the * {@linkplain Components#REGISTRY registry}. * * @param id The {@link Identifier} the type is registered with(it's here just for accesibility, however * you may also get access to it using the {@linkplain Components#REGISTRY registry} and a * {@link ComponentType} instance). - * @param defaultFactory A factory to a default {@link Component} instance, that this type may produce, + * @param defaultFactory A default factory for an instance of {@link T} instance, that this type may produce, * if no specific factory is defined under the container * {@link org.quiltmc.qsl.component.impl.injection.ComponentEntry}.
      * Used only during component injections or creation of @@ -42,9 +41,9 @@ * @param isInstant Whether this {@linkplain ComponentType type} will be instantly initialized when put in a * container. Useful for {@link Tickable}s or componens you want to initialize on * {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer container} creation. - * @param The generic type of {@link Component} this type will provide. Most of the time, you would + * @param The generic type of component this type will provide. Most of the time, you would * want this to be an interface providing all the needed API you may use to interact with a - * {@link Component} of this {@linkplain ComponentType type}. + * component of this {@linkplain ComponentType type}. * @author 0xJoeMama */ public record ComponentType(Identifier id, ComponentFactory defaultFactory, @@ -52,48 +51,30 @@ public record ComponentType(Identifier id, ComponentFactory defaultFactory /** * We provide a {@link NetworkCodec} to be used with manual registry sync, until the registry sync API is merged. */ - public static final NetworkCodec> NETWORK_CODEC = - NetworkCodec.VAR_INT.map( - Components.REGISTRY::getRawId, rawId -> ClientSyncHandler.getInstance().getType(rawId)); + public static final NetworkCodec> NETWORK_CODEC = NetworkCodec.VAR_INT.map( + Components.REGISTRY::getRawId, + rawId -> ClientSyncHandler.getInstance().getType(rawId) + ); /** * @see Static */ private static final Static STATIC_CACHE = new Static(); - /** - * Performed an unchecked unsafe cast on the provided component.
      - * Used to attempt to translate any {@linkplain Component normal component} into a specific type. - * - * @param component The {@link Component} the cast is to be performed on. - * @return Instead of letting the {@link ClassCastException} be thrown on invalid casts, we catch it and return - * {@link Maybe#nothing()} if the component cannot be cast. - * Otherwise, we just wrap the cast result into a {@link Maybe}. - */ - @SuppressWarnings("unchecked") - public Maybe cast(Object component) { - // TODO: SUS - try { - return Maybe.just((T) component); - } catch (ClassCastException ignored) { - return Maybe.nothing(); - } - } - /** * A {@linkplain ComponentType type} functions as its own {@link ComponentFactory} using the provided * {@link ComponentType#defaultFactory}. * - * @param operations The {@link ComponentCreationContext} that the {@link Component} may use. - * @return A {@link Component} of type {@link T}. + * @param ctx The {@link ComponentCreationContext} that the component can use. + * @return A component of type {@link T}. */ @Override - public T create(ComponentCreationContext operations) { + public T create(ComponentCreationContext ctx) { if (this.isStatic) { // First check for static components - return STATIC_CACHE.getOrCreate(this, operations); + return STATIC_CACHE.getOrCreate(this, ctx); } // Otherwise just create a new one. - return this.defaultFactory.create(operations); + return this.defaultFactory.create(ctx); } /** @@ -119,7 +100,7 @@ private Static() { } * * @param type The type of the component to be created. * @param operations The operations to use as initialization arguments. - * @param The type of {@linkplain Component component} to be created. + * @param The type of component to be created. * @return A singleton {@link C} instance. */ @SuppressWarnings("unchecked") diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index f0b1da90d3..5686f21ea7 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -37,7 +37,7 @@ import java.util.function.BiConsumer; /** - * A base container for all {@link Component}s that a {@link ComponentProvider} contains. + * A base container for all components that a {@link ComponentProvider} contains. * The implementation of this, needs to not take up too much runtime, since the methods in here may be called really * often. *

      @@ -136,7 +136,8 @@ static ComponentContainer.Factory> createSingleF * * @see ComponentContainer#createSingleFactory(ComponentType) */ - static ComponentContainer.Factory> createSingleFactory(ComponentType type, ComponentFactory factory) { + static ComponentContainer.Factory> createSingleFactory(ComponentType type, + ComponentFactory factory) { return SingleComponentContainer.createFactory(new ComponentEntry<>(type, factory)); } @@ -169,7 +170,7 @@ static Builder builder(Object obj) { /** * The deepest level implementation of {@link org.quiltmc.qsl.component.api.Components#expose}.
      - * This takes in a wildcarded type and only returns a {@link Component} without casting it.
      + * This takes in a generic type and only returns a cast {@link C} instance. * This is type-unsafe and if not implemented correctly, may lead to crashes with {@link ClassCastException}s.
      * *

      @@ -179,7 +180,7 @@ static Builder builder(Object obj) { * @return Should return {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided {@link ComponentType} * is not contained in the current container. * Otherwise, should always return {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the contained - * {@link Component} instance. + * {@link C} instance. */ Maybe expose(ComponentType type); @@ -213,7 +214,7 @@ static Builder builder(Object obj) { * Most of the time this method is invoked by {@link ComponentContainer#tick}.
      * * @param provider The provider is passed in so that {@link SyncChannel#syncFromQueue} can use it, when creating a - * packet to sync data to the client. + * packet to sync data to the client. * @implNote The best way to sync components at the moment is using {@link SyncChannel#syncFromQueue}, which takes * in a {@link Queue} of components that need syncing. */ @@ -239,12 +240,12 @@ interface Factory { * * @param provider The {@link ComponentProvider} that will contain the created {@link ComponentContainer}. * @param entries A {@link List} containing all the entries that were manually added by the - * {@link Builder}. - * @param saveOperation The operation to be run by the contained {@link Component}s to mark the - * {@linkplain ComponentProvider provider} as needing to save. + * {@link Builder}. + * @param saveOperation The operation to be run by the contained components to mark the containing + * {@linkplain ComponentProvider provider} as needing to save. * @param ticking Whether this container can tick. * @param syncChannel The {@link SyncChannel} representing the {@link ComponentProvider} that contains the - * created {@link ComponentContainer}. + * created {@link ComponentContainer}. * @return A {@link ComponentContainer} created using the specified parameters. */ T generate(ComponentProvider provider, diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java index 10474b0bf0..c2bd776232 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java @@ -20,7 +20,7 @@ * Java is now gonna complain since we need 2 more things: the AComponent interface as well as the ADefaultComponent default class. * Creating them is as simple as this: *

      {@code
      - * public interface AComponent extends Component {
      + * public interface AComponent {
        *     void doSomething();
        *
        *     String getStringData();
      @@ -52,7 +52,7 @@
        * The {@link org.quiltmc.qsl.component.api.ComponentType} we have created does exist, but nothing actually exposes it's interface.
      * For that to happen we need to inject our type into game objects. *

      - * Game Objects that can have {@linkplain org.quiltmc.qsl.component.api.Component components} injected to them are by convention called {@link org.quiltmc.qsl.component.api.provider.ComponentProvider}s.
      + * Game Objects that can have components injected to them are by convention called {@link org.quiltmc.qsl.component.api.provider.ComponentProvider}s.
      * The {@linkplain org.quiltmc.qsl.component.api.provider.ComponentProvider providers} implemented by default are the following: *

        *
      • BlockEntity
      • From 4b0e39fc81c4f76fcd35c3cf23f8a7aa247fd3af Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Sun, 24 Jul 2022 19:26:24 +0300 Subject: [PATCH 64/70] Revamped the way to perform injections. --- .../qsl/component/api/ComponentType.java | 3 +- .../quiltmc/qsl/component/api/Components.java | 95 ++--------------- .../api/container/ComponentContainer.java | 2 +- .../injection/ComponentEntry.java | 42 +++++++- .../api/injection/ComponentInjector.java | 100 ++++++++++++++++++ .../predicate/DynamicInjectionPredicate.java | 2 +- .../predicate/InjectionPredicate.java | 2 +- .../qsl/component/api/sync/SyncChannel.java | 5 +- .../qsl/component/impl/CommonInitializer.java | 4 +- .../qsl/component/impl/ComponentsImpl.java | 20 ++-- .../container/AbstractComponentContainer.java | 2 +- .../container/LazyComponentContainer.java | 2 +- .../container/OnAccessComponentContainer.java | 2 +- .../container/SimpleComponentContainer.java | 2 +- .../container/SingleComponentContainer.java | 2 +- .../injection/manager/InjectionManager.java | 31 +++--- .../cached/CachedInjectionManager.java | 4 +- .../dynamic/DynamicInjectionManager.java | 4 +- .../cached/ClassInjectionPredicate.java | 20 +--- .../DynamicClassInjectionPredicate.java | 2 +- .../dynamic/DynamicWrappedPredicate.java | 4 +- .../resources/quilt_component.mixins.json | 1 + .../qsl/component/test/ComponentTestMod.java | 63 +++++++---- 23 files changed, 244 insertions(+), 170 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/{impl => api}/injection/ComponentEntry.java (53%) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{ => injection}/predicate/DynamicInjectionPredicate.java (92%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/{ => injection}/predicate/InjectionPredicate.java (91%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 6262a349db..8ce8eb03eb 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -18,6 +18,7 @@ import net.minecraft.util.Identifier; import org.quiltmc.qsl.component.api.component.Tickable; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; @@ -34,7 +35,7 @@ * {@link ComponentType} instance). * @param defaultFactory A default factory for an instance of {@link T} instance, that this type may produce, * if no specific factory is defined under the container - * {@link org.quiltmc.qsl.component.impl.injection.ComponentEntry}.
        + * {@link ComponentEntry}.
        * Used only during component injections or creation of * {@linkplain org.quiltmc.qsl.component.api.container.ComponentContainer containers}. * @param isStatic Whether this {@linkplain ComponentType type} works as a static type. diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 5dc701f924..21463acb73 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -16,26 +16,20 @@ package org.quiltmc.qsl.component.api; +import org.jetbrains.annotations.ApiStatus; + import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; -import org.jetbrains.annotations.ApiStatus; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.component.Tickable; -import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; -import org.quiltmc.qsl.component.impl.injection.predicate.cached.FilteredInheritedInjectionPredicate; -import org.quiltmc.qsl.component.impl.injection.predicate.cached.InheritedInjectionPredicate; -import org.quiltmc.qsl.component.impl.injection.predicate.cached.RedirectedInjectionPredicate; -import org.quiltmc.qsl.component.impl.injection.predicate.dynamic.DynamicClassInjectionPredicate; import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import java.util.Set; -import java.util.function.Predicate; - /** * The external version of the component API, meant to be used by modders.
        * Use this and not {@link ComponentsImpl}.
        @@ -56,10 +50,12 @@ public final class Components { // end registry // begin injection methods - /** * The most manual method of injection.
        - * Callers can provide custom {@link InjectionPredicate}s and also custom {@linkplain ComponentEntry entries} + * Callers can provide custom {@link InjectionPredicate}s and also custom {@linkplain ComponentEntry entries}. + * + *

        + * For users who wish to use an easier method of injection, see {@link org.quiltmc.qsl.component.api.injection.ComponentInjector}. * * @param predicate The {@linkplain InjectionPredicate predicate} used for the injection * @param entry The {@linkplain ComponentEntry entry} used for the injection. @@ -70,79 +66,9 @@ public final class Components { public static void inject(InjectionPredicate predicate, ComponentEntry entry) { ComponentsImpl.inject(predicate, entry); } - - /** - * The simplest method of injection.
        - * Injects the provided {@link ComponentType} into all direct instances of the provided {@link Class}. - * - * @param clazz The target class(must implement {@link ComponentProvider}). - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is - * used). - * @param The type held by the injected type. - * @see ClassInjectionPredicate - */ - public static void inject(Class clazz, ComponentType type) { - ComponentsImpl.inject(new ClassInjectionPredicate(clazz), new ComponentEntry<>(type)); - } - - /** - * Similar to {@link Components#inject(Class, ComponentType)} except it injects into all subclasses and indirect - * instances of the provided class. - * - * @param clazz The highest class in the hierarchy that will be injected. - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} is - * used). - * @param The type held by the injected type. - * @see InheritedInjectionPredicate - */ - public static void injectInheritage(Class clazz, ComponentType type) { - ComponentsImpl.inject(new InheritedInjectionPredicate(clazz), new ComponentEntry<>(type)); - } - - /** - * Similar to {@link Components#injectInheritage(Class, ComponentType)}, except it skips the provided classes in - * the hierarchy. - * - * @param clazz The highest class in the hierarchy that will be injected. - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the - * type} is used). - * @param exceptions The classes to avoid injecting into. - * @param The type help by the provided type. - * @see FilteredInheritedInjectionPredicate - */ - public static void injectInheritanceExcept(Class clazz, ComponentType type, Class... exceptions) { - ComponentsImpl.inject(new FilteredInheritedInjectionPredicate(clazz, exceptions), new ComponentEntry<>(type)); - } - - /** - * TODO: This is supposed to be merged with {@link Components#inject(Class, ComponentType)} and a mapping to - * redirections is to be created. - */ - public static void injectRedirected(Class mainClass, ComponentType type, Class... others) { - ComponentsImpl.inject(new RedirectedInjectionPredicate(mainClass, Set.of(others)), new ComponentEntry<>(type)); - } - - /** - * Dynamically injects into the provided {@link Class} using the provided predicate.
        - * For more info on dynamic injection check - * {@link org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate}; - * - * @param clazz The target class(must implement {@link ComponentProvider}). - * @param type The type to inject(the {@linkplain ComponentType#defaultFactory() default factory of the type} - * is used). - * @param predicate The predicate used to determine if injection is possible. - * @param The type of component that will be injected. - * @param

        The type of the provider that the dynamic injection targets. - */ - public static void injectDynamic(Class

        clazz, ComponentType type, - Predicate

        predicate) { - ComponentsImpl.inject(new DynamicClassInjectionPredicate<>(clazz, predicate), new ComponentEntry<>(type)); - } - // end injection methods // begin registration methods - /** * The proper way to expose component instances.
        * This does type-checking and also makes sure a {@link ComponentProvider} is given.
        @@ -151,7 +77,7 @@ public static void injectDynamic(Class

        clazz * * @param id The {@link ComponentType} to expose. * @param obj Any object will work. If it does not implement {@link ComponentProvider} an empty will be instantly - * returned. + * returned. * @param The type of component held by the {@link ComponentType}. * @param The object to attempt to expose the component on. * @return Either {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the result of expose called on the provider's @@ -222,6 +148,5 @@ public static ComponentType registerStatic(Identifier id, ComponentFactor public static ComponentType registerInstant(Identifier id, ComponentFactory factory) { return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, true)); } - // end registration method } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index 5686f21ea7..0e6bc85c02 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -29,7 +29,7 @@ import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.container.*; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import java.util.ArrayList; import java.util.List; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentEntry.java similarity index 53% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentEntry.java index 4bc96c7925..52c5c06541 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/ComponentEntry.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentEntry.java @@ -14,14 +14,25 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.impl.injection; +package org.quiltmc.qsl.component.api.injection; + +import java.util.Objects; import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.ComponentCreationContext; import org.quiltmc.qsl.component.api.ComponentFactory; import org.quiltmc.qsl.component.api.ComponentType; -public record ComponentEntry(ComponentType type, ComponentFactory factory) { +public class ComponentEntry { + private final ComponentType type; + private final ComponentFactory factory; + + public ComponentEntry(ComponentType type, ComponentFactory factory) { + this.type = type; + this.factory = factory; + } + public ComponentEntry(ComponentType type) { this(type, type.defaultFactory()); } @@ -29,4 +40,31 @@ public ComponentEntry(ComponentType type) { public C apply(@Nullable Runnable saveOperation, @Nullable Runnable syncOperation) { return this.factory.create(new ComponentCreationContext(saveOperation, syncOperation)); } + + public ComponentType type() { + return this.type; + } + + public ComponentFactory factory() { + return this.factory; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (ComponentEntry) obj; + return Objects.equals(this.type, that.type) && + Objects.equals(this.factory, that.factory); + } + + @Override + public int hashCode() { + return Objects.hash(this.type, this.factory); + } + + @Override + public String toString() { + return String.format("ComponentEntry[type=%s, factory=%s]", this.type, this.factory); + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java new file mode 100644 index 0000000000..8ae4a5580c --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java @@ -0,0 +1,100 @@ +package org.quiltmc.qsl.component.api.injection; + +import java.util.List; +import java.util.function.Predicate; + +import org.quiltmc.qsl.base.api.util.Maybe; +import org.quiltmc.qsl.component.api.ComponentFactory; +import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.Components; +import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; +import org.quiltmc.qsl.component.impl.injection.predicate.cached.FilteredInheritedInjectionPredicate; +import org.quiltmc.qsl.component.impl.injection.predicate.cached.InheritedInjectionPredicate; +import org.quiltmc.qsl.component.impl.injection.predicate.dynamic.DynamicWrappedPredicate; +import org.quiltmc.qsl.component.impl.util.ErrorUtil; + +public class ComponentInjector { + protected final Class target; + protected List> entries; + protected InjectionPredicate predicate; + + public ComponentInjector(Class target) { + this.target = target; + this.predicate = new ClassInjectionPredicate(this.target); + this.entries = List.of(); + } + + public static ComponentInjector injector(Class clazz) { + Class properClass = asProvider(clazz).>castUnchecked().unwrapOrThrow( + ErrorUtil.illegalArgument("Class %s is not a ComponentProvider implementor!") + ); + return new ComponentInjector<>(properClass); + } + + public static Maybe> asProvider(Class clazz) { + var currClass = clazz; + + while (currClass != null) { + for (Class currInterface : clazz.getInterfaces()) { + if (currInterface == ComponentProvider.class) { + // we can safely cast, since this method checks for that + return Maybe.just(clazz).castUnchecked(); + } + } + + currClass = clazz.getSuperclass(); + } + + return Maybe.nothing(); + } + + public ComponentInjector inherited() { + this.predicate = new InheritedInjectionPredicate(this.target); + return this; + } + + public ComponentInjector exclude(Class... classes) { + if (this.predicate instanceof InheritedInjectionPredicate) { + this.predicate = new FilteredInheritedInjectionPredicate(this.target, classes); + return this; + } + + throw new IllegalStateException("To exclude classes from an injection, the injection must be inherited!"); + } + + public ComponentInjector dynamic(Predicate dynamicCondition) { + this.predicate = new DynamicWrappedPredicate<>(this.predicate, dynamicCondition); + return this; + } + + public EntryBuilder entry(ComponentType type) { + return new EntryBuilder<>(type); + } + + public void inject() { + // TODO: Maybe create a vararg equivalent to the inject method + this.entries.forEach(entry -> Components.inject(this.predicate, entry)); + } + + public class EntryBuilder { + private final ComponentType type; + private ComponentFactory factory; + + public EntryBuilder(ComponentType type) { + this.type = type; + this.factory = type.defaultFactory(); + } + + public EntryBuilder factory(ComponentFactory factory) { + this.factory = factory; + return this; + } + + public ComponentInjector add() { + ComponentInjector.this.entries.add(new ComponentEntry<>(this.type, this.factory)); + return ComponentInjector.this; + } + } +} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/DynamicInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/predicate/DynamicInjectionPredicate.java similarity index 92% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/DynamicInjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/predicate/DynamicInjectionPredicate.java index 6b86d16d4e..67c6e2a6c5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/DynamicInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/predicate/DynamicInjectionPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.predicate; +package org.quiltmc.qsl.component.api.injection.predicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/InjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/predicate/InjectionPredicate.java similarity index 91% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/InjectionPredicate.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/predicate/InjectionPredicate.java index adfaf5934b..e61ff06a42 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/predicate/InjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/predicate/InjectionPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.quiltmc.qsl.component.api.predicate; +package org.quiltmc.qsl.component.api.injection.predicate; public interface InjectionPredicate { boolean isClassValid(Class clazz); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java index ac04998acf..5a1eb3763e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java @@ -163,6 +163,7 @@ public void send(Collection players, ComponentProvider provi ServerPlayNetworking.send(players.isEmpty() ? this.playerProvider.apply(providerAsP) : players, this.channelId, buf); } + // TODO: Figure out a way to avoid the unsafe casting if possible public void syncFromQueue(Queue> pendingSync, Function, Syncable> mapper, ComponentProvider provider) { this.syncFromQueue(pendingSync, mapper, provider, List.of()); } @@ -208,7 +209,7 @@ public void handleServerPushedSync(MinecraftClient client, PacketByteBuf buf) { public void handleClientSyncRequest(MinecraftServer server, ServerPlayerEntity sender, PacketByteBuf buf) { buf.retain(); server.execute(() -> { - Queue queued = this.queueCodec.decode(buf); // we retrive the queue of identifying data + Queue queued = this.queueCodec.decode(buf); // we retrieve the queue of identifying data while (!queued.isEmpty()) { var identifyingData = queued.poll(); @@ -218,7 +219,7 @@ public void handleClientSyncRequest(MinecraftServer server, ServerPlayerEntity s return; } - // force sync the target container + // force sync the target provider this.forceSync(provider, sender); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java index 9c177bece8..5e6040dcad 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/CommonInitializer.java @@ -16,8 +16,10 @@ package org.quiltmc.qsl.component.impl; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.ApiStatus; + +import net.minecraft.util.Identifier; + import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.component.impl.event.CommonEventListener; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 5fa48dcd15..aaa33dacd3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -16,24 +16,26 @@ package org.quiltmc.qsl.component.impl; +import java.util.ArrayList; +import java.util.List; + import com.mojang.serialization.Lifecycle; +import org.jetbrains.annotations.ApiStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.SimpleRegistry; -import org.jetbrains.annotations.ApiStatus; + import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; -import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.predicate.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.cached.CachedInjectionManager; import org.quiltmc.qsl.component.impl.injection.manager.dynamic.DynamicInjectionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; @ApiStatus.Internal public class ComponentsImpl { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index c7ec05944f..6ac9f1aea3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -28,7 +28,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 1ff04ed94b..bc60f2c5ed 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -24,7 +24,7 @@ import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import java.util.IdentityHashMap; import java.util.List; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index d59aa3ab52..621fc950af 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -23,7 +23,7 @@ import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import java.util.IdentityHashMap; import java.util.List; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 989e2f761d..4fcd65cf83 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -21,7 +21,7 @@ import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import java.util.IdentityHashMap; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java index e32b088b47..b495a3c6e5 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java @@ -27,7 +27,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import java.util.ArrayDeque; import java.util.List; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java index 2990a2ee59..36b77d7b06 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java @@ -16,41 +16,36 @@ package org.quiltmc.qsl.component.impl.injection.manager; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + import net.minecraft.util.Util; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; -import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import java.util.*; -import java.util.stream.Stream; - public abstract class InjectionManager

        { private final Map>> injections = new HashMap<>(); private final Map, List> cache = new IdentityHashMap<>(); + // TODO: See what happens when the type collides public void inject(P predicate, ComponentEntry componentEntry) { ComponentType type = componentEntry.type(); if (Components.REGISTRY.get(type.id()) == null) { throw ErrorUtil.illegalArgument("The target id %s does not match any registered component", type).get(); } - if (this.injections.containsKey(predicate)) { - List> componentEntries = this.injections.get(predicate); - if (componentEntries.stream().anyMatch(applied -> applied.type() == type)) { - throw ErrorUtil.illegalArgument( - "Cannot inject the predicate %s with id %s more than once! Consider creating a new component type!", - predicate, type.id() - ).get(); - } - - componentEntries.add(componentEntry); - } else { - this.injections.put(predicate, Util.make(new ArrayList<>(), injections -> injections.add(componentEntry))); - } + var targetBucket = this.injections.computeIfAbsent(predicate, p -> new ArrayList<>()); + targetBucket.add(componentEntry); this.cache.clear(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java index 860398a879..df46c9b3a0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java @@ -19,9 +19,9 @@ import java.util.List; import java.util.Objects; -import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; +import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.InjectionManager; public class CachedInjectionManager extends InjectionManager> { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java index 7351e351a0..f83d7d5473 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java @@ -22,9 +22,9 @@ import java.util.stream.Collectors; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.injection.predicate.DynamicInjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.injection.manager.InjectionManager; public class DynamicInjectionManager extends InjectionManager { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java index 19a6a5e0ff..83fbd518b9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/cached/ClassInjectionPredicate.java @@ -16,29 +16,15 @@ package org.quiltmc.qsl.component.impl.injection.predicate.cached; -import java.util.Arrays; -import java.util.Objects; +import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; -import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; -import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import org.quiltmc.qsl.component.impl.util.ErrorUtil; +import java.util.Objects; public class ClassInjectionPredicate implements InjectionPredicate { protected final Class clazz; public ClassInjectionPredicate(Class clazz) { - if (implementsComponentProvider(clazz)) { - this.clazz = clazz; - } else { - throw ErrorUtil.illegalArgument( - "Cannot create an injection predicate for a class that doesn't implement ComponentProvider" - ).get(); - } - } - - private static boolean implementsComponentProvider(Class clazz) { - return Arrays.stream(clazz.getInterfaces()).anyMatch(it -> it == ComponentProvider.class) - || (clazz.getSuperclass() != null && implementsComponentProvider(clazz.getSuperclass())); + this.clazz = clazz; } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java index 25714e05e9..db419a475d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicClassInjectionPredicate.java @@ -18,7 +18,7 @@ import java.util.function.Predicate; -import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.injection.predicate.DynamicInjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java index 685db1ec04..683f1b431b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/predicate/dynamic/DynamicWrappedPredicate.java @@ -18,8 +18,8 @@ import java.util.function.Predicate; -import org.quiltmc.qsl.component.api.predicate.DynamicInjectionPredicate; -import org.quiltmc.qsl.component.api.predicate.InjectionPredicate; +import org.quiltmc.qsl.component.api.injection.predicate.DynamicInjectionPredicate; +import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; public class DynamicWrappedPredicate

        implements DynamicInjectionPredicate { diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index ef1fe9460d..bbeb2cf459 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -3,6 +3,7 @@ "package": "org.quiltmc.qsl.component.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "RegistryAccessor", "block.entity.BlockEntityMixin", "block.entity.DirectBlockEntityTickInvokerMixin", "chunk.ChunkMixin", diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 198cfd4681..0f859e6867 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -16,7 +16,10 @@ package org.quiltmc.qsl.component.test; +import java.util.UUID; + import com.mojang.serialization.Codec; + import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.Blocks; @@ -39,7 +42,7 @@ import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.WorldChunk; + import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; import org.quiltmc.qsl.block.entity.api.QuiltBlockEntityTypeBuilder; @@ -47,12 +50,14 @@ import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.component.field.SyncedGenericSerializableField; +import org.quiltmc.qsl.component.api.injection.ComponentInjector; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; -import org.quiltmc.qsl.component.impl.injection.ComponentEntry; -import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; -import org.quiltmc.qsl.component.test.component.*; - -import java.util.UUID; +import org.quiltmc.qsl.component.test.component.ChunkInventorySerializable; +import org.quiltmc.qsl.component.test.component.DefaultFloatSerializable; +import org.quiltmc.qsl.component.test.component.DefaultIntegerSerializable; +import org.quiltmc.qsl.component.test.component.DefaultInventorySerializable; +import org.quiltmc.qsl.component.test.component.InventorySerializable; +import org.quiltmc.qsl.component.test.component.SaveFloatSerializable; public class ComponentTestMod implements ModInitializer { public static final String MOD_ID = "quilt_component_test"; @@ -152,21 +157,39 @@ public void onInitialize(ModContainer mod) { Block.STATE_IDS.add(TEST_BLOCK.getDefaultState()); // Cached Injection - Components.inject(CreeperEntity.class, CREEPER_EXPLODE_TIME); - Components.injectInheritage(CowEntity.class, COW_INVENTORY); - Components.injectInheritanceExcept(HostileEntity.class, HOSTILE_EXPLODE_TIME, CreeperEntity.class); - Components.inject(ChestBlockEntity.class, CHEST_NUMBER); - Components.injectInheritage(Chunk.class, CHUNK_INVENTORY); - Components.inject( - new ClassInjectionPredicate(WorldChunk.class), - new ComponentEntry<>(CHUNK_INVENTORY, ChunkInventorySerializable::new) - ); // Components.inject(MinecraftServer.class, SERVER_TICK); - Components.injectInheritage(ServerPlayerEntity.class, PLAYER_TICK); - Components.injectInheritage(PlayerEntity.class, UUID_THING); - Components.injectInheritage(World.class, SAVE_FLOAT); - - // Dynamic Injection + ComponentInjector.injector(CreeperEntity.class) + .entry(CREEPER_EXPLODE_TIME).add() + .inject(); + ComponentInjector.injector(Chunk.class) + .entry(CHUNK_INVENTORY).factory(ChunkInventorySerializable::new).add() + .inherited() + .inject(); + ComponentInjector.injector(CreeperEntity.class) + .entry(CREEPER_EXPLODE_TIME).add() + .inject(); + ComponentInjector.injector(HostileEntity.class) + .entry(HOSTILE_EXPLODE_TIME).add() + .inherited() + .exclude(CreeperEntity.class) + .inject(); + ComponentInjector.injector(ChestBlockEntity.class) + .entry(CHEST_NUMBER).add() + .inject(); + ComponentInjector.injector(CowEntity.class) + .entry(COW_INVENTORY).add() + .inject(); + ComponentInjector.injector(ServerPlayerEntity.class) + .entry(PLAYER_TICK).add() + .inject(); + ComponentInjector.injector(PlayerEntity.class) + .entry(UUID_THING).add() + .inherited() + .inject(); + ComponentInjector.injector(World.class) + .entry(SAVE_FLOAT).add() + .inherited() + .inject(); } public static final BlockEntityType TEST_BE_TYPE = From c51ed9b00471adc95b5904b63a32ae1f24b1d00f Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 25 Jul 2022 09:27:16 +0300 Subject: [PATCH 65/70] Removed invalid mixin --- .../resources/quilt_component.mixins.json | 1 - .../qsl/component/test/ComponentTestMod.java | 46 +++++++++---------- .../component/test/ServerTickListener.java | 5 ++ 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/library/data/component/src/main/resources/quilt_component.mixins.json b/library/data/component/src/main/resources/quilt_component.mixins.json index bbeb2cf459..ef1fe9460d 100644 --- a/library/data/component/src/main/resources/quilt_component.mixins.json +++ b/library/data/component/src/main/resources/quilt_component.mixins.json @@ -3,7 +3,6 @@ "package": "org.quiltmc.qsl.component.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "RegistryAccessor", "block.entity.BlockEntityMixin", "block.entity.DirectBlockEntityTickInvokerMixin", "chunk.ChunkMixin", diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 0f859e6867..4c21b91f7b 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -159,37 +159,37 @@ public void onInitialize(ModContainer mod) { // Cached Injection // Components.inject(MinecraftServer.class, SERVER_TICK); ComponentInjector.injector(CreeperEntity.class) - .entry(CREEPER_EXPLODE_TIME).add() - .inject(); + .entry(CREEPER_EXPLODE_TIME).add() + .inject(); ComponentInjector.injector(Chunk.class) - .entry(CHUNK_INVENTORY).factory(ChunkInventorySerializable::new).add() - .inherited() - .inject(); + .entry(CHUNK_INVENTORY).factory(ChunkInventorySerializable::new).add() + .inherited() + .inject(); ComponentInjector.injector(CreeperEntity.class) - .entry(CREEPER_EXPLODE_TIME).add() - .inject(); + .entry(CREEPER_EXPLODE_TIME).add() + .inject(); ComponentInjector.injector(HostileEntity.class) - .entry(HOSTILE_EXPLODE_TIME).add() - .inherited() - .exclude(CreeperEntity.class) - .inject(); + .entry(HOSTILE_EXPLODE_TIME).add() + .inherited() + .exclude(CreeperEntity.class) + .inject(); ComponentInjector.injector(ChestBlockEntity.class) - .entry(CHEST_NUMBER).add() - .inject(); + .entry(CHEST_NUMBER).add() + .inject(); ComponentInjector.injector(CowEntity.class) - .entry(COW_INVENTORY).add() - .inject(); + .entry(COW_INVENTORY).add() + .inject(); ComponentInjector.injector(ServerPlayerEntity.class) - .entry(PLAYER_TICK).add() - .inject(); + .entry(PLAYER_TICK).add() + .inject(); ComponentInjector.injector(PlayerEntity.class) - .entry(UUID_THING).add() - .inherited() - .inject(); + .entry(UUID_THING).add() + .inherited() + .inject(); ComponentInjector.injector(World.class) - .entry(SAVE_FLOAT).add() - .inherited() - .inject(); + .entry(SAVE_FLOAT).add() + .inherited() + .inject(); } public static final BlockEntityType TEST_BE_TYPE = diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index d6d9f102fc..0695d2588b 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -32,6 +32,7 @@ import net.minecraft.world.explosion.Explosion; import org.quiltmc.qsl.base.api.event.ListenerPhase; +import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; @@ -79,6 +80,10 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { } } + Components.expose(ComponentTestMod.CREEPER_EXPLODE_TIME, player).ifJust(defaultIntegerSerializable -> { + + }); + player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); }); } From b3ac896532cd874b391ec14ee63ed0ccfee14740 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 25 Jul 2022 12:27:12 +0300 Subject: [PATCH 66/70] Fixed various issues and resolved some todoes --- .../quiltmc/qsl/component/api/Components.java | 11 ++-- .../api/injection/ComponentInjector.java | 22 +++---- .../qsl/component/api/sync/SyncChannel.java | 33 ++++++++--- .../qsl/component/impl/ComponentsImpl.java | 6 +- .../container/AbstractComponentContainer.java | 59 ++++++++++--------- .../container/SingleComponentContainer.java | 34 +++++------ .../injection/manager/InjectionManager.java | 18 +++--- .../qsl/component/impl/util/level/Level.java | 43 ++++++++++++++ 8 files changed, 144 insertions(+), 82 deletions(-) create mode 100644 library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/level/Level.java diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index 21463acb73..de996a591c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -58,14 +58,14 @@ public final class Components { * For users who wish to use an easier method of injection, see {@link org.quiltmc.qsl.component.api.injection.ComponentInjector}. * * @param predicate The {@linkplain InjectionPredicate predicate} used for the injection - * @param entry The {@linkplain ComponentEntry entry} used for the injection. - * @param The type of the injected component. + * @param entries The {@linkplain ComponentEntry entries} that will be injected. * @see InjectionPredicate * @see ComponentEntry */ - public static void inject(InjectionPredicate predicate, ComponentEntry entry) { - ComponentsImpl.inject(predicate, entry); + public static void inject(InjectionPredicate predicate, ComponentEntry... entries) { + ComponentsImpl.inject(predicate, entries); } + // end injection methods // begin registration methods @@ -118,7 +118,7 @@ public static ComponentType register(Identifier id, ComponentType type public static ComponentType register(Identifier id, ComponentFactory factory) { if (factory instanceof ComponentType) { throw ErrorUtil.illegalArgument("Do NOT register ComponentTypes as factories, use the correct method") - .get(); + .get(); } return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, false)); @@ -148,5 +148,6 @@ public static ComponentType registerStatic(Identifier id, ComponentFactor public static ComponentType registerInstant(Identifier id, ComponentFactory factory) { return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, true)); } + // end registration method } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java index 8ae4a5580c..d3ae216355 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java @@ -1,14 +1,15 @@ package org.quiltmc.qsl.component.api.injection; +import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentFactory; import org.quiltmc.qsl.component.api.ComponentType; -import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.injection.predicate.cached.ClassInjectionPredicate; import org.quiltmc.qsl.component.impl.injection.predicate.cached.FilteredInheritedInjectionPredicate; import org.quiltmc.qsl.component.impl.injection.predicate.cached.InheritedInjectionPredicate; @@ -17,34 +18,34 @@ public class ComponentInjector { protected final Class target; - protected List> entries; + protected final List> entries; protected InjectionPredicate predicate; public ComponentInjector(Class target) { this.target = target; this.predicate = new ClassInjectionPredicate(this.target); - this.entries = List.of(); + this.entries = new ArrayList<>(); } public static ComponentInjector injector(Class clazz) { - Class properClass = asProvider(clazz).>castUnchecked().unwrapOrThrow( - ErrorUtil.illegalArgument("Class %s is not a ComponentProvider implementor!") + Class properClass = ComponentInjector.asProvider(clazz).unwrapOrThrow( + ErrorUtil.illegalArgument("Class %s is not a ComponentProvider implementor!", clazz) ); return new ComponentInjector<>(properClass); } - public static Maybe> asProvider(Class clazz) { + public static Maybe> asProvider(Class clazz) { var currClass = clazz; while (currClass != null) { - for (Class currInterface : clazz.getInterfaces()) { + for (Class currInterface : currClass.getInterfaces()) { if (currInterface == ComponentProvider.class) { - // we can safely cast, since this method checks for that + // we can safely cast, since the class implements ComponentProvider return Maybe.just(clazz).castUnchecked(); } } - currClass = clazz.getSuperclass(); + currClass = currClass.getSuperclass(); } return Maybe.nothing(); @@ -74,8 +75,7 @@ public EntryBuilder entry(ComponentType type) { } public void inject() { - // TODO: Maybe create a vararg equivalent to the inject method - this.entries.forEach(entry -> Components.inject(this.predicate, entry)); + ComponentsImpl.inject(this.predicate, this.entries.toArray(ComponentEntry[]::new)); } public class EntryBuilder { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java index 5a1eb3763e..aee15b1a4e 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java @@ -110,7 +110,6 @@ public class SyncChannel

        { provider -> PlayerLookup.all((MinecraftServer) provider) // only called server side so the cast is safe ); - // TODO: Do we need accessors for these fields? protected final Identifier channelId; protected final NetworkCodec codec; protected final Function identifyingDataTransformer; @@ -163,12 +162,11 @@ public void send(Collection players, ComponentProvider provi ServerPlayNetworking.send(players.isEmpty() ? this.playerProvider.apply(providerAsP) : players, this.channelId, buf); } - // TODO: Figure out a way to avoid the unsafe casting if possible - public void syncFromQueue(Queue> pendingSync, Function, Syncable> mapper, ComponentProvider provider) { - this.syncFromQueue(pendingSync, mapper, provider, List.of()); + public void syncFromQueue(Queue> pendingSync, ComponentProvider provider) { + this.syncFromQueue(pendingSync, provider, List.of()); } - public void syncFromQueue(Queue> pendingSync, Function, Syncable> mapper, ComponentProvider provider, Collection players) { + public void syncFromQueue(Queue> pendingSync, ComponentProvider provider, Collection players) { if (pendingSync.isEmpty()) { return; } @@ -179,7 +177,7 @@ public void syncFromQueue(Queue> pendingSync, Function>(); provider.getComponentContainer().forEach((type, component) -> { @@ -245,7 +242,7 @@ public void forceSync(ComponentProvider provider, ServerPlayerEntity sender) { } }); - this.syncFromQueue(queue, type -> ((Syncable) provider.expose(type).unwrap()), provider, Collections.singletonList(sender)); + this.syncFromQueue(queue, provider, Collections.singletonList(sender)); } @Environment(EnvType.CLIENT) @@ -271,6 +268,26 @@ public void sendMassRequests() { ClientPlayNetworking.send(this.channelId, buf); } + public NetworkCodec getCodec() { + return this.codec; + } + + public Function getIdentifyingDataTransformer() { + return this.identifyingDataTransformer; + } + + public Function getClientLocator() { + return this.clientLocator; + } + + public BiFunction getServerLocator() { + return this.serverLocator; + } + + public Function> getPlayerProvider() { + return this.playerProvider; + } + public Identifier getChannelId() { return this.channelId; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index aaa33dacd3..8d8ca02360 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -49,11 +49,11 @@ public class ComponentsImpl { public static final Logger LOGGER = LoggerFactory.getLogger("Quilt Component"); - public static void inject(InjectionPredicate predicate, ComponentEntry componentEntry) { + public static void inject(InjectionPredicate predicate, ComponentEntry... entries) { if (predicate instanceof DynamicInjectionPredicate dynamicPredicate) { - DYNAMIC_MANAGER.inject(dynamicPredicate, componentEntry); + DYNAMIC_MANAGER.inject(dynamicPredicate, entries); } else { - CACHED_MANAGER.inject(predicate, componentEntry); + CACHED_MANAGER.inject(predicate, entries); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index 6ac9f1aea3..f1859847b9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -16,25 +16,30 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Queue; +import java.util.function.Function; + +import org.jetbrains.annotations.Nullable; + import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.component.NbtSerializable; -import org.quiltmc.qsl.component.api.component.Syncable; import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; -import java.util.*; -import java.util.function.Function; - public abstract class AbstractComponentContainer implements ComponentContainer { protected final ContainerOperations operations; protected final List> nbtComponents; @@ -43,8 +48,8 @@ public abstract class AbstractComponentContainer implements ComponentContainer { protected final Maybe> syncContext; public AbstractComponentContainer(@Nullable Runnable saveOperation, - boolean ticking, - @Nullable SyncChannel syncChannel) { + boolean ticking, + @Nullable SyncChannel syncChannel) { this.ticking = ticking ? Maybe.just(new ArrayList<>()) : Maybe.nothing(); this.nbtComponents = new ArrayList<>(); this.syncContext = Maybe.wrap(syncChannel); @@ -59,9 +64,9 @@ public AbstractComponentContainer(@Nullable Runnable saveOperation, public void writeNbt(NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); this.nbtComponents.forEach(type -> this.expose(type) - .map(it -> ((NbtSerializable) it)) - .ifJust(nbtComponent -> NbtSerializable.writeTo( - rootQslNbt, nbtComponent, type.id())) + .map(it -> ((NbtSerializable) it)) + .ifJust(nbtComponent -> NbtSerializable.writeTo( + rootQslNbt, nbtComponent, type.id())) ); if (!rootQslNbt.isEmpty()) { @@ -74,20 +79,20 @@ public void readNbt(NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); rootQslNbt.getKeys().stream() - .map(Identifier::new) // All encoded component types *must* strictly be identifiers - .map(Components.REGISTRY::get) - .filter(Objects::nonNull) - .forEach(type -> this.expose(type) - .map(component -> ((NbtSerializable) component)) - .ifJust(component -> NbtSerializable.readFrom(component, type.id(), rootQslNbt))); + .map(Identifier::new) // All encoded component types *must* strictly be identifiers + .map(Components.REGISTRY::get) + .filter(Objects::nonNull) + .forEach(type -> this.expose(type) + .map(component -> ((NbtSerializable) component)) + .ifJust(component -> NbtSerializable.readFrom(component, type.id(), rootQslNbt))); } @Override public void tick(ComponentProvider provider) { this.ticking.ifJust(componentTypes -> componentTypes.forEach(type -> this.expose(type) - .map(it -> ((Tickable) it)) - .ifJust(tickingComponent -> tickingComponent.tick( - provider))) + .map(it -> ((Tickable) it)) + .ifJust(tickingComponent -> tickingComponent.tick( + provider))) ).ifNothing(() -> { throw ErrorUtil.illegalState("Attempted to tick a non-ticking container").get(); }); @@ -97,13 +102,10 @@ public void tick(ComponentProvider provider) { @Override public void sync(ComponentProvider provider) { - this.syncContext.ifJust(channel -> channel.syncFromQueue( - this.pendingSync.unwrap(), - type -> (Syncable) this.expose(type).unwrap(), - provider - )).ifNothing(() -> { - throw ErrorUtil.illegalState("Attempted to sync a non-syncable container!").get(); - }); + this.syncContext.ifJust(channel -> channel.syncFromQueue(this.pendingSync.unwrap(), provider)) + .ifNothing(() -> { + throw ErrorUtil.illegalState("Attempted to sync a non-syncable container!").get(); + }); } protected abstract void addComponent(ComponentType type, COMP component); @@ -131,6 +133,5 @@ protected COMP initializeComponent(ComponentEntry componentEntry) { return component; } - public record ContainerOperations(@Nullable Runnable saveOperation, - @Nullable Function, Runnable> syncOperationFactory) { } + public record ContainerOperations(@Nullable Runnable saveOperation, @Nullable Function, Runnable> syncOperationFactory) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java index b495a3c6e5..b162f8989d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java @@ -16,23 +16,24 @@ package org.quiltmc.qsl.component.impl.container; -import net.minecraft.nbt.NbtCompound; +import java.util.ArrayDeque; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + import org.jetbrains.annotations.Nullable; + +import net.minecraft.nbt.NbtCompound; + import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.component.NbtSerializable; -import org.quiltmc.qsl.component.api.component.Syncable; import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.api.injection.ComponentEntry; - -import java.util.ArrayDeque; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Supplier; public class SingleComponentContainer implements ComponentContainer { private final ComponentType type; @@ -41,8 +42,7 @@ public class SingleComponentContainer implements ComponentContainer { private Lazy entry; private boolean shouldSync = false; - protected SingleComponentContainer(ComponentType type, boolean ticking, - @Nullable SyncChannel syncChannel) { + protected SingleComponentContainer(ComponentType type, boolean ticking, @Nullable SyncChannel syncChannel) { this.type = type; this.ticking = ticking; this.syncChannel = Maybe.wrap(syncChannel); @@ -77,8 +77,8 @@ public void readNbt(NbtCompound providerRootNbt) { String idString = this.type.id().toString(); if (providerRootNbt.getKeys().contains(idString)) { this.expose(this.type) - .map(it -> ((NbtSerializable) it)) - .ifJust(nbtComponent -> NbtSerializable.readFrom(nbtComponent, this.type.id(), providerRootNbt)); + .map(it -> ((NbtSerializable) it)) + .ifJust(nbtComponent -> NbtSerializable.readFrom(nbtComponent, this.type.id(), providerRootNbt)); } } @@ -86,19 +86,15 @@ public void readNbt(NbtCompound providerRootNbt) { public void tick(ComponentProvider provider) { if (this.ticking) { this.expose(this.type) - .map(it -> ((Tickable) it)) - .ifJust(tickingComponent -> tickingComponent.tick(provider)); + .map(it -> ((Tickable) it)) + .ifJust(tickingComponent -> tickingComponent.tick(provider)); } } @Override public void sync(ComponentProvider provider) { if (this.shouldSync) { - this.syncChannel.ifJust(channel -> channel.syncFromQueue( - new ArrayDeque<>(List.of(this.type)), - type -> (Syncable) this.entry.get(), - provider - )); + this.syncChannel.ifJust(channel -> channel.syncFromQueue(new ArrayDeque<>(List.of(this.type)), provider)); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java index 36b77d7b06..82cb0ae4a2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java @@ -17,6 +17,7 @@ package org.quiltmc.qsl.component.impl.injection.manager; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; @@ -26,7 +27,6 @@ import net.minecraft.util.Util; import org.quiltmc.qsl.base.api.util.Maybe; -import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; @@ -37,15 +37,19 @@ public abstract class InjectionManager

        { private final Map>> injections = new HashMap<>(); private final Map, List> cache = new IdentityHashMap<>(); - // TODO: See what happens when the type collides - public void inject(P predicate, ComponentEntry componentEntry) { - ComponentType type = componentEntry.type(); - if (Components.REGISTRY.get(type.id()) == null) { - throw ErrorUtil.illegalArgument("The target id %s does not match any registered component", type).get(); + // When a type collides, one of the two variants will override the other one. + // That would mean only the last added type, will ever be properly processed. + public void inject(P predicate, ComponentEntry... entries) { + for (ComponentEntry entry : entries) { + var type = entry.type(); + + if (Components.REGISTRY.get(type.id()) == null) { + throw ErrorUtil.illegalArgument("The target id %s does not match any registered component", type).get(); + } } var targetBucket = this.injections.computeIfAbsent(predicate, p -> new ArrayList<>()); - targetBucket.add(componentEntry); + Collections.addAll(targetBucket, entries); this.cache.clear(); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/level/Level.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/level/Level.java new file mode 100644 index 0000000000..10c0e964c1 --- /dev/null +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/level/Level.java @@ -0,0 +1,43 @@ +package org.quiltmc.qsl.component.impl.util.level; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.server.MinecraftServer; + +import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.provider.ComponentProvider; +import org.quiltmc.qsl.component.api.sync.SyncChannel; + +public final class Level implements ComponentProvider { + private final boolean isClient; + private final ComponentContainer container; + @Nullable + private MinecraftServer server; + + private Level(boolean isClient) { + this.isClient = isClient; + var builder = ComponentContainer.builder(this); + if (!this.isClient) { + builder.syncing(SyncChannel.LEVEL).ticking().saving(this::save).build(ComponentContainer.LAZY_FACTORY); + } + this.container = builder.build(ComponentContainer.LAZY_FACTORY); + } + + public static Level createClient() { + return new Level(true); + } + + public static Level createServer(MinecraftServer server) { + Level level = new Level(false); + level.server = server; + return level; + } + + public void save() { + } + + @Override + public ComponentContainer getComponentContainer() { + return this.container; + } +} From 374134b354f988e779ea37cb7637c7cdf8ca39a4 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 1 Aug 2022 17:29:04 +0300 Subject: [PATCH 67/70] Component injections are now the responsibility of ComponentContainer.Builders --- .../api/ComponentCreationContext.java | 16 +++++++ .../qsl/component/api/ComponentFactory.java | 16 +++++++ .../api/component/field/GenericField.java | 16 +++++++ ...SerializableField.java => SavedField.java} | 10 ++--- ...izableField.java => SyncedSavedField.java} | 6 +-- .../api/container/ComponentContainer.java | 45 +++++++++++++------ .../api/injection/ComponentInjector.java | 16 +++++++ .../qsl/component/api/sync/SyncChannel.java | 9 +--- .../qsl/component/impl/ComponentsImpl.java | 2 +- .../container/AbstractComponentContainer.java | 3 +- .../container/LazyComponentContainer.java | 31 +++++++------ .../container/OnAccessComponentContainer.java | 27 ++++++----- .../container/SimpleComponentContainer.java | 19 ++++---- .../impl/util/ComponentProviderState.java | 2 + .../qsl/component/impl/util/level/Level.java | 16 +++++++ .../mixin/block/entity/BlockEntityMixin.java | 1 + .../qsl/component/mixin/chunk/ChunkMixin.java | 3 +- .../component/mixin/entity/EntityMixin.java | 3 +- .../qsl/component/test/ComponentTestMod.java | 13 +++--- .../test/mixin/client/MixinInGameHud.java | 32 ++++++------- 20 files changed, 189 insertions(+), 97 deletions(-) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/{GenericSerializableField.java => SavedField.java} (82%) rename library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/{SyncedGenericSerializableField.java => SyncedSavedField.java} (82%) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java index 0d68faeb25..baa43b0fbe 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api; import org.jetbrains.annotations.Nullable; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java index 737a37cc6e..c54aa5605c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentFactory.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api; /** diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericField.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericField.java index 1d92c97fcf..d52920e40f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericField.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericField.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.component.field; public interface GenericField { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericSerializableField.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SavedField.java similarity index 82% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericSerializableField.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SavedField.java index 2f4a2726ac..ccce982382 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/GenericSerializableField.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SavedField.java @@ -25,17 +25,17 @@ import org.quiltmc.qsl.component.api.component.NbtSerializable; import org.quiltmc.qsl.component.impl.ComponentsImpl; -public class GenericSerializableField implements GenericField, NbtSerializable { +public class SavedField implements GenericField, NbtSerializable { protected final Codec codec; @Nullable private final Runnable saveOperation; protected T value; - public GenericSerializableField(ComponentCreationContext ctx, Codec codec) { + public SavedField(ComponentCreationContext ctx, Codec codec) { this(ctx, codec, null); } - public GenericSerializableField(ComponentCreationContext ops, Codec codec, T defaultValue) { + public SavedField(ComponentCreationContext ops, Codec codec, T defaultValue) { this.saveOperation = ops.saveOperation(); this.codec = codec; this.value = defaultValue; @@ -68,8 +68,8 @@ public NbtCompound write() { var ret = new NbtCompound(); if (this.value != null) { this.codec.encodeStart(NbtOps.INSTANCE, this.value) - .resultOrPartial(ComponentsImpl.LOGGER::error) - .ifPresent(nbtElement -> ret.put("Value", nbtElement)); + .resultOrPartial(ComponentsImpl.LOGGER::error) + .ifPresent(nbtElement -> ret.put("Value", nbtElement)); } return ret; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SyncedGenericSerializableField.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SyncedSavedField.java similarity index 82% rename from library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SyncedGenericSerializableField.java rename to library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SyncedSavedField.java index d2631fdae9..9b3a68a205 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SyncedGenericSerializableField.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/field/SyncedSavedField.java @@ -25,18 +25,18 @@ import org.quiltmc.qsl.component.api.component.Syncable; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; -public class SyncedGenericSerializableField extends GenericSerializableField implements Syncable { +public class SyncedSavedField extends SavedField implements Syncable { private final NetworkCodec networkCodec; @Nullable private final Runnable syncOperation; - public SyncedGenericSerializableField(ComponentCreationContext ctx, Codec codec, NetworkCodec networkCodec) { + public SyncedSavedField(ComponentCreationContext ctx, Codec codec, NetworkCodec networkCodec) { super(ctx, codec); this.networkCodec = networkCodec; this.syncOperation = ctx.syncOperation(); } - public SyncedGenericSerializableField(ComponentCreationContext ops, Codec codec, NetworkCodec networkCodec, T defaultValue) { + public SyncedSavedField(ComponentCreationContext ops, Codec codec, NetworkCodec networkCodec, T defaultValue) { super(ops, codec, defaultValue); this.syncOperation = ops.syncOperation(); this.networkCodec = networkCodec; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index 0e6bc85c02..8cb4dd0a64 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -16,9 +16,16 @@ package org.quiltmc.qsl.component.api.container; -import net.minecraft.nbt.NbtCompound; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.function.BiConsumer; + import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; + +import net.minecraft.nbt.NbtCompound; + import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentFactory; @@ -26,15 +33,16 @@ import org.quiltmc.qsl.component.api.component.NbtSerializable; import org.quiltmc.qsl.component.api.component.Syncable; import org.quiltmc.qsl.component.api.component.Tickable; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.container.*; -import org.quiltmc.qsl.component.api.injection.ComponentEntry; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.function.BiConsumer; +import org.quiltmc.qsl.component.impl.ComponentsImpl; +import org.quiltmc.qsl.component.impl.container.CompositeComponentContainer; +import org.quiltmc.qsl.component.impl.container.EmptyComponentContainer; +import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; +import org.quiltmc.qsl.component.impl.container.OnAccessComponentContainer; +import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; +import org.quiltmc.qsl.component.impl.container.SingleComponentContainer; /** * A base container for all components that a {@link ComponentProvider} contains. @@ -249,7 +257,7 @@ interface Factory { * @return A {@link ComponentContainer} created using the specified parameters. */ T generate(ComponentProvider provider, - Lazy>> entries, + List> entries, @Nullable Runnable saveOperation, boolean ticking, @Nullable SyncChannel syncChannel @@ -263,16 +271,18 @@ T generate(ComponentProvider provider, */ class Builder { private final ComponentProvider provider; - private final Lazy>> injections; + private final List> entries; private boolean ticking; @Nullable private Runnable saveOperation; @Nullable private SyncChannel syncChannel; + private boolean acceptsInjections; private Builder(ComponentProvider provider) { this.provider = provider; - this.injections = Lazy.of(ArrayList::new); + this.entries = new ArrayList<>(); + this.acceptsInjections = false; this.saveOperation = null; this.syncChannel = null; } @@ -293,7 +303,7 @@ public Builder syncing(SyncChannel syncChannel) { } public Builder add(ComponentEntry componentEntry) { - this.injections.get().add(componentEntry); + this.entries.add(componentEntry); return this; } @@ -315,9 +325,18 @@ public Builder add(ComponentType... types) { return this; } + public Builder acceptsInjections() { + this.acceptsInjections = true; + return this; + } + public T build(ComponentContainer.Factory factory) { // TODO: See if we can cache the builder at some stage to reduce object creation. - return factory.generate(this.provider, this.injections, this.saveOperation, this.ticking, this.syncChannel); + if (this.acceptsInjections) { + this.entries.addAll(ComponentsImpl.getInjections(this.provider)); + } + + return factory.generate(this.provider, this.entries, this.saveOperation, this.ticking, this.syncChannel); } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java index d3ae216355..9c73995b92 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.api.injection; import java.util.ArrayList; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java index aee15b1a4e..aacc9722c8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java @@ -296,14 +296,7 @@ public Identifier getChannelId() { public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof SyncChannel that)) return false; - return Stream.of( - Objects.equals(this.channelId, that.channelId), - Objects.equals(this.codec, that.codec), - Objects.equals(this.identifyingDataTransformer, that.identifyingDataTransformer), - Objects.equals(this.clientLocator, that.clientLocator), - Objects.equals(this.serverLocator, that.serverLocator), - Objects.equals(this.playerProvider, that.playerProvider) - ).reduce(Boolean::logicalAnd).orElse(false); + return this.channelId.equals(that.channelId); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index 8d8ca02360..bc1f98f98f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -61,7 +61,7 @@ public static List> getInjections(ComponentProvider provider) var result = new ArrayList>(); result.addAll(CACHED_MANAGER.getInjections(provider)); result.addAll(DYNAMIC_MANAGER.getInjections(provider)); - return result; + return List.copyOf(result); } public static ComponentType register(Identifier id, ComponentType type) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index f1859847b9..50432f0471 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -65,8 +65,7 @@ public void writeNbt(NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); this.nbtComponents.forEach(type -> this.expose(type) .map(it -> ((NbtSerializable) it)) - .ifJust(nbtComponent -> NbtSerializable.writeTo( - rootQslNbt, nbtComponent, type.id())) + .ifJust(nbtComponent -> NbtSerializable.writeTo(rootQslNbt, nbtComponent, type.id())) ); if (!rootQslNbt.isEmpty()) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index bc60f2c5ed..b971f75c08 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -16,36 +16,36 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.function.BiConsumer; + import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.base.api.util.Lazy; import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.api.injection.ComponentEntry; - -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.function.BiConsumer; public class LazyComponentContainer extends AbstractComponentContainer { - public static final ComponentContainer.Factory FACTORY = - (provider, injections, saveOperation, ticking, syncChannel) -> - new LazyComponentContainer(provider, saveOperation, ticking, syncChannel); + public static final ComponentContainer.Factory FACTORY = LazyComponentContainer::new; + private final Map, Lazy>> components; protected LazyComponentContainer( ComponentProvider provider, + List> entries, @Nullable Runnable saveOperation, boolean ticking, @Nullable SyncChannel syncChannel ) { super(saveOperation, ticking, syncChannel); - this.components = this.createLazyMap(provider); + this.components = this.createLazyMap(entries, provider); } public static void move(LazyComponentContainer from, LazyComponentContainer into) { @@ -80,11 +80,10 @@ public void forEach(BiConsumer, ? super Object> action) { @Override protected void addComponent(ComponentType type, COMP component) { } - private Map, Lazy>> createLazyMap(ComponentProvider provider) { - // TODO: Consider adding a way to directly add components to the builder. + // TODO: Add provider as a parameter for the ComponentFactory create method. + private Map, Lazy>> createLazyMap(List> entries, ComponentProvider ignoredProvider) { var map = new IdentityHashMap, Lazy>>(); - ComponentsImpl.getInjections(provider) - .forEach(injection -> map.put(injection.type(), this.createLazy(injection))); + entries.forEach(componentEntry -> map.put(componentEntry.type(), this.createLazy(componentEntry))); return map; } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index 621fc950af..1df69c2221 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -16,33 +16,33 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; + import com.mojang.datafixers.util.Either; import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.ComponentsImpl; -import org.quiltmc.qsl.component.api.injection.ComponentEntry; - -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; // Suggestion from Technici4n from fabric. May help improve performance and memory footprint once done. public class OnAccessComponentContainer extends AbstractComponentContainer { - public static final Factory FACTORY = - (provider, injections, saveOperation, ticking, syncChannel) -> - new OnAccessComponentContainer(provider, saveOperation, ticking, syncChannel); + public static final Factory FACTORY = OnAccessComponentContainer::new; + private final Map, Either, Object>> components; protected OnAccessComponentContainer(ComponentProvider provider, + List> entries, @Nullable Runnable saveOperation, boolean ticking, @Nullable SyncChannel syncChannel) { super(saveOperation, ticking, syncChannel); - this.components = this.createComponents(provider); + this.components = this.createComponents(entries, provider); } @Override @@ -64,10 +64,9 @@ protected void addComponent(ComponentType type, COMP component) { this.components.put(type, Either.right(component)); } - private Map, Either, Object>> createComponents(ComponentProvider provider) { - List> injections = ComponentsImpl.getInjections(provider); + private Map, Either, Object>> createComponents(List> entries, ComponentProvider ignoredProvider) { var map = new IdentityHashMap, Either, Object>>(); - injections.forEach(entry -> { + entries.forEach(entry -> { ComponentType type = entry.type(); if (type.isStatic() || type.isInstant()) { this.initializeComponent(entry); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index 4fcd65cf83..a84d7bc888 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -16,24 +16,25 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.stream.Stream; + import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; -import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.api.injection.ComponentEntry; +import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.util.ErrorUtil; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.stream.Stream; - public class SimpleComponentContainer extends AbstractComponentContainer { public static final ComponentContainer.Factory FACTORY = - (provider, injections, saveOperation, ticking, syncChannel) -> new SimpleComponentContainer( - saveOperation, ticking, syncChannel, injections.get().stream() - ); + (provider, entries, saveOperation, ticking, syncChannel) -> + new SimpleComponentContainer(saveOperation, ticking, syncChannel, entries.stream()); + private final Map, Object> components; protected SimpleComponentContainer(@Nullable Runnable saveOperation, diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java index b02be176fa..15c3f537dc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java @@ -80,6 +80,7 @@ private LazyComponentContainer initLevelContainer(MinecraftServer server) { .saving(this::markDirty) .syncing(SyncChannel.LEVEL) .ticking() + .acceptsInjections() .build(ComponentContainer.LAZY_FACTORY); } @@ -88,6 +89,7 @@ private LazyComponentContainer initWorldContainer(ServerWorld world) { .saving(this::markDirty) .syncing(SyncChannel.WORLD) .ticking() + .acceptsInjections() .build(ComponentContainer.LAZY_FACTORY); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/level/Level.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/level/Level.java index 10c0e964c1..72ebf900d9 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/level/Level.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/level/Level.java @@ -1,3 +1,19 @@ +/* + * Copyright 2022 QuiltMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.quiltmc.qsl.component.impl.util.level; import org.jetbrains.annotations.Nullable; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java index 0e58d0eaf7..b3eea8b1d3 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java @@ -56,6 +56,7 @@ private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, Block .saving(this::markDirty) .ticking() .syncing(SyncChannel.BLOCK_ENTITY) + .acceptsInjections() .build(ComponentContainer.LAZY_FACTORY); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java index 90bb7555eb..53f73e4a7d 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java @@ -52,7 +52,8 @@ public ComponentContainer getComponentContainer() { @Inject(method = "", at = @At("RETURN")) private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, ChunkSection[] chunkSections, BlendingData blendingData, CallbackInfo ci) { LazyComponentContainer.Builder builder = ComponentContainer.builder(this) - .saving(() -> this.setNeedsSaving(true)); + .saving(() -> this.setNeedsSaving(true)) + .acceptsInjections(); if ((Chunk) (Object) this instanceof WorldChunk) { builder.syncing(SyncChannel.CHUNK).ticking(); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java index 3f9fda510e..5e00e5310c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java @@ -46,7 +46,8 @@ public ComponentContainer getComponentContainer() { @Inject(method = "", at = @At("RETURN")) private void onEntityInit(EntityType entityType, World world, CallbackInfo ci) { - var builder = ComponentContainer.builder(this); + var builder = ComponentContainer.builder(this) + .acceptsInjections(); if (!world.isClient) { builder.syncing(SyncChannel.ENTITY).ticking(); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index 4c21b91f7b..cd03854aca 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -49,7 +49,7 @@ import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.component.Tickable; -import org.quiltmc.qsl.component.api.component.field.SyncedGenericSerializableField; +import org.quiltmc.qsl.component.api.component.field.SyncedSavedField; import org.quiltmc.qsl.component.api.injection.ComponentInjector; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; import org.quiltmc.qsl.component.test.component.ChunkInventorySerializable; @@ -76,9 +76,9 @@ public class ComponentTestMod implements ModInitializer { new Identifier(MOD_ID, "hostile_explode_time"), DefaultIntegerSerializable::new ); - public static final ComponentType> CHEST_NUMBER = Components.register( + public static final ComponentType> CHEST_NUMBER = Components.register( new Identifier(MOD_ID, "chest_number"), - operations -> new SyncedGenericSerializableField<>(operations, Codec.INT, NetworkCodec.VAR_INT, 200) + operations -> new SyncedSavedField<>(operations, Codec.INT, NetworkCodec.VAR_INT, 200) ); public static final ComponentType CHUNK_INVENTORY = Components.register( new Identifier(MOD_ID, "chunk_inventory"), @@ -93,9 +93,9 @@ public class ComponentTestMod implements ModInitializer { new Identifier(ComponentTestMod.MOD_ID, "test_be_int"), DefaultIntegerSerializable::new ); - public static final ComponentType> UUID_THING = Components.register( + public static final ComponentType> UUID_THING = Components.register( new Identifier(MOD_ID, "uuid_thing"), - (ops) -> new SyncedGenericSerializableField<>(ops, Codecs.UUID, NetworkCodec.UUID) + (ops) -> new SyncedSavedField<>(ops, Codecs.UUID, NetworkCodec.UUID) ); public static final ComponentType PLAYER_TICK = Components.registerInstant( new Identifier(MOD_ID, "player_tick"), @@ -165,9 +165,6 @@ public void onInitialize(ModContainer mod) { .entry(CHUNK_INVENTORY).factory(ChunkInventorySerializable::new).add() .inherited() .inject(); - ComponentInjector.injector(CreeperEntity.class) - .entry(CREEPER_EXPLODE_TIME).add() - .inject(); ComponentInjector.injector(HostileEntity.class) .entry(HOSTILE_EXPLODE_TIME).add() .inherited() diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index 5489baf7ed..e097571b93 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -16,25 +16,24 @@ package org.quiltmc.qsl.component.test.mixin.client; -import net.minecraft.block.entity.BlockEntity; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.Vec3d; + import org.quiltmc.qsl.component.test.ComponentTestMod; import org.quiltmc.qsl.component.test.component.DefaultIntegerSerializable; import org.quiltmc.qsl.component.test.component.SaveFloatSerializable; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(InGameHud.class) public abstract class MixinInGameHud { @@ -74,12 +73,13 @@ private void renderCustom(MatrixStack matrices, float tickDelta, CallbackInfo ci MinecraftClient.getInstance().textRenderer.draw(matrices, uuidString, 10, 30, 0xFAFAFA); }); - Vec3d pos = MinecraftClient.getInstance().crosshairTarget.getPos(); - BlockPos lookAt = new BlockPos(pos); - BlockEntity blockEntity = MinecraftClient.getInstance().world.getBlockEntity(lookAt); - if (blockEntity != null) { - blockEntity.expose(ComponentTestMod.CHEST_NUMBER) - .ifJust(defaultIntegerSerializable -> System.out.println(defaultIntegerSerializable.getValue())); - } + // Vec3d pos = MinecraftClient.getInstance().crosshairTarget.getPos(); + // BlockPos lookAt = new BlockPos(pos); + // BlockEntity blockEntity = MinecraftClient.getInstance().world.getBlockEntity(lookAt); +// if (blockEntity != null) { +// blockEntity.expose(ComponentTestMod.CHEST_NUMBER) +// .ifJust(defaultIntegerSerializable -> System.out.println(defaultIntegerSerializable.getValue +// ())); +// } } } From 23b240ee1479d0d66ceeaeda3f94e3e362356e00 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Mon, 1 Aug 2022 18:10:27 +0300 Subject: [PATCH 68/70] Added the default component container factory that will be used. --- .../component/api/container/ComponentContainer.java | 1 + .../org/quiltmc/qsl/component/impl/ComponentsImpl.java | 5 +++++ .../component/impl/util/ComponentProviderState.java | 10 +++++----- .../component/mixin/block/entity/BlockEntityMixin.java | 3 ++- .../quiltmc/qsl/component/mixin/chunk/ChunkMixin.java | 3 ++- .../qsl/component/mixin/chunk/WorldChunkMixin.java | 10 ++++++++-- .../qsl/component/mixin/entity/EntityMixin.java | 3 ++- 7 files changed, 25 insertions(+), 10 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index 8cb4dd0a64..e0dd3bd970 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -169,6 +169,7 @@ static ComponentContainer createComposite(ComponentContainer main, ComponentCont * @throws UnsupportedOperationException If the provided object does not implement {@link ComponentProvider}. */ static Builder builder(Object obj) { + // TODO: Is there a way to avoid this instanceof check? if (!(obj instanceof ComponentProvider provider)) { throw new UnsupportedOperationException("Cannot create a container for a non-provider object"); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java index bc1f98f98f..360306b968 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/ComponentsImpl.java @@ -30,6 +30,7 @@ import net.minecraft.util.registry.SimpleRegistry; import org.quiltmc.qsl.component.api.ComponentType; +import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.injection.predicate.DynamicInjectionPredicate; import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; @@ -48,6 +49,10 @@ public class ComponentsImpl { public static final DynamicInjectionManager DYNAMIC_MANAGER = new DynamicInjectionManager(); public static final Logger LOGGER = LoggerFactory.getLogger("Quilt Component"); + public static final ComponentContainer.Factory DEFAULT_FACTORY = (provider, entries, saveOperation, ticking, syncChannel) -> + entries.isEmpty() ? + ComponentContainer.EMPTY : + ComponentContainer.LAZY_FACTORY.generate(provider, entries, saveOperation, ticking, syncChannel); public static void inject(InjectionPredicate predicate, ComponentEntry... entries) { if (predicate instanceof DynamicInjectionPredicate dynamicPredicate) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java index 15c3f537dc..e6ec5c751b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/util/ComponentProviderState.java @@ -29,7 +29,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; +import org.quiltmc.qsl.component.impl.ComponentsImpl; // TODO: Fix this public class ComponentProviderState extends PersistentState implements ComponentProvider { @@ -75,22 +75,22 @@ public ComponentContainer getComponentContainer() { return this.container; } - private LazyComponentContainer initLevelContainer(MinecraftServer server) { + private ComponentContainer initLevelContainer(MinecraftServer server) { return ComponentContainer.builder(server) .saving(this::markDirty) .syncing(SyncChannel.LEVEL) .ticking() .acceptsInjections() - .build(ComponentContainer.LAZY_FACTORY); + .build(ComponentsImpl.DEFAULT_FACTORY); } - private LazyComponentContainer initWorldContainer(ServerWorld world) { + private ComponentContainer initWorldContainer(ServerWorld world) { return ComponentContainer.builder(world) .saving(this::markDirty) .syncing(SyncChannel.WORLD) .ticking() .acceptsInjections() - .build(ComponentContainer.LAZY_FACTORY); + .build(ComponentsImpl.DEFAULT_FACTORY); } public static class ClientComponentProviderState implements ComponentProvider { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java index b3eea8b1d3..9eadf7b5fa 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/block/entity/BlockEntityMixin.java @@ -32,6 +32,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.quiltmc.qsl.component.impl.ComponentsImpl; @Mixin(BlockEntity.class) public abstract class BlockEntityMixin implements ComponentProvider { @@ -57,7 +58,7 @@ private void onInit(BlockEntityType blockEntityType, BlockPos blockPos, Block .ticking() .syncing(SyncChannel.BLOCK_ENTITY) .acceptsInjections() - .build(ComponentContainer.LAZY_FACTORY); + .build(ComponentsImpl.DEFAULT_FACTORY); } @Inject(method = "toNbt", at = @At("TAIL")) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java index 53f73e4a7d..f91c4fbe4b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/ChunkMixin.java @@ -34,6 +34,7 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; +import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; @Mixin(Chunk.class) @@ -59,6 +60,6 @@ private void onInit(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView builder.syncing(SyncChannel.CHUNK).ticking(); } - this.qsl$container = builder.build(ComponentContainer.LAZY_FACTORY); + this.qsl$container = builder.build(ComponentsImpl.DEFAULT_FACTORY); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java index 3ef5db10cd..3a8b4a5382 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/chunk/WorldChunkMixin.java @@ -40,13 +40,19 @@ @Mixin(WorldChunk.class) public abstract class WorldChunkMixin extends Chunk implements ComponentProvider { - public WorldChunkMixin(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry registry, long l, @Nullable ChunkSection[] chunkSections, @Nullable BlendingData blendingData) { + public WorldChunkMixin(ChunkPos chunkPos, UpgradeData upgradeData, HeightLimitView heightLimitView, + Registry registry, long l, @Nullable ChunkSection[] chunkSections, + @Nullable BlendingData blendingData) { super(chunkPos, upgradeData, heightLimitView, registry, l, chunkSections, blendingData); } - @Inject(method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/ProtoChunk;Lnet/minecraft/world/chunk/WorldChunk$PostLoadProcessor;)V", at = @At("TAIL")) + @Inject( + method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/ProtoChunk;Lnet/minecraft/world/chunk/WorldChunk$PostLoadProcessor;)V", + at = @At("TAIL") + ) private void copyComponentData(ServerWorld serverWorld, ProtoChunk protoChunk, WorldChunk.PostLoadProcessor postLoadProcessor, CallbackInfo ci) { var target = protoChunk instanceof ReadOnlyChunk readOnly ? readOnly.getWrappedChunk() : protoChunk; + // FIXME: Does not work and I have no idea why it did up to this point! it still captures the old reference LazyComponentContainer.move( (LazyComponentContainer) target.getComponentContainer(), (LazyComponentContainer) this.getComponentContainer() diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java index 5e00e5310c..f570f366b4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/entity/EntityMixin.java @@ -16,6 +16,7 @@ package org.quiltmc.qsl.component.mixin.entity; +import org.quiltmc.qsl.component.impl.ComponentsImpl; import org.quiltmc.qsl.component.impl.container.LazyComponentContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -53,7 +54,7 @@ private void onEntityInit(EntityType entityType, World world, CallbackInfo ci builder.syncing(SyncChannel.ENTITY).ticking(); } - this.qsl$container = builder.build(LazyComponentContainer.FACTORY); + this.qsl$container = builder.build(ComponentsImpl.DEFAULT_FACTORY); } @Inject(method = "writeNbt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;writeCustomDataToNbt(Lnet/minecraft/nbt/NbtCompound;)V")) From 64375492e199d39bbb8d3fbf59a840256ca754a3 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Tue, 9 Aug 2022 12:48:16 +0300 Subject: [PATCH 69/70] Nullificating Part 01 --- .../org/quiltmc/qsl/base/api/util/Lazy.java | 35 +- .../org/quiltmc/qsl/base/api/util/Maybe.java | 560 ------------------ .../api/ComponentCreationContext.java | 2 +- .../quiltmc/qsl/component/api/Components.java | 44 +- .../api/component/NbtSerializable.java | 2 +- .../api/container/ComponentContainer.java | 7 +- .../api/injection/ComponentInjector.java | 20 +- .../qsl/component/api/package-info.java | 5 +- .../api/provider/ComponentProvider.java | 20 +- .../qsl/component/api/sync/SyncChannel.java | 28 +- .../client/sync/ClientRegistryPacket.java | 8 +- .../container/AbstractComponentContainer.java | 90 +-- .../CompositeComponentContainer.java | 9 +- .../container/EmptyComponentContainer.java | 13 +- .../container/LazyComponentContainer.java | 37 +- .../container/OnAccessComponentContainer.java | 55 +- .../container/SimpleComponentContainer.java | 7 +- .../container/SingleComponentContainer.java | 40 +- .../injection/manager/InjectionManager.java | 8 +- .../cached/CachedInjectionManager.java | 2 +- .../dynamic/DynamicInjectionManager.java | 6 +- .../component/mixin/sync/WorldChunkMixin.java | 2 +- .../qsl/component/test/ComponentTestMod.java | 60 +- .../component/test/ServerTickListener.java | 15 +- .../quiltmc/qsl/component/test/TestBlock.java | 2 +- .../qsl/component/test/TestBlockEntity.java | 2 +- .../test/client/TestBlockEntityRenderer.java | 42 +- .../test/mixin/client/MixinInGameHud.java | 9 - 28 files changed, 321 insertions(+), 809 deletions(-) delete mode 100644 library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java index 24235d2ec2..b4de88eff2 100644 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java +++ b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Lazy.java @@ -20,6 +20,8 @@ import java.util.function.Function; import java.util.function.Supplier; +import org.jetbrains.annotations.Nullable; + /** * Represents a value that is only initialized once it's needed.
        * Similar to {@link com.google.common.base.Suppliers#memoize}. @@ -249,14 +251,15 @@ public T unwrapOrGet(Supplier defaultSupplier) { public static final class OfSupplier extends Lazy { private Supplier supplier; // There is no overhead to using a Maybe here since Maybe has statically evaluated returns for Nothing instances.. - private Maybe value; + @Nullable + private T value; /** * @param supplier The {@link Supplier} used to initialize the value. */ private OfSupplier(Supplier supplier) { this.supplier = supplier; - this.value = Maybe.nothing(); + this.value = null; } /** @@ -264,12 +267,12 @@ private OfSupplier(Supplier supplier) { */ @Override public T get() { - if (this.value.isNothing()) { - this.value = Maybe.just(this.supplier.get()); + if (this.value == null) { + this.value = this.supplier.get(); this.supplier = null; } - return this.value.unwrap(); + return this.value; } /** @@ -277,7 +280,7 @@ public T get() { */ @Override public Lazy map(Function mapper) { - return this.value.isJust() ? filled(mapper.apply(this.get())) : of(() -> mapper.apply(this.supplier.get())); + return this.value != null ? filled(mapper.apply(this.get())) : of(() -> mapper.apply(this.supplier.get())); } /** @@ -285,7 +288,7 @@ public Lazy map(Function mapper) { */ @Override public Lazy flatMap(Function> mapper) { - return this.value.isJust() ? mapper.apply(this.get()) : of(() -> mapper.apply(this.get()).get()); + return this.value != null ? mapper.apply(this.get()) : of(() -> mapper.apply(this.get()).get()); } /** @@ -293,7 +296,7 @@ public Lazy flatMap(Function> mapper) { */ @Override public boolean isFilled() { - return this.value.isJust(); + return this.value != null; } /** @@ -301,7 +304,10 @@ public boolean isFilled() { */ @Override public Lazy ifFilled(Consumer action) { - this.value.ifJust(action); + if (this.value != null) { + action.accept(this.value); + } + return this; } @@ -310,7 +316,10 @@ public Lazy ifFilled(Consumer action) { */ @Override public Lazy ifEmpty(Runnable action) { - this.value.ifNothing(action); + if (this.value == null) { + action.run(); + } + return this; } @@ -319,7 +328,7 @@ public Lazy ifEmpty(Runnable action) { */ @Override public boolean isEmpty() { - return this.value.isNothing(); + return this.value == null; } /** @@ -327,7 +336,7 @@ public boolean isEmpty() { */ @Override public T unwrapOr(T defaultValue) { - return this.value.unwrapOr(defaultValue); + return this.value != null ? this.value : defaultValue; } /** @@ -335,7 +344,7 @@ public T unwrapOr(T defaultValue) { */ @Override public T unwrapOrGet(Supplier defaultSupplier) { - return this.value.unwrapOrGet(defaultSupplier); + return this.value != null ? this.value : defaultSupplier.get(); } } } diff --git a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java b/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java deleted file mode 100644 index 04a4b61d32..0000000000 --- a/library/core/qsl_base/src/main/java/org/quiltmc/qsl/base/api/util/Maybe.java +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright 2022 QuiltMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.quiltmc.qsl.base.api.util; - -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.Supplier; - -/** - * Represents a monad that can either contain a value or no value.
        - * Similar to the {@link Optional} class but with some performance improvements - * and quality of life changes.
        - * - *

        - * Can either be {@link Just} or {@link Nothing}.
        - * {@link Just} instances contain a value of type {@link T}.
        - * {@link Nothing} instances all contain no data.
        - * - * @param The type of the wrapped object - * @author 0xJoeMama - */ -public abstract sealed class Maybe permits Maybe.Just, Maybe.Nothing { - /** - * Similar function to {@link Optional#ofNullable} function.
        - * Wraps a {@link T} value into an {@link Maybe}. - * - * @param value A {@link Nullable} value that will be wrapped into a {@link Maybe}. - * @param The type of object the {@link Maybe} instance will hold. - * @return An instance of {@link Just} if the provided value is not null,
        - * otherwise a {@link Nothing} instance. - * @see Optional#ofNullable - */ - public static Maybe wrap(@Nullable T value) { - return value != null ? just(value) : nothing(); - } - - /** - * Similar function to {@link Optional#of}.
        - * Wraps the provided value into a {@link Just} instance. - * - * @param value A {@linkplain org.jetbrains.annotations.NotNull non-null} value that is to be wrapped. - * @param The type of object the {@link Maybe} instance will hold. - * @return A {@link Just} instance containing the provided value. - * @see Optional#of - */ - public static Maybe just(T value) { - return new Just<>(value); - } - - /** - * Similar function to {@link Optional#empty()}. - * - * @param The type the {@link Nothing} instance will take the form of. - * @return A {@link Nothing} instance after casting it to the proper type. - * @see Optional#empty() - */ - public static Maybe nothing() { - return Nothing.INSTANCE.castUnchecked(); - } - - /** - * Converts an {@link Optional} into a {@link Maybe}.
        - * Exists for the sake of inter-operability. - * - * @param opt The {@link Optional} whose value will be wrapped in a {@link Maybe}. - * @param The type of the value, which the {@link Maybe} instance will contain. - * @return A {@link Maybe} instance containing the value contained in the provided {@link Optional}. - */ - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - // Obviously since we need to convert, the parameter is Optional. - public static Maybe fromOptional(Optional opt) { - return opt.map(Maybe::just).orElseGet(Maybe::nothing); - } - - /** - * Maps the internal value of this {@link Maybe} into a new {@link Maybe} with a different value
        - * using the provided {@link Function}. - * - * @param transformer A {@link T} -> {@link U} function used in the mapping process. - * @param The type of the value after the mapping operation. - * @return A new {@link Just} instance containing the mapped value if the current instance is a {@link Just}, - * otherwise {@link Nothing}. - * @see Optional#map - */ - public abstract Maybe map(Function transformer); - - /** - * Filters the current instance, based on whether it follows the provided {@link Predicate}. - * - * @param predicate A {@link Predicate} instance which may use the current value. - * @return The current instance if {@link Predicate#test} returns true, otherwise {@link Nothing}. - * @see Optional#filter - */ - public abstract Maybe filter(Predicate predicate); - - /** - * Filters the current instance based on whether mapping it with the provided {@link Function} provides - * {@link Nothing} or {@link Just}. - * Can be used as {@link Optional#flatMap} or as the bind operation of this monad. - * The table below explains in detail. - * - * @param transform A {@link Function} returning a {@link Maybe} instance instead of directly returning the - * mapping value. - * @param The value the returned {@link Maybe} will contain. - * @return

      - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
      ThisFunction ValueReturn Value
      {@link Just}{@link Nothing}{@link Nothing}
      {@link Nothing}Skipped{@link Nothing}
      {@link Just} A{@link Just} B{@link Just} B
      - * @see Optional#flatMap - */ - public abstract Maybe filterMap(Function> transform); - - /** - * Whether the current instance is {@link Nothing} or not. - * - * @return A boolean expressing the aforementioned fact. - * @see Optional#isEmpty() - */ - public abstract boolean isNothing(); - - /** - * Whether the current instance is {@link Just} or not. - * - * @return A boolean expressing the aforementioned fact. - * @see Optional#isPresent() - */ - public abstract boolean isJust(); - - /** - * Applies the provided {@link Consumer} to the current value, if the current instance is {@link Just}. - * - * @param action A {@link Consumer} that may use the current value. - * @return This instance(for chaining). - * @see Optional#ifPresent - */ - public abstract Maybe ifJust(Consumer action); - - /** - * Runs the provided {@link Runnable} if the current instance is {@link Nothing}. - * - * @param runnable The action to run. - * @return This instance(for chaining). - */ - public abstract Maybe ifNothing(Runnable runnable); - - /** - * Performs an operation similar to the boolean or operation on the current instance, using the one - * provided. - * The table below describes the different return values. - * - * @param supplier A {@link Supplier} of a {@link Maybe}, be it {@link Just} or {@link Nothing}. - * @return - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
      ThisSupplierReturn Value
      {@link Just}SkippedThis instance
      {@link Nothing}{@link Just}The created {@link Just}
      {@link Nothing}{@link Nothing}{@link Nothing}
      - * @see Optional#or - */ - public abstract Maybe or(Supplier> supplier); - - /** - * Performs an operation similar to the boolean and operation on the current instance using the one - * provided. - * The table below describes the different return values. - * - * @param other A {@link Supplier} of a {@link Maybe} instance, be it {@link Nothing} or {@link Just}. - * @return - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
      ThisSupplierReturn Value
      {@link Nothing}Skipped{@link Nothing}
      {@link Just}{@link Nothing}{@link Nothing}
      {@link Just} A{@link Just} B{@link Just} A
      - */ - public abstract Maybe and(Supplier> other); - - /** - * Returns the {@link T} value container in the current {@link Maybe} instance. - * - * @return The {@link T} value that was wrapped. - * @throws IllegalStateException if the current instance is {@link Nothing}. - * @see Optional#orElseThrow() - */ - public abstract T unwrap() throws IllegalStateException; - - /** - * Works like {@link Maybe#unwrap()} except that it doesn't throw if the current instance if {@link Nothing}. - * In that case it returns the provided {@link T} value. - * - * @param defaultValue The value to get if the current instance if {@link Nothing}. - * @return The current {@link T} value if the current instance is {@link Just}, otherwise the provided {@link T} - * value. - * @see Optional#orElse - */ - public abstract T unwrapOr(T defaultValue); - - /** - * Works like {@link Maybe#unwrapOr} except that it lazily evaluates the return value using the provided - * {@link Supplier}. - * - * @param supplier A {@link Supplier} that will create the {@link T} value to be returns if the current instance - * is {@link Nothing}. - * @return The current {@link T} value if the current instance if {@link Just}, - * otherwise the value produces by calling {@link Supplier#get()} on the provided {@link Supplier}. - * @see Optional#orElseGet - */ - public abstract T unwrapOrGet(Supplier supplier); - - /** - * Works like {@link Maybe#unwrap} except it throws the provided {@link Throwable} and not the default one. - * - * @param throwableSupplier The {@link Throwable} to throw. - * @return The contained value, if it exists. - * @throws E A customizable throwable. - */ - public abstract T unwrapOrThrow(Supplier throwableSupplier) throws E; - - /** - * Turns the current {@link Maybe} instance into an {@link Optional}, for inter-operability. - * - * @return {@link Optional#empty()} if the current instance is {@link Nothing}, - * otherwise an {@link Optional} containing the current value. - */ - public abstract Optional toOptional(); - - /** - * Attempts to perform and unchecked, unsafe cast on the current instance. - * - * @param The target type - * @return The cast instance. - */ - @SuppressWarnings("unchecked") - public Maybe castUnchecked() { - return (Maybe) this; - } - - /** - * The {@link Maybe} state representing the absence of a value. - * - * @param In this case this type parameter is unused. - */ - public static final class Nothing extends Maybe { - /** - * A singleton instance is used for Nothing since it doesn't contain data and can therefore be cast to any - * Maybe type. - */ - private static final Nothing INSTANCE = new Nothing<>(); - - private Nothing() { } - - /** - * @see Maybe#map - */ - @Override - public Maybe map(Function transformer) { - return nothing(); - } - - /** - * @see Maybe#filter - */ - @Override - public Maybe filter(Predicate predicate) { - return this; - } - - /** - * @see Maybe#filterMap - */ - @Override - public Maybe filterMap(Function> transform) { - return nothing(); - } - - /** - * @see Maybe#isNothing - */ - @Override - public boolean isNothing() { - return true; - } - - /** - * @see Maybe#isJust - */ - @Override - public boolean isJust() { - return false; - } - - /** - * @see Maybe#ifJust - */ - @Override - public Maybe ifJust(Consumer action) { - return this; - } - - /** - * @see Maybe#ifNothing - */ - @Override - public Maybe ifNothing(Runnable runnable) { - runnable.run(); - return this; - } - - /** - * @see Maybe#or - */ - @Override - public Maybe or(Supplier> supplier) { - return supplier.get(); - } - - /** - * @see Maybe#and - */ - @Override - public Maybe and(Supplier> other) { - return this; - } - - /** - * @see Maybe#unwrap - */ - @Override - public T unwrap() throws IllegalStateException { - throw new IllegalStateException("Attempted to unwrap a None!"); - } - - /** - * @see Maybe#unwrapOr - */ - @Override - public T unwrapOr(T defaultValue) { - return defaultValue; - } - - /** - * @see Maybe#unwrapOrGet - */ - @Override - public T unwrapOrGet(Supplier supplier) { - return supplier.get(); - } - - /** - * @see Maybe#unwrapOrThrow - */ - @Override - public T unwrapOrThrow(Supplier throwableSupplier) throws E { - throw throwableSupplier.get(); - } - - /** - * @see Maybe#toOptional - */ - @Override - public Optional toOptional() { - return Optional.empty(); - } - } - - /** - * The {@link Maybe} state representing the existence of a {@link T} value. - * - * @param The type of the contained value. - */ - public static final class Just extends Maybe { - private final T value; - - private Just(T value) { - this.value = value; - } - - /** - * @see Maybe#map - */ - @Override - public Maybe map(Function transformer) { - return just(transformer.apply(this.unwrap())); - } - - /** - * @see Maybe#filter - */ - @Override - public Maybe filter(Predicate predicate) { - return predicate.test(this.unwrap()) ? this : nothing(); - } - - /** - * @see Maybe#filterMap - */ - @Override - public Maybe filterMap(Function> transform) { - return transform.apply(this.unwrap()); - } - - /** - * @see Maybe#isNothing - */ - @Override - public boolean isNothing() { - return false; - } - - /** - * @see Maybe#isJust - */ - @Override - public boolean isJust() { - return true; - } - - /** - * @see Maybe#ifJust - */ - @Override - public Maybe ifJust(Consumer action) { - action.accept(this.unwrap()); - return this; - } - - /** - * @see Maybe#ifNothing - */ - @Override - public Maybe ifNothing(Runnable runnable) { - return this; - } - - /** - * @see Maybe#or - */ - @Override - public Maybe or(Supplier> supplier) { - return this; - } - - /** - * @see Maybe#and - */ - @Override - public Maybe and(Supplier> other) { - Maybe otherMaybe = other.get(); - return otherMaybe.isNothing() ? nothing() : this; - } - - /** - * @see Maybe#unwrap - */ - @Override - public T unwrap() { - return this.value; - } - - /** - * @see Maybe#unwrapOr - */ - @Override - public T unwrapOr(T defaultValue) { - return this.unwrap(); - } - - /** - * @see Maybe#unwrapOrGet - */ - @Override - public T unwrapOrGet(Supplier supplier) { - return this.unwrap(); - } - - /** - * @see Maybe#unwrapOrThrow - */ - @Override - public T unwrapOrThrow(Supplier throwableSupplier) { - return this.unwrap(); - } - - /** - * @see Maybe#toOptional - */ - @Override - public Optional toOptional() { - // Using Optional$of since our value should never be null! - return Optional.of(this.value); - } - } -} diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java index baa43b0fbe..18f06d0cc1 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentCreationContext.java @@ -28,7 +28,7 @@ * * @author 0xJoeMama */ -@SuppressWarnings("ClassCanBeRecord")// we want the class to be extendable to people can create their own Contexes +@SuppressWarnings("ClassCanBeRecord") // we want the class to be extendable to people can create their own Contexts public class ComponentCreationContext { private final @Nullable Runnable saveOperation; private final @Nullable Runnable syncOperation; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java index de996a591c..c0524a2404 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/Components.java @@ -16,13 +16,15 @@ package org.quiltmc.qsl.component.api; +import java.util.function.Consumer; + import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; @@ -50,12 +52,14 @@ public final class Components { // end registry // begin injection methods + /** * The most manual method of injection.
      * Callers can provide custom {@link InjectionPredicate}s and also custom {@linkplain ComponentEntry entries}. * *

      - * For users who wish to use an easier method of injection, see {@link org.quiltmc.qsl.component.api.injection.ComponentInjector}. + * For users who wish to use an easier method of injection, see + * {@link org.quiltmc.qsl.component.api.injection.ComponentInjector}. * * @param predicate The {@linkplain InjectionPredicate predicate} used for the injection * @param entries The {@linkplain ComponentEntry entries} that will be injected. @@ -68,33 +72,43 @@ public static void inject(InjectionPredicate predicate, ComponentEntry... ent // end injection methods - // begin registration methods /** * The proper way to expose component instances.
      * This does type-checking and also makes sure a {@link ComponentProvider} is given.
      * This should be used where interface injection cannot apply(in other words custom implementations of * {@link ComponentProvider}).
      * - * @param id The {@link ComponentType} to expose. - * @param obj Any object will work. If it does not implement {@link ComponentProvider} an empty will be instantly - * returned. - * @param The type of component held by the {@link ComponentType}. - * @param The object to attempt to expose the component on. - * @return Either {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the result of expose called on the provider's - * container - * or {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided object is not a + * @param type The {@link ComponentType} to expose. + * @param obj Any object will work. If it does not implement {@link ComponentProvider} an empty will be instantly + * returned. + * @param The type of component held by the {@link ComponentType}. + * @param The object to attempt to expose the component on. + * @return Either the result of expose called on the provider's container + * or null if the provided object is not a * {@link ComponentProvider}. * @see ComponentProvider#expose * @see org.quiltmc.qsl.component.api.container.ComponentContainer#expose */ - public static Maybe expose(ComponentType id, S obj) { + @Nullable + public static C expose(ComponentType type, S obj) { + if (obj instanceof ComponentProvider provider) { + return provider.getComponentContainer().expose(type); + } + + return null; + } + + @Nullable + public static C ifPresent(S obj, ComponentType type, Consumer action) { if (obj instanceof ComponentProvider provider) { - return provider.getComponentContainer().expose(id); + return provider.ifPresent(type, action); } - return Maybe.nothing(); + return null; } + // begin registration methods + /** * Register a manually created {@link ComponentType}. * @@ -118,7 +132,7 @@ public static ComponentType register(Identifier id, ComponentType type public static ComponentType register(Identifier id, ComponentFactory factory) { if (factory instanceof ComponentType) { throw ErrorUtil.illegalArgument("Do NOT register ComponentTypes as factories, use the correct method") - .get(); + .get(); } return ComponentsImpl.register(id, new ComponentType<>(id, factory, false, false)); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtSerializable.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtSerializable.java index 75e1aee212..88fd9f748b 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtSerializable.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/component/NbtSerializable.java @@ -23,7 +23,7 @@ public interface NbtSerializable { @SuppressWarnings("unchecked") - static void readFrom(NbtSerializable nbtSerializable, Identifier id, NbtCompound root) { + static void readFrom(NbtCompound root, NbtSerializable nbtSerializable, Identifier id) { NbtElement nbtTarget = root.get(id.toString()); switch (nbtSerializable.nbtType()) { case NbtElement.BYTE_TYPE -> ((NbtSerializable) nbtSerializable).read((NbtByte) nbtTarget); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index e0dd3bd970..b33901b7e0 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -27,7 +27,6 @@ import net.minecraft.nbt.NbtCompound; import org.quiltmc.qsl.base.api.util.Lazy; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentFactory; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.component.NbtSerializable; @@ -186,12 +185,12 @@ static Builder builder(Object obj) { * This method is called really often, so it is advised you make it have a really fast runtime. * * @param type The type to expose. - * @return Should return {@link org.quiltmc.qsl.base.api.util.Maybe.Nothing} if the provided {@link ComponentType} + * @return Should return null if the provided {@link ComponentType} * is not contained in the current container. - * Otherwise, should always return {@link org.quiltmc.qsl.base.api.util.Maybe.Just} the contained + * Otherwise, should always return the contained instance of {@link C} * {@link C} instance. */ - Maybe expose(ComponentType type); + C expose(ComponentType type); /** * Serializes the {@link NbtSerializable}s this {@linkplain ComponentContainer container} contains, into the diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java index 9c73995b92..6f1f9ca974 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/injection/ComponentInjector.java @@ -20,7 +20,8 @@ import java.util.List; import java.util.function.Predicate; -import org.quiltmc.qsl.base.api.util.Maybe; +import org.jetbrains.annotations.Nullable; + import org.quiltmc.qsl.component.api.ComponentFactory; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; @@ -44,27 +45,32 @@ public ComponentInjector(Class target) { } public static ComponentInjector injector(Class clazz) { - Class properClass = ComponentInjector.asProvider(clazz).unwrapOrThrow( - ErrorUtil.illegalArgument("Class %s is not a ComponentProvider implementor!", clazz) - ); + Class properClass = ComponentInjector.asProvider(clazz); + + if (properClass == null) { + throw ErrorUtil.illegalArgument("Class %s is not a ComponentProvider implementor!", clazz).get(); + } + return new ComponentInjector<>(properClass); } - public static Maybe> asProvider(Class clazz) { + @SuppressWarnings("unchecked") + @Nullable + public static Class asProvider(Class clazz) { var currClass = clazz; while (currClass != null) { for (Class currInterface : currClass.getInterfaces()) { if (currInterface == ComponentProvider.class) { // we can safely cast, since the class implements ComponentProvider - return Maybe.just(clazz).castUnchecked(); + return (Class) clazz; } } currClass = currClass.getSuperclass(); } - return Maybe.nothing(); + return null; } public ComponentInjector inherited() { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java index c2bd776232..f9e8f04890 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java @@ -104,9 +104,8 @@ *

        *
      1. You always get back the type that matches your {@link org.quiltmc.qsl.component.api.ComponentType}. In this case that would be an AComponent instance.
      2. *
      3. - * You always get back a {@link org.quiltmc.qsl.base.api.util.Maybe} instance. You need to use its methods to perform actions on the component. - * Furthermore it's not recommended to attempt to {@linkplain org.quiltmc.qsl.base.api.util.Maybe#unwrap() unwrap} the instance, because in the - * case the injection failed(for whatever reason), this will crash the game instance. + * You always get back a {@link org.jetbrains.annotations.Nullable} instance. + * You need to be careful using its methods to perform actions on the component. *
      4. *
      * diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java index fc009ecee1..0d1b766516 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/provider/ComponentProvider.java @@ -16,6 +16,10 @@ package org.quiltmc.qsl.component.api.provider; +import java.util.function.Consumer; + +import org.jetbrains.annotations.Nullable; + import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; @@ -24,7 +28,6 @@ import net.minecraft.world.chunk.Chunk; import org.quiltmc.qsl.base.api.util.InjectedInterface; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.container.ComponentContainer; @@ -84,9 +87,20 @@ default ComponentContainer getComponentContainer() { * * @param type The {@linkplain ComponentType type} we want to query. * @param The type of the held component. - * @return A {@link Maybe} instance following the rules defined in {@link Components#expose(ComponentType, Object)}. + * @return A {@link Nullable} object following the rules defined in {@link Components#expose(ComponentType, Object)}. */ - default Maybe expose(ComponentType type) { + @Nullable + default C expose(ComponentType type) { return this.getComponentContainer().expose(type); } + + @Nullable + default C ifPresent(ComponentType type, Consumer action) { + C component = this.expose(type); + if (component != null) { + action.accept(component); + } + + return component; + } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java index aacc9722c8..1baeef3d04 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java @@ -25,7 +25,6 @@ import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; -import java.util.stream.Stream; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -87,7 +86,8 @@ public class SyncChannel

      { Chunk::getPos, chunkPos -> ClientResolution.chunk(chunkPos), (serverPlayer, chunkPos) -> serverPlayer.getWorld().getChunk(chunkPos.x, chunkPos.z), - chunk -> PlayerLookup.tracking(((ServerWorld) ((WorldChunk) chunk).getWorld()), chunk.getPos()) // only called server side so the cast is safe + chunk -> PlayerLookup.tracking(((ServerWorld) ((WorldChunk) chunk).getWorld()), chunk.getPos()) + // only called server side so the cast is safe ); // **Careful**: This only works with WorldChunks not other chunk types! // World @@ -121,9 +121,9 @@ public class SyncChannel

      { protected final NetworkCodec> queueCodec; public SyncChannel(Identifier channelId, NetworkCodec codec, - Function identifyingDataTransformer, - Function clientLocator, BiFunction serverLocator, - Function> playerProvider) { + Function identifyingDataTransformer, + Function clientLocator, BiFunction serverLocator, + Function> playerProvider) { this.channelId = channelId; this.codec = codec; this.identifyingDataTransformer = identifyingDataTransformer; @@ -159,14 +159,16 @@ public void send(Collection players, ComponentProvider provi P providerAsP = (P) provider; var buf = this.toClientBuffer(providerAsP); // append provider data filler.fill(buf); // append all the container data - ServerPlayNetworking.send(players.isEmpty() ? this.playerProvider.apply(providerAsP) : players, this.channelId, buf); + ServerPlayNetworking.send( + players.isEmpty() ? this.playerProvider.apply(providerAsP) : players, this.channelId, buf); } public void syncFromQueue(Queue> pendingSync, ComponentProvider provider) { this.syncFromQueue(pendingSync, provider, List.of()); } - public void syncFromQueue(Queue> pendingSync, ComponentProvider provider, Collection players) { + public void syncFromQueue(Queue> pendingSync, ComponentProvider provider, + Collection players) { if (pendingSync.isEmpty()) { return; } @@ -177,7 +179,7 @@ public void syncFromQueue(Queue> pendingSync, ComponentProvider while (!pendingSync.isEmpty()) { var currentType = pendingSync.poll(); ComponentType.NETWORK_CODEC.encode(buf, currentType); // append type rawId - ((Syncable) provider.expose(currentType).unwrap()).writeToBuf(buf); // append component data + provider.ifPresent(currentType, o -> ((Syncable) o).writeToBuf(buf)); } }); } @@ -197,7 +199,7 @@ public void handleServerPushedSync(MinecraftClient client, PacketByteBuf buf) { for (int i = 0; i < size; i++) { ComponentType type = ComponentType.NETWORK_CODEC.decode(buf); // consume rawId - provider.expose(type).ifJust(component -> ((Syncable) component).readFromBuf(buf)); // consume component data + provider.ifPresent(type, o -> ((Syncable) o).readFromBuf(buf)); } buf.release(); // make sure the buffer is properly freed @@ -231,7 +233,8 @@ public void handleClientSyncRequest(MinecraftServer server, ServerPlayerEntity s * * @param provider The provider to force the sync on. * @param sender The client that requested the sync. - * @apiNote Avoid using this to sync components. Sync should be initiated from the server, unless specifically needed. + * @apiNote Avoid using this to sync components. Sync should be initiated from the server, unless specifically + * needed. */ public void forceSync(ComponentProvider provider, ServerPlayerEntity sender) { var queue = new ArrayDeque>(); @@ -301,7 +304,10 @@ public boolean equals(Object obj) { @Override public int hashCode() { - return Objects.hash(this.channelId, this.codec, this.identifyingDataTransformer, this.clientLocator, this.serverLocator, this.playerProvider); + return Objects.hash( + this.channelId, this.codec, this.identifyingDataTransformer, this.clientLocator, this.serverLocator, + this.playerProvider + ); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java index 5649170086..0d1a81635a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/client/sync/ClientRegistryPacket.java @@ -16,6 +16,7 @@ package org.quiltmc.qsl.component.impl.client.sync; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; @@ -28,7 +29,6 @@ import net.minecraft.util.collection.IdList; import net.minecraft.util.registry.Registry; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.networking.api.PacketByteBufs; @Environment(EnvType.CLIENT) @@ -53,12 +53,12 @@ public static Either, Identifier> createIdList(PacketByteBuf buf, Identifier id = buf.readIdentifier(); // consume identifier int rawId = buf.readVarInt(); // consumer rawId - Maybe type = Maybe.fromOptional(targetRegistry.getOrEmpty(id)); - if (type.isNothing()) { + Optional type = targetRegistry.getOrEmpty(id); + if (type.isEmpty()) { return Either.right(id); } - ret.set(type.unwrap(), rawId); + ret.set(type.get(), rawId); } return Either.left(ret); diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index 50432f0471..1b77177807 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -19,7 +19,6 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.Queue; import java.util.function.Function; @@ -28,7 +27,6 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.component.NbtSerializable; @@ -37,36 +35,43 @@ import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.sync.SyncChannel; -import org.quiltmc.qsl.component.impl.util.ErrorUtil; import org.quiltmc.qsl.component.impl.util.StringConstants; public abstract class AbstractComponentContainer implements ComponentContainer { protected final ContainerOperations operations; protected final List> nbtComponents; - protected final Maybe>> ticking; - protected final Maybe>> pendingSync; - protected final Maybe> syncContext; + @Nullable + protected final List> ticking; + @Nullable + protected final Queue> pendingSync; + @Nullable + protected final SyncChannel syncContext; public AbstractComponentContainer(@Nullable Runnable saveOperation, - boolean ticking, - @Nullable SyncChannel syncChannel) { - this.ticking = ticking ? Maybe.just(new ArrayList<>()) : Maybe.nothing(); + boolean ticking, + @Nullable SyncChannel syncChannel) { + this.ticking = ticking ? new ArrayList<>() : null; this.nbtComponents = new ArrayList<>(); - this.syncContext = Maybe.wrap(syncChannel); - this.pendingSync = this.syncContext.map(it -> new ArrayDeque<>()); + this.syncContext = syncChannel; + this.pendingSync = this.syncContext != null ? new ArrayDeque<>() : null; this.operations = new ContainerOperations( saveOperation, - type -> () -> this.pendingSync.ifJust(pending -> pending.add(type)) + type -> () -> { + if (this.pendingSync != null) { + this.pendingSync.add(type); + } + } ); } @Override public void writeNbt(NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); - this.nbtComponents.forEach(type -> this.expose(type) - .map(it -> ((NbtSerializable) it)) - .ifJust(nbtComponent -> NbtSerializable.writeTo(rootQslNbt, nbtComponent, type.id())) - ); + + for (ComponentType type : this.nbtComponents) { + Object current = this.expose(type); + NbtSerializable.writeTo(rootQslNbt, (NbtSerializable) current, type.id()); + } if (!rootQslNbt.isEmpty()) { providerRootNbt.put(StringConstants.COMPONENT_ROOT, rootQslNbt); @@ -77,34 +82,36 @@ public void writeNbt(NbtCompound providerRootNbt) { public void readNbt(NbtCompound providerRootNbt) { var rootQslNbt = providerRootNbt.getCompound(StringConstants.COMPONENT_ROOT); - rootQslNbt.getKeys().stream() - .map(Identifier::new) // All encoded component types *must* strictly be identifiers - .map(Components.REGISTRY::get) - .filter(Objects::nonNull) - .forEach(type -> this.expose(type) - .map(component -> ((NbtSerializable) component)) - .ifJust(component -> NbtSerializable.readFrom(component, type.id(), rootQslNbt))); + for (String nbtKey : rootQslNbt.getKeys()) { + var id = new Identifier(nbtKey); // All keys *must* be identifiers + var type = Components.REGISTRY.get(id); + + if (type != null) { + Object current = this.expose(type); + NbtSerializable.readFrom(rootQslNbt, (NbtSerializable) current, id); + } + } } @Override public void tick(ComponentProvider provider) { - this.ticking.ifJust(componentTypes -> componentTypes.forEach(type -> this.expose(type) - .map(it -> ((Tickable) it)) - .ifJust(tickingComponent -> tickingComponent.tick( - provider))) - ).ifNothing(() -> { - throw ErrorUtil.illegalState("Attempted to tick a non-ticking container").get(); - }); - - this.sync(provider); + if (this.ticking != null) { + for (ComponentType type : this.ticking) { + Object current = this.expose(type); + ((Tickable) current).tick(provider); + } + + this.sync(provider); + } } @Override public void sync(ComponentProvider provider) { - this.syncContext.ifJust(channel -> channel.syncFromQueue(this.pendingSync.unwrap(), provider)) - .ifNothing(() -> { - throw ErrorUtil.illegalState("Attempted to sync a non-syncable container!").get(); - }); + if (this.syncContext != null) { + this.syncContext.syncFromQueue(this.pendingSync, provider); + } else { + throw new UnsupportedOperationException("Attempted to sync a non-syncable container!"); + } } protected abstract void addComponent(ComponentType type, COMP component); @@ -121,16 +128,15 @@ protected COMP initializeComponent(ComponentEntry componentEntry) { this.nbtComponents.add(type); } - this.ticking.ifJust(componentTypes -> { - if (component instanceof Tickable) { - componentTypes.add(type); - } - }); + if (this.ticking != null) { + this.ticking.add(type); + } this.addComponent(type, component); return component; } - public record ContainerOperations(@Nullable Runnable saveOperation, @Nullable Function, Runnable> syncOperationFactory) { } + public record ContainerOperations(@Nullable Runnable saveOperation, + @Nullable Function, Runnable> syncOperationFactory) { } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java index 1dd2147adf..a30816cb68 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/CompositeComponentContainer.java @@ -18,9 +18,10 @@ import java.util.function.BiConsumer; +import org.jetbrains.annotations.Nullable; + import net.minecraft.nbt.NbtCompound; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; @@ -34,9 +35,11 @@ public CompositeComponentContainer(ComponentContainer main, ComponentContainer f this.fallback = fallback; } + @Nullable @Override - public Maybe expose(ComponentType type) { - return this.main.expose(type).or(() -> this.fallback.expose(type)); + public C expose(ComponentType type) { + C mainC = this.main.expose(type); + return mainC != null ? mainC : this.fallback.expose(type); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java index a79a4324f8..651ce957ef 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/EmptyComponentContainer.java @@ -16,14 +16,16 @@ package org.quiltmc.qsl.component.impl.container; +import java.util.function.BiConsumer; + +import org.jetbrains.annotations.Nullable; + import net.minecraft.nbt.NbtCompound; -import org.quiltmc.qsl.base.api.util.Maybe; + import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.provider.ComponentProvider; -import java.util.function.BiConsumer; - public final class EmptyComponentContainer implements ComponentContainer { public static final EmptyComponentContainer INSTANCE = new EmptyComponentContainer(); @@ -32,9 +34,10 @@ public final class EmptyComponentContainer implements ComponentContainer { private EmptyComponentContainer() { } + @Nullable @Override - public Maybe expose(ComponentType type) { - return Maybe.nothing(); + public C expose(ComponentType type) { + return null; } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index b971f75c08..146f6d6fe8 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -19,13 +19,11 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; -import java.util.Queue; import java.util.function.BiConsumer; import org.jetbrains.annotations.Nullable; import org.quiltmc.qsl.base.api.util.Lazy; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.injection.ComponentEntry; @@ -35,7 +33,7 @@ public class LazyComponentContainer extends AbstractComponentContainer { public static final ComponentContainer.Factory FACTORY = LazyComponentContainer::new; - private final Map, Lazy>> components; + private final Map, Lazy> components; protected LazyComponentContainer( ComponentProvider provider, @@ -54,26 +52,32 @@ public static void move(LazyComponentContainer from, LazyComponentContainer into })); into.nbtComponents.addAll(from.nbtComponents); - into.pendingSync.ifJust(intoPending -> from.pendingSync.ifJust(intoPending::addAll)); - into.ticking.ifJust(intoTicking -> from.ticking.ifJust(intoTicking::addAll)); + + if (into.pendingSync != null && from.pendingSync != null) { + into.pendingSync.addAll(from.pendingSync); + } + + if (into.ticking != null && from.ticking != null) { + into.ticking.addAll(from.ticking); + } from.components.clear(); from.nbtComponents.clear(); - from.ticking.ifJust(List::clear); - from.pendingSync.ifJust(Queue::clear); } + @SuppressWarnings("unchecked") @Override - public Maybe expose(ComponentType type) { - return this.components.containsKey(type) ? this.components.get(type).unwrap().castUnchecked() : - Maybe.nothing(); + public C expose(ComponentType type) { + // the cast to C should never fail since the only way the ComponentType instance can be a key is if the + // component is a C instance + return this.components.containsKey(type) ? (C) this.components.get(type) : null; } @Override public void forEach(BiConsumer, ? super Object> action) { // unwrap will work here since all Lazies are Just instances for this. this.components.forEach( - (type, componentLazy) -> componentLazy.ifFilled(component -> action.accept(type, component.unwrap())) + (type, componentLazy) -> componentLazy.ifFilled(component -> action.accept(type, component)) ); } @@ -81,20 +85,21 @@ public void forEach(BiConsumer, ? super Object> action) { protected void addComponent(ComponentType type, COMP component) { } // TODO: Add provider as a parameter for the ComponentFactory create method. - private Map, Lazy>> createLazyMap(List> entries, ComponentProvider ignoredProvider) { - var map = new IdentityHashMap, Lazy>>(); + private Map, Lazy> createLazyMap(List> entries, + ComponentProvider ignoredProvider) { + var map = new IdentityHashMap, Lazy>(); entries.forEach(componentEntry -> map.put(componentEntry.type(), this.createLazy(componentEntry))); return map; } - private Lazy> createLazy(ComponentEntry componentEntry) { + private Lazy createLazy(ComponentEntry componentEntry) { ComponentType type = componentEntry.type(); if (type.isStatic() || type.isInstant()) { var component = this.initializeComponent(componentEntry); - return Lazy.filled(Maybe.just(component)); // this cast will obviously never fail + return Lazy.filled(component); // this cast will obviously never fail } - return Lazy.of(() -> (Maybe.just(this.initializeComponent(componentEntry)))); // same here + return Lazy.of(() -> this.initializeComponent(componentEntry)); // same here } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java index 1df69c2221..2d840e1761 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/OnAccessComponentContainer.java @@ -24,7 +24,6 @@ import com.mojang.datafixers.util.Either; import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.provider.ComponentProvider; @@ -34,7 +33,8 @@ public class OnAccessComponentContainer extends AbstractComponentContainer { public static final Factory FACTORY = OnAccessComponentContainer::new; - private final Map, Either, Object>> components; + private final Map, ComponentEntry> supported; + private final Map, Object> components; protected OnAccessComponentContainer(ComponentProvider provider, List> entries, @@ -42,21 +42,31 @@ protected OnAccessComponentContainer(ComponentProvider provider, boolean ticking, @Nullable SyncChannel syncChannel) { super(saveOperation, ticking, syncChannel); + this.supported = new IdentityHashMap<>(); this.components = this.createComponents(entries, provider); } + @SuppressWarnings("unchecked") + @Nullable @Override - public Maybe expose(ComponentType type) { - return Maybe.fromOptional(this.components.get(type).right()) - .or(() -> this.supports(type) ? - Maybe.just(this.initializeComponent(this.components.get(type).left().orElseThrow())) : - Maybe.nothing()) - .castUnchecked(); + public C expose(ComponentType type) { + return (C) this.components.computeIfAbsent(type, innerType -> { + if (this.supported.containsKey(innerType)) { + ComponentEntry entry = this.supported.get(innerType); + + if (entry != null) { + this.supported.remove(innerType); + return this.initializeComponent(entry); + } + } + + return null; + }); } @Override public void forEach(BiConsumer, ? super Object> action) { - this.components.forEach((type, either) -> either.ifRight(component -> action.accept(type, component))); + this.components.forEach(action); } @Override @@ -64,21 +74,24 @@ protected void addComponent(ComponentType type, COMP component) { this.components.put(type, Either.right(component)); } - private Map, Either, Object>> createComponents(List> entries, ComponentProvider ignoredProvider) { - var map = new IdentityHashMap, Either, Object>>(); - entries.forEach(entry -> { + private Map, Object> createComponents(List> entries, + ComponentProvider ignoredProvider) { + var ret = new IdentityHashMap, Object>(); + + for (ComponentEntry entry : entries) { ComponentType type = entry.type(); - if (type.isStatic() || type.isInstant()) { - this.initializeComponent(entry); - } else { - map.put(type, Either.left(entry)); + + // If the type can be instantly initialized we initialize it! + if (type.isInstant() || type.isStatic()) { + ret.computeIfAbsent(type, innerType -> this.initializeComponent(entry)); + this.supported.remove(type); + continue; } - }); - return map; - } + // Otherwise we just mark it as supported + this.supported.putIfAbsent(type, entry); + } - private boolean supports(ComponentType type) { - return this.components.containsKey(type); + return ret; } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java index a84d7bc888..d5a0b289e2 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SimpleComponentContainer.java @@ -23,7 +23,6 @@ import org.jetbrains.annotations.Nullable; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.injection.ComponentEntry; @@ -47,9 +46,11 @@ protected SimpleComponentContainer(@Nullable Runnable saveOperation, types.close(); } + @Nullable + @SuppressWarnings("unchecked") @Override - public Maybe expose(ComponentType type) { - return Maybe.wrap(this.components.get(type)).castUnchecked(); + public C expose(ComponentType type) { + return (C) this.components.get(type); } @Override diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java index b162f8989d..2dfbd3c2dd 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/SingleComponentContainer.java @@ -26,7 +26,6 @@ import net.minecraft.nbt.NbtCompound; import org.quiltmc.qsl.base.api.util.Lazy; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.component.NbtSerializable; import org.quiltmc.qsl.component.api.component.Tickable; @@ -37,15 +36,17 @@ public class SingleComponentContainer implements ComponentContainer { private final ComponentType type; - private final Maybe> syncChannel; + @Nullable + private final SyncChannel syncChannel; private final boolean ticking; private Lazy entry; private boolean shouldSync = false; - protected SingleComponentContainer(ComponentType type, boolean ticking, @Nullable SyncChannel syncChannel) { + protected SingleComponentContainer(ComponentType type, boolean ticking, + @Nullable SyncChannel syncChannel) { this.type = type; this.ticking = ticking; - this.syncChannel = Maybe.wrap(syncChannel); + this.syncChannel = syncChannel; } public static ComponentContainer.Factory> createFactory(ComponentEntry entry) { @@ -58,9 +59,11 @@ public static ComponentContainer.Factory> create }; } + @SuppressWarnings("unchecked") + @Nullable @Override - public Maybe expose(ComponentType type) { - return (type == this.type ? Maybe.just(this.entry.get()) : Maybe.nothing()).castUnchecked(); + public C expose(ComponentType type) { + return type == this.type ? (C) this.entry.get() : null; } @Override @@ -76,25 +79,34 @@ public void writeNbt(NbtCompound providerRootNbt) { public void readNbt(NbtCompound providerRootNbt) { String idString = this.type.id().toString(); if (providerRootNbt.getKeys().contains(idString)) { - this.expose(this.type) - .map(it -> ((NbtSerializable) it)) - .ifJust(nbtComponent -> NbtSerializable.readFrom(nbtComponent, this.type.id(), providerRootNbt)); + T component = this.expose(this.type); + if (component instanceof NbtSerializable nbtComponent) { + NbtSerializable.readFrom(providerRootNbt, nbtComponent, this.type.id()); + } } } @Override public void tick(ComponentProvider provider) { if (this.ticking) { - this.expose(this.type) - .map(it -> ((Tickable) it)) - .ifJust(tickingComponent -> tickingComponent.tick(provider)); + T obj = this.expose(this.type); + if (obj == null) { + throw new UnsupportedOperationException("Attempted to tick a non-tickable container!"); + } + + ((Tickable) obj).tick(provider); } } @Override public void sync(ComponentProvider provider) { - if (this.shouldSync) { - this.syncChannel.ifJust(channel -> channel.syncFromQueue(new ArrayDeque<>(List.of(this.type)), provider)); + if (this.syncChannel != null) { + if (this.shouldSync) { + this.entry.ifFilled( + t -> this.syncChannel.syncFromQueue(new ArrayDeque<>(List.of(this.type)), provider)); + } + } else { + throw new UnsupportedOperationException("Attempted to sync a non-syncable container!"); } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java index 82cb0ae4a2..1aec622ae4 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/InjectionManager.java @@ -22,11 +22,11 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Stream; import net.minecraft.util.Util; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.injection.predicate.InjectionPredicate; @@ -60,12 +60,12 @@ protected Stream>>> streamEntries() { return this.injections.entrySet().stream(); } - protected Maybe> getCache(Class clazz) { + protected Optional> getCache(Class clazz) { if (!this.cache.containsKey(clazz)) { - return Maybe.nothing(); + return Optional.empty(); } - return Maybe.just(this.cache.get(clazz)); + return Optional.of(this.cache.get(clazz)); } protected void record(Class providerClass, List injections) { diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java index df46c9b3a0..a41d243f2f 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/cached/CachedInjectionManager.java @@ -28,7 +28,7 @@ public class CachedInjectionManager extends InjectionManager> getInjections(ComponentProvider provider) { Class providerClass = provider.getClass(); - return this.getCache(providerClass).unwrapOrGet(() -> { + return this.getCache(providerClass).orElseGet(() -> { List> componentEntries = this.initInjections(providerClass); this.record(providerClass, componentEntries); return componentEntries; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java index f83d7d5473..5dbbd0fd87 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/injection/manager/dynamic/DynamicInjectionManager.java @@ -18,10 +18,10 @@ import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Collectors; -import org.quiltmc.qsl.base.api.util.Maybe; import org.quiltmc.qsl.component.api.injection.predicate.DynamicInjectionPredicate; import org.quiltmc.qsl.component.api.provider.ComponentProvider; import org.quiltmc.qsl.component.api.injection.ComponentEntry; @@ -35,8 +35,8 @@ public List> getInjections(ComponentProvider provider) { return this.getCache(providerClass).or(() -> { var injections = this.initInjections(providerClass); this.record(providerClass, injections); - return Maybe.just(injections); - }).unwrap().stream() + return Optional.of(injections); + }).orElseGet(List::of).stream() .map(dynamicInjection -> dynamicInjection.test(provider) ? dynamicInjection.componentEntries() : null) // After check the dynamic side .filter(Objects::nonNull) .flatMap(List::stream) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java index c10135135f..be21f13606 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/mixin/sync/WorldChunkMixin.java @@ -30,7 +30,7 @@ @Mixin(WorldChunk.class) public class WorldChunkMixin { - @Inject(method = "method_31716", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V")) + @Inject(method = "m_pptwysxt", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;)V")) private void initialBlockEntitySync(BlockPos blockPos, BlockEntityType blockEntityType, NbtCompound nbtCompound, CallbackInfo ci) { SyncChannel.BLOCK_ENTITY.requestSync(blockPos); } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java index cd03854aca..d269e06138 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ComponentTestMod.java @@ -53,7 +53,6 @@ import org.quiltmc.qsl.component.api.injection.ComponentInjector; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; import org.quiltmc.qsl.component.test.component.ChunkInventorySerializable; -import org.quiltmc.qsl.component.test.component.DefaultFloatSerializable; import org.quiltmc.qsl.component.test.component.DefaultIntegerSerializable; import org.quiltmc.qsl.component.test.component.DefaultInventorySerializable; import org.quiltmc.qsl.component.test.component.InventorySerializable; @@ -108,16 +107,16 @@ public class ComponentTestMod implements ModInitializer { } var props = player.getWorld().getServer().getSaveProperties(); - if (props instanceof MinecraftServer levelProperties && player.getWorld().getTime() % 100 == 0) { - player.sendMessage(Text.literal( - levelProperties.expose(SAVE_FLOAT) - .map(DefaultFloatSerializable::get) - .unwrapOr(0f) - .toString() - ), false); + if (props instanceof MinecraftServer server && player.getWorld().getTime() % 100 == 0) { + server.ifPresent( + SAVE_FLOAT, + saveFloatSerializable -> player.sendMessage( + Text.literal(String.valueOf(saveFloatSerializable.get())), false + ) + ); } - player.expose(UUID_THING).ifJust(uuidGenericComponent -> { + player.ifPresent(UUID_THING, uuidGenericComponent -> { Entity vehicle = player.getVehicle(); if (vehicle != null) { @@ -157,36 +156,35 @@ public void onInitialize(ModContainer mod) { Block.STATE_IDS.add(TEST_BLOCK.getDefaultState()); // Cached Injection - // Components.inject(MinecraftServer.class, SERVER_TICK); ComponentInjector.injector(CreeperEntity.class) - .entry(CREEPER_EXPLODE_TIME).add() - .inject(); + .entry(CREEPER_EXPLODE_TIME).add() + .inject(); ComponentInjector.injector(Chunk.class) - .entry(CHUNK_INVENTORY).factory(ChunkInventorySerializable::new).add() - .inherited() - .inject(); + .entry(CHUNK_INVENTORY).factory(ChunkInventorySerializable::new).add() + .inherited() + .inject(); ComponentInjector.injector(HostileEntity.class) - .entry(HOSTILE_EXPLODE_TIME).add() - .inherited() - .exclude(CreeperEntity.class) - .inject(); + .entry(HOSTILE_EXPLODE_TIME).add() + .inherited() + .exclude(CreeperEntity.class) + .inject(); ComponentInjector.injector(ChestBlockEntity.class) - .entry(CHEST_NUMBER).add() - .inject(); + .entry(CHEST_NUMBER).add() + .inject(); ComponentInjector.injector(CowEntity.class) - .entry(COW_INVENTORY).add() - .inject(); + .entry(COW_INVENTORY).add() + .inject(); ComponentInjector.injector(ServerPlayerEntity.class) - .entry(PLAYER_TICK).add() - .inject(); + .entry(PLAYER_TICK).add() + .inject(); ComponentInjector.injector(PlayerEntity.class) - .entry(UUID_THING).add() - .inherited() - .inject(); + .entry(UUID_THING).add() + .inherited() + .inject(); ComponentInjector.injector(World.class) - .entry(SAVE_FLOAT).add() - .inherited() - .inject(); + .entry(SAVE_FLOAT).add() + .inherited() + .inject(); } public static final BlockEntityType TEST_BE_TYPE = diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java index 0695d2588b..2708ae429e 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/ServerTickListener.java @@ -32,7 +32,6 @@ import net.minecraft.world.explosion.Explosion; import org.quiltmc.qsl.base.api.event.ListenerPhase; -import org.quiltmc.qsl.component.api.ComponentType; import org.quiltmc.qsl.component.api.Components; import org.quiltmc.qsl.lifecycle.api.event.ServerWorldTickEvents; @@ -58,7 +57,7 @@ public void endWorldTick(MinecraftServer server, ServerWorld world) { } private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { - chunk.expose(ComponentTestMod.CHUNK_INVENTORY).ifJust(inventory -> { + chunk.ifPresent(ComponentTestMod.CHUNK_INVENTORY, inventory -> { ItemStack playerStack = player.getInventory().getStack(9); ItemStack stack = inventory.getStack(0); if (!playerStack.isEmpty()) { @@ -80,10 +79,6 @@ private void currentChunkTick(ServerPlayerEntity player, Chunk chunk) { } } - Components.expose(ComponentTestMod.CREEPER_EXPLODE_TIME, player).ifJust(defaultIntegerSerializable -> { - - }); - player.sendMessage(Text.literal(inventory.getStack(0).toString()), true); }); } @@ -92,7 +87,7 @@ private void currentChunkBETick(ServerWorld world, Chunk chunk) { chunk.getBlockEntityPositions().stream() .map(chunk::getBlockEntity) .filter(Objects::nonNull) - .forEach(blockEntity -> blockEntity.expose(ComponentTestMod.CHEST_NUMBER).ifJust(integerComponent -> { + .forEach(blockEntity -> blockEntity.ifPresent(ComponentTestMod.CHEST_NUMBER, integerComponent -> { integerComponent.setValue(integerComponent.getValue() - 1); integerComponent.save(); integerComponent.sync(); @@ -105,7 +100,7 @@ private void currentChunkBETick(ServerWorld world, Chunk chunk) { private void hostileTick(ServerWorld world) { world.getEntitiesByType(TypeFilter.instanceOf(HostileEntity.class), hostile -> true) - .forEach(hostile -> hostile.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME).ifJust(explodeTime -> { + .forEach(hostile -> hostile.ifPresent(ComponentTestMod.HOSTILE_EXPLODE_TIME, explodeTime -> { if (explodeTime.get() <= 200) { explodeTime.increment(); explodeTime.save(); @@ -123,7 +118,7 @@ private void hostileTick(ServerWorld world) { private void creeperTick(ServerWorld world) { world.getEntitiesByType(EntityType.CREEPER, creeper -> true) - .forEach(creeper -> Components.expose(ComponentTestMod.CREEPER_EXPLODE_TIME, creeper).ifJust(explodeTime -> { + .forEach(creeper -> Components.ifPresent(creeper, ComponentTestMod.CREEPER_EXPLODE_TIME, explodeTime -> { if (explodeTime.get() > 0) { explodeTime.decrement(); explodeTime.save(); @@ -135,7 +130,7 @@ private void creeperTick(ServerWorld world) { private void cowTick(ServerWorld world) { world.getEntitiesByType(TypeFilter.instanceOf(CowEntity.class), cowEntity -> true).forEach(entity -> - entity.expose(ComponentTestMod.COW_INVENTORY).ifJust(inventoryComponent -> { + entity.ifPresent(ComponentTestMod.COW_INVENTORY, inventoryComponent -> { if (inventoryComponent.isEmpty()) { world.createExplosion( entity, diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java index 61fdfc9ea3..68913277e4 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlock.java @@ -64,7 +64,7 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt if (!handStack.isEmpty()) { final MutableObject ret = new MutableObject<>(ActionResult.PASS); - be.expose(ComponentTestMod.CHUNK_INVENTORY).ifJust(inventoryComponent -> { + be.ifPresent(ComponentTestMod.CHUNK_INVENTORY, inventoryComponent -> { var stack = inventoryComponent.getStack(0); if (stack.isEmpty()) { diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index cddeae52ef..3a62991a68 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -58,7 +58,7 @@ public static void tick(World world, BlockPos pos, Block } if (blockEntity.expose(ComponentTestMod.CHUNK_INVENTORY).map(InventorySerializable::isEmpty).unwrapOr(true)) { - blockEntity.expose(ComponentTestMod.TEST_BE_INT).ifJust(integerComponent -> { + blockEntity.ifPresent(ComponentTestMod.TEST_BE_INT, integerComponent -> { if (integerComponent.get() % 40 == 0) { HashSet set = new HashSet<>(List.of(pos)); expand(pos, pos, world, set); diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java index 149cee0795..11a6cb1528 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/client/TestBlockEntityRenderer.java @@ -16,15 +16,12 @@ package org.quiltmc.qsl.component.test.client; -import java.util.function.Predicate; - import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.block.entity.BlockEntityRenderer; import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; import net.minecraft.util.math.Vec3f; import org.quiltmc.qsl.component.test.ComponentTestMod; @@ -32,24 +29,25 @@ public class TestBlockEntityRenderer implements BlockEntityRenderer { @Override - public void render(TestBlockEntity entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { - entity.expose(ComponentTestMod.CHUNK_INVENTORY) - .map(inventoryComponent -> inventoryComponent.getStack(0)) - .filter(Predicate.not(ItemStack::isEmpty)) - .ifJust(itemStack -> { - matrices.push(); - matrices.translate(0.5f, 1, 0.5f); - matrices.multiply(Vec3f.NEGATIVE_Y.getDegreesQuaternion(System.currentTimeMillis() % 360)); - MinecraftClient.getInstance().getItemRenderer().renderItem( - itemStack, - ModelTransformation.Mode.GROUND, - 0xffffff, - OverlayTexture.DEFAULT_UV, - matrices, - vertexConsumers, - 0 - ); - matrices.pop(); - }); + public void render(TestBlockEntity entity, float tickDelta, MatrixStack matrices, + VertexConsumerProvider vertexConsumers, int light, int overlay) { + entity.ifPresent(ComponentTestMod.CHUNK_INVENTORY, chunkInventorySerializable -> { + var itemStack = chunkInventorySerializable.getStack(0); + if (!itemStack.isEmpty()) { + matrices.push(); + matrices.translate(0.5f, 1, 0.5f); + matrices.multiply(Vec3f.NEGATIVE_Y.getDegreesQuaternion(System.currentTimeMillis() % 360)); + MinecraftClient.getInstance().getItemRenderer().renderItem( + itemStack, + ModelTransformation.Mode.GROUND, + 0xffffff, + OverlayTexture.DEFAULT_UV, + matrices, + vertexConsumers, + 0 + ); + matrices.pop(); + } + }); } } diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index e097571b93..e51217c1be 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -72,14 +72,5 @@ private void renderCustom(MatrixStack matrices, float tickDelta, CallbackInfo ci var uuidString = uuidField.getValue().toString(); MinecraftClient.getInstance().textRenderer.draw(matrices, uuidString, 10, 30, 0xFAFAFA); }); - - // Vec3d pos = MinecraftClient.getInstance().crosshairTarget.getPos(); - // BlockPos lookAt = new BlockPos(pos); - // BlockEntity blockEntity = MinecraftClient.getInstance().world.getBlockEntity(lookAt); -// if (blockEntity != null) { -// blockEntity.expose(ComponentTestMod.CHEST_NUMBER) -// .ifJust(defaultIntegerSerializable -> System.out.println(defaultIntegerSerializable.getValue -// ())); -// } } } From 541ef90b3430c4f979e2e21105be63351bde6b06 Mon Sep 17 00:00:00 2001 From: 0xJoeMama <0xjoemama@gmail.com> Date: Wed, 10 Aug 2022 16:25:02 +0300 Subject: [PATCH 70/70] Nullification Part 02 --- .../qsl/component/api/ComponentType.java | 15 ++--- .../api/container/ComponentContainer.java | 2 - .../qsl/component/api/package-info.java | 1 + .../qsl/component/api/sync/SyncChannel.java | 1 + .../container/AbstractComponentContainer.java | 2 +- .../container/LazyComponentContainer.java | 2 +- .../qsl/component/test/TestBlockEntity.java | 60 ++++++++++--------- .../test/mixin/client/MixinInGameHud.java | 47 +++++++++------ 8 files changed, 74 insertions(+), 56 deletions(-) diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java index 8ce8eb03eb..cf4325691a 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/ComponentType.java @@ -16,15 +16,16 @@ package org.quiltmc.qsl.component.api; +import java.util.IdentityHashMap; +import java.util.Map; + import net.minecraft.util.Identifier; + import org.quiltmc.qsl.component.api.component.Tickable; import org.quiltmc.qsl.component.api.injection.ComponentEntry; import org.quiltmc.qsl.component.api.sync.codec.NetworkCodec; import org.quiltmc.qsl.component.impl.client.sync.ClientSyncHandler; -import java.util.IdentityHashMap; -import java.util.Map; - /** * A global identifier for a specific type of component.
      * This class must always exist as singleton instances, which have to be registered under the @@ -108,11 +109,11 @@ private Static() { } public C getOrCreate(ComponentType type, ComponentCreationContext operations) { if (this.staticInstances.containsKey(type)) { return (C) this.staticInstances.get(type); - } else { - C singleton = type.defaultFactory.create(operations); - this.staticInstances.put(type, singleton); - return singleton; } + + C singleton = type.defaultFactory.create(operations); + this.staticInstances.put(type, singleton); + return singleton; } } } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java index b33901b7e0..f034795f39 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/container/ComponentContainer.java @@ -116,8 +116,6 @@ public interface ComponentContainer { * *

      * May be used as the default container for our implementations in the future. - * - * @deprecated Experimental */ @ApiStatus.Experimental ComponentContainer.Factory ON_ACCESS_FACTORY = OnAccessComponentContainer.FACTORY; diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java index f9e8f04890..eabf805cbc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/package-info.java @@ -1,3 +1,4 @@ +// TODO: Rewrite docs to suit the newest changes! /** *

      Quilt Component API

      * An QSL library module, allowing the attachment/querying of arbitrary data and/or behaviour to various game objects. diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java index 1baeef3d04..8cd8d6fd08 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/api/sync/SyncChannel.java @@ -208,6 +208,7 @@ public void handleServerPushedSync(MinecraftClient client, PacketByteBuf buf) { public void handleClientSyncRequest(MinecraftServer server, ServerPlayerEntity sender, PacketByteBuf buf) { buf.retain(); + server.execute(() -> { Queue queued = this.queueCodec.decode(buf); // we retrieve the queue of identifying data diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java index 1b77177807..bdb175c00c 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/AbstractComponentContainer.java @@ -128,7 +128,7 @@ protected COMP initializeComponent(ComponentEntry componentEntry) { this.nbtComponents.add(type); } - if (this.ticking != null) { + if (this.ticking != null && component instanceof Tickable) { this.ticking.add(type); } diff --git a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java index 146f6d6fe8..52bc2733bc 100644 --- a/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java +++ b/library/data/component/src/main/java/org/quiltmc/qsl/component/impl/container/LazyComponentContainer.java @@ -70,7 +70,7 @@ public static void move(LazyComponentContainer from, LazyComponentContainer into public C expose(ComponentType type) { // the cast to C should never fail since the only way the ComponentType instance can be a key is if the // component is a C instance - return this.components.containsKey(type) ? (C) this.components.get(type) : null; + return this.components.containsKey(type) ? (C) this.components.get(type).get() : null; } @Override diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java index 3a62991a68..664021e7f0 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/TestBlockEntity.java @@ -37,51 +37,55 @@ import org.quiltmc.qsl.component.api.container.ComponentContainer; import org.quiltmc.qsl.component.api.sync.SyncChannel; import org.quiltmc.qsl.component.impl.container.SimpleComponentContainer; -import org.quiltmc.qsl.component.test.component.InventorySerializable; public class TestBlockEntity extends BlockEntity { private final ComponentContainer container = ComponentContainer.builder(this) - .saving(this::markDirty) - .ticking() - .add(ComponentTestMod.TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) - .syncing(SyncChannel.BLOCK_ENTITY) - .build(SimpleComponentContainer.FACTORY); - private final ComponentContainer composite = ComponentContainer.createComposite(this.container, super.getComponentContainer()); + .saving(this::markDirty) + .ticking() + .add(ComponentTestMod.TEST_BE_INT, ComponentTestMod.CHUNK_INVENTORY) + .syncing(SyncChannel.BLOCK_ENTITY) + .build(SimpleComponentContainer.FACTORY); + + private final ComponentContainer composite = ComponentContainer.createComposite( + this.container, super.getComponentContainer()); public TestBlockEntity(BlockPos blockPos, BlockState blockState) { super(ComponentTestMod.TEST_BE_TYPE, blockPos, blockState); } - public static void tick(World world, BlockPos pos, BlockState ignoredState, T blockEntity) { + public static void tick(World world, BlockPos pos, BlockState ignoredState, + T blockEntity) { if (world.isClient) { return; } - if (blockEntity.expose(ComponentTestMod.CHUNK_INVENTORY).map(InventorySerializable::isEmpty).unwrapOr(true)) { - blockEntity.ifPresent(ComponentTestMod.TEST_BE_INT, integerComponent -> { - if (integerComponent.get() % 40 == 0) { - HashSet set = new HashSet<>(List.of(pos)); - expand(pos, pos, world, set); - } + blockEntity.ifPresent(ComponentTestMod.CHUNK_INVENTORY, chunkInventorySerializable -> { + if (!chunkInventorySerializable.isEmpty()) { + blockEntity.ifPresent(ComponentTestMod.TEST_BE_INT, integerComponent -> { + if (integerComponent.get() % 40 == 0) { + HashSet set = new HashSet<>(List.of(pos)); + expand(pos, pos, world, set); + } - integerComponent.increment(); - integerComponent.save(); - }); - } + integerComponent.increment(); + integerComponent.save(); + }); + } + }); } private static void expand(BlockPos initialPos, BlockPos pos, World world, Set visited) { Arrays.stream(Direction.values()) - .map(pos::offset) - .filter(visited::add) - .forEach(offsetPos -> { - BlockState stateAt = world.getBlockState(offsetPos); - if (stateAt.isAir()) { - world.setBlockState(offsetPos, Blocks.DIAMOND_BLOCK.getDefaultState()); - } else if (stateAt.isOf(Blocks.DIAMOND_BLOCK) && initialPos.isWithinDistance(offsetPos, 5)) { - expand(initialPos, offsetPos, world, visited); - } - }); + .map(pos::offset) + .filter(visited::add) + .forEach(offsetPos -> { + BlockState stateAt = world.getBlockState(offsetPos); + if (stateAt.isAir()) { + world.setBlockState(offsetPos, Blocks.DIAMOND_BLOCK.getDefaultState()); + } else if (stateAt.isOf(Blocks.DIAMOND_BLOCK) && initialPos.isWithinDistance(offsetPos, 5)) { + expand(initialPos, offsetPos, world, visited); + } + }); } @Override diff --git a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java index e51217c1be..1d66ea0e81 100644 --- a/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java +++ b/library/data/component/src/testmod/java/org/quiltmc/qsl/component/test/mixin/client/MixinInGameHud.java @@ -32,14 +32,15 @@ import net.minecraft.util.math.ChunkPos; import org.quiltmc.qsl.component.test.ComponentTestMod; -import org.quiltmc.qsl.component.test.component.DefaultIntegerSerializable; -import org.quiltmc.qsl.component.test.component.SaveFloatSerializable; @Mixin(InGameHud.class) public abstract class MixinInGameHud { @Shadow @Final private ItemRenderer itemRenderer; + @Shadow + @Final + private MinecraftClient client; @Shadow public abstract TextRenderer getTextRenderer(); @@ -47,30 +48,42 @@ public abstract class MixinInGameHud { @SuppressWarnings("ConstantConditions") @Inject(method = "render", at = @At("TAIL")) private void renderCustom(MatrixStack matrices, float tickDelta, CallbackInfo ci) { - MinecraftClient.getInstance().world - .expose(ComponentTestMod.SAVE_FLOAT) - .map(SaveFloatSerializable::get) - .map(String::valueOf) - .ifJust(saveFloat -> this.getTextRenderer().draw(matrices, saveFloat, 10, 20, 0xfafafa)); + this.client.world + .ifPresent(ComponentTestMod.SAVE_FLOAT, saveFloatSerializable -> + this.getTextRenderer().draw( + matrices, + String.valueOf(saveFloatSerializable.get()), + 10, 10, + 0xfafafa + ) + ); - Entity entity = MinecraftClient.getInstance().targetedEntity; + Entity entity = this.client.targetedEntity; if (entity != null) { - entity.expose(ComponentTestMod.HOSTILE_EXPLODE_TIME) - .map(DefaultIntegerSerializable::get) - .ifJust(integer -> this.getTextRenderer().draw(matrices, integer.toString(), 10, 10, 0xfafafa)); + entity.ifPresent( + ComponentTestMod.HOSTILE_EXPLODE_TIME, + defaultIntegerSerializable -> this.getTextRenderer().draw( + matrices, + String.valueOf(defaultIntegerSerializable.get()), + 10, 10, + 0xfafafa + ) + ); } - ChunkPos chunkPos = MinecraftClient.getInstance().player.getChunkPos(); - MinecraftClient.getInstance().world.getChunk(chunkPos.x, chunkPos.z).expose(ComponentTestMod.CHUNK_INVENTORY) - .map(defaultInventoryComponent -> defaultInventoryComponent.getStack(0)) - .ifJust(itemStack -> this.itemRenderer.renderInGui(itemStack, 10, 10)); + ChunkPos chunkPos = this.client.player.getChunkPos(); + this.client.world.getChunk(chunkPos.x, chunkPos.z) + .ifPresent(ComponentTestMod.CHUNK_INVENTORY, chunkInventorySerializable -> { + var stack = chunkInventorySerializable.getStack(0); + this.itemRenderer.renderInGui(stack, 10, 20); + }); - MinecraftClient.getInstance().player.expose(ComponentTestMod.UUID_THING).ifJust(uuidField -> { + this.client.player.ifPresent(ComponentTestMod.UUID_THING, uuidField -> { if (uuidField.getValue() == null) { return; } var uuidString = uuidField.getValue().toString(); - MinecraftClient.getInstance().textRenderer.draw(matrices, uuidString, 10, 30, 0xFAFAFA); + this.client.textRenderer.draw(matrices, uuidString, 10, 30, 0xFAFAFA); }); } }