crude dev tool for chunk unloading
- add a dev utility that allows us to force-unload chunks - move mechanical arm scrollbox - fix oxidizing blocks trying to access a blockstate from unloaded chunks when on the border
This commit is contained in:
parent
5a7c09aa25
commit
770fbd6aaa
7 changed files with 220 additions and 14 deletions
|
@ -1,5 +1,7 @@
|
|||
package com.simibubi.create;
|
||||
|
||||
import com.simibubi.create.foundation.command.ChunkUtil;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
@ -59,6 +61,7 @@ public class Create {
|
|||
public static RedstoneLinkNetworkHandler redstoneLinkNetworkHandler;
|
||||
public static TorquePropagator torquePropagator;
|
||||
public static ServerLagger lagger;
|
||||
public static ChunkUtil chunkUtil;
|
||||
|
||||
private static final NonNullLazyValue<CreateRegistrate> registrate = CreateRegistrate.lazy(ID);
|
||||
|
||||
|
@ -94,6 +97,10 @@ public class Create {
|
|||
torquePropagator = new TorquePropagator();
|
||||
lagger = new ServerLagger();
|
||||
|
||||
chunkUtil = new ChunkUtil();
|
||||
chunkUtil.init();
|
||||
MinecraftForge.EVENT_BUS.register(chunkUtil);
|
||||
|
||||
AllPackets.registerPackets();
|
||||
AllTriggers.register();
|
||||
AllWorldFeatures.reload();
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOpt
|
|||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.JukeboxBlock;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
@ -22,6 +23,7 @@ import net.minecraft.nbt.ListNBT;
|
|||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -81,9 +83,20 @@ public class ArmTileEntity extends KineticTileEntity {
|
|||
super.addBehaviours(behaviours);
|
||||
|
||||
selectionMode = new ScrollOptionBehaviour<>(SelectionMode.class, Lang.translate("mechanical_arm.selection_mode"), this,
|
||||
new CenteredSideValueBoxTransform((blockState, direction) -> {
|
||||
return direction != Direction.DOWN && direction != Direction.UP;
|
||||
}));
|
||||
new CenteredSideValueBoxTransform((blockState, direction) -> direction != Direction.DOWN && direction != Direction.UP) {
|
||||
@Override
|
||||
protected Vec3d getLocalOffset(BlockState state) {
|
||||
int yPos = state.get(ArmBlock.CEILING) ? 16 - 3 : 3;
|
||||
Vec3d location = VecHelper.voxelSpace(8, yPos, 14.5);
|
||||
location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(getSide()), Direction.Axis.Y);
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getScale() {
|
||||
return .3f;
|
||||
}
|
||||
});
|
||||
selectionMode.requiresWrench();
|
||||
behaviours.add(selectionMode);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.command.Commands;
|
||||
|
||||
|
@ -9,10 +8,15 @@ public class AllCommands {
|
|||
|
||||
public static void register(CommandDispatcher<CommandSource> dispatcher) {
|
||||
dispatcher.register(Commands.literal("create")
|
||||
.then(ToggleDebugCommand.register())
|
||||
.then(OverlayConfigCommand.register())
|
||||
.then(ClearBufferCacheCommand.register())
|
||||
// .then(KillTPSCommand.register()) //Commented out for release
|
||||
//general purpose
|
||||
.then(ToggleDebugCommand.register())
|
||||
.then(OverlayConfigCommand.register())
|
||||
|
||||
//dev-util
|
||||
//Comment out for release
|
||||
.then(ClearBufferCacheCommand.register())
|
||||
.then(ChunkUtilCommand.register())
|
||||
// .then(KillTPSCommand.register())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.server.ChunkHolder;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChunkUtil {
|
||||
private static final Logger LOGGER = LogManager.getLogger("Create/ChunkUtil");
|
||||
final EnumSet<Heightmap.Type> POST_FEATURES = EnumSet.of(Heightmap.Type.OCEAN_FLOOR, Heightmap.Type.WORLD_SURFACE, Heightmap.Type.MOTION_BLOCKING, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES);
|
||||
|
||||
private final List<Long> markedChunks;
|
||||
private final List<Long> interestingChunks;
|
||||
|
||||
public ChunkUtil() {
|
||||
LOGGER.debug("Chunk Util constructed");
|
||||
markedChunks = new LinkedList<>();
|
||||
interestingChunks = new LinkedList<>();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
ChunkStatus.FULL = new ChunkStatus("full", ChunkStatus.HEIGHTMAPS, 0, POST_FEATURES, ChunkStatus.Type.LEVELCHUNK,
|
||||
(_0, _1, _2, _3, _4, future, _6, chunk) -> future.apply(chunk),
|
||||
(_0, _1, _2, _3, future, chunk) -> {
|
||||
if (markedChunks.contains(chunk.getPos().asLong())) {
|
||||
LOGGER.debug("trying to load unforced chunk " + chunk.getPos().toString() + ", returning chunk loading error");
|
||||
//this.reloadChunk(world.getChunkProvider(), chunk.getPos());
|
||||
return ChunkHolder.MISSING_CHUNK_FUTURE;
|
||||
} else {
|
||||
//LOGGER.debug("regular, chunkStatus: " + chunk.getStatus().toString());
|
||||
return future.apply(chunk);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public boolean reloadChunk(ServerChunkProvider provider, ChunkPos pos) {
|
||||
ChunkHolder holder = provider.chunkManager.loadedChunks.remove(pos.asLong());
|
||||
provider.chunkManager.immutableLoadedChunksDirty = true;
|
||||
if (holder != null) {
|
||||
provider.chunkManager.chunksToUnload.put(pos.asLong(), holder);
|
||||
provider.chunkManager.scheduleSave(pos.asLong(), holder);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean unloadChunk(ServerChunkProvider provider, ChunkPos pos) {
|
||||
this.interestingChunks.add(pos.asLong());
|
||||
this.markedChunks.add(pos.asLong());
|
||||
|
||||
return this.reloadChunk(provider, pos);
|
||||
}
|
||||
|
||||
public int clear(ServerChunkProvider provider) {
|
||||
LinkedList<Long> copy = new LinkedList<>(this.markedChunks);
|
||||
|
||||
int size = this.markedChunks.size();
|
||||
this.markedChunks.clear();
|
||||
|
||||
copy.forEach(l -> reForce(provider, new ChunkPos(l)));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public void reForce(ServerChunkProvider provider, ChunkPos pos) {
|
||||
provider.forceChunk(pos, true);
|
||||
provider.forceChunk(pos, false);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void chunkUnload(ChunkEvent.Unload event) {
|
||||
//LOGGER.debug("Chunk Unload: " + event.getChunk().getPos().toString());
|
||||
if (interestingChunks.contains(event.getChunk().getPos().asLong())) {
|
||||
LOGGER.info("Interesting Chunk Unload: " + event.getChunk().getPos().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void chunkLoad(ChunkEvent.Load event) {
|
||||
//LOGGER.debug("Chunk Load: " + event.getChunk().getPos().toString());
|
||||
|
||||
ChunkPos pos = event.getChunk().getPos();
|
||||
if (interestingChunks.contains(pos.asLong())) {
|
||||
LOGGER.info("Interesting Chunk Load: " + pos.toString());
|
||||
if (!markedChunks.contains(pos.asLong()))
|
||||
interestingChunks.remove(pos.asLong());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.simibubi.create.Create;
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.command.Commands;
|
||||
import net.minecraft.command.arguments.ColumnPosArgument;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.ColumnPos;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
|
||||
public class ChunkUtilCommand {
|
||||
|
||||
public static ArgumentBuilder<CommandSource, ?> register() {
|
||||
return Commands.literal("chunk")
|
||||
.requires(cs -> cs.hasPermissionLevel(2))
|
||||
.then(Commands.literal("reload").then(Commands.argument("pos", ColumnPosArgument.columnPos())
|
||||
.executes(ctx -> {
|
||||
//chunk reload <pos>
|
||||
ColumnPos columnPos = ColumnPosArgument.fromBlockPos(ctx, "pos");
|
||||
ChunkPos chunkPos = new ChunkPos(columnPos.x >> 4, columnPos.z >> 4);
|
||||
ServerChunkProvider chunkProvider = ctx.getSource().getWorld().getChunkProvider();
|
||||
|
||||
boolean success = Create.chunkUtil.reloadChunk(chunkProvider, chunkPos);
|
||||
|
||||
if (success) {
|
||||
ctx.getSource().sendFeedback(new StringTextComponent("scheduled unload for chunk " + chunkPos.toString() + ", might need to repeat command"), true);
|
||||
return 1;
|
||||
} else {
|
||||
ctx.getSource().sendFeedback(new StringTextComponent("unable to schedule unload, is chunk " + chunkPos.toString() + " loaded?"), true);
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
))
|
||||
.then(Commands.literal("unload").then(Commands.argument("pos", ColumnPosArgument.columnPos())
|
||||
.executes(ctx -> {
|
||||
//chunk unload <pos>
|
||||
ColumnPos columnPos = ColumnPosArgument.fromBlockPos(ctx, "pos");
|
||||
ChunkPos chunkPos = new ChunkPos(columnPos.x >> 4, columnPos.z >> 4);
|
||||
ServerChunkProvider chunkProvider = ctx.getSource().getWorld().getChunkProvider();
|
||||
|
||||
boolean success = Create.chunkUtil.unloadChunk(chunkProvider, chunkPos);
|
||||
ctx.getSource().sendFeedback(new StringTextComponent("added chunk " + chunkPos.toString() + " to unload list"), true);
|
||||
|
||||
if (success) {
|
||||
ctx.getSource().sendFeedback(new StringTextComponent("scheduled unload for chunk " + chunkPos.toString() + ", might need to repeat command"), true);
|
||||
return 1;
|
||||
} else {
|
||||
ctx.getSource().sendFeedback(new StringTextComponent("unable to schedule unload, is chunk " + chunkPos.toString() + " loaded?"), true);
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
))
|
||||
.then(Commands.literal("clear")
|
||||
.executes(ctx -> {
|
||||
//chunk clear
|
||||
int count = Create.chunkUtil.clear(ctx.getSource().getWorld().getChunkProvider());
|
||||
ctx.getSource().sendFeedback(new StringTextComponent("removed " + count + " entries from unload list"), false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
|
||||
}
|
||||
}
|
|
@ -1,12 +1,7 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.OptionalDouble;
|
||||
import java.util.Random;
|
||||
|
||||
import com.simibubi.create.content.curiosities.tools.SandPaperItem;
|
||||
import com.simibubi.create.content.palettes.MetalBlock;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
@ -21,6 +16,10 @@ import net.minecraft.world.IBlockReader;
|
|||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.OptionalDouble;
|
||||
import java.util.Random;
|
||||
|
||||
public class OxidizingBlock extends MetalBlock {
|
||||
|
||||
public static final IntegerProperty OXIDIZATION = IntegerProperty.create("oxidization", 0, 7);
|
||||
|
@ -56,6 +55,8 @@ public class OxidizingBlock extends MetalBlock {
|
|||
LinkedList<Integer> neighbors = new LinkedList<>();
|
||||
for (Direction facing : Direction.values()) {
|
||||
BlockPos neighbourPos = pos.offset(facing);
|
||||
if (!worldIn.isAreaLoaded(neighbourPos, 0))
|
||||
continue;
|
||||
if (!worldIn.isBlockPresent(neighbourPos))
|
||||
continue;
|
||||
BlockState neighborState = worldIn.getBlockState(neighbourPos);
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
public net.minecraft.network.play.ServerPlayNetHandler field_147365_f # floatingTickCount
|
||||
|
||||
# CubeParticle
|
||||
protected net.minecraft.client.particle.Particle field_228343_B_ # collidedY
|
||||
protected net.minecraft.client.particle.Particle field_228343_B_ # collidedY
|
||||
|
||||
# Needed for ChunkUtil, maybe remove these for releases
|
||||
# ChunkManager
|
||||
public net.minecraft.world.server.ChunkManager func_219212_a(JLnet/minecraft/world/server/ChunkHolder;)V #scheduleSave
|
||||
public net.minecraft.world.server.ChunkManager field_219251_e #loadedChunks
|
||||
public net.minecraft.world.server.ChunkManager field_219262_p #immutableLoadedChunksDirty
|
||||
public net.minecraft.world.server.ChunkManager field_219253_g #chunksToUnload
|
||||
|
||||
# ChunkStatus
|
||||
public-f net.minecraft.world.chunk.ChunkStatus field_222617_m #FULL
|
||||
public net.minecraft.world.chunk.ChunkStatus$IGenerationWorker
|
||||
public net.minecraft.world.chunk.ChunkStatus$ILoadingWorker
|
Loading…
Reference in a new issue