Add DhBlockPosMutable and make the original immutable

This is to prevent issues with some methods accidentally mutating shared positions
This commit is contained in:
James Seibel
2024-08-30 07:35:59 -05:00
parent 628c9b071f
commit b1f154a0ea
14 changed files with 177 additions and 94 deletions
@@ -32,6 +32,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhBlockPosMutable;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
import com.seibel.distanthorizons.core.util.LodUtil;
@@ -237,7 +238,7 @@ public class LodDataBuilder
private static boolean blockVisible(IChunkWrapper chunkWrapper, int relBlockX, int blockY, int relBlockZ)
{
DhBlockPos originalBlockPos = new DhBlockPos(relBlockX,blockY,relBlockZ);
DhBlockPos testBlockPos = new DhBlockPos(relBlockX,blockY,relBlockZ);
final DhBlockPosMutable testBlockPos = new DhBlockPosMutable(relBlockX,blockY,relBlockZ);
// up/down
if (blockInDirectionVisible(chunkWrapper, EDhDirection.UP, originalBlockPos, testBlockPos))
@@ -272,20 +273,20 @@ public class LodDataBuilder
return false;
}
private static boolean blockInDirectionVisible(IChunkWrapper chunkWrapper, EDhDirection direction, DhBlockPos originalBlockPos, DhBlockPos testBlockPos)
private static boolean blockInDirectionVisible(IChunkWrapper chunkWrapper, EDhDirection direction, DhBlockPos originalBlockPos, DhBlockPosMutable testBlockPos)
{
originalBlockPos.mutateOffset(direction, testBlockPos);
// if the block is next to the border of a chunk, assume it's visible
if (testBlockPos.x < 0 || testBlockPos.x >= LodUtil.CHUNK_WIDTH)
if (testBlockPos.getX() < 0 || testBlockPos.getX() >= LodUtil.CHUNK_WIDTH)
{
return true;
}
if (testBlockPos.z < 0 || testBlockPos.z >= LodUtil.CHUNK_WIDTH)
if (testBlockPos.getZ() < 0 || testBlockPos.getZ() >= LodUtil.CHUNK_WIDTH)
{
return true;
}
if (testBlockPos.y < chunkWrapper.getMinBuildHeight() || testBlockPos.y > chunkWrapper.getMaxBuildHeight())
if (testBlockPos.getY() < chunkWrapper.getMinBuildHeight() || testBlockPos.getY() > chunkWrapper.getMaxBuildHeight())
{
return true;
}
@@ -202,7 +202,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable
// log the start of this attempt
LOGGER.info("Attempting to determine sub-dimension for [" + MC_CLIENT.getWrappedClientLevel().getDimensionType().getDimensionName() + "]");
LOGGER.info("Player block pos in dimension: [" + this.playerData.playerBlockPos.x + "," + this.playerData.playerBlockPos.y + "," + this.playerData.playerBlockPos.z + "]");
LOGGER.info("Player block pos in dimension: [" + this.playerData.playerBlockPos.getX() + "," + this.playerData.playerBlockPos.getY() + "," + this.playerData.playerBlockPos.getZ() + "]");
LOGGER.info("Potential Sub Dimension folders: [" + this.potentialLevelFolders.size() + "]");
SubDimCompare mostSimilarSubDim = null;
@@ -315,7 +315,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable
// get the player data for this dimension folder
SubDimensionPlayerData testPlayerData = new SubDimensionPlayerData(testLevelFolder);
LOGGER.info("Last known player pos: [" + testPlayerData.playerBlockPos.x + "," + testPlayerData.playerBlockPos.y + "," + testPlayerData.playerBlockPos.z + "]");
LOGGER.info("Last known player pos: [" + testPlayerData.playerBlockPos.getX() + "," + testPlayerData.playerBlockPos.getY() + "," + testPlayerData.playerBlockPos.getZ() + "]");
// check if the block positions are close
int playerBlockDist = testPlayerData.playerBlockPos.getManhattanDistance(this.playerData.playerBlockPos);
@@ -127,9 +127,9 @@ public class SubDimensionPlayerData
public void toTomlFile(CommentedFileConfig toml)
{
// player block pos
toml.add(PLAYER_BLOCK_POS_X_PATH, this.playerBlockPos.x);
toml.add(PLAYER_BLOCK_POS_Y_PATH, this.playerBlockPos.y);
toml.add(PLAYER_BLOCK_POS_Z_PATH, this.playerBlockPos.z);
toml.add(PLAYER_BLOCK_POS_X_PATH, this.playerBlockPos.getX());
toml.add(PLAYER_BLOCK_POS_Y_PATH, this.playerBlockPos.getY());
toml.add(PLAYER_BLOCK_POS_Z_PATH, this.playerBlockPos.getZ());
toml.save();
}
@@ -138,7 +138,7 @@ public class SubDimensionPlayerData
@Override
public String toString()
{
return "PlayerBlockPos: [" + this.playerBlockPos.x + "," + this.playerBlockPos.y + "," + this.playerBlockPos.z + "]";
return "PlayerBlockPos: [" + this.playerBlockPos.getX() + "," + this.playerBlockPos.getY() + "," + this.playerBlockPos.getZ() + "]";
}
}
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.core.generation;
import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhBlockPosMutable;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
@@ -49,8 +50,8 @@ public class DhLightingEngine
* Since these objects are always mutated anyway, using a {@link ThreadLocal} will allow us to
* only create as many of these {@link DhBlockPos} as necessary.
*/
private static final ThreadLocal<DhBlockPos> PRIMARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPos());
private static final ThreadLocal<DhBlockPos> SECONDARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPos());
private static final ThreadLocal<DhBlockPosMutable> PRIMARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPosMutable());
private static final ThreadLocal<DhBlockPosMutable> SECONDARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPosMutable());
@@ -119,8 +120,8 @@ public class DhLightingEngine
//==================//
// get and set the adjacent chunk's initial block lights
final DhBlockPos relLightBlockPos = PRIMARY_BLOCK_POS_REF.get();
final DhBlockPos relBlockPos = SECONDARY_BLOCK_POS_REF.get();
final DhBlockPosMutable relLightBlockPos = PRIMARY_BLOCK_POS_REF.get();
final DhBlockPosMutable relBlockPos = SECONDARY_BLOCK_POS_REF.get();
ArrayList<DhBlockPos> blockLightPosList = chunk.getWorldBlockLightPosList();
for (int blockLightIndex = 0; blockLightIndex < blockLightPosList.size(); blockLightIndex++) // using iterators in high traffic areas can cause GC issues due to allocating a bunch of iterators, use an indexed for-loop instead
@@ -131,10 +132,10 @@ public class DhLightingEngine
// get the light
IBlockStateWrapper blockState = chunk.getBlockState(relLightBlockPos);
int lightValue = blockState.getLightEmission();
blockLightWorldPosQueue.push(blockLightPos.x, blockLightPos.y, blockLightPos.z, lightValue);
blockLightWorldPosQueue.push(blockLightPos.getX(), blockLightPos.getY(), blockLightPos.getZ(), lightValue);
// set the light
chunk.setDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, lightValue);
chunk.setDhBlockLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), lightValue);
}
@@ -168,11 +169,11 @@ public class DhLightingEngine
// add sky light to the queue
DhBlockPos skyLightPos = new DhBlockPos(chunk.getMinBlockX() + relX, y, chunk.getMinBlockZ() + relZ);
skyLightWorldPosQueue.push(skyLightPos.x, skyLightPos.y, skyLightPos.z, maxSkyLight);
skyLightWorldPosQueue.push(skyLightPos.getX(), skyLightPos.getY(), skyLightPos.getZ(), maxSkyLight);
// set the chunk's sky light
skyLightPos.mutateToChunkRelativePos(relBlockPos);
chunk.setDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, maxSkyLight);
chunk.setDhSkyLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), maxSkyLight);
}
}
}
@@ -189,13 +190,13 @@ public class DhLightingEngine
// block light
this.propagateLightPosList(blockLightWorldPosQueue, adjacentChunkHolder,
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z),
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, newLightValue));
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhBlockLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ()),
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhBlockLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), newLightValue));
// sky light
this.propagateLightPosList(skyLightWorldPosQueue, adjacentChunkHolder,
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z),
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, newLightValue));
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhSkyLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ()),
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhSkyLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), newLightValue));
}
catch (Exception e)
{
@@ -225,8 +226,8 @@ public class DhLightingEngine
// these objects are saved so they can be mutated throughout the method,
// this reduces the number of allocations necessary, reducing GC pressure
final LightPos lightPos = new LightPos(0, 0, 0, 0);
final DhBlockPos neighbourBlockPos = PRIMARY_BLOCK_POS_REF.get();
final DhBlockPos relNeighbourBlockPos = SECONDARY_BLOCK_POS_REF.get();
final DhBlockPosMutable neighbourBlockPos = PRIMARY_BLOCK_POS_REF.get();
final DhBlockPosMutable relNeighbourBlockPos = SECONDARY_BLOCK_POS_REF.get();
// update each light position
@@ -247,14 +248,14 @@ public class DhLightingEngine
// only continue if the light position is inside one of our chunks
IChunkWrapper neighbourChunk = adjacentChunkHolder.getByBlockPos(neighbourBlockPos.x, neighbourBlockPos.z);
IChunkWrapper neighbourChunk = adjacentChunkHolder.getByBlockPos(neighbourBlockPos.getX(), neighbourBlockPos.getZ());
if (neighbourChunk == null)
{
// the light pos is outside our generator's range, ignore it
continue;
}
if (relNeighbourBlockPos.y < neighbourChunk.getMinNonEmptyHeight() || relNeighbourBlockPos.y > neighbourChunk.getMaxBuildHeight())
if (relNeighbourBlockPos.getY() < neighbourChunk.getMinNonEmptyHeight() || relNeighbourBlockPos.getY() > neighbourChunk.getMaxBuildHeight())
{
// the light pos is outside the chunk's min/max height,
// this can happen if given a chunk that hasn't finished generating
@@ -281,7 +282,7 @@ public class DhLightingEngine
// now that light has been propagated to this blockPos
// we need to queue it up so its neighbours can be propagated as well
lightPosQueue.push(neighbourBlockPos.x, neighbourBlockPos.y, neighbourBlockPos.z, targetLevel);
lightPosQueue.push(neighbourBlockPos.getX(), neighbourBlockPos.getY(), neighbourBlockPos.getZ(), targetLevel);
}
}
}
@@ -301,7 +302,7 @@ public class DhLightingEngine
@FunctionalInterface
interface ISetLightFunc { void setLight(IChunkWrapper chunk, DhBlockPos pos, int lightValue); }
private static class LightPos extends DhBlockPos
private static class LightPos extends DhBlockPosMutable
{
public int lightValue;
@@ -410,9 +411,9 @@ public class DhLightingEngine
{
int subIndex = this.index * INTS_PER_LIGHT_POS;
pos.x = this.lightPositions.getInt(subIndex);
pos.y = this.lightPositions.getInt(subIndex + 1);
pos.z = this.lightPositions.getInt(subIndex + 2);
pos.setX(this.lightPositions.getInt(subIndex));
pos.setY(this.lightPositions.getInt(subIndex + 1));
pos.setZ(this.lightPositions.getInt(subIndex + 2));
pos.lightValue = this.lightPositions.getInt(subIndex + 3);
this.index--;
@@ -22,18 +22,25 @@ package com.seibel.distanthorizons.core.pos;
import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.util.LodUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/** @see DhBlockPosMutable */
public class DhBlockPos
{
/** Useful for methods that need a position passed in but won't actually be used */
public static final DhBlockPos ZERO = new DhBlockPos(0, 0, 0);
public int x;
public int y;
public int z;
protected int x;
public int getX() { return this.x; }
protected int y;
public int getY() { return this.y; }
protected int z;
public int getZ() { return this.z; }
@@ -59,12 +66,14 @@ public class DhBlockPos
//========//
/** creates a new {@link DhBlockPos} with the given offset from the current pos. */
public DhBlockPos offset(EDhDirection direction) { return this.mutateOffset(direction, null); }
public DhBlockPos createOffset(EDhDirection direction) { return this.mutateOrCreateOffset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, null); }
/** if not null, mutates "mutablePos" so it matches the current pos after being offset. Otherwise creates a new {@link DhBlockPos}. */
public DhBlockPos mutateOffset(EDhDirection direction, @Nullable DhBlockPos mutablePos) { return this.mutateOffset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, mutablePos); }
public void mutateOffset(EDhDirection direction, @NotNull DhBlockPosMutable mutablePos) { this.mutateOrCreateOffset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, mutablePos); }
public DhBlockPos offset(int x, int y, int z) { return this.mutateOffset(x,y,z, null); }
public DhBlockPos mutateOffset(int x, int y, int z, @Nullable DhBlockPos mutablePos)
public DhBlockPos createOffset(int x, int y, int z) { return this.mutateOrCreateOffset(x,y,z, null); }
public void mutateOffset(int x, int y, int z, @NotNull DhBlockPosMutable mutablePos) { this.mutateOrCreateOffset(x, y, z, mutablePos); }
protected DhBlockPos mutateOrCreateOffset(int x, int y, int z, @Nullable DhBlockPosMutable mutablePos)
{
int newX = this.x + x;
int newY = this.y + y;
@@ -86,31 +95,25 @@ public class DhBlockPos
//==========//
// mutators //
//==========//
//================//
// chunk relative //
//================//
/** Returns a new {@link DhBlockPos} limited to a value between 0 and 15 (inclusive) */
public DhBlockPos createChunkRelativePos() { return this.mutateOrCreateChunkRelativePos(null); }
/** Limits the input {@link DhBlockPos} to a value between 0 and 15 (inclusive) */
public void mutateToChunkRelativePos(DhBlockPos mutableBlockPos) { this.mutateOrCreateChunkRelativePos(mutableBlockPos); }
public void mutateToChunkRelativePos(DhBlockPosMutable mutableBlockPos) { this.mutateOrCreateChunkRelativePos(mutableBlockPos); }
/**
* Limits the block position to a value between 0 and 15 (inclusive)
* If not null, mutates "mutableBlockPos"
*
* @return the mutated or created {@link DhBlockPos}
*/
private DhBlockPos mutateOrCreateChunkRelativePos(@Nullable DhBlockPos mutableBlockPos)
protected DhBlockPos mutateOrCreateChunkRelativePos(@Nullable DhBlockPosMutable mutableBlockPos)
{
// move the position into the range -15 and +15
int relX = (this.x % LodUtil.CHUNK_WIDTH);
// if the position is negative move it into the range 0 and 15
relX = (relX < 0) ? (relX + LodUtil.CHUNK_WIDTH) : relX;
int relZ = (this.z % LodUtil.CHUNK_WIDTH);
relZ = (relZ < 0) ? (relZ + LodUtil.CHUNK_WIDTH) : relZ;
int relX = convertWorldPosToChunkRelative(this.x);
// the y value shouldn't need to be changed
int relZ = convertWorldPosToChunkRelative(this.z);
if (mutableBlockPos != null)
@@ -127,6 +130,15 @@ public class DhBlockPos
}
}
protected static int convertWorldPosToChunkRelative(int xOrZ)
{
// move the position into the range -15 and +15
int relPos = (xOrZ % LodUtil.CHUNK_WIDTH);
// if the position is negative move it into the range 0 and 15
relPos = (relPos < 0) ? (relPos + LodUtil.CHUNK_WIDTH) : relPos;
return relPos;
}
//==========//
@@ -170,6 +182,6 @@ public class DhBlockPos
@Override
public int hashCode() { return Objects.hash(this.x, this.y, this.z); }
@Override
public String toString() { return "DHBlockPos["+this.x+", "+this.y+", "+this.z+"]"; }
public String toString() { return "DHBlockPos["+ this.x +", "+ this.y +", "+ this.z +"]"; }
}
@@ -41,8 +41,8 @@ public class DhBlockPos2D
public DhBlockPos2D(DhBlockPos blockPos)
{
this.x = blockPos.x;
this.z = blockPos.z;
this.x = blockPos.getX();
this.z = blockPos.getZ();
}
public static DhBlockPos2D fromPos2D(Pos2D pos) { return new DhBlockPos2D(pos.x, pos.y); }
@@ -0,0 +1,71 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2023 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.core.pos;
import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.util.LodUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public class DhBlockPosMutable extends DhBlockPos
{
/** Useful for methods that need a position passed in but won't actually be used */
public static final DhBlockPosMutable ZERO = new DhBlockPosMutable(0, 0, 0);
public void setX(int x) { this.x = x; }
public void setY(int y) { this.y = y; }
public void setZ(int z) { this.z = z; }
//==============//
// constructors //
//==============//
public DhBlockPosMutable(int x, int y, int z) { super(x,y,z); }
public DhBlockPosMutable() { super(0, 0, 0); }
public DhBlockPosMutable(DhBlockPos pos) { super(pos); }
public DhBlockPosMutable(DhBlockPos2D pos, int y) { super(pos.x, y, pos.z); }
//========//
// offset //
//========//
/** @see DhBlockPos#createOffset(EDhDirection) */
public DhBlockPosMutable createOffset(EDhDirection direction) { return new DhBlockPosMutable(super.mutateOrCreateOffset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, null)); }
/** @see DhBlockPos#createOffset(int, int, int) */
public DhBlockPosMutable createOffset(int x, int y, int z) { return new DhBlockPosMutable(this.mutateOrCreateOffset(x,y,z, null)); }
//================//
// chunk relative //
//================//
public DhBlockPosMutable createChunkRelativePos() { return new DhBlockPosMutable(this.mutateOrCreateChunkRelativePos(null)); }
}
@@ -46,7 +46,7 @@ public class DhChunkPos
public DhChunkPos(DhBlockPos blockPos)
{
// >> 4 is the Same as div 16
this(blockPos.x >> 4, blockPos.z >> 4);
this(blockPos.getX() >> 4, blockPos.getZ() >> 4);
}
public DhChunkPos(DhBlockPos2D blockPos)
{
@@ -81,8 +81,8 @@ public class DhChunkPos
int maxBlockX = minBlockX + LodUtil.CHUNK_WIDTH;
int maxBlockZ = minBlockZ + LodUtil.CHUNK_WIDTH;
return minBlockX <= pos.x && pos.x <= maxBlockX
&& minBlockZ <= pos.z && pos.z <= maxBlockZ;
return minBlockX <= pos.getX() && pos.getX() <= maxBlockX
&& minBlockZ <= pos.getZ() && pos.getZ() <= maxBlockZ;
}
public long getLong() { return toLong(this.x, this.z); }
@@ -105,8 +105,8 @@ public class DhSectionPos
/** Returns the section pos at the requested detail level containing the given BlockPos */
public static long encodeContaining(byte outputSectionDetailLevel, DhBlockPos pos)
{
int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.x, false);
int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.z, false);
int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.getX(), false);
int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.getZ(), false);
long blockPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
return convertToDetailLevel(blockPos, outputSectionDetailLevel);
}
@@ -475,7 +475,7 @@ public class LodRenderer
public void setModelViewMatrixOffset(DhBlockPos pos, DhApiRenderParam renderEventParam) throws IllegalStateException
{
Vec3d cam = MC_RENDER.getCameraExactPosition();
Vec3f modelPos = new Vec3f((float) (pos.x - cam.x), (float) (pos.y - cam.y), (float) (pos.z - cam.z));
Vec3f modelPos = new Vec3f((float) (pos.getX() - cam.x), (float) (pos.getY() - cam.y), (float) (pos.getZ() - cam.z));
IDhApiShaderProgram shaderProgram = this.lodRenderProgram;
@@ -181,8 +181,8 @@ public class BeaconRenderHandler
if (this.beaconBlockPosSet.add(beacon.blockPos))
{
DhApiRenderableBox beaconBox = new DhApiRenderableBox(
new DhApiVec3d(beacon.blockPos.x, beacon.blockPos.y+1, beacon.blockPos.z),
new DhApiVec3d(beacon.blockPos.x+1, BEAM_TOP_Y, beacon.blockPos.z+1),
new DhApiVec3d(beacon.blockPos.getX(), beacon.blockPos.getY() +1, beacon.blockPos.getZ()),
new DhApiVec3d(beacon.blockPos.getX() +1, BEAM_TOP_Y, beacon.blockPos.getZ() +1),
beacon.color,
EDhApiBlockMaterial.ILLUMINATED
);
@@ -198,9 +198,9 @@ public class BeaconRenderHandler
{
this.beaconBoxGroup.removeIf((box) ->
{
return box.minPos.x == beaconPos.x
&& box.minPos.y == beaconPos.y+1 // plus 1 because the beam starts above the beacon
&& box.minPos.z == beaconPos.z;
return box.minPos.x == beaconPos.getX()
&& box.minPos.y == beaconPos.getY() +1 // plus 1 because the beam starts above the beacon
&& box.minPos.z == beaconPos.getZ();
});
this.beaconBoxGroup.triggerBoxChange();
}
@@ -212,9 +212,9 @@ public class BeaconRenderHandler
for (int i = 0; i < this.beaconBoxGroup.size(); i++)
{
DhApiRenderableBox box = this.beaconBoxGroup.get(i);
if (box.minPos.x == pos.x
&& box.minPos.y == pos.y+1 // plus 1 because the beam starts above the beacon
&& box.minPos.z == pos.z)
if (box.minPos.x == pos.getX()
&& box.minPos.y == pos.getY() +1 // plus 1 because the beam starts above the beacon
&& box.minPos.z == pos.getZ())
{
box.color = newBeam.color;
this.beaconBoxGroup.triggerBoxChange();
@@ -60,7 +60,7 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
public String getTableName() { return "BeaconBeam"; }
@Override
public String createWhereStatement(DhBlockPos pos) { return "BlockPosX = "+pos.x+" AND BlockPosY = "+pos.y+" AND BlockPosZ = "+pos.z; }
public String createWhereStatement(DhBlockPos pos) { return "BlockPosX = "+ pos.getX() +" AND BlockPosY = "+ pos.getY() +" AND BlockPosZ = "+ pos.getZ(); }
@@ -100,9 +100,9 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
PreparedStatement statement = this.createPreparedStatement(sql);
int i = 1;
statement.setObject(i++, dto.blockPos.x);
statement.setObject(i++, dto.blockPos.y);
statement.setObject(i++, dto.blockPos.z);
statement.setObject(i++, dto.blockPos.getX());
statement.setObject(i++, dto.blockPos.getY());
statement.setObject(i++, dto.blockPos.getZ());
statement.setObject(i++, dto.color.getRed());
statement.setObject(i++, dto.color.getGreen());
@@ -132,9 +132,9 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
statement.setObject(i++, System.currentTimeMillis()); // last modified unix time
statement.setObject(i++, dto.blockPos.x);
statement.setObject(i++, dto.blockPos.y);
statement.setObject(i++, dto.blockPos.z);
statement.setObject(i++, dto.blockPos.getX());
statement.setObject(i++, dto.blockPos.getY());
statement.setObject(i++, dto.blockPos.getZ());
return statement;
}
@@ -23,15 +23,12 @@ import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.level.IDhClientLevel;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.world.IDhClientWorld;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.coreapi.util.MathUtil;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.util.math.Vec3f;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
/**
@@ -143,7 +140,7 @@ public class RenderUtil
{
// if the player is a significant distance above the work, increase the
// near clip plane to fix Z imprecision issues
int playerHeight = MC.getPlayerBlockPos().y;
int playerHeight = MC.getPlayerBlockPos().getY();
int levelMaxHeight = level.getMaxHeight();
if (playerHeight > levelMaxHeight + 1_000)
{
@@ -22,6 +22,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.DhBlockPosMutable;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
@@ -94,7 +95,7 @@ public interface IChunkWrapper extends IBindable
ArrayList<DhBlockPos> getWorldBlockLightPosList();
default boolean blockPosInsideChunk(DhBlockPos blockPos) { return this.blockPosInsideChunk(blockPos.x, blockPos.y, blockPos.z); }
default boolean blockPosInsideChunk(DhBlockPos blockPos) { return this.blockPosInsideChunk(blockPos.getX(), blockPos.getY(), blockPos.getZ()); }
default boolean blockPosInsideChunk(int x, int y, int z)
{
return (x >= this.getMinBlockX() && x <= this.getMaxBlockX()
@@ -111,7 +112,7 @@ public interface IChunkWrapper extends IBindable
String toString();
default IBlockStateWrapper getBlockState(DhBlockPos pos) { return this.getBlockState(pos.x, pos.y, pos.z); }
default IBlockStateWrapper getBlockState(DhBlockPos pos) { return this.getBlockState(pos.getX(), pos.getY(), pos.getZ()); }
IBlockStateWrapper getBlockState(int relX, int relY, int relZ);
IBiomeWrapper getBiome(int relX, int relY, int relZ);
@@ -322,15 +323,15 @@ public interface IChunkWrapper extends IBindable
}
// light emitting blocks (if the light changes then the LOD definitely needs to be updated)
final DhBlockPos relPos = new DhBlockPos();
final DhBlockPosMutable relPos = new DhBlockPosMutable();
ArrayList<DhBlockPos> lightPosList = this.getWorldBlockLightPosList();
for (int i = 0; i < lightPosList.size(); i++)
{
DhBlockPos pos = lightPosList.get(i);
pos.mutateToChunkRelativePos(relPos);
hash = (hash * primeBlockMultiplier) + this.getBlockState(relPos.x, relPos.y, relPos.z).hashCode();
hash = (hash * primeHeightMultiplier) + relPos.y;
hash = (hash * primeBlockMultiplier) + this.getBlockState(relPos.getX(), relPos.getY(), relPos.getZ()).hashCode();
hash = (hash * primeHeightMultiplier) + relPos.getY();
}
@@ -344,7 +345,7 @@ public interface IChunkWrapper extends IBindable
AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(this, neighbourChunkList);
// since beacons emit light we can check only the positions that are emitting light
final DhBlockPos relPos = new DhBlockPos();
final DhBlockPosMutable relPos = new DhBlockPosMutable();
ArrayList<DhBlockPos> blockPosList = this.getWorldBlockLightPosList();
for (int i = 0; i < blockPosList.size(); i++)
{
@@ -371,7 +372,7 @@ public interface IChunkWrapper extends IBindable
static Color getBeaconColor(DhBlockPos beaconPos, AdjacentChunkHolder chunkHolder)
{
DhBlockPos beaconRelPos = beaconPos.createChunkRelativePos();
DhBlockPos baseRelPos = new DhBlockPos(0, beaconRelPos.y-1, 0);
DhBlockPosMutable baseRelPos = new DhBlockPosMutable(0, beaconRelPos.getY() -1, 0);
@@ -383,14 +384,14 @@ public interface IChunkWrapper extends IBindable
{
for (int z = -1; z <= 1; z++)
{
baseRelPos.x = beaconRelPos.x + x;
baseRelPos.z = beaconRelPos.z + z;
baseRelPos.setX(beaconRelPos.getX() + x);
baseRelPos.setZ(beaconRelPos.getZ() + z);
baseRelPos.mutateToChunkRelativePos(baseRelPos);
IChunkWrapper chunk = chunkHolder.getByBlockPos(beaconPos.x + x, beaconPos.z + z);
IChunkWrapper chunk = chunkHolder.getByBlockPos(beaconPos.getX() + x, beaconPos.getZ() + z);
if (chunk != null)
{
IBlockStateWrapper block = chunk.getBlockState(baseRelPos.x, baseRelPos.y, baseRelPos.z);
IBlockStateWrapper block = chunk.getBlockState(baseRelPos.getX(), baseRelPos.getY(), baseRelPos.getZ());
if (!block.isBeaconBaseBlock())
{
return null;
@@ -411,11 +412,11 @@ public interface IChunkWrapper extends IBindable
int blue = 0;
boolean glassBlockFound = false;
IChunkWrapper centerChunk = chunkHolder.getByBlockPos(beaconPos.x, beaconPos.z);
IChunkWrapper centerChunk = chunkHolder.getByBlockPos(beaconPos.getX(), beaconPos.getZ());
int maxY = centerChunk.getMaxNonEmptyHeight();
for (int y = beaconRelPos.y+1; y <= maxY; y++)
for (int y = beaconRelPos.getY() +1; y <= maxY; y++)
{
IBlockStateWrapper block = centerChunk.getBlockState(beaconRelPos.x, y, beaconRelPos.z);
IBlockStateWrapper block = centerChunk.getBlockState(beaconRelPos.getX(), y, beaconRelPos.getZ());
if (!block.isAir() && block.getOpacity() == LodUtil.BLOCK_FULLY_OPAQUE)
{
return null;