227 lines
9.6 KiB
Java
227 lines
9.6 KiB
Java
package com.hypixel.hytale.builtin.blockphysics;
|
|
|
|
import com.hypixel.hytale.builtin.blocktick.system.ChunkBlockTickSystem;
|
|
import com.hypixel.hytale.component.ArchetypeChunk;
|
|
import com.hypixel.hytale.component.CommandBuffer;
|
|
import com.hypixel.hytale.component.ComponentAccessor;
|
|
import com.hypixel.hytale.component.DisableProcessingAssert;
|
|
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.math.util.ChunkUtil;
|
|
import com.hypixel.hytale.server.core.asset.type.blocktick.BlockTickStrategy;
|
|
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
|
import com.hypixel.hytale.server.core.blocktype.component.BlockPhysics;
|
|
import com.hypixel.hytale.server.core.universe.world.World;
|
|
import com.hypixel.hytale.server.core.universe.world.chunk.AbstractCachedAccessor;
|
|
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
|
import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
|
|
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
|
|
import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection;
|
|
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
|
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
|
import java.util.Set;
|
|
import java.util.logging.Level;
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
|
|
public class BlockPhysicsSystems {
|
|
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
|
public static final int MAX_SUPPORT_RADIUS = 14;
|
|
|
|
public static class CachedAccessor extends AbstractCachedAccessor {
|
|
private static final ThreadLocal<BlockPhysicsSystems.CachedAccessor> THREAD_LOCAL = ThreadLocal.withInitial(BlockPhysicsSystems.CachedAccessor::new);
|
|
private static final int PHYSICS_COMPONENT = 0;
|
|
private static final int FLUID_COMPONENT = 1;
|
|
private static final int BLOCK_COMPONENT = 2;
|
|
protected BlockSection selfBlockSection;
|
|
protected BlockPhysics selfPhysics;
|
|
protected FluidSection selfFluidSection;
|
|
|
|
protected CachedAccessor() {
|
|
super(3);
|
|
}
|
|
|
|
@Nonnull
|
|
public static BlockPhysicsSystems.CachedAccessor of(
|
|
ComponentAccessor<ChunkStore> commandBuffer,
|
|
BlockSection blockSection,
|
|
BlockPhysics section,
|
|
FluidSection fluidSection,
|
|
int cx,
|
|
int cy,
|
|
int cz,
|
|
int radius
|
|
) {
|
|
BlockPhysicsSystems.CachedAccessor accessor = THREAD_LOCAL.get();
|
|
accessor.init(commandBuffer, cx, cy, cz, radius);
|
|
accessor.insertSectionComponent(0, section, cx, cy, cz);
|
|
accessor.insertSectionComponent(1, fluidSection, cx, cy, cz);
|
|
accessor.insertSectionComponent(2, blockSection, cx, cy, cz);
|
|
accessor.selfBlockSection = blockSection;
|
|
accessor.selfPhysics = section;
|
|
accessor.selfFluidSection = fluidSection;
|
|
return accessor;
|
|
}
|
|
|
|
@Nullable
|
|
public BlockPhysics getBlockPhysics(int cx, int cy, int cz) {
|
|
return this.getComponentSection(cx, cy, cz, 0, BlockPhysics.getComponentType());
|
|
}
|
|
|
|
@Nullable
|
|
public FluidSection getFluidSection(int cx, int cy, int cz) {
|
|
return this.getComponentSection(cx, cy, cz, 1, FluidSection.getComponentType());
|
|
}
|
|
|
|
@Nullable
|
|
public BlockSection getBlockSection(int cx, int cy, int cz) {
|
|
return this.getComponentSection(cx, cy, cz, 2, BlockSection.getComponentType());
|
|
}
|
|
|
|
public void performBlockUpdate(int x, int y, int z, int maxSupportDistance) {
|
|
for (int ix = -1; ix < 2; ix++) {
|
|
int wx = x + ix;
|
|
|
|
for (int iz = -1; iz < 2; iz++) {
|
|
int wz = z + iz;
|
|
|
|
for (int iy = -1; iy < 2; iy++) {
|
|
int wy = y + iy;
|
|
BlockPhysics physics = this.getBlockPhysics(ChunkUtil.chunkCoordinate(wx), ChunkUtil.chunkCoordinate(wy), ChunkUtil.chunkCoordinate(wz));
|
|
int support = physics != null ? physics.get(wx, wy, wz) : 0;
|
|
if (support <= maxSupportDistance) {
|
|
BlockSection blockChunk = this.getBlockSection(ChunkUtil.chunkCoordinate(wx), ChunkUtil.chunkCoordinate(wy), ChunkUtil.chunkCoordinate(wz));
|
|
if (blockChunk != null) {
|
|
blockChunk.setTicking(wx, wy, wz, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void performBlockUpdate(int x, int y, int z) {
|
|
for (int ix = -1; ix < 2; ix++) {
|
|
int wx = x + ix;
|
|
|
|
for (int iz = -1; iz < 2; iz++) {
|
|
int wz = z + iz;
|
|
|
|
for (int iy = -1; iy < 2; iy++) {
|
|
int wy = y + iy;
|
|
BlockSection blockChunk = this.getBlockSection(ChunkUtil.chunkCoordinate(wx), ChunkUtil.chunkCoordinate(wy), ChunkUtil.chunkCoordinate(wz));
|
|
if (blockChunk != null) {
|
|
blockChunk.setTicking(wx, wy, wz, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class Ticking extends EntityTickingSystem<ChunkStore> implements DisableProcessingAssert {
|
|
private static final Query<ChunkStore> QUERY = Query.and(
|
|
ChunkSection.getComponentType(), BlockSection.getComponentType(), BlockPhysics.getComponentType(), FluidSection.getComponentType()
|
|
);
|
|
private static final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(
|
|
new SystemDependency<>(Order.AFTER, ChunkBlockTickSystem.PreTick.class), new SystemDependency<>(Order.BEFORE, ChunkBlockTickSystem.Ticking.class)
|
|
);
|
|
|
|
@Nonnull
|
|
@Override
|
|
public Query<ChunkStore> getQuery() {
|
|
return QUERY;
|
|
}
|
|
|
|
@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
|
|
) {
|
|
ChunkSection section = archetypeChunk.getComponent(index, ChunkSection.getComponentType());
|
|
|
|
assert section != null;
|
|
|
|
try {
|
|
BlockSection blockSection = archetypeChunk.getComponent(index, BlockSection.getComponentType());
|
|
|
|
assert blockSection != null;
|
|
|
|
if (blockSection.getTickingBlocksCountCopy() <= 0) {
|
|
return;
|
|
}
|
|
|
|
BlockPhysics blockPhysics = archetypeChunk.getComponent(index, BlockPhysics.getComponentType());
|
|
|
|
assert blockPhysics != null;
|
|
|
|
FluidSection fluidSection = archetypeChunk.getComponent(index, FluidSection.getComponentType());
|
|
|
|
assert fluidSection != null;
|
|
|
|
WorldChunk worldChunk = commandBuffer.getComponent(section.getChunkColumnReference(), WorldChunk.getComponentType());
|
|
BlockPhysicsSystems.CachedAccessor accessor = BlockPhysicsSystems.CachedAccessor.of(
|
|
commandBuffer, blockSection, blockPhysics, fluidSection, section.getX(), section.getY(), section.getZ(), 14
|
|
);
|
|
blockSection.forEachTicking(
|
|
worldChunk,
|
|
accessor,
|
|
section.getY(),
|
|
(wc, accessor1, localX, localY, localZ, blockId) -> {
|
|
BlockPhysics phys = accessor1.selfPhysics;
|
|
boolean isDeco = phys.isDeco(localX, localY, localZ);
|
|
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
|
if (blockType == null || blockId == 0) {
|
|
return BlockTickStrategy.IGNORED;
|
|
} else if (blockType.canBePlacedAsDeco() && isDeco) {
|
|
return BlockTickStrategy.IGNORED;
|
|
} else {
|
|
World world = wc.getWorld();
|
|
Store<EntityStore> entityStore = world.getEntityStore().getStore();
|
|
int blockX = wc.getX() << 5 | localX;
|
|
int blockZ = wc.getZ() << 5 | localZ;
|
|
int filler = accessor1.selfBlockSection.getFiller(localX, localY, localZ);
|
|
int rotation = accessor1.selfBlockSection.getRotationIndex(localX, localY, localZ);
|
|
|
|
return switch (BlockPhysicsUtil.applyBlockPhysics(
|
|
entityStore,
|
|
wc.getReference(),
|
|
accessor,
|
|
accessor1.selfBlockSection,
|
|
accessor1.selfPhysics,
|
|
accessor1.selfFluidSection,
|
|
blockX,
|
|
localY,
|
|
blockZ,
|
|
blockType,
|
|
rotation,
|
|
filler
|
|
)) {
|
|
case WAITING_CHUNK -> BlockTickStrategy.WAIT_FOR_ADJACENT_CHUNK_LOAD;
|
|
case VALID -> BlockTickStrategy.IGNORED;
|
|
case INVALID -> BlockTickStrategy.SLEEP;
|
|
};
|
|
}
|
|
}
|
|
);
|
|
} catch (Exception var12) {
|
|
((HytaleLogger.Api)BlockPhysicsSystems.LOGGER.at(Level.SEVERE).withCause(var12)).log("Failed to tick chunk: %s", section);
|
|
}
|
|
}
|
|
}
|
|
}
|