Абстракция Generi c Класс объекта - PullRequest
0 голосов
/ 12 марта 2020

Привет

В игре Minecraft вы должны передавать данные между клиентом и сервером, чтобы синхронизировать c материал, одну из вещей это должно быть синхронизировано в определенных обстоятельствах TileEntities с рендером. Данные хранятся на сервере и отправляются клиенту, который затем используется для рендеринга.

Вы создаете класс, содержащий данные, которые необходимо синхронизировать, и присоединяете его к API создания канала под названием " SimpleImpl ». Мой сетевой объект и объект сообщения:

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());
    }
}

Затем я инициализирую его в своем основном классе мода, который используется объектами в моем проекте мода.

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

Проблема и это вопрос поста; прямо сейчас я создаю новый класс сообщений из формулы, которой я следую в MessageChunkLoader (publi c stati c метод кодирования и декодирования и метод handle). Я хотел бы создать более общий класс c для создания классов сообщений для TileEntities, но у меня возникли проблемы с этим. Вот текущий класс:

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;
    }
}

Основная проблема в том, что мне не хватает Java навыков, чтобы заставить его работать так, как я хочу. Метод handle прост, так как он не является c и должен быть настроен для каждого TileEntity сообщения, но методы encode и decode, которые должны быть stati c, вызывают у меня проблемы. Я понятия не имею, что я пытаюсь достичь, возможно, спрашивать не повредит. Может быть, решение проще, чем я думаю.

...