make SchematicGenerator properly lazy
This commit is contained in:
parent
b19942dfa6
commit
2146400d7e
10 changed files with 157 additions and 28 deletions
|
@ -1,11 +1,8 @@
|
|||
package org.dimdev.dimdoors.listener;
|
||||
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.ServerTask;
|
||||
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;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.dimdev.dimdoors.pockets;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
@ -13,7 +15,7 @@ import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
|||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PocketTemplate {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
@ -66,11 +68,12 @@ public class PocketTemplate {
|
|||
SchematicPlacer.place(this.schematic, world, origin, blockUpdate);
|
||||
}
|
||||
|
||||
public List<RiftBlockEntity> placeRiftsOnly(Pocket pocket) {
|
||||
public Map<BlockPos, RiftBlockEntity> getAbsoluteRifts(Pocket pocket) {
|
||||
pocket.setSize(schematic.getWidth(), schematic.getHeight(), schematic.getLength());
|
||||
ServerWorld world = DimensionalDoorsInitializer.getWorld(pocket.getWorld());
|
||||
BlockPos origin = pocket.getOrigin();
|
||||
return SchematicPlacer.placeRiftsOnly(this.schematic, world, origin);
|
||||
Map<BlockPos, RiftBlockEntity> absoluteRifts = SchematicPlacer.getAbsoluteRifts(this.schematic, pocket.getOrigin());
|
||||
World world = DimensionalDoorsInitializer.getWorld(pocket.getWorld());
|
||||
absoluteRifts.values().forEach(rift -> rift.setWorld(world));
|
||||
return absoluteRifts;
|
||||
}
|
||||
|
||||
public void place(LazyGenerationPocket pocket, Chunk chunk, BlockPos originalOrigin, boolean blockUpdate) {
|
||||
|
|
|
@ -29,7 +29,7 @@ public abstract class LazyPocketGenerator extends PocketGenerator {
|
|||
public static Queue<Chunk> generationQueue = new LinkedList<>();
|
||||
|
||||
|
||||
private List<LazyModifier> lazyModifierList = new ArrayList<>();
|
||||
protected List<LazyModifier> lazyModifierList = new ArrayList<>();
|
||||
|
||||
public void generateChunk(LazyGenerationPocket pocket, Chunk chunk) {
|
||||
lazyModifierList.forEach(modifier -> modifier.applyToChunk(pocket, chunk));
|
||||
|
|
|
@ -15,11 +15,8 @@ import net.minecraft.util.math.Vec3i;
|
|||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.util.registry.SimpleRegistry;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
|
||||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
import org.dimdev.dimdoors.pockets.TemplateUtils;
|
||||
import org.dimdev.dimdoors.pockets.modifier.Modifier;
|
||||
import org.dimdev.dimdoors.pockets.modifier.RiftManager;
|
||||
|
@ -182,7 +179,7 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationParame
|
|||
}
|
||||
});
|
||||
}
|
||||
manager.getRifts().forEach(rift -> rift.getDestination().setLocation(new Location((ServerWorld) Objects.requireNonNull(rift.getWorld()), rift.getPos())));
|
||||
manager.getRifts().forEach(rift -> rift.getDestination().setLocation(new Location(world, rift.getPos())));
|
||||
TemplateUtils.registerRifts(manager.getRifts(), parameters.getLinkTo(), parameters.getLinkProperties(), pocket);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.dimdev.dimdoors.pockets.generator;
|
||||
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
@ -12,6 +13,7 @@ import org.apache.logging.log4j.Logger;
|
|||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
import org.dimdev.dimdoors.pockets.PocketLoader;
|
||||
import org.dimdev.dimdoors.pockets.PocketTemplate;
|
||||
import org.dimdev.dimdoors.pockets.modifier.AbsoluteRiftBlockEntityModifier;
|
||||
import org.dimdev.dimdoors.pockets.modifier.RiftManager;
|
||||
import org.dimdev.dimdoors.util.PocketGenerationParameters;
|
||||
import org.dimdev.dimdoors.util.schematic.Schematic;
|
||||
|
@ -43,6 +45,8 @@ public class SchematicGenerator extends LazyPocketGenerator{
|
|||
private final List<RiftBlockEntity> rifts = new ArrayList<>();
|
||||
private BlockPos origin;
|
||||
|
||||
private AbsoluteRiftBlockEntityModifier queuedRiftBlockEntities;
|
||||
|
||||
public SchematicGenerator() {
|
||||
}
|
||||
|
||||
|
@ -106,6 +110,14 @@ public class SchematicGenerator extends LazyPocketGenerator{
|
|||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LazyPocketGenerator cloneWithLazyModifiers(BlockPos originalOrigin) {
|
||||
LazyPocketGenerator generator = super.cloneWithLazyModifiers(originalOrigin);
|
||||
generator.lazyModifierList.add(0, queuedRiftBlockEntities);
|
||||
|
||||
return generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LazyPocketGenerator cloneWithEmptyModifiers(BlockPos originalOrigin) {
|
||||
SchematicGenerator generator = (SchematicGenerator) super.cloneWithEmptyModifiers(originalOrigin);
|
||||
|
@ -134,7 +146,10 @@ public class SchematicGenerator extends LazyPocketGenerator{
|
|||
LOGGER.info("Generating pocket from template " + templateID + " at location " + pocket.getOrigin());
|
||||
|
||||
if (pocket instanceof LazyGenerationPocket) {
|
||||
rifts.addAll(template.placeRiftsOnly(pocket));
|
||||
Map<BlockPos, RiftBlockEntity> absoluteRifts = template.getAbsoluteRifts(pocket);
|
||||
rifts.addAll(absoluteRifts.values());
|
||||
|
||||
queuedRiftBlockEntities = new AbsoluteRiftBlockEntityModifier(absoluteRifts);
|
||||
} else {
|
||||
template.place(pocket, blockUpdate);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
package org.dimdev.dimdoors.pockets.modifier;
|
||||
|
||||
import net.fabricmc.fabric.api.util.NbtType;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
|
||||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
import org.dimdev.dimdoors.util.PocketGenerationParameters;
|
||||
import org.dimdev.dimdoors.world.pocket.type.LazyGenerationPocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class AbsoluteRiftBlockEntityModifier implements LazyModifier {
|
||||
public static final String KEY = "block_entity";
|
||||
|
||||
private Map<BlockPos, RiftBlockEntity> rifts;
|
||||
private Map<BlockPos, CompoundTag> serializedRifts;
|
||||
|
||||
public AbsoluteRiftBlockEntityModifier() {
|
||||
}
|
||||
|
||||
public AbsoluteRiftBlockEntityModifier(Map<BlockPos, RiftBlockEntity> rifts) {
|
||||
this.rifts = rifts;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier fromTag(CompoundTag tag) {
|
||||
serializedRifts = tag.getList("rifts", NbtType.COMPOUND).parallelStream().unordered().map(CompoundTag.class::cast)
|
||||
.collect(Collectors.toConcurrentMap(compound -> {
|
||||
int[] ints = compound.getIntArray("Pos");
|
||||
return new BlockPos(ints[0], ints[1], ints[2]);
|
||||
}, compound -> compound));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(CompoundTag tag) {
|
||||
LazyModifier.super.toTag(tag);
|
||||
|
||||
ListTag riftsTag;
|
||||
if (rifts != null) {
|
||||
riftsTag = rifts.values().parallelStream().unordered().map(rift -> rift.toTag(new CompoundTag())).collect(Collectors.toCollection(ListTag::new));
|
||||
} else {
|
||||
riftsTag = new ListTag();
|
||||
riftsTag.addAll(serializedRifts.values());
|
||||
}
|
||||
tag.put("rifts", riftsTag);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModifierType<? extends Modifier> getType() {
|
||||
return ModifierType.ABSOLUTE_RIFT_BLOCK_ENTITY_MODIFIER_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(PocketGenerationParameters parameters, RiftManager manager) {
|
||||
if (!manager.isPocketLazy()) { // rifts is guaranteed to exist at this stage since this modifier is not supposed to be loaded from json
|
||||
World world = DimensionalDoorsInitializer.getWorld(manager.getPocket().getWorld());
|
||||
rifts.values().forEach(world::addBlockEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(PocketGenerationParameters parameters, Pocket.PocketBuilder<?, ?> builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyToChunk(LazyGenerationPocket pocket, Chunk chunk) {
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
BlockBox chunkBox = BlockBox.create(chunkPos.getStartX(), chunk.getBottomY(), chunkPos.getStartZ(), chunkPos.getEndX(), chunk.getTopY(), chunkPos.getEndZ());
|
||||
|
||||
if (rifts != null) {
|
||||
rifts.entrySet().stream().unordered().filter(entry -> chunkBox.contains(entry.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
.forEach((pos, rift) -> {
|
||||
rifts.remove(pos);
|
||||
chunk.setBlockEntity(rift);
|
||||
});
|
||||
} else {
|
||||
serializedRifts.entrySet().stream().unordered().filter(entry -> chunkBox.contains(entry.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
.forEach((pos, riftTag) -> {
|
||||
rifts.remove(pos);
|
||||
chunk.setBlockEntity(BlockEntity.createFromTag(pos, chunk.getBlockState(pos), riftTag));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ public interface Modifier {
|
|||
ModifierType<RiftDataModifier> RIFT_DATA_MODIFIER_TYPE = register(new Identifier("dimdoors", RiftDataModifier.KEY), RiftDataModifier::new);
|
||||
ModifierType<RelativeReferenceModifier> RELATIVE_REFERENCE_MODIFIER_TYPE = register(new Identifier("dimdoors", RelativeReferenceModifier.KEY), RelativeReferenceModifier::new);
|
||||
ModifierType<OffsetModifier> OFFSET_MODIFIER_TYPE = register(new Identifier("dimdoors", OffsetModifier.KEY), OffsetModifier::new);
|
||||
ModifierType<AbsoluteRiftBlockEntityModifier> ABSOLUTE_RIFT_BLOCK_ENTITY_MODIFIER_TYPE = register(new Identifier("dimdoors", AbsoluteRiftBlockEntityModifier.KEY), AbsoluteRiftBlockEntityModifier::new);
|
||||
|
||||
Modifier fromTag(CompoundTag tag);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
import org.dimdev.dimdoors.rift.targets.IdMarker;
|
||||
import org.dimdev.dimdoors.world.pocket.type.LazyGenerationPocket;
|
||||
import org.dimdev.dimdoors.world.pocket.type.Pocket;
|
||||
|
||||
public class RiftManager {
|
||||
|
@ -90,4 +91,8 @@ public class RiftManager {
|
|||
public List<RiftBlockEntity> getRifts() {
|
||||
return rifts;
|
||||
}
|
||||
|
||||
public boolean isPocketLazy() {
|
||||
return pocket instanceof LazyGenerationPocket;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import net.minecraft.server.world.ServerChunkManager;
|
|||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
|
||||
import org.dimdev.dimdoors.util.BlockBoxUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -145,12 +146,22 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
|
||||
ServerChunkManager serverChunkManager = world.getChunkManager();
|
||||
|
||||
ChunkSection[] sections = chunk.getSectionArray();
|
||||
|
||||
BlockPos.stream(intersection).forEach(blockPos -> {
|
||||
if(chunk.getBlockState(blockPos).isAir()) {
|
||||
int x = Math.floorMod(blockPos.getX(), 16);
|
||||
int y = Math.floorMod(blockPos.getY(), 16);
|
||||
int z = Math.floorMod(blockPos.getZ(), 16);
|
||||
int sectionY = chunk.getSectionIndex(blockPos.getY());
|
||||
ChunkSection section = sections[sectionY];
|
||||
if (section == null) {
|
||||
section = new ChunkSection(sectionY);
|
||||
sections[sectionY] = section;
|
||||
}
|
||||
if(section.getBlockState(x, y, z).isAir()) {
|
||||
BlockState newState = this.blockContainer.get(blockPos.subtract(origin));
|
||||
if (!newState.isAir()) {
|
||||
chunk.setBlockState(blockPos, newState, false);
|
||||
section.setBlockState(x, y, z, newState, false);
|
||||
if (blockUpdate) serverChunkManager.markForUpdate(blockPos);
|
||||
}
|
||||
}
|
||||
|
@ -191,8 +202,8 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
}));
|
||||
}
|
||||
|
||||
public List<RiftBlockEntity> placeRiftsOnly(BlockPos origin, ServerWorld world) {
|
||||
List<RiftBlockEntity> rifts = new ArrayList<>();
|
||||
public Map<BlockPos, RiftBlockEntity> getAbsoluteRifts(BlockPos origin) {
|
||||
Map<BlockPos, RiftBlockEntity> rifts = new HashMap<>();
|
||||
this.blockEntityContainer.forEach( (blockPos, tag) -> {
|
||||
BlockPos actualPos = origin.add(blockPos);
|
||||
|
||||
|
@ -203,13 +214,7 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
|
|||
BlockState state = getBlockState(blockPos);
|
||||
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);
|
||||
}
|
||||
world.toServerWorld().addBlockEntity(blockEntity);
|
||||
rifts.add((RiftBlockEntity) blockEntity);
|
||||
rifts.put(actualPos, (RiftBlockEntity) blockEntity);
|
||||
}
|
||||
});
|
||||
return rifts;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package org.dimdev.dimdoors.util.schematic;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
@ -38,15 +40,15 @@ public final class SchematicPlacer {
|
|||
blockSample.place(origin, world, blockUpdate, false);
|
||||
}
|
||||
|
||||
public static List<RiftBlockEntity> placeRiftsOnly(Schematic schematic, ServerWorld world, BlockPos origin) {
|
||||
LOGGER.debug("Placing schematic rifts only: {}", schematic.getMetadata().getName());
|
||||
public static Map<BlockPos, RiftBlockEntity> getAbsoluteRifts(Schematic schematic, BlockPos origin) {
|
||||
LOGGER.debug("Placing schematic: {}", schematic.getMetadata().getName());
|
||||
for (String id : schematic.getMetadata().getRequiredMods()) {
|
||||
if (!FabricLoader.getInstance().isModLoaded(id)) {
|
||||
LOGGER.warn("Schematic \"" + schematic.getMetadata().getName() + "\" depends on mod \"" + id + "\", which is missing!");
|
||||
}
|
||||
}
|
||||
RelativeBlockSample blockSample = Schematic.getBlockSample(schematic);
|
||||
return blockSample.placeRiftsOnly(origin, world);
|
||||
return blockSample.getAbsoluteRifts(origin);
|
||||
}
|
||||
|
||||
public static void place(Schematic schematic, ServerWorld world, Chunk chunk, BlockPos origin, boolean blockUpdate) {
|
||||
|
|
Loading…
Reference in a new issue