132 lines
5.7 KiB
Java
132 lines
5.7 KiB
Java
package com.hypixel.hytale.builtin.blocktick.system;
|
|
|
|
import com.hypixel.hytale.builtin.blocktick.BlockTickPlugin;
|
|
import com.hypixel.hytale.component.ArchetypeChunk;
|
|
import com.hypixel.hytale.component.CommandBuffer;
|
|
import com.hypixel.hytale.component.ComponentType;
|
|
import com.hypixel.hytale.component.Ref;
|
|
import com.hypixel.hytale.component.Store;
|
|
import com.hypixel.hytale.component.dependency.Dependency;
|
|
import com.hypixel.hytale.component.dependency.Order;
|
|
import com.hypixel.hytale.component.dependency.SystemDependency;
|
|
import com.hypixel.hytale.component.query.Query;
|
|
import com.hypixel.hytale.component.system.tick.EntityTickingSystem;
|
|
import com.hypixel.hytale.logger.HytaleLogger;
|
|
import com.hypixel.hytale.server.core.asset.type.blocktick.BlockTickManager;
|
|
import com.hypixel.hytale.server.core.asset.type.blocktick.BlockTickStrategy;
|
|
import com.hypixel.hytale.server.core.asset.type.blocktick.config.TickProcedure;
|
|
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
|
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource;
|
|
import com.hypixel.hytale.server.core.universe.world.World;
|
|
import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk;
|
|
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
|
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
|
import java.time.Instant;
|
|
import java.util.Set;
|
|
import java.util.logging.Level;
|
|
import javax.annotation.Nonnull;
|
|
|
|
public class ChunkBlockTickSystem {
|
|
protected static final HytaleLogger LOGGER = BlockTickPlugin.get().getLogger();
|
|
|
|
public static class PreTick extends EntityTickingSystem<ChunkStore> {
|
|
private static final ComponentType<ChunkStore, BlockChunk> COMPONENT_TYPE = BlockChunk.getComponentType();
|
|
|
|
@Override
|
|
public Query<ChunkStore> getQuery() {
|
|
return COMPONENT_TYPE;
|
|
}
|
|
|
|
@Override
|
|
public boolean isParallel(int archetypeChunkSize, int taskCount) {
|
|
return EntityTickingSystem.maybeUseParallel(archetypeChunkSize, taskCount);
|
|
}
|
|
|
|
@Override
|
|
public void tick(
|
|
float dt,
|
|
int index,
|
|
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
|
@Nonnull Store<ChunkStore> store,
|
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
|
) {
|
|
Instant time = commandBuffer.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()).getGameTime();
|
|
BlockChunk chunk = archetypeChunk.getComponent(index, COMPONENT_TYPE);
|
|
|
|
assert chunk != null;
|
|
|
|
try {
|
|
chunk.preTick(time);
|
|
} catch (Throwable var9) {
|
|
((HytaleLogger.Api)ChunkBlockTickSystem.LOGGER.at(Level.SEVERE).withCause(var9)).log("Failed to pre-tick chunk: %s", chunk);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class Ticking extends EntityTickingSystem<ChunkStore> {
|
|
private static final ComponentType<ChunkStore, WorldChunk> COMPONENT_TYPE = WorldChunk.getComponentType();
|
|
private static final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, ChunkBlockTickSystem.PreTick.class));
|
|
|
|
@Override
|
|
public Query<ChunkStore> getQuery() {
|
|
return COMPONENT_TYPE;
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
|
return DEPENDENCIES;
|
|
}
|
|
|
|
@Override
|
|
public void tick(
|
|
float dt,
|
|
int index,
|
|
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
|
@Nonnull Store<ChunkStore> store,
|
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
|
) {
|
|
Ref<ChunkStore> reference = archetypeChunk.getReferenceTo(index);
|
|
WorldChunk worldChunk = archetypeChunk.getComponent(index, COMPONENT_TYPE);
|
|
|
|
try {
|
|
tick(reference, worldChunk);
|
|
} catch (Throwable var9) {
|
|
((HytaleLogger.Api)ChunkBlockTickSystem.LOGGER.at(Level.SEVERE).withCause(var9)).log("Failed to tick chunk: %s", worldChunk);
|
|
}
|
|
}
|
|
|
|
protected static void tick(Ref<ChunkStore> ref, @Nonnull WorldChunk worldChunk) {
|
|
int ticked = worldChunk.getBlockChunk().forEachTicking(ref, worldChunk, (r, c, localX, localY, localZ, blockId) -> {
|
|
World world = c.getWorld();
|
|
int blockX = c.getX() << 5 | localX;
|
|
int blockZ = c.getZ() << 5 | localZ;
|
|
return tickProcedure(world, c, blockX, localY, blockZ, blockId);
|
|
});
|
|
if (ticked > 0) {
|
|
ChunkBlockTickSystem.LOGGER.at(Level.FINER).log("Ticked %d blocks in chunk (%d, %d)", ticked, worldChunk.getX(), worldChunk.getZ());
|
|
}
|
|
}
|
|
|
|
protected static BlockTickStrategy tickProcedure(@Nonnull World world, @Nonnull WorldChunk chunk, int blockX, int blockY, int blockZ, int blockId) {
|
|
if (world.getWorldConfig().isBlockTicking() && BlockTickManager.hasBlockTickProvider()) {
|
|
TickProcedure procedure = BlockTickPlugin.get().getTickProcedure(blockId);
|
|
if (procedure == null) {
|
|
return BlockTickStrategy.IGNORED;
|
|
} else {
|
|
try {
|
|
return procedure.onTick(world, chunk, blockX, blockY, blockZ, blockId);
|
|
} catch (Throwable var9) {
|
|
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
|
((HytaleLogger.Api)ChunkBlockTickSystem.LOGGER.at(Level.WARNING).withCause(var9))
|
|
.log("Failed to tick block at (%d, %d, %d) ID %s in world %s:", blockX, blockY, blockZ, blockType.getId(), world.getName());
|
|
return BlockTickStrategy.SLEEP;
|
|
}
|
|
}
|
|
} else {
|
|
return BlockTickStrategy.IGNORED;
|
|
}
|
|
}
|
|
}
|
|
}
|