Hytale Modding
Server Plugins

Block Components

Learn how to use the block components.

Overview

In this guide, you'll learn how to use block components to create a ticking block.

Info

For a more complete reference, you may also want to review FarmingSystems.Ticking, as much of the underlying logic is based on its implementation.

Steps

1. ExampleBlock - holds block behavior

public class ExampleBlock implements Component<ChunkStore> {

    public static final BuilderCodec CODEC;

    public ExampleBlock() {

    }

    public static ComponentType getComponentType() {
        return ExamplePlugin.get().getExampleBlockComponentType();
    }

    public void runBlockAction(int x, int y, int z, World world) {
        world.execute(() -> {
            world.setBlock(x + 1, y, z, "Rock_Ice");
        });
    }

    @Nullable
    public Component<ChunkStore> clone() {
        return new ExampleBlock();
    }

    static {
        CODEC = BuilderCodec.builder(ExampleBlock.class, ExampleBlock::new).build();
    }
}

ExampleBlock stores the behavior for the block. Here, it simply places an Ice Block at x + 1 relative to its current position when it ticks.


2. ExampleSystem - handles ticking

public class ExampleSystem extends EntityTickingSystem {
    private static final Query QUERY = Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType());

    public void tick(float dt, int index, @Nonnull ArchetypeChunk archetypeChunk, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer) {
        BlockSection blocks = (BlockSection) archetypeChunk.getComponent(index, BlockSection.getComponentType());

        assert blocks != null;

        if (blocks.getTickingBlocksCountCopy() != 0) {
            ChunkSection section = (ChunkSection) archetypeChunk.getComponent(index, ChunkSection.getComponentType());

            assert section != null;

            BlockComponentChunk blockComponentChunk = (BlockComponentChunk) commandBuffer.getComponent(section.getChunkColumnReference(), BlockComponentChunk.getComponentType());

            assert blockComponentChunk != null;

            blocks.forEachTicking(blockComponentChunk, commandBuffer, section.getY(), (blockComponentChunk1, commandBuffer1, localX, localY, localZ, blockId) ->
            {
                Ref<ChunkStore> blockRef = blockComponentChunk1.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ));
                if (blockRef == null) {
                    return BlockTickStrategy.IGNORED;
                } else {
                    ExampleBlock exampleBlock = (ExampleBlock) commandBuffer1.getComponent(blockRef, ExampleBlock.getComponentType());
                    if (exampleBlock != null) {
                        WorldChunk worldChunk = (WorldChunk) commandBuffer.getComponent(section.getChunkColumnReference(), WorldChunk.getComponentType());

                        int globalX = localX + (worldChunk.getX() * 32);
                        int globalZ = localZ + (worldChunk.getZ() * 32);

                        exampleBlock.runBlockAction(globalX, localY, globalZ, worldChunk.getWorld());

                        return BlockTickStrategy.CONTINUE;

                    } else {
                        return BlockTickStrategy.IGNORED;
                    }
                }
            });
        }
    }

    @Nullable
    public Query getQuery() {
        return QUERY;
    }
}
  • Get the block component
ExampleBlock exampleBlock = (ExampleBlock) commandBuffer1.getComponent(blockRef, ExampleBlock.getComponentType());
  • Convert local chunk coordinates to world coordinates
int globalX = localX + (worldChunk.getX() * 32);
int globalZ = localZ + (worldChunk.getZ() * 32);
  • Run the block logic
exampleBlock.runBlockAction(globalX, localY, globalZ, worldChunk.getWorld());
  • Keep the block ticking in the next tick
return BlockTickStrategy.CONTINUE;

3. ExamplePlugin - registers components and systems

public class ExamplePlugin extends JavaPlugin {
    protected static ExamplePlugin instance;
    private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
    private ComponentType exampleBlockComponentType;

    public static ExamplePlugin get() {
        return instance;
    }

    public ExamplePlugin(@Nonnull JavaPluginInit init) {
        super(init);
        LOGGER.atInfo().log("Hello from " + this.getName() + " version " + this.getManifest().getVersion().toString());
    }

    @Override
    protected void setup() {
        instance = this;
        LOGGER.atInfo().log("Setting up plugin " + this.getName());
        this.exampleBlockComponentType = this.getChunkStoreRegistry().registerComponent(ExampleBlock.class, "ExampleBlock", ExampleBlock.CODEC);
        this.getChunkStoreRegistry().registerSystem(new ExampleSystem());

    }

    public ComponentType getExampleBlockComponentType() {
        return this.exampleBlockComponentType;
    }
}

4. Configure In-Game

block-component-1

block-component-2

With this logic, the block will now continuously place an Ice Block at the coordinates x + 1 relative to its current position every time it ticks.

Geschrieben von Bird