Skip to content
Open
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
12 changes: 6 additions & 6 deletions docs/content/Development/Data-Sync-System/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ title: "Usage"

### Registering classes with the sync system

At the core of the system are the `ISyncManaged` and `ISyncAnnotated` interfaces, which allow for their fields to have sync annotations..
All block entities which should be synchronised or saved must extend the abstract class `ManagedSyncBlockEntity`.
At the core of the system are the `ISyncManaged` and `ISyncAnnotated` interfaces, which allow for their fields to have sync annotations.

`ISyncManaged` should be used for classes with any form of persistent state, and cannot be instantiated or reassigned.<br>
`ISyncAnnotated` should be used for record-like classes that hold data, and must define a no-args constructor.
- `ISyncManaged` should be used for classes with any form of persistent state, and cannot be instantiated or reassigned.
- `ISyncAnnotated` should be used for record-like classes that hold data, and must define a no-args constructor.

All `ISyncManaged` objects must belong to a root managed sync object. There are two default types of root sync objects:

!!! warning
Block entities that inherit `ManagedSyncBlockEntity` must call `ManagedSyncBlockEntity::updateTick`***every tick*** within their ticker, or they will not be saved.
- `ManagedSyncBlockEntity` is a block entity storing its data through the system. The `Block` class using this `BlockEntity` must implement `ManagedSyncEntityBlock`.
- `ManagedSavedData` is a `SavedData` object that stores data through the system.

#### Example of `ISyncManaged` usage
```java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.gregtechceu.gtceu.api.machine.MetaMachine;
import com.gregtechceu.gtceu.api.machine.MultiblockMachineDefinition;
import com.gregtechceu.gtceu.api.machine.feature.*;
import com.gregtechceu.gtceu.api.sync_system.managed.ManagedSyncEntityBlock;
import com.gregtechceu.gtceu.common.machine.owner.MachineOwner;
import com.gregtechceu.gtceu.utils.ExtendedUseOnContext;
import com.gregtechceu.gtceu.utils.GTUtil;
Expand All @@ -34,12 +35,9 @@
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.storage.loot.LootParams;
Expand All @@ -59,7 +57,7 @@
@SuppressWarnings("deprecation")
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class MetaMachineBlock extends Block implements EntityBlock {
public class MetaMachineBlock extends Block implements ManagedSyncEntityBlock {

@Getter
public final MachineDefinition definition;
Expand Down Expand Up @@ -380,26 +378,4 @@ public static int colorTinted(BlockState blockState, @Nullable BlockAndTintGette
public final BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return getDefinition().getBlockEntityType().create(pos, state);
}

@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state,
BlockEntityType<T> blockEntityType) {
if (blockEntityType == getDefinition().getBlockEntityType()) {
if (!level.isClientSide) {
return (pLevel, pPos, pState, pTile) -> {
if (pTile instanceof MetaMachine metaMachine) {
metaMachine.serverTick();
}
};
} else {
return (pLevel, pPos, pState, pTile) -> {
if (pTile instanceof MetaMachine metaMachine) {
metaMachine.clientTick();
}
};
}
}
return null;
}
}
20 changes: 2 additions & 18 deletions src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.gregtechceu.gtceu.api.pipenet.LevelPipeNet;
import com.gregtechceu.gtceu.api.pipenet.PipeNet;
import com.gregtechceu.gtceu.api.registry.registrate.provider.GTBlockstateProvider;
import com.gregtechceu.gtceu.api.sync_system.managed.ManagedSyncEntityBlock;
import com.gregtechceu.gtceu.client.model.pipe.PipeModel;
import com.gregtechceu.gtceu.common.data.GTItems;
import com.gregtechceu.gtceu.common.data.GTMaterialBlocks;
Expand Down Expand Up @@ -43,7 +44,6 @@
import net.minecraft.world.level.*;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
Expand Down Expand Up @@ -73,7 +73,7 @@
@MethodsReturnNonnullByDefault
public abstract class PipeBlock<PipeType extends Enum<PipeType> & IPipeType<NodeDataType>, NodeDataType,
WorldPipeNetType extends LevelPipeNet<NodeDataType, ? extends PipeNet<NodeDataType>>> extends Block
implements EntityBlock, SimpleWaterloggedBlock {
implements ManagedSyncEntityBlock, SimpleWaterloggedBlock {

public final PipeType pipeType;

Expand Down Expand Up @@ -436,22 +436,6 @@ public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos,
return getShapes(connections);
}

@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state,
BlockEntityType<T> blockEntityType) {
if (blockEntityType == getBlockEntityType()) {
if (!level.isClientSide) {
return (pLevel, pPos, pState, pTile) -> {
if (pTile instanceof IPipeNode<?, ?> pipeNode) {
pipeNode.serverTick();
}
};
}
}
return null;
}

@Override
public BlockState getAppearance(BlockState state, BlockAndTintGetter level, BlockPos pos, Direction side,
@Nullable BlockState sourceState, @Nullable BlockPos sourcePos) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.gregtechceu.gtceu.api.blockentity;

import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.sync_system.ISyncManaged;
import com.gregtechceu.gtceu.api.sync_system.managed.ISyncManaged;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
import com.gregtechceu.gtceu.api.item.tool.IToolGridHighlight;
import com.gregtechceu.gtceu.api.machine.TickableSubscription;
import com.gregtechceu.gtceu.api.pipenet.*;
import com.gregtechceu.gtceu.api.sync_system.ManagedSyncBlockEntity;
import com.gregtechceu.gtceu.api.sync_system.annotations.RerenderOnChanged;
import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField;
import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient;
import com.gregtechceu.gtceu.api.sync_system.managed.ManagedSyncBlockEntity;
import com.gregtechceu.gtceu.common.data.GTMaterialBlocks;
import com.gregtechceu.gtceu.common.data.GTMaterials;
import com.gregtechceu.gtceu.utils.ExtendedUseOnContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.gregtechceu.gtceu.api.cover.CoverDefinition;
import com.gregtechceu.gtceu.api.machine.TickableSubscription;
import com.gregtechceu.gtceu.api.registry.GTRegistries;
import com.gregtechceu.gtceu.api.sync_system.ISyncManaged;
import com.gregtechceu.gtceu.api.sync_system.managed.ISyncManaged;
import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable;
import com.gregtechceu.gtceu.utils.GTUtil;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
import com.gregtechceu.gtceu.api.item.tool.GTToolType;
import com.gregtechceu.gtceu.api.item.tool.IToolGridHighlight;
import com.gregtechceu.gtceu.api.machine.MetaMachine;
import com.gregtechceu.gtceu.api.sync_system.ISyncManaged;
import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder;
import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField;
import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient;
import com.gregtechceu.gtceu.api.sync_system.managed.ISyncManaged;
import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable;
import com.gregtechceu.gtceu.client.renderer.cover.ICoverRenderer;
import com.gregtechceu.gtceu.client.renderer.cover.IDynamicCoverRenderer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import com.gregtechceu.gtceu.api.gui.widget.SlotWidget;
import com.gregtechceu.gtceu.api.machine.MachineCoverContainer;
import com.gregtechceu.gtceu.api.machine.MetaMachine;
import com.gregtechceu.gtceu.api.sync_system.ISyncManaged;
import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder;
import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField;
import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient;
import com.gregtechceu.gtceu.api.sync_system.managed.ISyncManaged;
import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler;

import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.gregtechceu.gtceu.api.cover.filter;

import com.gregtechceu.gtceu.api.sync_system.ISyncManaged;
import com.gregtechceu.gtceu.api.sync_system.managed.ISyncManaged;

import net.minecraft.world.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import com.gregtechceu.gtceu.api.machine.trait.MachineTraitType;
import com.gregtechceu.gtceu.api.machine.trait.feature.IFrontFacingTrait;
import com.gregtechceu.gtceu.api.machine.trait.feature.IRenderingTrait;
import com.gregtechceu.gtceu.api.sync_system.ISyncManaged;
import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder;
import com.gregtechceu.gtceu.api.sync_system.annotations.RerenderOnChanged;
import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField;
import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient;
import com.gregtechceu.gtceu.api.sync_system.managed.ISyncManaged;
import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable;
import com.gregtechceu.gtceu.utils.GTUtil;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
import com.gregtechceu.gtceu.api.machine.trait.feature.IRenderingTrait;
import com.gregtechceu.gtceu.api.misc.*;
import com.gregtechceu.gtceu.api.pattern.util.RelativeDirection;
import com.gregtechceu.gtceu.api.sync_system.ManagedSyncBlockEntity;
import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder;
import com.gregtechceu.gtceu.api.sync_system.annotations.RerenderOnChanged;
import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField;
import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient;
import com.gregtechceu.gtceu.api.sync_system.managed.ManagedSyncBlockEntity;
import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable;
import com.gregtechceu.gtceu.client.model.IBlockEntityRendererBakedModel;
import com.gregtechceu.gtceu.client.model.machine.MachineRenderState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.gregtechceu.gtceu.api.machine.MetaMachine;
import com.gregtechceu.gtceu.api.machine.TickableSubscription;
import com.gregtechceu.gtceu.api.sync_system.ISyncManaged;
import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder;
import com.gregtechceu.gtceu.api.sync_system.managed.ISyncManaged;
import com.gregtechceu.gtceu.client.model.machine.MachineRenderState;
import com.gregtechceu.gtceu.common.machine.trait.AutoOutputTrait;
import com.gregtechceu.gtceu.common.machine.trait.CleanroomProviderTrait;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import com.gregtechceu.gtceu.api.capability.ICoverable;
import com.gregtechceu.gtceu.api.cover.CoverBehavior;
import com.gregtechceu.gtceu.api.cover.CoverDefinition;
import com.gregtechceu.gtceu.api.sync_system.ISyncManaged;
import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder;
import com.gregtechceu.gtceu.api.sync_system.annotations.RerenderOnChanged;
import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField;
import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient;
import com.gregtechceu.gtceu.api.sync_system.managed.ISyncManaged;
import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable;
import com.gregtechceu.gtceu.common.blockentity.FluidPipeBlockEntity;
import com.gregtechceu.gtceu.common.blockentity.ItemPipeBlockEntity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient;
import com.gregtechceu.gtceu.api.sync_system.data_transformers.ValueTransformer;
import com.gregtechceu.gtceu.api.sync_system.data_transformers.ValueTransformers;
import com.gregtechceu.gtceu.api.sync_system.managed.ISyncManaged;

import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import lombok.Getter;
import lombok.SneakyThrows;
import org.jetbrains.annotations.Nullable;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.Supplier;

/**
* Static data for {@link ISyncManaged} classes.
Expand Down Expand Up @@ -45,23 +47,21 @@ public static ClassSyncData getClassData(Class<?> cls) {
private final Set<FieldSyncData> clientSyncFields = new ObjectOpenHashSet<>();
@Getter
private final Set<FieldSyncData> serverSaveFields = new ObjectOpenHashSet<>();
@Getter
private @Nullable Supplier<?> clientsideConstructor = null;

@SneakyThrows
private ClassSyncData(Class<?> clazz) {
var isManaged = ISyncManaged.class.isAssignableFrom(clazz);
var isAnnotated = ISyncAnnotated.class.isAssignableFrom(clazz);

if (!isManaged && !isAnnotated)
throw new IllegalArgumentException("Cannot create class sync data for non-sync class");
if (isManaged && isAnnotated) throw new IllegalArgumentException(
"Class %s cannot inherit both ISyncAnnotated and ISyncManaged".formatted(clazz.getName()));
if (!isManaged)
throw new IllegalArgumentException("Cannot create class sync data for non sync managed class.");

MethodHandles.Lookup privateLookup;
try {
privateLookup = MethodHandles.privateLookupIn(clazz, LOOKUP);
} catch (IllegalAccessException e) {
GTCEu.LOGGER.error("Sync: Failed to create method handle lookup for class {}", clazz);
throw e;
throw new RuntimeException(e);
}

Map<String, List<MethodHandle>> changeListeners = new HashMap<>();
Expand Down Expand Up @@ -103,7 +103,7 @@ private ClassSyncData(Class<?> clazz) {
} catch (IllegalAccessException e) {
GTCEu.LOGGER.error("Sync: Failed to acquire variable handle for field {} {}", field.getName(),
clazz.getName());
throw e;
throw new RuntimeException(e);
}

FieldSyncData syncData = new FieldSyncData(field, handle, ValueTransformers.get(field.getGenericType()),
Expand All @@ -114,7 +114,7 @@ private ClassSyncData(Class<?> clazz) {
}

Class<?> parent = clazz.getSuperclass();
if (ISyncManaged.class.isAssignableFrom(parent) || ISyncAnnotated.class.isAssignableFrom(parent)) {
if (ISyncManaged.class.isAssignableFrom(parent)) {
ClassSyncData parentHandles = CACHE.get(parent);
managedFields.addAll(parentHandles.managedFields);
clientSyncFields.addAll(parentHandles.clientSyncFields);
Expand All @@ -134,4 +134,13 @@ public void setCustomTransformerForField(String fieldName, ValueTransformer<?> t
.findFirst()
.ifPresent(fieldData -> fieldData.setTransformer(transformer));
}

/**
* Allows this class to be instantiated on the client when being synced.
*
* @param ctor The constructor/supplier to be called when instantiating this class on the client.
*/
public void setClientsideConstructor(@Nullable Supplier<?> ctor) {
clientsideConstructor = ctor;
}
}
Loading
Loading