still causes massive loadage if requested more than 2 chunks. Don't really know why. WIP I guess

This commit is contained in:
gnembon committed 2020-02-29 00:00:53 -04:00
1 parent e549c4df64
commit f43bd968bb
4 files changed
+136 -26

No files matched your search

@@ -2,7 +2,9 @@ package carpet.fakes;
import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.ChunkPos;
import java.util.List;
public interface ThreadedAnvilChunkStorageInterface public interface ThreadedAnvilChunkStorageInterface
{ {
void regenerateChunkRegion(ChunkPos from, ChunkPos to); void regenerateChunkRegion(List<ChunkPos> requestedChunks);
} }
@@ -26,8 +26,12 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@@ -82,15 +86,8 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem
} }
@Override @Override
public void regenerateChunkRegion(ChunkPos from, ChunkPos to) public void regenerateChunkRegion(List<ChunkPos> requestedChunks)
{ {
List<ChunkPos> chunksToConvert = new ArrayList<>();
int xmax = Math.max(from.x, to.x);
int zmax = Math.max(from.z, to.z);
for (int x = Math.min(from.x, to.x); x <= xmax; x++) for (int z = Math.min(from.z, to.z); z <= zmax; z++)
{
chunksToConvert.add(new ChunkPos(x,z));
}
//flushning all tasks on the thread executor so all futures are ready - we don't want any deadlocks //flushning all tasks on the thread executor so all futures are ready - we don't want any deadlocks
mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0);
@@ -101,8 +98,30 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem
runnable.run(); runnable.run();
} }
List<ChunkHolder> createdChunks = new ArrayList<>(); Set<ChunkPos> loadedChunks = new HashSet<>();
for (ChunkPos chpos : chunksToConvert) for (ChunkPos pos: requestedChunks)
{
Chunk chunk = world.getChunk(pos.x, pos.z, ChunkStatus.FULL, false);
if (chunk != null && chunk.getStatus() != ChunkStatus.EMPTY)
loadedChunks.add(pos);
}
CarpetSettings.LOG.error("Area has "+requestedChunks.size()+" chunks");
CarpetSettings.LOG.error("Area has "+loadedChunks.size()+" loaded chunks");
Map<ChunkPos,ChunkStatus> targetStatus = new HashMap<>();
for (ChunkPos pos: requestedChunks)
{
Chunk chunk = world.getChunk(pos.x, pos.z, ChunkStatus.EMPTY, true);
if (chunk == null || chunk.getStatus() == ChunkStatus.EMPTY)
continue;
//unloaded areas can have unknown skirt chunk area
targetStatus.put(pos, loadedChunks.contains(pos)?chunk.getStatus():ChunkStatus.STRUCTURE_STARTS);
}
CarpetSettings.LOG.error("Area has "+targetStatus.size()+" chunks for removal");
for (ChunkPos chpos : targetStatus.keySet())
{ {
Long id = chpos.toLong(); Long id = chpos.toLong();
//chunk is currently in memory in some shape or form / loaded / unloaded / queued / cached //chunk is currently in memory in some shape or form / loaded / unloaded / queued / cached
@@ -147,7 +166,6 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem
field_18807.put(id, newHolder); field_18807.put(id, newHolder);
//loadedChunks.add(id); //loadedChunks.add(id);
((ChunkHolderInterface)newHolder).setDefaultProtoChunk(chpos, mainThreadExecutor); ((ChunkHolderInterface)newHolder).setDefaultProtoChunk(chpos, mainThreadExecutor);
createdChunks.add(newHolder);
} }
//getting rid of all signs //getting rid of all signs
this.chunkHolderListDirty = true; this.chunkHolderListDirty = true;
@@ -163,13 +181,16 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem
for (ChunkStatus status : ChunkStatus.createOrderedList()) for (ChunkStatus status : ChunkStatus.createOrderedList())
{ {
CarpetSettings.LOG.error("Creating layer: " + status.getId()); CarpetSettings.LOG.error("Creating layer: " + status.getId() + " for "+targetStatus.size()+" chunks");
if (status == ChunkStatus.LIGHT) if (status == ChunkStatus.LIGHT)
{ {
serverLightingProvider.setTaskBatchSize(chunksToConvert.size() + 20); //break;
serverLightingProvider.setTaskBatchSize(targetStatus.size() + 20);
} }
for (ChunkPos chpos : chunksToConvert) for (ChunkPos chpos : new ArrayList<>(targetStatus.keySet()))
{ {
if (targetStatus.get(chpos) == status)
targetStatus.remove(chpos);
//if (status==ChunkStatus.LIGHT) //if (status==ChunkStatus.LIGHT)
//{ //{
// serverLightingProvider.tick(); // serverLightingProvider.tick();
@@ -1677,23 +1677,60 @@ public class CarpetExpression
this.expr.addLazyFunction("reset_chunk", -1, (c, t, lv) -> this.expr.addLazyFunction("reset_chunk", -1, (c, t, lv) ->
{ {
CarpetContext cc = (CarpetContext)c; CarpetContext cc = (CarpetContext)c;
List<ChunkPos> requestedChunks = new ArrayList<>();
if (lv.size() == 1)
{
//either one block or list of chunks
Value first = lv.get(0).evalValue(c);
if (first instanceof ListValue)
{
List<Value> listVal = ((ListValue) first).getItems();
int offset = 0;
BlockValue.LocatorResult locator = BlockValue.fromParamValues(cc, listVal, 0, false, false);
requestedChunks.add(new ChunkPos(locator.block.getPos()));
while (listVal.size() > locator.offset)
{
locator = BlockValue.fromParamValues(cc, listVal, locator.offset, false, false);
requestedChunks.add(new ChunkPos(locator.block.getPos()));
}
}
else
{
BlockValue.LocatorResult locator = BlockValue.fromParamValues(cc, Collections.singletonList(first), 0, false, false);
requestedChunks.add(new ChunkPos(locator.block.getPos()));
}
}
else
{
BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0);
ChunkPos from = new ChunkPos(locator.block.getPos());
if (lv.size() > locator.offset)
{
locator = BlockValue.fromParams(cc, lv, locator.offset);
ChunkPos to = new ChunkPos(locator.block.getPos());
int xmax = Math.max(from.x, to.x);
int zmax = Math.max(from.z, to.z);
for (int x = Math.min(from.x, to.x); x <= xmax; x++) for (int z = Math.min(from.z, to.z); z <= zmax; z++)
{
requestedChunks.add(new ChunkPos(x,z));
}
CarpetSettings.LOG.error("Regenerating from "+Math.min(from.x, to.x)+", "+Math.min(from.z, to.z)+" to "+Math.max(from.x, to.x)+", "+Math.max(from.z, to.z));
}
else
{
requestedChunks.add(from);
}
}
ServerWorld world = cc.s.getWorld(); ServerWorld world = cc.s.getWorld();
BlockPos pos = locator.block.getPos();
BlockPos temp = pos;
if (lv.size() > locator.offset )
{
BlockValue.LocatorResult locator2 = BlockValue.fromParams(cc, lv, locator.offset);
temp = locator2.block.getPos();
}
BlockPos toPos = temp;
((CarpetContext)c).s.getMinecraftServer().submitAndJoin( () -> ((CarpetContext)c).s.getMinecraftServer().submitAndJoin( () ->
{ {
((ThreadedAnvilChunkStorageInterface) world.getChunkManager().threadedAnvilChunkStorage).regenerateChunkRegion(new ChunkPos(pos), new ChunkPos(toPos)); ((ThreadedAnvilChunkStorageInterface) world.getChunkManager().threadedAnvilChunkStorage).regenerateChunkRegion(requestedChunks);
world.getChunk(pos); for (ChunkPos chpos: requestedChunks)
this.forceChunkUpdate(pos, world); if (world.getChunk(chpos.x, chpos.z, ChunkStatus.FULL, false) != null)
this.forceChunkUpdate(chpos.getCenterBlockPos(), world);
}); });
return LazyValue.NULL; return LazyValue.NULL;
}); });
@@ -188,6 +188,56 @@ public class BlockValue extends Value
} }
} }
public static LocatorResult fromParamValues(CarpetContext c, List<Value> params, int offset, boolean acceptString, boolean optional)
{
try
{
Value v1 = params.get(0 + offset);
//add conditional from string name
if (optional && v1 instanceof NullValue)
{
return new LocatorResult(null, 1+offset);
}
if (acceptString && v1 instanceof StringValue)
{
return new LocatorResult(fromString(v1.getString()), 1+offset);
}
if (v1 instanceof BlockValue)
{
return new LocatorResult(((BlockValue) v1), 1+offset);
}
if (v1 instanceof ListValue)
{
List<Value> args = ((ListValue) v1).getItems();
int xpos = (int) NumericValue.asNumber(args.get(0)).getLong();
int ypos = (int) NumericValue.asNumber(args.get(1)).getLong();
int zpos = (int) NumericValue.asNumber(args.get(2)).getLong();
return new LocatorResult(
new BlockValue(
null,
c.s.getWorld(),
new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos)
),
1+offset);
}
int xpos = (int) NumericValue.asNumber(v1).getLong();
int ypos = (int) NumericValue.asNumber( params.get(1 + offset)).getLong();
int zpos = (int) NumericValue.asNumber( params.get(2 + offset)).getLong();
return new LocatorResult(
new BlockValue(
null,
c.s.getWorld(),
new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos)
),
3+offset
);
}
catch (IndexOutOfBoundsException e)
{
throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string");
}
}
public BlockState getBlockState() public BlockState getBlockState()
{ {
if (blockState != null) if (blockState != null)