0

Hi

In the game Minecraft you have to send data between the client and the server in order to sync stuff, one of the things that need to be synced in particular circumstances is TileEntities with a render. The data is stored on the server and sent to the client which is thereafter used for render.

You create a class that contains the data that needs to be synced and attach it to a channel creation API called "SimpleImpl". My Network object and a Message Object:

public class IntercraftPacketHandler
{

    private static int index = 1;

    private static final ResourceLocation CHANNEL_NAME     = new ResourceLocation(Reference.MODID,"network");
    private static final String           PROTOCOL_VERSION = new ResourceLocation(Reference.MODID,"1").toString();


    public static SimpleChannel getNetworkChannel()
    {
        final SimpleChannel channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME)
                .clientAcceptedVersions(version -> true)
                .serverAcceptedVersions(version -> true)
                .networkProtocolVersion(()      -> PROTOCOL_VERSION)
                .simpleChannel();

        // Sync Capability Identity Hidden data message.

        channel.messageBuilder(MessageIdentityHidden.class,index)
                .encoder(MessageIdentityHidden::encode)
                .decoder(MessageIdentityHidden::decode)
                .consumer(MessageIdentityHidden::handle)
                .add(); index++;

        // Send TreeTapTileEntity data to client.

        channel.messageBuilder(MessageTreeTap.class,index)
                .encoder(MessageTreeTap::encode)
                .decoder(MessageTreeTap::decode)
                .consumer(MessageTreeTap::handle)
                .add(); index++;

        // Send ChunkLoaderTileEntity data to client.

        channel.messageBuilder(MessageChunkLoader.class,index)
                .encoder(MessageChunkLoader::encode)
                .decoder(MessageChunkLoader::decode)
                .consumer(MessageChunkLoader::handle)
                .add(); index++;

        return channel;
    }

}
public class MessageChunkLoader
{
    private BlockPos pos;
    private boolean  canLoad;

    public MessageChunkLoader(BlockPos pos,boolean canLoad)
    {
        this.pos     = pos;
        this.canLoad = canLoad;
    }


    public void handle(Supplier<NetworkEvent.Context> ctx)
    {
        ctx.get().enqueueWork(() -> {
            try {
                ChunkLoaderBaseTileEntity tile = (ChunkLoaderBaseTileEntity) Minecraft.getInstance().world.getTileEntity(pos);
                tile.canLoad = canLoad;

            } catch (NullPointerException err) {
                System.out.println(String.format("Could not find ChunkLoaderTileEntity at %s %s %s!",pos.getX(),pos.getY(),pos.getZ()));
            }

        });
    }

    public static void encode(MessageChunkLoader message, PacketBuffer buffer)
    {
        buffer.writeBlockPos(message.pos);
        buffer.writeBoolean(message.canLoad);
    }

    public static MessageChunkLoader decode(final PacketBuffer buffer)
    {
        return new MessageChunkLoader(buffer.readBlockPos(),buffer.readBoolean());
    }
}

I then initialize it in my main mod class used by objects in my mod project.

@Mod(Reference.MODID)
public class IntercraftCore
{
    public static final SimpleChannel NETWORK = IntercraftPacketHandler.getNetworkChannel();
...

The problem and this post's question; right now I create a new message class from the formula I follow in MessageChunkLoader (public static encode & decode method and a handle method). I would like to create a more generic class for creating message classes for TileEntities, but I'm having problems with that. Here's the current class:

public abstract class MessageTileEntity<T extends TileEntity>
{
    protected final BlockPos pos;
    protected final Class<T> clazz;

    public MessageTileEntity(BlockPos pos, Class<T> clazz)
    {
        this.pos = pos;
        this.clazz = clazz;
    }

    public abstract void handle(Supplier<NetworkEvent.Context> ctx);

    protected T getTileEntity()
    {
        try {
            return clazz.cast(Minecraft.getInstance().world.getTileEntity(pos));
        } catch (NullPointerException e) {
            System.out.println(String.format("Could not find %s at [%d %d %d]!",clazz.getSimpleName(),pos.getX(),pos.getY(),pos.getZ()));
            throw e;
        } catch (ClassCastException e) {
            System.out.println(String.format("TileEntity at [%d %d %d] is not %s!",pos.getX(),pos.getY(),pos.getZ(),clazz.getSimpleName()));
            throw e;
        }
    }

    public static void encode(MessageTileEntity message, PacketBuffer buffer)
    {

    }

    public static MessageTileEntity decode(final PacketBuffer buffer)
    {
        return null;
    }
}

The main problem is I lack the proper Java skills to make it like I want it to function. The method handle is easy as it's non-static and needs to be custom to every TileEntity message, but the methods encode and decode which needs to be static gives me problems. I have no idea what I'm trying to achieve is possible, asking won't hurt. Maybe the solution is easier than I think.

Simon
  • 95
  • 1
  • 11
  • 1
    You can't use generics from the class level inside a static method. You may be able to achieve what you want by passing it in via the method level though. More info: https://stackoverflow.com/questions/936377/static-method-in-a-generic-class – Tim Hunter Mar 12 '20 at 14:31
  • Do you mean something like this? `public static void encode(T message, PacketBuffer buffer)` It allows me to get the object back, but I can't override it or make a generic implementation for me to encode/decode the data. – Simon Mar 12 '20 at 16:07

0 Answers0