added LazyCompatibleModifier
lazy schematic gen now marks placed blocks for update
This commit is contained in:
parent
d9fd741db3
commit
08e772d2cb
7 changed files with 89 additions and 21 deletions
|
@ -7,6 +7,7 @@ import net.minecraft.server.world.ServerWorld;
|
|||
import net.minecraft.world.chunk.WorldChunk;
|
||||
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
|
||||
import org.dimdev.dimdoors.pockets.generator.LazyPocketGenerator;
|
||||
import org.dimdev.dimdoors.pockets.modifier.LazyCompatibleModifier;
|
||||
import org.dimdev.dimdoors.world.ModDimensions;
|
||||
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
|
||||
import org.dimdev.dimdoors.world.pocket.type.LazyGenerationPocket;
|
||||
|
@ -21,6 +22,7 @@ public class ChunkLoadListener implements ServerChunkEvents.Load {
|
|||
if (LazyPocketGenerator.currentlyGenerating) {
|
||||
LazyPocketGenerator.generationQueue.add(chunk);
|
||||
} else {
|
||||
LazyCompatibleModifier.runQueuedModifications(chunk);
|
||||
((LazyGenerationPocket) pocket).chunkLoaded(chunk);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import net.minecraft.server.world.ServerWorld;
|
|||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
|
@ -29,9 +30,10 @@ import org.dimdev.dimdoors.util.PocketGenerationParameters;
|
|||
import org.dimdev.dimdoors.util.TagEquations;
|
||||
import org.dimdev.dimdoors.util.math.Equation;
|
||||
import org.dimdev.dimdoors.util.math.Equation.EquationParseException;
|
||||
import org.dimdev.dimdoors.world.pocket.type.LazyGenerationPocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
public class DimensionalDoorModifier implements Modifier {
|
||||
public class DimensionalDoorModifier implements LazyCompatibleModifier {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final String KEY = "door";
|
||||
|
||||
|
@ -88,7 +90,7 @@ public class DimensionalDoorModifier implements Modifier {
|
|||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
Modifier.super.toTag(tag);
|
||||
LazyCompatibleModifier.super.toTag(tag);
|
||||
|
||||
tag.putString("facing", facing.asString());
|
||||
tag.putString("door_type", doorTypeString);
|
||||
|
@ -134,11 +136,8 @@ public class DimensionalDoorModifier implements Modifier {
|
|||
BlockPos pocketOrigin = manager.getPocket().getOrigin();
|
||||
BlockPos pos = new BlockPos(xEquation.apply(variableMap) + pocketOrigin.getX(), yEquation.apply(variableMap) + pocketOrigin.getY(), zEquation.apply(variableMap) + pocketOrigin.getZ());
|
||||
|
||||
ServerWorld world = parameters.getWorld();
|
||||
BlockState lower = doorType.getDefaultState().with(DimensionalDoorBlock.HALF, DoubleBlockHalf.LOWER).with(DimensionalDoorBlock.FACING, facing);
|
||||
world.setBlockState(pos, lower);
|
||||
world.setBlockState(pos.up(), doorType.getDefaultState().with(DimensionalDoorBlock.HALF, DoubleBlockHalf.UPPER).with(DimensionalDoorBlock.FACING, facing));
|
||||
|
||||
BlockState upper = doorType.getDefaultState().with(DimensionalDoorBlock.HALF, DoubleBlockHalf.UPPER).with(DimensionalDoorBlock.FACING, facing);
|
||||
EntranceRiftBlockEntity rift = ModBlockEntityTypes.ENTRANCE_RIFT.instantiate(pos, lower);
|
||||
|
||||
if (doorData == null) {
|
||||
|
@ -150,7 +149,24 @@ public class DimensionalDoorModifier implements Modifier {
|
|||
|
||||
manager.add(rift);
|
||||
|
||||
world.addBlockEntity(rift);
|
||||
if (manager.getPocket() instanceof LazyGenerationPocket) {
|
||||
|
||||
// queue two separate tasks, Cubic Chunks may cause the positions to be in different chunks.
|
||||
queueChunkModificationTask(new ChunkPos(pos), chunk -> {
|
||||
chunk.setBlockState(pos, lower, false);
|
||||
chunk.setBlockEntity(rift);
|
||||
});
|
||||
queueChunkModificationTask(new ChunkPos(pos.up()), chunk -> {
|
||||
chunk.setBlockState(pos.up(), upper, false);
|
||||
});
|
||||
} else {
|
||||
ServerWorld world = parameters.getWorld();
|
||||
|
||||
world.setBlockState(pos, lower);
|
||||
world.setBlockState(pos.up(), upper);
|
||||
|
||||
world.addBlockEntity(rift);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package org.dimdev.dimdoors.pockets.modifier;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface LazyCompatibleModifier extends Modifier {
|
||||
LinkedHashMap<ChunkPos, Queue<Consumer<Chunk>>> chunkModificationQueue = new LinkedHashMap<>();
|
||||
|
||||
static void runQueuedModifications(Chunk chunk) {
|
||||
Queue<Consumer<Chunk>> tasks = chunkModificationQueue.remove(chunk.getPos());
|
||||
if (tasks == null) return;
|
||||
Iterator<Consumer<Chunk>> iterator = tasks.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Consumer<Chunk> task = iterator.next();
|
||||
iterator.remove();
|
||||
task.accept(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
static void runLeftoverModifications(World world) {
|
||||
new HashSet<>(chunkModificationQueue.keySet()).forEach(chunkPos -> world.getChunk(chunkPos.getStartPos())); // seems safest for Cubic Chunks reasons;
|
||||
}
|
||||
|
||||
default void queueChunkModificationTask(ChunkPos pos, Consumer<Chunk> task) {
|
||||
chunkModificationQueue.compute(pos, ((chunkPos, chunkTaskQueue) -> {
|
||||
if (chunkTaskQueue == null) chunkTaskQueue = new LinkedList<>();
|
||||
chunkTaskQueue.add(task);
|
||||
return chunkTaskQueue;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
default CompoundTag toTag(CompoundTag tag) {
|
||||
return Modifier.super.toTag(tag);
|
||||
}
|
||||
}
|
|
@ -52,13 +52,11 @@ public class RiftManager {
|
|||
|
||||
return true;
|
||||
}
|
||||
// TODO: should we register the rift here?
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean consume(int id, Predicate<RiftBlockEntity> consumer) {
|
||||
if (map.containsKey(id) && consumer.test(map.get(id))) {
|
||||
// TODO: should we register the rift here?
|
||||
map.remove(id);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.apache.logging.log4j.Logger;
|
|||
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
|
||||
import org.dimdev.dimdoors.pockets.generator.LazyPocketGenerator;
|
||||
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
|
||||
import org.dimdev.dimdoors.pockets.modifier.LazyCompatibleModifier;
|
||||
import org.dimdev.dimdoors.pockets.modifier.LazyModifier;
|
||||
import org.dimdev.dimdoors.pockets.modifier.Modifier;
|
||||
import org.dimdev.dimdoors.pockets.modifier.RiftManager;
|
||||
|
@ -142,7 +143,7 @@ public abstract class PocketGeneratorReference extends VirtualSingularPocket {
|
|||
generator.applyModifiers(parameters, manager);
|
||||
|
||||
this.applyModifiers(parameters, manager);
|
||||
generator.setup(pocket, manager, parameters, setupLoot != null ? setupLoot : generator.isSetupLoot());
|
||||
|
||||
if (pocket instanceof LazyGenerationPocket) {
|
||||
if (!(generator instanceof LazyPocketGenerator)) throw new RuntimeException("pocket was instance of LazyGenerationPocket but generator was not instance of LazyPocketGenerator");
|
||||
LazyGenerationPocket lazyPocket = (LazyGenerationPocket) pocket;
|
||||
|
@ -155,21 +156,22 @@ public abstract class PocketGeneratorReference extends VirtualSingularPocket {
|
|||
|
||||
LazyPocketGenerator.currentlyGenerating = false;
|
||||
|
||||
/*
|
||||
TODO: some sort of generationQueueMap where some non lazy modifications can be stored as Consumer<Chunk> so that they can be accessed by ChunkLoadListener
|
||||
We want (mostly) everything to be placed during chunk load with lazy gen so that we don't experience any breakage with redstone or modded multiblocks/ cable stuff.
|
||||
*/
|
||||
|
||||
while (!LazyPocketGenerator.generationQueue.isEmpty()) {
|
||||
Chunk chunk = LazyPocketGenerator.generationQueue.remove();
|
||||
|
||||
LazyCompatibleModifier.runQueuedModifications(chunk);
|
||||
MinecraftServer server = DimensionalDoorsInitializer.getServer();
|
||||
DimensionalDoorsInitializer.getServer().send(new ServerTask(server.getTicks(), () -> (lazyPocket).chunkLoaded(chunk)));
|
||||
}
|
||||
|
||||
LazyCompatibleModifier.runLeftoverModifications(DimensionalDoorsInitializer.getWorld(lazyPocket.getWorld()));
|
||||
} else {
|
||||
LazyPocketGenerator.generationQueue.clear();
|
||||
LazyPocketGenerator.currentlyGenerating = false;
|
||||
LazyPocketGenerator.generationQueue.clear();
|
||||
}
|
||||
|
||||
generator.setup(pocket, manager, parameters, setupLoot != null ? setupLoot : generator.isSetupLoot());
|
||||
|
||||
return pocket;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.google.common.collect.HashBiMap;
|
|||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
|
@ -128,7 +129,7 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
}
|
||||
}
|
||||
|
||||
public void place(BlockPos origin, StructureWorldAccess world, Chunk chunk, boolean biomes) {
|
||||
public void place(BlockPos origin, ServerWorld world, Chunk chunk, boolean biomes) {
|
||||
ChunkPos pos = chunk.getPos();
|
||||
BlockBox chunkBox = BlockBox.create(pos.getStartX(), chunk.getBottomY(), pos.getStartZ(), pos.getEndX(), chunk.getTopY(), pos.getEndZ());
|
||||
BlockBox schemBox = BlockBox.create(origin.getX(), origin.getY(), origin.getZ(), origin.getX() + schematic.getWidth() - 1, origin.getY() + schematic.getHeight() - 1, origin.getZ() + schematic.getLength() - 1);
|
||||
|
@ -136,7 +137,13 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
if (!BlockBoxUtil.isRealBox(intersection)) return;
|
||||
|
||||
BlockPos.stream(intersection).forEach(blockPos -> {
|
||||
if(chunk.getBlockState(blockPos).isAir()) chunk.setBlockState(blockPos, this.blockContainer.get(blockPos.subtract(origin)), false);
|
||||
if(chunk.getBlockState(blockPos).isAir()) {
|
||||
BlockState newState = this.blockContainer.get(blockPos.subtract(origin));
|
||||
if (!newState.isAir()) {
|
||||
chunk.setBlockState(blockPos, newState, false);
|
||||
world.getChunkManager().markForUpdate(blockPos);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: depending on size of blockEntityContainer it might be faster to iterate over BlockPos.stream(intersection) instead
|
||||
|
@ -171,7 +178,7 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
}));
|
||||
}
|
||||
|
||||
public List<RiftBlockEntity> placeRiftsOnly(BlockPos origin, StructureWorldAccess world) {
|
||||
public List<RiftBlockEntity> placeRiftsOnly(BlockPos origin, ServerWorld world) {
|
||||
List<RiftBlockEntity> rifts = new ArrayList<>();
|
||||
this.blockEntityContainer.forEach( (blockPos, tag) -> {
|
||||
BlockPos actualPos = origin.add(blockPos);
|
||||
|
@ -184,6 +191,7 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
BlockEntity blockEntity = BlockEntity.createFromTag(actualPos, state, tag);
|
||||
if (blockEntity instanceof RiftBlockEntity) {
|
||||
world.setBlockState(actualPos, state, 0);
|
||||
world.getChunkManager().markForUpdate(blockPos);
|
||||
if (state.getBlock() instanceof DoorBlock) {
|
||||
world.setBlockState(actualPos.up(), getBlockState(blockPos.up()), 0);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
@ -37,7 +38,7 @@ public final class SchematicPlacer {
|
|||
blockSample.place(origin, world, false);
|
||||
}
|
||||
|
||||
public static List<RiftBlockEntity> placeRiftsOnly(Schematic schematic, StructureWorldAccess world, BlockPos origin) {
|
||||
public static List<RiftBlockEntity> placeRiftsOnly(Schematic schematic, ServerWorld world, BlockPos origin) {
|
||||
LOGGER.debug("Placing schematic rifts only: {}", schematic.getMetadata().getName());
|
||||
for (String id : schematic.getMetadata().getRequiredMods()) {
|
||||
if (!FabricLoader.getInstance().isModLoaded(id)) {
|
||||
|
@ -48,7 +49,7 @@ public final class SchematicPlacer {
|
|||
return blockSample.placeRiftsOnly(origin, world);
|
||||
}
|
||||
|
||||
public static void place(Schematic schematic, StructureWorldAccess world, Chunk chunk, BlockPos origin) {
|
||||
public static void place(Schematic schematic, ServerWorld world, Chunk chunk, BlockPos origin) {
|
||||
LOGGER.debug("Placing schematic: {}", schematic.getMetadata().getName());
|
||||
for (String id : schematic.getMetadata().getRequiredMods()) {
|
||||
if (!FabricLoader.getInstance().isModLoaded(id)) {
|
||||
|
|
Loading…
Add table
Reference in a new issue