src: update 6 files
This commit is contained in:
@@ -21,122 +21,123 @@ 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.BlockChunk;
|
||||||
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
||||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
public class ChunkBlockTickSystem {
|
public class ChunkBlockTickSystem {
|
||||||
protected static final HytaleLogger LOGGER = BlockTickPlugin.get().getLogger();
|
protected static final HytaleLogger LOGGER = BlockTickPlugin.get().getLogger();
|
||||||
|
|
||||||
public ChunkBlockTickSystem() {
|
public ChunkBlockTickSystem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PreTick extends EntityTickingSystem<ChunkStore> {
|
public static class PreTick extends EntityTickingSystem<ChunkStore> {
|
||||||
private static final ComponentType<ChunkStore, BlockChunk> COMPONENT_TYPE = BlockChunk.getComponentType();
|
private static final ComponentType<ChunkStore, BlockChunk> COMPONENT_TYPE = BlockChunk.getComponentType();
|
||||||
|
|
||||||
public PreTick() {
|
public PreTick() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query<ChunkStore> getQuery() {
|
public Query<ChunkStore> getQuery() {
|
||||||
return COMPONENT_TYPE;
|
return COMPONENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isParallel(int archetypeChunkSize, int taskCount) {
|
public boolean isParallel(int archetypeChunkSize, int taskCount) {
|
||||||
return EntityTickingSystem.useParallel(archetypeChunkSize, taskCount);
|
return EntityTickingSystem.useParallel(archetypeChunkSize, taskCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(
|
public void tick(
|
||||||
float dt,
|
float dt,
|
||||||
int index,
|
int index,
|
||||||
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
||||||
@Nonnull Store<ChunkStore> store,
|
@Nonnull Store<ChunkStore> store,
|
||||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||||
) {
|
) {
|
||||||
Instant time = commandBuffer.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()).getGameTime();
|
Instant time = commandBuffer.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()).getGameTime();
|
||||||
BlockChunk chunk = archetypeChunk.getComponent(index, COMPONENT_TYPE);
|
BlockChunk chunk = archetypeChunk.getComponent(index, COMPONENT_TYPE);
|
||||||
|
|
||||||
assert chunk != null;
|
assert chunk != null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
chunk.preTick(time);
|
chunk.preTick(time);
|
||||||
} catch (Throwable var9) {
|
} catch (Throwable var9) {
|
||||||
ChunkBlockTickSystem.LOGGER.at(Level.SEVERE).withCause(var9).log("Failed to pre-tick chunk: %s", chunk);
|
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));
|
|
||||||
|
|
||||||
public Ticking() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@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) {
|
|
||||||
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);
|
|
||||||
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;
|
}
|
||||||
}
|
|
||||||
}
|
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));
|
||||||
|
|
||||||
|
public Ticking() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,373 +41,374 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
|||||||
import it.unimi.dsi.fastutil.ints.IntIterator;
|
import it.unimi.dsi.fastutil.ints.IntIterator;
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
public class FluidSystems {
|
public class FluidSystems {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||||
private static final int MAX_CHANGES_PER_PACKET = 1024;
|
private static final int MAX_CHANGES_PER_PACKET = 1024;
|
||||||
|
|
||||||
public FluidSystems() {
|
public FluidSystems() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EnsureFluidSection extends HolderSystem<ChunkStore> {
|
public static class EnsureFluidSection extends HolderSystem<ChunkStore> {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), Query.not(FluidSection.getComponentType()));
|
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), Query.not(FluidSection.getComponentType()));
|
||||||
|
|
||||||
public EnsureFluidSection() {
|
public EnsureFluidSection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
holder.addComponent(FluidSection.getComponentType(), new FluidSection());
|
holder.addComponent(FluidSection.getComponentType(), new FluidSection());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Query<ChunkStore> getQuery() {
|
public Query<ChunkStore> getQuery() {
|
||||||
return QUERY;
|
return QUERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Set<Dependency<ChunkStore>> getDependencies() {
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
||||||
return RootDependency.firstSet();
|
return RootDependency.firstSet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LoadPacketGenerator extends ChunkStore.LoadFuturePacketDataQuerySystem {
|
public static class LoadPacketGenerator extends ChunkStore.LoadFuturePacketDataQuerySystem {
|
||||||
public LoadPacketGenerator() {
|
public LoadPacketGenerator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fetch(
|
public void fetch(
|
||||||
int index,
|
int index,
|
||||||
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
||||||
Store<ChunkStore> store,
|
Store<ChunkStore> store,
|
||||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
||||||
PlayerRef query,
|
PlayerRef query,
|
||||||
@Nonnull List<CompletableFuture<Packet>> results
|
@Nonnull List<CompletableFuture<Packet>> results
|
||||||
) {
|
) {
|
||||||
ChunkColumn chunkColumnComponent = archetypeChunk.getComponent(index, ChunkColumn.getComponentType());
|
ChunkColumn chunkColumnComponent = archetypeChunk.getComponent(index, ChunkColumn.getComponentType());
|
||||||
|
|
||||||
assert chunkColumnComponent != null;
|
assert chunkColumnComponent != null;
|
||||||
|
|
||||||
for (Ref<ChunkStore> sectionRef : chunkColumnComponent.getSections()) {
|
for (Ref<ChunkStore> sectionRef : chunkColumnComponent.getSections()) {
|
||||||
FluidSection fluidSectionComponent = commandBuffer.getComponent(sectionRef, FluidSection.getComponentType());
|
FluidSection fluidSectionComponent = commandBuffer.getComponent(sectionRef, FluidSection.getComponentType());
|
||||||
if (fluidSectionComponent != null) {
|
if (fluidSectionComponent != null) {
|
||||||
results.add(fluidSectionComponent.getCachedPacket().exceptionally(throwable -> {
|
results.add(fluidSectionComponent.getCachedPacket().exceptionally(throwable -> {
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
FluidSystems.LOGGER.at(Level.SEVERE).withCause(throwable).log("Exception when compressing chunk fluids:");
|
FluidSystems.LOGGER.at(Level.SEVERE).withCause(throwable).log("Exception when compressing chunk fluids:");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}).thenApply(Function.identity()));
|
}).thenApply(Function.identity()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query<ChunkStore> getQuery() {
|
public Query<ChunkStore> getQuery() {
|
||||||
return ChunkColumn.getComponentType();
|
return ChunkColumn.getComponentType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MigrateFromColumn extends ChunkColumnMigrationSystem {
|
public static class MigrateFromColumn extends ChunkColumnMigrationSystem {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private final Query<ChunkStore> QUERY = Query.and(ChunkColumn.getComponentType(), BlockChunk.getComponentType());
|
private final Query<ChunkStore> QUERY = Query.and(ChunkColumn.getComponentType(), BlockChunk.getComponentType());
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(new SystemDependency<>(Order.BEFORE, LegacyModule.MigrateLegacySections.class));
|
private final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(new SystemDependency<>(Order.BEFORE, LegacyModule.MigrateLegacySections.class));
|
||||||
|
|
||||||
public MigrateFromColumn() {
|
public MigrateFromColumn() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
ChunkColumn chunkColumnComponent = holder.getComponent(ChunkColumn.getComponentType());
|
ChunkColumn chunkColumnComponent = holder.getComponent(ChunkColumn.getComponentType());
|
||||||
|
|
||||||
assert chunkColumnComponent != null;
|
assert chunkColumnComponent != null;
|
||||||
|
|
||||||
BlockChunk blockChunkComponent = holder.getComponent(BlockChunk.getComponentType());
|
BlockChunk blockChunkComponent = holder.getComponent(BlockChunk.getComponentType());
|
||||||
|
|
||||||
assert blockChunkComponent != null;
|
assert blockChunkComponent != null;
|
||||||
|
|
||||||
Holder<ChunkStore>[] sections = chunkColumnComponent.getSectionHolders();
|
Holder<ChunkStore>[] sections = chunkColumnComponent.getSectionHolders();
|
||||||
BlockSection[] legacySections = blockChunkComponent.getMigratedSections();
|
BlockSection[] legacySections = blockChunkComponent.getMigratedSections();
|
||||||
if (legacySections != null) {
|
if (legacySections != null) {
|
||||||
for (int i = 0; i < sections.length; i++) {
|
for (int i = 0; i < sections.length; i++) {
|
||||||
Holder<ChunkStore> section = sections[i];
|
Holder<ChunkStore> section = sections[i];
|
||||||
BlockSection paletteSection = legacySections[i];
|
BlockSection paletteSection = legacySections[i];
|
||||||
if (section != null && paletteSection != null) {
|
if (section != null && paletteSection != null) {
|
||||||
FluidSection fluid = paletteSection.takeMigratedFluid();
|
FluidSection fluid = paletteSection.takeMigratedFluid();
|
||||||
if (fluid != null) {
|
if (fluid != null) {
|
||||||
section.putComponent(FluidSection.getComponentType(), fluid);
|
section.putComponent(FluidSection.getComponentType(), fluid);
|
||||||
blockChunkComponent.markNeedsSaving();
|
blockChunkComponent.markNeedsSaving();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Query<ChunkStore> getQuery() {
|
public Query<ChunkStore> getQuery() {
|
||||||
return this.QUERY;
|
return this.QUERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Set<Dependency<ChunkStore>> getDependencies() {
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
||||||
return this.DEPENDENCIES;
|
return this.DEPENDENCIES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ReplicateChanges extends EntityTickingSystem<ChunkStore> implements RunWhenPausedSystem<ChunkStore> {
|
public static class ReplicateChanges extends EntityTickingSystem<ChunkStore> implements RunWhenPausedSystem<ChunkStore> {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), FluidSection.getComponentType());
|
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), FluidSection.getComponentType());
|
||||||
|
|
||||||
public ReplicateChanges() {
|
public ReplicateChanges() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isParallel(int archetypeChunkSize, int taskCount) {
|
public boolean isParallel(int archetypeChunkSize, int taskCount) {
|
||||||
return EntityTickingSystem.useParallel(archetypeChunkSize, taskCount);
|
return EntityTickingSystem.useParallel(archetypeChunkSize, taskCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(
|
public void tick(
|
||||||
float dt,
|
float dt,
|
||||||
int index,
|
int index,
|
||||||
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
||||||
@Nonnull Store<ChunkStore> store,
|
@Nonnull Store<ChunkStore> store,
|
||||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||||
) {
|
) {
|
||||||
FluidSection fluidSectionComponent = archetypeChunk.getComponent(index, FluidSection.getComponentType());
|
FluidSection fluidSectionComponent = archetypeChunk.getComponent(index, FluidSection.getComponentType());
|
||||||
|
|
||||||
assert fluidSectionComponent != null;
|
assert fluidSectionComponent != null;
|
||||||
|
|
||||||
IntOpenHashSet changes = fluidSectionComponent.getAndClearChangedPositions();
|
IntOpenHashSet changes = fluidSectionComponent.getAndClearChangedPositions();
|
||||||
if (!changes.isEmpty()) {
|
if (!changes.isEmpty()) {
|
||||||
|
ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, ChunkSection.getComponentType());
|
||||||
|
|
||||||
|
assert chunkSectionComponent != null;
|
||||||
|
|
||||||
|
World world = commandBuffer.getExternalData().getWorld();
|
||||||
|
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||||
|
int sectionY = chunkSectionComponent.getY();
|
||||||
|
world.execute(() -> {
|
||||||
|
if (worldChunkComponent != null && worldChunkComponent.getWorld() != null) {
|
||||||
|
worldChunkComponent.getWorld().getChunkLighting().invalidateLightInChunkSection(worldChunkComponent, sectionY);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Collection<PlayerRef> playerRefs = store.getExternalData().getWorld().getPlayerRefs();
|
||||||
|
if (playerRefs.isEmpty()) {
|
||||||
|
changes.clear();
|
||||||
|
} else {
|
||||||
|
long chunkIndex = ChunkUtil.indexChunk(fluidSectionComponent.getX(), fluidSectionComponent.getZ());
|
||||||
|
if (changes.size() >= 1024) {
|
||||||
|
ObjectArrayList<PlayerRef> playersCopy = new ObjectArrayList<>(playerRefs);
|
||||||
|
fluidSectionComponent.getCachedPacket().whenComplete((packetx, throwable) -> {
|
||||||
|
if (throwable != null) {
|
||||||
|
FluidSystems.LOGGER.at(Level.SEVERE).withCause(throwable).log("Exception when compressing chunk fluids:");
|
||||||
|
} else {
|
||||||
|
for (PlayerRef playerRefx : playersCopy) {
|
||||||
|
Ref<EntityStore> refx = playerRefx.getReference();
|
||||||
|
if (refx != null && refx.isValid()) {
|
||||||
|
ChunkTracker trackerx = playerRefx.getChunkTracker();
|
||||||
|
if (trackerx.isLoaded(chunkIndex)) {
|
||||||
|
playerRefx.getPacketHandler().writeNoCache(packetx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
changes.clear();
|
||||||
|
} else {
|
||||||
|
if (changes.size() == 1) {
|
||||||
|
int change = changes.iterator().nextInt();
|
||||||
|
int x = ChunkUtil.minBlock(fluidSectionComponent.getX()) + ChunkUtil.xFromIndex(change);
|
||||||
|
int y = ChunkUtil.minBlock(fluidSectionComponent.getY()) + ChunkUtil.yFromIndex(change);
|
||||||
|
int z = ChunkUtil.minBlock(fluidSectionComponent.getZ()) + ChunkUtil.zFromIndex(change);
|
||||||
|
int fluid = fluidSectionComponent.getFluidId(change);
|
||||||
|
byte level = fluidSectionComponent.getFluidLevel(change);
|
||||||
|
ServerSetFluid packet = new ServerSetFluid(x, y, z, fluid, level);
|
||||||
|
|
||||||
|
for (PlayerRef playerRef : playerRefs) {
|
||||||
|
Ref<EntityStore> ref = playerRef.getReference();
|
||||||
|
if (ref != null && ref.isValid()) {
|
||||||
|
ChunkTracker tracker = playerRef.getChunkTracker();
|
||||||
|
if (tracker.isLoaded(chunkIndex)) {
|
||||||
|
playerRef.getPacketHandler().writeNoCache(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SetFluidCmd[] cmds = new SetFluidCmd[changes.size()];
|
||||||
|
IntIterator iter = changes.intIterator();
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
int change = iter.nextInt();
|
||||||
|
int fluid = fluidSectionComponent.getFluidId(change);
|
||||||
|
byte level = fluidSectionComponent.getFluidLevel(change);
|
||||||
|
cmds[i++] = new SetFluidCmd((short) change, fluid, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerSetFluids packet = new ServerSetFluids(
|
||||||
|
fluidSectionComponent.getX(), fluidSectionComponent.getY(), fluidSectionComponent.getZ(), cmds
|
||||||
|
);
|
||||||
|
|
||||||
|
for (PlayerRef playerRefx : playerRefs) {
|
||||||
|
Ref<EntityStore> ref = playerRefx.getReference();
|
||||||
|
if (ref != null && ref.isValid()) {
|
||||||
|
ChunkTracker tracker = playerRefx.getChunkTracker();
|
||||||
|
if (tracker.isLoaded(chunkIndex)) {
|
||||||
|
playerRefx.getPacketHandler().writeNoCache(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Query<ChunkStore> getQuery() {
|
||||||
|
return QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
||||||
|
return RootDependency.lastSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SetupSection extends HolderSystem<ChunkStore> {
|
||||||
|
@Nonnull
|
||||||
|
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), FluidSection.getComponentType());
|
||||||
|
@Nonnull
|
||||||
|
private static final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, FluidSystems.MigrateFromColumn.class));
|
||||||
|
|
||||||
|
public SetupSection() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
|
ChunkSection chunkSectionComponent = holder.getComponent(ChunkSection.getComponentType());
|
||||||
|
|
||||||
|
assert chunkSectionComponent != null;
|
||||||
|
|
||||||
|
FluidSection fluidSectionComponent = holder.getComponent(FluidSection.getComponentType());
|
||||||
|
|
||||||
|
assert fluidSectionComponent != null;
|
||||||
|
|
||||||
|
fluidSectionComponent.load(chunkSectionComponent.getX(), chunkSectionComponent.getY(), chunkSectionComponent.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Query<ChunkStore> getQuery() {
|
||||||
|
return QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
||||||
|
return DEPENDENCIES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Ticking extends EntityTickingSystem<ChunkStore> {
|
||||||
|
@Nonnull
|
||||||
|
private static final Query<ChunkStore> QUERY = Query.and(FluidSection.getComponentType(), ChunkSection.getComponentType());
|
||||||
|
@Nonnull
|
||||||
|
private static final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(
|
||||||
|
new SystemDependency<>(Order.AFTER, ChunkBlockTickSystem.PreTick.class), new SystemDependency<>(Order.BEFORE, ChunkBlockTickSystem.Ticking.class)
|
||||||
|
);
|
||||||
|
|
||||||
|
public Ticking() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParallel(int archetypeChunkSize, int taskCount) {
|
||||||
|
return EntityTickingSystem.useParallel(archetypeChunkSize, taskCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(
|
||||||
|
float dt,
|
||||||
|
int index,
|
||||||
|
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
||||||
|
@Nonnull Store<ChunkStore> store,
|
||||||
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||||
|
) {
|
||||||
ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, ChunkSection.getComponentType());
|
ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, ChunkSection.getComponentType());
|
||||||
|
|
||||||
assert chunkSectionComponent != null;
|
assert chunkSectionComponent != null;
|
||||||
|
|
||||||
World world = commandBuffer.getExternalData().getWorld();
|
FluidSection fluidSectionComponent = archetypeChunk.getComponent(index, FluidSection.getComponentType());
|
||||||
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType());
|
|
||||||
int sectionY = chunkSectionComponent.getY();
|
assert fluidSectionComponent != null;
|
||||||
world.execute(() -> {
|
|
||||||
if (worldChunkComponent != null && worldChunkComponent.getWorld() != null) {
|
Ref<ChunkStore> chunkRef = chunkSectionComponent.getChunkColumnReference();
|
||||||
worldChunkComponent.getWorld().getChunkLighting().invalidateLightInChunkSection(worldChunkComponent, sectionY);
|
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||||
}
|
|
||||||
});
|
assert blockChunkComponent != null;
|
||||||
Collection<PlayerRef> playerRefs = store.getExternalData().getWorld().getPlayerRefs();
|
|
||||||
if (playerRefs.isEmpty()) {
|
BlockSection blockSection = blockChunkComponent.getSectionAtIndex(fluidSectionComponent.getY());
|
||||||
changes.clear();
|
if (blockSection != null) {
|
||||||
} else {
|
if (blockSection.getTickingBlocksCountCopy() != 0) {
|
||||||
long chunkIndex = ChunkUtil.indexChunk(fluidSectionComponent.getX(), fluidSectionComponent.getZ());
|
FluidTicker.CachedAccessor accessor = FluidTicker.CachedAccessor.of(commandBuffer, fluidSectionComponent, blockSection, 5);
|
||||||
if (changes.size() >= 1024) {
|
blockSection.forEachTicking(accessor, commandBuffer, fluidSectionComponent.getY(), (accessor1, commandBuffer1, x, y, z, block) -> {
|
||||||
ObjectArrayList<PlayerRef> playersCopy = new ObjectArrayList<>(playerRefs);
|
FluidSection fluidSection1 = accessor1.selfFluidSection;
|
||||||
fluidSectionComponent.getCachedPacket().whenComplete((packetx, throwable) -> {
|
BlockSection blockSection1 = accessor1.selfBlockSection;
|
||||||
if (throwable != null) {
|
int fluidId = fluidSection1.getFluidId(x, y, z);
|
||||||
FluidSystems.LOGGER.at(Level.SEVERE).withCause(throwable).log("Exception when compressing chunk fluids:");
|
if (fluidId == 0) {
|
||||||
} else {
|
return BlockTickStrategy.IGNORED;
|
||||||
for (PlayerRef playerRefx : playersCopy) {
|
} else {
|
||||||
Ref<EntityStore> refx = playerRefx.getReference();
|
Fluid fluid = Fluid.getAssetMap().getAsset(fluidId);
|
||||||
if (refx != null && refx.isValid()) {
|
int blockX = fluidSection1.getX() << 5 | x;
|
||||||
ChunkTracker trackerx = playerRefx.getChunkTracker();
|
int blockZ = fluidSection1.getZ() << 5 | z;
|
||||||
if (trackerx.isLoaded(chunkIndex)) {
|
return fluid.getTicker().tick(commandBuffer1, accessor1, fluidSection1, blockSection1, fluid, fluidId, blockX, y, blockZ);
|
||||||
playerRefx.getPacketHandler().writeNoCache(packetx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
changes.clear();
|
|
||||||
} else {
|
|
||||||
if (changes.size() == 1) {
|
|
||||||
int change = changes.iterator().nextInt();
|
|
||||||
int x = ChunkUtil.minBlock(fluidSectionComponent.getX()) + ChunkUtil.xFromIndex(change);
|
|
||||||
int y = ChunkUtil.minBlock(fluidSectionComponent.getY()) + ChunkUtil.yFromIndex(change);
|
|
||||||
int z = ChunkUtil.minBlock(fluidSectionComponent.getZ()) + ChunkUtil.zFromIndex(change);
|
|
||||||
int fluid = fluidSectionComponent.getFluidId(change);
|
|
||||||
byte level = fluidSectionComponent.getFluidLevel(change);
|
|
||||||
ServerSetFluid packet = new ServerSetFluid(x, y, z, fluid, level);
|
|
||||||
|
|
||||||
for (PlayerRef playerRef : playerRefs) {
|
|
||||||
Ref<EntityStore> ref = playerRef.getReference();
|
|
||||||
if (ref != null && ref.isValid()) {
|
|
||||||
ChunkTracker tracker = playerRef.getChunkTracker();
|
|
||||||
if (tracker.isLoaded(chunkIndex)) {
|
|
||||||
playerRef.getPacketHandler().writeNoCache(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SetFluidCmd[] cmds = new SetFluidCmd[changes.size()];
|
|
||||||
IntIterator iter = changes.intIterator();
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
int change = iter.nextInt();
|
|
||||||
int fluid = fluidSectionComponent.getFluidId(change);
|
|
||||||
byte level = fluidSectionComponent.getFluidLevel(change);
|
|
||||||
cmds[i++] = new SetFluidCmd((short)change, fluid, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerSetFluids packet = new ServerSetFluids(
|
|
||||||
fluidSectionComponent.getX(), fluidSectionComponent.getY(), fluidSectionComponent.getZ(), cmds
|
|
||||||
);
|
|
||||||
|
|
||||||
for (PlayerRef playerRefx : playerRefs) {
|
|
||||||
Ref<EntityStore> ref = playerRefx.getReference();
|
|
||||||
if (ref != null && ref.isValid()) {
|
|
||||||
ChunkTracker tracker = playerRefx.getChunkTracker();
|
|
||||||
if (tracker.isLoaded(chunkIndex)) {
|
|
||||||
playerRefx.getPacketHandler().writeNoCache(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changes.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Query<ChunkStore> getQuery() {
|
public Query<ChunkStore> getQuery() {
|
||||||
return QUERY;
|
return QUERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Set<Dependency<ChunkStore>> getDependencies() {
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
||||||
return RootDependency.lastSet();
|
return DEPENDENCIES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SetupSection extends HolderSystem<ChunkStore> {
|
|
||||||
@Nonnull
|
|
||||||
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), FluidSection.getComponentType());
|
|
||||||
@Nonnull
|
|
||||||
private static final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, FluidSystems.MigrateFromColumn.class));
|
|
||||||
|
|
||||||
public SetupSection() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
|
||||||
ChunkSection chunkSectionComponent = holder.getComponent(ChunkSection.getComponentType());
|
|
||||||
|
|
||||||
assert chunkSectionComponent != null;
|
|
||||||
|
|
||||||
FluidSection fluidSectionComponent = holder.getComponent(FluidSection.getComponentType());
|
|
||||||
|
|
||||||
assert fluidSectionComponent != null;
|
|
||||||
|
|
||||||
fluidSectionComponent.load(chunkSectionComponent.getX(), chunkSectionComponent.getY(), chunkSectionComponent.getZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Query<ChunkStore> getQuery() {
|
|
||||||
return QUERY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Set<Dependency<ChunkStore>> getDependencies() {
|
|
||||||
return DEPENDENCIES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Ticking extends EntityTickingSystem<ChunkStore> {
|
|
||||||
@Nonnull
|
|
||||||
private static final Query<ChunkStore> QUERY = Query.and(FluidSection.getComponentType(), ChunkSection.getComponentType());
|
|
||||||
@Nonnull
|
|
||||||
private static final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(
|
|
||||||
new SystemDependency<>(Order.AFTER, ChunkBlockTickSystem.PreTick.class), new SystemDependency<>(Order.BEFORE, ChunkBlockTickSystem.Ticking.class)
|
|
||||||
);
|
|
||||||
|
|
||||||
public Ticking() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isParallel(int archetypeChunkSize, int taskCount) {
|
|
||||||
return EntityTickingSystem.useParallel(archetypeChunkSize, taskCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick(
|
|
||||||
float dt,
|
|
||||||
int index,
|
|
||||||
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
|
||||||
@Nonnull Store<ChunkStore> store,
|
|
||||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
|
||||||
) {
|
|
||||||
ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, ChunkSection.getComponentType());
|
|
||||||
|
|
||||||
assert chunkSectionComponent != null;
|
|
||||||
|
|
||||||
FluidSection fluidSectionComponent = archetypeChunk.getComponent(index, FluidSection.getComponentType());
|
|
||||||
|
|
||||||
assert fluidSectionComponent != null;
|
|
||||||
|
|
||||||
Ref<ChunkStore> chunkRef = chunkSectionComponent.getChunkColumnReference();
|
|
||||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
|
||||||
|
|
||||||
assert blockChunkComponent != null;
|
|
||||||
|
|
||||||
BlockSection blockSection = blockChunkComponent.getSectionAtIndex(fluidSectionComponent.getY());
|
|
||||||
if (blockSection != null) {
|
|
||||||
if (blockSection.getTickingBlocksCountCopy() != 0) {
|
|
||||||
FluidTicker.CachedAccessor accessor = FluidTicker.CachedAccessor.of(commandBuffer, fluidSectionComponent, blockSection, 5);
|
|
||||||
blockSection.forEachTicking(accessor, commandBuffer, fluidSectionComponent.getY(), (accessor1, commandBuffer1, x, y, z, block) -> {
|
|
||||||
FluidSection fluidSection1 = accessor1.selfFluidSection;
|
|
||||||
BlockSection blockSection1 = accessor1.selfBlockSection;
|
|
||||||
int fluidId = fluidSection1.getFluidId(x, y, z);
|
|
||||||
if (fluidId == 0) {
|
|
||||||
return BlockTickStrategy.IGNORED;
|
|
||||||
} else {
|
|
||||||
Fluid fluid = Fluid.getAssetMap().getAsset(fluidId);
|
|
||||||
int blockX = fluidSection1.getX() << 5 | x;
|
|
||||||
int blockZ = fluidSection1.getZ() << 5 | z;
|
|
||||||
return fluid.getTicker().tick(commandBuffer1, accessor1, fluidSection1, blockSection1, fluid, fluidId, blockX, y, blockZ);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Query<ChunkStore> getQuery() {
|
|
||||||
return QUERY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Set<Dependency<ChunkStore>> getDependencies() {
|
|
||||||
return DEPENDENCIES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.hypixel.hytale.server.core.event.events.ecs;
|
|||||||
import com.hypixel.hytale.component.system.CancellableEcsEvent;
|
import com.hypixel.hytale.component.system.CancellableEcsEvent;
|
||||||
import com.hypixel.hytale.math.vector.Vector3i;
|
import com.hypixel.hytale.math.vector.Vector3i;
|
||||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -39,376 +39,377 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
|||||||
import it.unimi.dsi.fastutil.ints.IntIterator;
|
import it.unimi.dsi.fastutil.ints.IntIterator;
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class ChunkSystems {
|
public class ChunkSystems {
|
||||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||||
private static final int MAX_CHANGES_PER_PACKET = 1024;
|
private static final int MAX_CHANGES_PER_PACKET = 1024;
|
||||||
|
|
||||||
public ChunkSystems() {
|
public ChunkSystems() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EnsureBlockSection extends HolderSystem<ChunkStore> {
|
public static class EnsureBlockSection extends HolderSystem<ChunkStore> {
|
||||||
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), Query.not(BlockSection.getComponentType()));
|
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), Query.not(BlockSection.getComponentType()));
|
||||||
|
|
||||||
public EnsureBlockSection() {
|
public EnsureBlockSection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
holder.ensureComponent(BlockSection.getComponentType());
|
holder.ensureComponent(BlockSection.getComponentType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Query<ChunkStore> getQuery() {
|
public Query<ChunkStore> getQuery() {
|
||||||
return QUERY;
|
return QUERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Set<Dependency<ChunkStore>> getDependencies() {
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
||||||
return RootDependency.firstSet();
|
return RootDependency.firstSet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LoadBlockSection extends HolderSystem<ChunkStore> {
|
public static class LoadBlockSection extends HolderSystem<ChunkStore> {
|
||||||
public LoadBlockSection() {
|
public LoadBlockSection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
BlockSection section = holder.getComponent(BlockSection.getComponentType());
|
BlockSection section = holder.getComponent(BlockSection.getComponentType());
|
||||||
|
|
||||||
assert section != null;
|
|
||||||
|
|
||||||
section.loaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Query<ChunkStore> getQuery() {
|
|
||||||
return BlockSection.getComponentType();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class OnChunkLoad extends RefSystem<ChunkStore> {
|
|
||||||
private static final Query<ChunkStore> QUERY = Query.and(ChunkColumn.getComponentType(), WorldChunk.getComponentType());
|
|
||||||
private static final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, ChunkSystems.OnNewChunk.class));
|
|
||||||
|
|
||||||
public OnChunkLoad() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEntityAdded(
|
|
||||||
@Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer
|
|
||||||
) {
|
|
||||||
ChunkColumn chunk = commandBuffer.getComponent(ref, ChunkColumn.getComponentType());
|
|
||||||
|
|
||||||
assert chunk != null;
|
|
||||||
|
|
||||||
WorldChunk worldChunk = commandBuffer.getComponent(ref, WorldChunk.getComponentType());
|
|
||||||
|
|
||||||
assert worldChunk != null;
|
|
||||||
|
|
||||||
Ref<ChunkStore>[] sections = chunk.getSections();
|
|
||||||
Holder<ChunkStore>[] sectionHolders = chunk.takeSectionHolders();
|
|
||||||
boolean isNonTicking = commandBuffer.getArchetype(ref).contains(ChunkStore.REGISTRY.getNonTickingComponentType());
|
|
||||||
if (sectionHolders != null && sectionHolders.length > 0 && sectionHolders[0] != null) {
|
|
||||||
for (int i = 0; i < sectionHolders.length; i++) {
|
|
||||||
if (isNonTicking) {
|
|
||||||
sectionHolders[i].ensureComponent(ChunkStore.REGISTRY.getNonTickingComponentType());
|
|
||||||
} else {
|
|
||||||
sectionHolders[i].tryRemoveComponent(ChunkStore.REGISTRY.getNonTickingComponentType());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChunkSection section = sectionHolders[i].getComponent(ChunkSection.getComponentType());
|
|
||||||
if (section == null) {
|
|
||||||
sectionHolders[i].addComponent(ChunkSection.getComponentType(), new ChunkSection(ref, worldChunk.getX(), i, worldChunk.getZ()));
|
|
||||||
} else {
|
|
||||||
section.load(ref, worldChunk.getX(), i, worldChunk.getZ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
commandBuffer.addEntities(sectionHolders, 0, sections, 0, sections.length, AddReason.LOAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < sections.length; i++) {
|
|
||||||
if (sections[i] == null) {
|
|
||||||
Holder<ChunkStore> newSection = ChunkStore.REGISTRY.newHolder();
|
|
||||||
if (isNonTicking) {
|
|
||||||
newSection.ensureComponent(ChunkStore.REGISTRY.getNonTickingComponentType());
|
|
||||||
} else {
|
|
||||||
newSection.tryRemoveComponent(ChunkStore.REGISTRY.getNonTickingComponentType());
|
|
||||||
}
|
|
||||||
|
|
||||||
newSection.addComponent(ChunkSection.getComponentType(), new ChunkSection(ref, worldChunk.getX(), i, worldChunk.getZ()));
|
|
||||||
sections[i] = commandBuffer.addEntity(newSection, AddReason.SPAWN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEntityRemove(
|
|
||||||
@Nonnull Ref<ChunkStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer
|
|
||||||
) {
|
|
||||||
ChunkColumn chunk = commandBuffer.getComponent(ref, ChunkColumn.getComponentType());
|
|
||||||
|
|
||||||
assert chunk != null;
|
|
||||||
|
|
||||||
Ref<ChunkStore>[] sections = chunk.getSections();
|
|
||||||
Holder<ChunkStore>[] holders = new Holder[sections.length];
|
|
||||||
|
|
||||||
for (int i = 0; i < sections.length; i++) {
|
|
||||||
Ref<ChunkStore> section = sections[i];
|
|
||||||
holders[i] = ChunkStore.REGISTRY.newHolder();
|
|
||||||
commandBuffer.removeEntity(section, holders[i], reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk.putSectionHolders(holders);
|
|
||||||
Arrays.fill(sections, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Query<ChunkStore> getQuery() {
|
|
||||||
return QUERY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Set<Dependency<ChunkStore>> getDependencies() {
|
|
||||||
return DEPENDENCIES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class OnNewChunk extends ChunkColumnMigrationSystem {
|
|
||||||
private static final Query<ChunkStore> QUERY = Query.and(WorldChunk.getComponentType(), Query.not(ChunkColumn.getComponentType()));
|
|
||||||
|
|
||||||
public OnNewChunk() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
|
||||||
Holder[] sectionHolders = new Holder[10];
|
|
||||||
|
|
||||||
for (int i = 0; i < sectionHolders.length; i++) {
|
|
||||||
sectionHolders[i] = ChunkStore.REGISTRY.newHolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.addComponent(ChunkColumn.getComponentType(), new ChunkColumn(sectionHolders));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Query<ChunkStore> getQuery() {
|
|
||||||
return QUERY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Set<Dependency<ChunkStore>> getDependencies() {
|
|
||||||
return RootDependency.firstSet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class OnNonTicking extends RefChangeSystem<ChunkStore, NonTicking<ChunkStore>> {
|
|
||||||
private final Archetype<ChunkStore> archetype = Archetype.of(WorldChunk.getComponentType(), ChunkColumn.getComponentType());
|
|
||||||
|
|
||||||
public OnNonTicking() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public ComponentType<ChunkStore, NonTicking<ChunkStore>> componentType() {
|
|
||||||
return ChunkStore.REGISTRY.getNonTickingComponentType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onComponentAdded(
|
|
||||||
@Nonnull Ref<ChunkStore> ref,
|
|
||||||
@Nonnull NonTicking<ChunkStore> component,
|
|
||||||
@Nonnull Store<ChunkStore> store,
|
|
||||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
|
||||||
) {
|
|
||||||
ChunkColumn column = commandBuffer.getComponent(ref, ChunkColumn.getComponentType());
|
|
||||||
|
|
||||||
assert column != null;
|
|
||||||
|
|
||||||
Ref<ChunkStore>[] sections = column.getSections();
|
|
||||||
|
|
||||||
for (int i = 0; i < sections.length; i++) {
|
|
||||||
Ref<ChunkStore> section = sections[i];
|
|
||||||
commandBuffer.ensureComponent(section, ChunkStore.REGISTRY.getNonTickingComponentType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onComponentSet(
|
|
||||||
@Nonnull Ref<ChunkStore> ref,
|
|
||||||
@Nullable NonTicking<ChunkStore> oldComponent,
|
|
||||||
@Nonnull NonTicking<ChunkStore> newComponent,
|
|
||||||
@Nonnull Store<ChunkStore> store,
|
|
||||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onComponentRemoved(
|
|
||||||
@Nonnull Ref<ChunkStore> ref,
|
|
||||||
@Nonnull NonTicking<ChunkStore> component,
|
|
||||||
@Nonnull Store<ChunkStore> store,
|
|
||||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
|
||||||
) {
|
|
||||||
ChunkColumn column = commandBuffer.getComponent(ref, ChunkColumn.getComponentType());
|
|
||||||
|
|
||||||
assert column != null;
|
|
||||||
|
|
||||||
Ref<ChunkStore>[] sections = column.getSections();
|
|
||||||
|
|
||||||
for (int i = 0; i < sections.length; i++) {
|
|
||||||
Ref<ChunkStore> section = sections[i];
|
|
||||||
commandBuffer.tryRemoveComponent(section, ChunkStore.REGISTRY.getNonTickingComponentType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Query<ChunkStore> getQuery() {
|
|
||||||
return this.archetype;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ReplicateChanges extends EntityTickingSystem<ChunkStore> implements RunWhenPausedSystem<ChunkStore> {
|
|
||||||
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), BlockSection.getComponentType());
|
|
||||||
|
|
||||||
public ReplicateChanges() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isParallel(int archetypeChunkSize, int taskCount) {
|
|
||||||
return EntityTickingSystem.useParallel(archetypeChunkSize, taskCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick(
|
|
||||||
float dt,
|
|
||||||
int index,
|
|
||||||
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
|
||||||
@Nonnull Store<ChunkStore> store,
|
|
||||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
|
||||||
) {
|
|
||||||
BlockSection blockSection = archetypeChunk.getComponent(index, BlockSection.getComponentType());
|
|
||||||
|
|
||||||
assert blockSection != null;
|
|
||||||
|
|
||||||
IntOpenHashSet changes = blockSection.getAndClearChangedPositions();
|
|
||||||
if (!changes.isEmpty()) {
|
|
||||||
ChunkSection section = archetypeChunk.getComponent(index, ChunkSection.getComponentType());
|
|
||||||
|
|
||||||
assert section != null;
|
assert section != null;
|
||||||
|
|
||||||
Collection<PlayerRef> players = store.getExternalData().getWorld().getPlayerRefs();
|
section.loaded = true;
|
||||||
if (players.isEmpty()) {
|
}
|
||||||
changes.clear();
|
|
||||||
} else {
|
|
||||||
long chunkIndex = ChunkUtil.indexChunk(section.getX(), section.getZ());
|
|
||||||
if (changes.size() >= 1024) {
|
|
||||||
ObjectArrayList<PlayerRef> playersCopy = new ObjectArrayList<>(players);
|
|
||||||
CompletableFuture<CachedPacket<SetChunk>> set = blockSection.getCachedChunkPacket(section.getX(), section.getY(), section.getZ());
|
|
||||||
set.thenAccept(s -> {
|
|
||||||
for (PlayerRef playerx : playersCopy) {
|
|
||||||
Ref<EntityStore> refx = playerx.getReference();
|
|
||||||
if (refx != null) {
|
|
||||||
ChunkTracker trackerx = playerx.getChunkTracker();
|
|
||||||
if (trackerx != null && trackerx.isLoaded(chunkIndex)) {
|
|
||||||
playerx.getPacketHandler().writeNoCache(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).exceptionally(throwable -> {
|
|
||||||
if (throwable != null) {
|
|
||||||
ChunkSystems.LOGGER.at(Level.SEVERE).withCause(throwable).log("Exception when compressing chunk fluids:");
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
@Override
|
||||||
});
|
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
changes.clear();
|
}
|
||||||
} else {
|
|
||||||
if (changes.size() == 1) {
|
|
||||||
int change = changes.iterator().nextInt();
|
|
||||||
int x = ChunkUtil.minBlock(section.getX()) + ChunkUtil.xFromIndex(change);
|
|
||||||
int y = ChunkUtil.minBlock(section.getY()) + ChunkUtil.yFromIndex(change);
|
|
||||||
int z = ChunkUtil.minBlock(section.getZ()) + ChunkUtil.zFromIndex(change);
|
|
||||||
int blockId = blockSection.get(change);
|
|
||||||
int filler = blockSection.getFiller(change);
|
|
||||||
int rotation = blockSection.getRotationIndex(change);
|
|
||||||
ServerSetBlock packet = new ServerSetBlock(x, y, z, blockId, (short)filler, (byte)rotation);
|
|
||||||
|
|
||||||
for (PlayerRef player : players) {
|
@Override
|
||||||
Ref<EntityStore> ref = player.getReference();
|
public Query<ChunkStore> getQuery() {
|
||||||
if (ref != null) {
|
return BlockSection.getComponentType();
|
||||||
ChunkTracker tracker = player.getChunkTracker();
|
}
|
||||||
if (tracker != null && tracker.isLoaded(chunkIndex)) {
|
}
|
||||||
player.getPacketHandler().writeNoCache(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SetBlockCmd[] cmds = new SetBlockCmd[changes.size()];
|
|
||||||
IntIterator iter = changes.intIterator();
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (iter.hasNext()) {
|
public static class OnChunkLoad extends RefSystem<ChunkStore> {
|
||||||
int change = iter.nextInt();
|
private static final Query<ChunkStore> QUERY = Query.and(ChunkColumn.getComponentType(), WorldChunk.getComponentType());
|
||||||
int blockId = blockSection.get(change);
|
private static final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, ChunkSystems.OnNewChunk.class));
|
||||||
int filler = blockSection.getFiller(change);
|
|
||||||
int rotation = blockSection.getRotationIndex(change);
|
|
||||||
cmds[i++] = new SetBlockCmd((short)change, blockId, (short)filler, (byte)rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerSetBlocks packet = new ServerSetBlocks(section.getX(), section.getY(), section.getZ(), cmds);
|
public OnChunkLoad() {
|
||||||
|
}
|
||||||
|
|
||||||
for (PlayerRef playerx : players) {
|
@Override
|
||||||
Ref<EntityStore> ref = playerx.getReference();
|
public void onEntityAdded(
|
||||||
if (ref != null) {
|
@Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||||
ChunkTracker tracker = playerx.getChunkTracker();
|
) {
|
||||||
if (tracker != null && tracker.isLoaded(chunkIndex)) {
|
ChunkColumn chunk = commandBuffer.getComponent(ref, ChunkColumn.getComponentType());
|
||||||
playerx.getPacketHandler().writeNoCache(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changes.clear();
|
assert chunk != null;
|
||||||
}
|
|
||||||
|
WorldChunk worldChunk = commandBuffer.getComponent(ref, WorldChunk.getComponentType());
|
||||||
|
|
||||||
|
assert worldChunk != null;
|
||||||
|
|
||||||
|
Ref<ChunkStore>[] sections = chunk.getSections();
|
||||||
|
Holder<ChunkStore>[] sectionHolders = chunk.takeSectionHolders();
|
||||||
|
boolean isNonTicking = commandBuffer.getArchetype(ref).contains(ChunkStore.REGISTRY.getNonTickingComponentType());
|
||||||
|
if (sectionHolders != null && sectionHolders.length > 0 && sectionHolders[0] != null) {
|
||||||
|
for (int i = 0; i < sectionHolders.length; i++) {
|
||||||
|
if (isNonTicking) {
|
||||||
|
sectionHolders[i].ensureComponent(ChunkStore.REGISTRY.getNonTickingComponentType());
|
||||||
|
} else {
|
||||||
|
sectionHolders[i].tryRemoveComponent(ChunkStore.REGISTRY.getNonTickingComponentType());
|
||||||
|
}
|
||||||
|
|
||||||
|
ChunkSection section = sectionHolders[i].getComponent(ChunkSection.getComponentType());
|
||||||
|
if (section == null) {
|
||||||
|
sectionHolders[i].addComponent(ChunkSection.getComponentType(), new ChunkSection(ref, worldChunk.getX(), i, worldChunk.getZ()));
|
||||||
|
} else {
|
||||||
|
section.load(ref, worldChunk.getX(), i, worldChunk.getZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commandBuffer.addEntities(sectionHolders, 0, sections, 0, sections.length, AddReason.LOAD);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
for (int i = 0; i < sections.length; i++) {
|
||||||
@Override
|
if (sections[i] == null) {
|
||||||
public Query<ChunkStore> getQuery() {
|
Holder<ChunkStore> newSection = ChunkStore.REGISTRY.newHolder();
|
||||||
return QUERY;
|
if (isNonTicking) {
|
||||||
}
|
newSection.ensureComponent(ChunkStore.REGISTRY.getNonTickingComponentType());
|
||||||
|
} else {
|
||||||
|
newSection.tryRemoveComponent(ChunkStore.REGISTRY.getNonTickingComponentType());
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
newSection.addComponent(ChunkSection.getComponentType(), new ChunkSection(ref, worldChunk.getX(), i, worldChunk.getZ()));
|
||||||
@Override
|
sections[i] = commandBuffer.addEntity(newSection, AddReason.SPAWN);
|
||||||
public Set<Dependency<ChunkStore>> getDependencies() {
|
}
|
||||||
return RootDependency.lastSet();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public void onEntityRemove(
|
||||||
|
@Nonnull Ref<ChunkStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||||
|
) {
|
||||||
|
ChunkColumn chunk = commandBuffer.getComponent(ref, ChunkColumn.getComponentType());
|
||||||
|
|
||||||
|
assert chunk != null;
|
||||||
|
|
||||||
|
Ref<ChunkStore>[] sections = chunk.getSections();
|
||||||
|
Holder<ChunkStore>[] holders = new Holder[sections.length];
|
||||||
|
|
||||||
|
for (int i = 0; i < sections.length; i++) {
|
||||||
|
Ref<ChunkStore> section = sections[i];
|
||||||
|
holders[i] = ChunkStore.REGISTRY.newHolder();
|
||||||
|
commandBuffer.removeEntity(section, holders[i], reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk.putSectionHolders(holders);
|
||||||
|
Arrays.fill(sections, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Query<ChunkStore> getQuery() {
|
||||||
|
return QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
||||||
|
return DEPENDENCIES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class OnNewChunk extends ChunkColumnMigrationSystem {
|
||||||
|
private static final Query<ChunkStore> QUERY = Query.and(WorldChunk.getComponentType(), Query.not(ChunkColumn.getComponentType()));
|
||||||
|
|
||||||
|
public OnNewChunk() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEntityAdd(@Nonnull Holder<ChunkStore> holder, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
|
Holder[] sectionHolders = new Holder[10];
|
||||||
|
|
||||||
|
for (int i = 0; i < sectionHolders.length; i++) {
|
||||||
|
sectionHolders[i] = ChunkStore.REGISTRY.newHolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.addComponent(ChunkColumn.getComponentType(), new ChunkColumn(sectionHolders));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEntityRemoved(@Nonnull Holder<ChunkStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Query<ChunkStore> getQuery() {
|
||||||
|
return QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
||||||
|
return RootDependency.firstSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class OnNonTicking extends RefChangeSystem<ChunkStore, NonTicking<ChunkStore>> {
|
||||||
|
private final Archetype<ChunkStore> archetype = Archetype.of(WorldChunk.getComponentType(), ChunkColumn.getComponentType());
|
||||||
|
|
||||||
|
public OnNonTicking() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public ComponentType<ChunkStore, NonTicking<ChunkStore>> componentType() {
|
||||||
|
return ChunkStore.REGISTRY.getNonTickingComponentType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onComponentAdded(
|
||||||
|
@Nonnull Ref<ChunkStore> ref,
|
||||||
|
@Nonnull NonTicking<ChunkStore> component,
|
||||||
|
@Nonnull Store<ChunkStore> store,
|
||||||
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||||
|
) {
|
||||||
|
ChunkColumn column = commandBuffer.getComponent(ref, ChunkColumn.getComponentType());
|
||||||
|
|
||||||
|
assert column != null;
|
||||||
|
|
||||||
|
Ref<ChunkStore>[] sections = column.getSections();
|
||||||
|
|
||||||
|
for (int i = 0; i < sections.length; i++) {
|
||||||
|
Ref<ChunkStore> section = sections[i];
|
||||||
|
commandBuffer.ensureComponent(section, ChunkStore.REGISTRY.getNonTickingComponentType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onComponentSet(
|
||||||
|
@Nonnull Ref<ChunkStore> ref,
|
||||||
|
@Nullable NonTicking<ChunkStore> oldComponent,
|
||||||
|
@Nonnull NonTicking<ChunkStore> newComponent,
|
||||||
|
@Nonnull Store<ChunkStore> store,
|
||||||
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onComponentRemoved(
|
||||||
|
@Nonnull Ref<ChunkStore> ref,
|
||||||
|
@Nonnull NonTicking<ChunkStore> component,
|
||||||
|
@Nonnull Store<ChunkStore> store,
|
||||||
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||||
|
) {
|
||||||
|
ChunkColumn column = commandBuffer.getComponent(ref, ChunkColumn.getComponentType());
|
||||||
|
|
||||||
|
assert column != null;
|
||||||
|
|
||||||
|
Ref<ChunkStore>[] sections = column.getSections();
|
||||||
|
|
||||||
|
for (int i = 0; i < sections.length; i++) {
|
||||||
|
Ref<ChunkStore> section = sections[i];
|
||||||
|
commandBuffer.tryRemoveComponent(section, ChunkStore.REGISTRY.getNonTickingComponentType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Query<ChunkStore> getQuery() {
|
||||||
|
return this.archetype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ReplicateChanges extends EntityTickingSystem<ChunkStore> implements RunWhenPausedSystem<ChunkStore> {
|
||||||
|
private static final Query<ChunkStore> QUERY = Query.and(ChunkSection.getComponentType(), BlockSection.getComponentType());
|
||||||
|
|
||||||
|
public ReplicateChanges() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParallel(int archetypeChunkSize, int taskCount) {
|
||||||
|
return EntityTickingSystem.useParallel(archetypeChunkSize, taskCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(
|
||||||
|
float dt,
|
||||||
|
int index,
|
||||||
|
@Nonnull ArchetypeChunk<ChunkStore> archetypeChunk,
|
||||||
|
@Nonnull Store<ChunkStore> store,
|
||||||
|
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||||
|
) {
|
||||||
|
BlockSection blockSection = archetypeChunk.getComponent(index, BlockSection.getComponentType());
|
||||||
|
|
||||||
|
assert blockSection != null;
|
||||||
|
|
||||||
|
IntOpenHashSet changes = blockSection.getAndClearChangedPositions();
|
||||||
|
if (!changes.isEmpty()) {
|
||||||
|
ChunkSection section = archetypeChunk.getComponent(index, ChunkSection.getComponentType());
|
||||||
|
|
||||||
|
assert section != null;
|
||||||
|
|
||||||
|
Collection<PlayerRef> players = store.getExternalData().getWorld().getPlayerRefs();
|
||||||
|
if (players.isEmpty()) {
|
||||||
|
changes.clear();
|
||||||
|
} else {
|
||||||
|
long chunkIndex = ChunkUtil.indexChunk(section.getX(), section.getZ());
|
||||||
|
if (changes.size() >= 1024) {
|
||||||
|
ObjectArrayList<PlayerRef> playersCopy = new ObjectArrayList<>(players);
|
||||||
|
CompletableFuture<CachedPacket<SetChunk>> set = blockSection.getCachedChunkPacket(section.getX(), section.getY(), section.getZ());
|
||||||
|
set.thenAccept(s -> {
|
||||||
|
for (PlayerRef playerx : playersCopy) {
|
||||||
|
Ref<EntityStore> refx = playerx.getReference();
|
||||||
|
if (refx != null) {
|
||||||
|
ChunkTracker trackerx = playerx.getChunkTracker();
|
||||||
|
if (trackerx != null && trackerx.isLoaded(chunkIndex)) {
|
||||||
|
playerx.getPacketHandler().writeNoCache(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
if (throwable != null) {
|
||||||
|
ChunkSystems.LOGGER.at(Level.SEVERE).withCause(throwable).log("Exception when compressing chunk fluids:");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
changes.clear();
|
||||||
|
} else {
|
||||||
|
if (changes.size() == 1) {
|
||||||
|
int change = changes.iterator().nextInt();
|
||||||
|
int x = ChunkUtil.minBlock(section.getX()) + ChunkUtil.xFromIndex(change);
|
||||||
|
int y = ChunkUtil.minBlock(section.getY()) + ChunkUtil.yFromIndex(change);
|
||||||
|
int z = ChunkUtil.minBlock(section.getZ()) + ChunkUtil.zFromIndex(change);
|
||||||
|
int blockId = blockSection.get(change);
|
||||||
|
int filler = blockSection.getFiller(change);
|
||||||
|
int rotation = blockSection.getRotationIndex(change);
|
||||||
|
ServerSetBlock packet = new ServerSetBlock(x, y, z, blockId, (short) filler, (byte) rotation);
|
||||||
|
|
||||||
|
for (PlayerRef player : players) {
|
||||||
|
Ref<EntityStore> ref = player.getReference();
|
||||||
|
if (ref != null) {
|
||||||
|
ChunkTracker tracker = player.getChunkTracker();
|
||||||
|
if (tracker != null && tracker.isLoaded(chunkIndex)) {
|
||||||
|
player.getPacketHandler().writeNoCache(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SetBlockCmd[] cmds = new SetBlockCmd[changes.size()];
|
||||||
|
IntIterator iter = changes.intIterator();
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
int change = iter.nextInt();
|
||||||
|
int blockId = blockSection.get(change);
|
||||||
|
int filler = blockSection.getFiller(change);
|
||||||
|
int rotation = blockSection.getRotationIndex(change);
|
||||||
|
cmds[i++] = new SetBlockCmd((short) change, blockId, (short) filler, (byte) rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerSetBlocks packet = new ServerSetBlocks(section.getX(), section.getY(), section.getZ(), cmds);
|
||||||
|
|
||||||
|
for (PlayerRef playerx : players) {
|
||||||
|
Ref<EntityStore> ref = playerx.getReference();
|
||||||
|
if (ref != null) {
|
||||||
|
ChunkTracker tracker = playerx.getChunkTracker();
|
||||||
|
if (tracker != null && tracker.isLoaded(chunkIndex)) {
|
||||||
|
playerx.getPacketHandler().writeNoCache(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Query<ChunkStore> getQuery() {
|
||||||
|
return QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Set<Dependency<ChunkStore>> getDependencies() {
|
||||||
|
return RootDependency.lastSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.hypixel.hytale.server.core.universe.world.storage.provider;
|
package com.hypixel.hytale.server.core.universe.world.storage.provider;
|
||||||
|
|
||||||
import com.hypixel.fastutil.longs.Long2ObjectConcurrentHashMap;
|
import com.hypixel.fastutil.longs.Long2ObjectConcurrentHashMap;
|
||||||
import com.hypixel.hytale.logger.HytaleLogger;
|
|
||||||
import com.hypixel.hytale.codec.Codec;
|
import com.hypixel.hytale.codec.Codec;
|
||||||
import com.hypixel.hytale.codec.KeyedCodec;
|
import com.hypixel.hytale.codec.KeyedCodec;
|
||||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||||
@@ -11,6 +10,7 @@ import com.hypixel.hytale.component.ResourceType;
|
|||||||
import com.hypixel.hytale.component.Store;
|
import com.hypixel.hytale.component.Store;
|
||||||
import com.hypixel.hytale.component.SystemGroup;
|
import com.hypixel.hytale.component.SystemGroup;
|
||||||
import com.hypixel.hytale.component.system.StoreSystem;
|
import com.hypixel.hytale.component.system.StoreSystem;
|
||||||
|
import com.hypixel.hytale.logger.HytaleLogger;
|
||||||
import com.hypixel.hytale.math.util.ChunkUtil;
|
import com.hypixel.hytale.math.util.ChunkUtil;
|
||||||
import com.hypixel.hytale.metrics.MetricProvider;
|
import com.hypixel.hytale.metrics.MetricProvider;
|
||||||
import com.hypixel.hytale.metrics.MetricResults;
|
import com.hypixel.hytale.metrics.MetricResults;
|
||||||
@@ -129,9 +129,13 @@ public class IndexedStorageChunkStorageProvider implements IChunkStorageProvider
|
|||||||
|
|
||||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||||
|
|
||||||
/** How long a region file can be idle before being closed (in milliseconds) */
|
/**
|
||||||
|
* How long a region file can be idle before being closed (in milliseconds)
|
||||||
|
*/
|
||||||
private static final long IDLE_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(5);
|
private static final long IDLE_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(5);
|
||||||
/** How often to check for idle region files (in milliseconds) */
|
/**
|
||||||
|
* How often to check for idle region files (in milliseconds)
|
||||||
|
*/
|
||||||
private static final long CLEANUP_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
|
private static final long CLEANUP_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -191,7 +195,7 @@ public class IndexedStorageChunkStorageProvider implements IChunkStorageProvider
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOGGER.at(Level.INFO).log("Starting region file cleanup task (idle timeout: %ds, interval: %ds)",
|
LOGGER.at(Level.INFO).log("Starting region file cleanup task (idle timeout: %ds, interval: %ds)",
|
||||||
IDLE_TIMEOUT_MS / 1000, CLEANUP_INTERVAL_MS / 1000);
|
IDLE_TIMEOUT_MS / 1000, CLEANUP_INTERVAL_MS / 1000);
|
||||||
cleanupExecutor = Executors.newSingleThreadScheduledExecutor(r -> {
|
cleanupExecutor = Executors.newSingleThreadScheduledExecutor(r -> {
|
||||||
Thread t = new Thread(r, "IndexedStorageCache-Cleanup");
|
Thread t = new Thread(r, "IndexedStorageCache-Cleanup");
|
||||||
t.setDaemon(true);
|
t.setDaemon(true);
|
||||||
@@ -247,7 +251,7 @@ public class IndexedStorageChunkStorageProvider implements IChunkStorageProvider
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.at(Level.FINE).log("Region %d not idle: lastAccess=%dms ago, activeOps=%d, threshold=%dms",
|
LOGGER.at(Level.FINE).log("Region %d not idle: lastAccess=%dms ago, activeOps=%d, threshold=%dms",
|
||||||
regionKey, idleTimeMs, activeOps, IDLE_TIMEOUT_MS);
|
regionKey, idleTimeMs, activeOps, IDLE_TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user