@@ -141,7 +141,7 @@ public class ServerApi
|
||||
//=======================//
|
||||
|
||||
public void serverChunkLoadEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); }
|
||||
public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); }
|
||||
public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, true); }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -311,6 +311,18 @@ public class SharedApi
|
||||
}
|
||||
|
||||
|
||||
// having a list of the nearby chunks is needed for lighting and beacon generation
|
||||
ArrayList<IChunkWrapper> nearbyChunkList;
|
||||
if (neighbourChunkList != null)
|
||||
{
|
||||
nearbyChunkList = neighbourChunkList;
|
||||
}
|
||||
else
|
||||
{
|
||||
nearbyChunkList = new ArrayList<>(1);
|
||||
nearbyChunkList.add(chunkWrapper);
|
||||
}
|
||||
|
||||
|
||||
// Save or populate the chunk wrapper's lighting
|
||||
// this is done so we don't have to worry about MC unloading the lighting data for this chunk
|
||||
@@ -330,24 +342,13 @@ public class SharedApi
|
||||
else
|
||||
{
|
||||
// generate the chunk's lighting, using neighboring chunks if present
|
||||
|
||||
ArrayList<IChunkWrapper> nearbyChunkList;
|
||||
if (neighbourChunkList != null)
|
||||
{
|
||||
nearbyChunkList = neighbourChunkList;
|
||||
}
|
||||
else
|
||||
{
|
||||
nearbyChunkList = new ArrayList<>(1);
|
||||
nearbyChunkList.add(chunkWrapper);
|
||||
}
|
||||
|
||||
DhLightingEngine.INSTANCE.lightChunk(chunkWrapper, nearbyChunkList, dhLevel.hasSkyLight() ? 15 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// get this chunk's active beacons
|
||||
List<BeaconBeamDTO> beaconBeamList = chunkWrapper.getAllActiveBeacons();
|
||||
List<BeaconBeamDTO> beaconBeamList = chunkWrapper.getAllActiveBeacons(nearbyChunkList);
|
||||
dhLevel.setBeaconBeamsForChunk(chunkWrapper.getChunkPos(), beaconBeamList);
|
||||
|
||||
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
package com.seibel.distanthorizons.core.generation;
|
||||
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
/** holds adjacent chunks without having to create new Pos objects */
|
||||
public class AdjacentChunkHolder
|
||||
{
|
||||
final IChunkWrapper[] chunkArray = new IChunkWrapper[9];
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public AdjacentChunkHolder(IChunkWrapper centerWrapper) { this.chunkArray[4] = centerWrapper; }
|
||||
|
||||
public AdjacentChunkHolder(IChunkWrapper centerWrapper, @NotNull ArrayList<IChunkWrapper> nearbyChunkList)
|
||||
{
|
||||
this.chunkArray[4] = centerWrapper;
|
||||
|
||||
DhChunkPos centerChunkPos = centerWrapper.getChunkPos();
|
||||
|
||||
// generate the list of chunk pos we need,
|
||||
// currently a 3x3 grid
|
||||
HashSet<DhChunkPos> requestedAdjacentPositions = new HashSet<>(9);
|
||||
for (int xOffset = -1; xOffset <= 1; xOffset++)
|
||||
{
|
||||
for (int zOffset = -1; zOffset <= 1; zOffset++)
|
||||
{
|
||||
DhChunkPos adjacentPos = new DhChunkPos(centerChunkPos.x + xOffset, centerChunkPos.z + zOffset);
|
||||
requestedAdjacentPositions.add(adjacentPos);
|
||||
}
|
||||
}
|
||||
|
||||
for (int chunkIndex = 0; chunkIndex < nearbyChunkList.size(); chunkIndex++) // using iterators in high traffic areas can cause GC issues due to allocating a bunch of iterators, use an indexed for-loop instead
|
||||
{
|
||||
IChunkWrapper chunk = nearbyChunkList.get(chunkIndex);
|
||||
if (chunk != null && requestedAdjacentPositions.contains(chunk.getChunkPos()))
|
||||
{
|
||||
// remove the newly found position
|
||||
requestedAdjacentPositions.remove(chunk.getChunkPos());
|
||||
|
||||
// add the adjacent chunk
|
||||
this.add(chunk);
|
||||
}
|
||||
|
||||
if (requestedAdjacentPositions.isEmpty())
|
||||
{
|
||||
// we found every chunk we needed, we don't need to keep iterating
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
public void add(IChunkWrapper centerWrapper)
|
||||
{
|
||||
DhChunkPos centerPos = this.chunkArray[4].getChunkPos();
|
||||
DhChunkPos offsetPos = centerWrapper.getChunkPos();
|
||||
|
||||
int offsetX = offsetPos.x - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int offsetZ = offsetPos.z - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)] = centerWrapper;
|
||||
}
|
||||
|
||||
public IChunkWrapper getByBlockPos(int blockX, int blockZ)
|
||||
{
|
||||
int chunkX = BitShiftUtil.divideByPowerOfTwo(blockX, 4);
|
||||
int chunkZ = BitShiftUtil.divideByPowerOfTwo(blockZ, 4);
|
||||
IChunkWrapper centerChunk = this.chunkArray[4];
|
||||
DhChunkPos centerPos = centerChunk.getChunkPos();
|
||||
if (centerPos.x == chunkX && centerPos.z == chunkZ)
|
||||
{
|
||||
return centerChunk;
|
||||
}
|
||||
|
||||
int offsetX = chunkX - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int offsetZ = chunkZ - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
return this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -306,64 +306,6 @@ public class DhLightingEngine
|
||||
|
||||
}
|
||||
|
||||
/** holds the adjacent chunks without having to create new Pos objects */
|
||||
private static class AdjacentChunkHolder
|
||||
{
|
||||
final IChunkWrapper[] chunkArray = new IChunkWrapper[9];
|
||||
|
||||
|
||||
public AdjacentChunkHolder(IChunkWrapper centerWrapper) { this.chunkArray[4] = centerWrapper; }
|
||||
|
||||
|
||||
public void add(IChunkWrapper centerWrapper)
|
||||
{
|
||||
DhChunkPos centerPos = this.chunkArray[4].getChunkPos();
|
||||
DhChunkPos offsetPos = centerWrapper.getChunkPos();
|
||||
|
||||
int offsetX = offsetPos.x - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int offsetZ = offsetPos.z - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)] = centerWrapper;
|
||||
}
|
||||
|
||||
public IChunkWrapper getByBlockPos(int blockX, int blockZ)
|
||||
{
|
||||
int chunkX = BitShiftUtil.divideByPowerOfTwo(blockX, 4);
|
||||
int chunkZ = BitShiftUtil.divideByPowerOfTwo(blockZ, 4);
|
||||
IChunkWrapper centerChunk = this.chunkArray[4];
|
||||
DhChunkPos centerPos = centerChunk.getChunkPos();
|
||||
if (centerPos.x == chunkX && centerPos.z == chunkZ)
|
||||
{
|
||||
return centerChunk;
|
||||
}
|
||||
|
||||
int offsetX = chunkX - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int offsetZ = chunkZ - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
return this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds all potential {@link LightPos} objects a lighting task may need.
|
||||
* This is done so existing {@link LightPos} objects can be repurposed instead of destroyed,
|
||||
|
||||
+44
-18
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.chunk;
|
||||
|
||||
import com.seibel.distanthorizons.core.generation.AdjacentChunkHolder;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
@@ -31,6 +32,8 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public interface IChunkWrapper extends IBindable
|
||||
@@ -38,6 +41,15 @@ public interface IChunkWrapper extends IBindable
|
||||
/** useful for debugging, but can slow down chunk operations quite a bit due to being called every time. */
|
||||
boolean RUN_RELATIVE_POS_INDEX_VALIDATION = ModInfo.IS_DEV_BUILD;
|
||||
|
||||
/** should be all lowercase */
|
||||
List<String> BEACON_BASE_BLOCK_NAME_LIST = Arrays.asList(
|
||||
"iron_block",
|
||||
"gold_block",
|
||||
"diamond_block",
|
||||
"emerald_block",
|
||||
"netherite_block"
|
||||
);
|
||||
|
||||
|
||||
|
||||
DhChunkPos getChunkPos();
|
||||
@@ -246,10 +258,12 @@ public interface IChunkWrapper extends IBindable
|
||||
return hash;
|
||||
}
|
||||
|
||||
default List<BeaconBeamDTO> getAllActiveBeacons()
|
||||
default List<BeaconBeamDTO> getAllActiveBeacons(ArrayList<IChunkWrapper> neighbourChunkList)
|
||||
{
|
||||
ArrayList<BeaconBeamDTO> beaconPosList = new ArrayList<>();
|
||||
|
||||
AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(this, neighbourChunkList);
|
||||
|
||||
// since beacons emit light we can check only the positions that are emitting light
|
||||
ArrayList<DhBlockPos> blockPosList = this.getBlockLightPosList();
|
||||
for (int i = 0; i < blockPosList.size(); i++)
|
||||
@@ -260,7 +274,7 @@ public interface IChunkWrapper extends IBindable
|
||||
IBlockStateWrapper block = this.getBlockState(relPos);
|
||||
if (block.getSerialString().toLowerCase().contains("minecraft:beacon"))
|
||||
{
|
||||
if (isBeaconActive(relPos.x, relPos.y, relPos.z, this))
|
||||
if (isBeaconActive(pos, adjacentChunkHolder))
|
||||
{
|
||||
BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), Color.WHITE);
|
||||
beaconPosList.add(beam);
|
||||
@@ -270,31 +284,43 @@ public interface IChunkWrapper extends IBindable
|
||||
|
||||
return beaconPosList;
|
||||
}
|
||||
static boolean isBeaconActive(int relBlockX, int y, int relBlockZ, IChunkWrapper chunkWrapper)
|
||||
static boolean isBeaconActive(DhBlockPos beaconPos, AdjacentChunkHolder chunkHolder)
|
||||
{
|
||||
DhBlockPos beaconRelPos = beaconPos.convertToChunkRelativePos();
|
||||
DhBlockPos baseRelPos = new DhBlockPos(0, beaconRelPos.y-1, 0);
|
||||
|
||||
for (int x = -1; x<= 1; x++)
|
||||
{
|
||||
for (int z = -1; z <= 1; z++)
|
||||
{
|
||||
if ((relBlockX + x < 0 || relBlockX + x >= LodUtil.CHUNK_WIDTH)
|
||||
|| (relBlockZ + z < 0 || relBlockZ + z >= LodUtil.CHUNK_WIDTH))
|
||||
{
|
||||
// if the beacon is on the border of a chunk and all other blocks are there, assume it's complete
|
||||
//TODO! Check adjacent chunk, if possible
|
||||
continue;
|
||||
}
|
||||
String blockId = chunkWrapper.getBlockState(relBlockX + x, y -1, relBlockZ + z).getSerialString();
|
||||
baseRelPos.x = beaconRelPos.x + x;
|
||||
baseRelPos.z = beaconRelPos.z + z;
|
||||
baseRelPos.mutateToChunkRelativePos(baseRelPos);
|
||||
|
||||
if (!(blockId.contains("diamond_block")
|
||||
|| blockId.contains("iron_block")
|
||||
|| blockId.contains("emerald_block")
|
||||
|| blockId.contains("netherite_block")
|
||||
|| blockId.contains("gold_block")))
|
||||
{
|
||||
return false;
|
||||
IChunkWrapper chunk = chunkHolder.getByBlockPos(beaconPos.x + x, beaconPos.z + z);
|
||||
if (chunk != null)
|
||||
{
|
||||
String blockSerial = chunk.getBlockState(baseRelPos.x, baseRelPos.y, baseRelPos.z).getSerialString();
|
||||
|
||||
boolean baseBlockFound = false;
|
||||
for (int i = 0; i < BEACON_BASE_BLOCK_NAME_LIST.size(); i++)
|
||||
{
|
||||
String baseBlockName = BEACON_BASE_BLOCK_NAME_LIST.get(i);
|
||||
if (blockSerial.contains(baseBlockName))
|
||||
{
|
||||
baseBlockFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!baseBlockFound)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user