Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.gregtechceu.gtceu.api.machine.MultiblockMachineDefinition;
import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMultiPart;
import com.gregtechceu.gtceu.api.machine.property.GTMachineModelProperties;
import com.gregtechceu.gtceu.api.machine.trait.MultiblockMachineTrait;
import com.gregtechceu.gtceu.api.pattern.BlockPattern;
import com.gregtechceu.gtceu.api.pattern.MultiblockState;
import com.gregtechceu.gtceu.api.pattern.MultiblockWorldSavedData;
Expand Down Expand Up @@ -123,6 +124,12 @@ public void onStructureFormed() {
}
part.addedToController(this);
}
updatePartPositions();

for (var trait : getTraitHolder().getAllTraits()) {
if (trait instanceof MultiblockMachineTrait multiblockMachineTrait)
multiblockMachineTrait.onStructureFormed();
}
}

/**
Expand All @@ -147,6 +154,11 @@ public void onStructureInvalid() {
parallelHatch = null;
parts.clear();
updatePartPositions();

for (var trait : getTraitHolder().getAllTraits()) {
if (trait instanceof MultiblockMachineTrait multiblockMachineTrait)
multiblockMachineTrait.onStructureInvalid();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package com.gregtechceu.gtceu.api.machine.trait;

import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.machine.MetaMachine;
import com.gregtechceu.gtceu.api.sync_system.data_transformers.ValueTransformer;
import com.gregtechceu.gtceu.api.sync_system.data_transformers.ValueTransformers;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;

import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
Expand All @@ -10,6 +16,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

public final class MachineTraitHolder {
Expand All @@ -18,10 +25,13 @@ public final class MachineTraitHolder {
private final List<MachineTrait> traits;
private final Map<MachineTraitType<?>, List<MachineTrait>> traitsByType;

private final Map<String, MachineTrait> traitsToSave;

public MachineTraitHolder(MetaMachine machine) {
this.machine = machine;
this.traits = new ObjectArrayList<>();
this.traitsByType = new Object2ObjectOpenHashMap<>();
this.traitsToSave = new Object2ObjectOpenHashMap<>();
}

public @UnmodifiableView List<MachineTrait> getAllTraits() {
Expand All @@ -40,6 +50,28 @@ public void attachTrait(MachineTrait trait) {
traits.add(trait);
}

/**
* Registers a trait to be synced/saved.
* Do not register a trait to be synced and also store that trait as a syncable machine field, otherwise the trait
* data will be duplicated. Use only one sync method.
*
* @param traitName Unique identifier for this trait.
* @param trait The trait to register
*/
public MachineTraitHolder syncTrait(String traitName, MachineTrait trait) {
if (trait.machine != machine) throw new IllegalArgumentException("Trait does not belong to this machine.");
if (traitsToSave.containsKey(traitName))
throw new IllegalArgumentException("Attempted to register duplicate trait save key \"" + traitName + "\"");
traitsToSave.put(traitName, trait);
return this;
}

@SuppressWarnings("unchecked")
public @Nullable <T extends MachineTrait> T getSyncTrait(String traitName) {
MachineTrait trait = traitsToSave.get(traitName);
return trait == null ? null : (T) trait;
}

/**
* Gets the first trait with the specified type.
*/
Expand All @@ -62,4 +94,39 @@ public <T extends MachineTrait> Optional<T> getTraitOptional(MachineTraitType<T>
if (traitList == null) return List.of();
return Collections.unmodifiableList(traitList);
}

private static class MachineTraitHolderTransformer implements ValueTransformer<MachineTraitHolder> {

@Override
public Tag serializeNBT(MachineTraitHolder value, TransformerContext<MachineTraitHolder> context) {
CompoundTag tag = new CompoundTag();

value.traitsToSave.forEach((k, v) -> tag.put(k,
v.getSyncDataHolder().serializeNBT(context.isClientSync(), context.isClientFullSyncUpdate())));

return tag;
}

@Override
public @Nullable MachineTraitHolder deserializeNBT(Tag tag, TransformerContext<MachineTraitHolder> context) {
var traitHolder = Objects.requireNonNull(context.currentValue());
var compoundTag = (CompoundTag) tag;

for (var key : compoundTag.getAllKeys()) {
var trait = traitHolder.getSyncTrait(key);
if (trait == null) {
GTCEu.LOGGER.warn("Attempted to deserialise syncable trait '{}', but no syncable trait has that ID",
key);
continue;
}
trait.getSyncDataHolder().deserializeNBT(compoundTag.getCompound("key"), context.isClientSync());
}

return null;
}
}

static {
ValueTransformers.registerTransformer(MachineTraitHolder.class, new MachineTraitHolderTransformer());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.gregtechceu.gtceu.api.machine.trait;

import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockControllerMachine;

public abstract class MultiblockMachineTrait extends MachineTrait {

public MultiblockMachineTrait(MultiblockControllerMachine multiMachine) {
super(multiMachine);
}

public void onStructureFormed() {}

public void onStructureInvalid() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public CompoundTag serializeNBT(boolean writeClientFields, boolean fullSync) {
CompoundTag tag = new CompoundTag();
for (var field : fieldsToSerialize) {
if (shouldSerializeField(field, writeClientFields, fullSync)) {
Tag nbtValue = serializeField(holder, field, writeClientFields);
Tag nbtValue = serializeField(holder, field, writeClientFields, fullSync);
tag.put(field.nbtSaveKey, nbtValue);
}
}
Expand Down Expand Up @@ -101,7 +101,7 @@ public void deserializeNBT(CompoundTag tag, boolean readingClientFields) {

@SuppressWarnings("unchecked")
private static Tag serializeField(ISyncManaged holder, FieldSyncData field,
boolean writeClientFields) {
boolean writeClientFields, boolean fullSync) {
Object currentValue = field.handle.get(holder);

if (!field.isSyncManaged && currentValue == null) {
Expand All @@ -115,7 +115,7 @@ private static Tag serializeField(ISyncManaged holder, FieldSyncData field,
if (field.transformer != null) {
return ((ValueTransformer<Object>) field.transformer).serializeNBT(currentValue,
new ValueTransformer.TransformerContext<>(holder, field.type, currentValue, field.fieldName,
writeClientFields));
writeClientFields, fullSync));
} else if (currentValue instanceof ISyncManaged syncObj) {
return syncObj.getSyncDataHolder().serializeNBT(writeClientFields);
} else {
Expand Down Expand Up @@ -150,7 +150,7 @@ private static void deserializeField(ISyncManaged holder, FieldSyncData field,
try {
var current = field.handle.get(holder);
Object result = transformer.deserializeNBT(savedValue, new ValueTransformer.TransformerContext<>(
holder, field.type, current, field.fieldName, readingClientFields));
holder, field.type, current, field.fieldName, readingClientFields, false));
if (result != current) {
field.handle.set(holder, result);
}
Expand All @@ -175,4 +175,20 @@ private static void deserializeField(ISyncManaged holder, FieldSyncData field,
GTCEu.LOGGER.error(e);
}
}

public static class SyncManagedTransformer implements ValueTransformer<ISyncManaged> {

@Override
public Tag serializeNBT(ISyncManaged value, TransformerContext<ISyncManaged> context) {
return value.getSyncDataHolder().serializeNBT(context.isClientSync(), context.isClientFullSyncUpdate());
}

@Override
public @Nullable ISyncManaged deserializeNBT(Tag tag, TransformerContext<ISyncManaged> context) {
ISyncManaged syncManaged = context.currentValue();
Objects.requireNonNull(syncManaged).getSyncDataHolder().deserializeNBT((CompoundTag) tag,
context.isClientSync());
return syncManaged;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ public interface ValueTransformer<T> {
* @param fieldName The name of the field being serialized, or a string denoting the current sync context if not
* being invoked directly on a field.
* @param isClientSync Whether NBT is currently being generated as part of a sync update to the client, not as NBT
* being
* written to the server save.
* being written to the server save.
*
*/
record TransformerContext<U>(@NotNull ISyncManaged holder, @NotNull TypeDeclaration type,
@Nullable U currentValue, @Nullable String fieldName, boolean isClientSync) {}
@Nullable U currentValue, @Nullable String fieldName, boolean isClientSync,
boolean isClientFullSyncUpdate) {}

/**
* Casts a given NBT tag to a specific tag type, throwing an error if the tag cannot be casted.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.gregtechceu.gtceu.api.recipe.GTRecipe;
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
import com.gregtechceu.gtceu.api.registry.GTRegistries;
import com.gregtechceu.gtceu.api.sync_system.ISyncManaged;
import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder;
import com.gregtechceu.gtceu.api.sync_system.TypeDeclaration;
import com.gregtechceu.gtceu.api.sync_system.data_transformers.collections.ListTransformer;
import com.gregtechceu.gtceu.api.sync_system.data_transformers.collections.MapTransformer;
Expand Down Expand Up @@ -177,6 +179,7 @@ public static <T> void registerTransformerSupplier(Class<T> type, Supplier<Value
}, StringTag.class);

registerTransformer(INBTSerializable.class, new NBTSerializableTransformer());
registerTransformer(ISyncManaged.class, new SyncDataHolder.SyncManagedTransformer());

registerTransformerSupplier(List.class, ListTransformer::new);
registerTransformerSupplier(Map.class, MapTransformer::new);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ private ValueTransformer.TransformerContext<T> getInnerElemContext(@Nullable T e
ValueTransformer.TransformerContext<List<T>> parentContext) {
return new TransformerContext<>(parentContext.holder(),
parentContext.type().getGenericTypeArgs()[0], elem, parentContext.fieldName() + "[element]",
parentContext.isClientSync());
parentContext.isClientSync(), parentContext.isClientFullSyncUpdate());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ private ValueTransformer.TransformerContext<K> getInnerKeyContext(@Nullable K ke
ValueTransformer.TransformerContext<Map<K, V>> parentContext) {
return new TransformerContext<>(parentContext.holder(),
parentContext.type().getGenericTypeArgs()[0], key, parentContext.fieldName() + "[key]",
parentContext.isClientSync());
parentContext.isClientSync(), parentContext.isClientFullSyncUpdate());
}

private ValueTransformer.TransformerContext<V> getInnerValueContext(@Nullable V value,
ValueTransformer.TransformerContext<Map<K, V>> parentContext) {
return new TransformerContext<>(parentContext.holder(),
parentContext.type().getGenericTypeArgs()[1], value,
parentContext.fieldName() + "[value]",
parentContext.isClientSync());
parentContext.isClientSync(), parentContext.isClientFullSyncUpdate());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private ValueTransformer.TransformerContext<T> getInnerElemContext(@Nullable T e
ValueTransformer.TransformerContext<T[]> parentContext) {
return new TransformerContext<>(parentContext.holder(),
parentContext.type().getArrayComponentType(), elem, parentContext.fieldName() + "[element]",
parentContext.isClientSync());
parentContext.isClientSync(), parentContext.isClientFullSyncUpdate());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ private ValueTransformer.TransformerContext<T> getInnerElemContext(@Nullable T e
ValueTransformer.TransformerContext<Set<T>> parentContext) {
return new TransformerContext<>(parentContext.holder(),
parentContext.type().getGenericTypeArgs()[0], elem, parentContext.fieldName() + "[element]",
parentContext.isClientSync());
parentContext.isClientSync(), parentContext.isClientSync());
}

@Override
Expand Down