Skip to content

Commit

Permalink
Merge pull request #581 from ValkyrienSkies/feature/new-terrain
Browse files Browse the repository at this point in the history
New terrain loading
  • Loading branch information
StewStrong authored Sep 28, 2023
2 parents 0bf1ea9 + be901b8 commit 939e4ee
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,19 @@ private void preRenderStatusEffectOverlay(final PoseStack matrices, final Callba
final IntegratedServer integratedServer = this.minecraft.getSingleplayerServer();
if (integratedServer != null) {
String physicsTPS = "Error";
String loadedVoxelChunks = "Error";
try {
// This is dangerous because we have to reach into the Server state from the Client, which can fail.
// So, put this in a try/catch block to catch any errors that may occur.
physicsTPS = " " + Math.round(VSGameUtilsKt.getVsPipeline(integratedServer).computePhysTps());
loadedVoxelChunks = " " + VSGameUtilsKt.getVsPipeline(integratedServer).getLoadedVoxelChunks();
} catch (final Exception e) {
e.printStackTrace();
}
final String worldPhysicsDebugText = "VS PhysTPS: " + physicsTPS;
debugText.add(worldPhysicsDebugText);
final String loadedVoxelChunkDebugText = "VS VoxelChunks: " + loadedVoxelChunks;
debugText.add(loadedVoxelChunkDebugText);
}

debugText.add("Using UDP: " + ValkyrienSkiesMod.getVsCore().getClientUsesUDP());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.valkyrienskies.core.api.ships.ClientShip;
import org.valkyrienskies.core.api.world.LevelYRange;
import org.valkyrienskies.mod.common.VSGameUtilsKt;
import org.valkyrienskies.mod.mixinducks.MixinBlockEntityInstanceManagerDuck;

Expand Down Expand Up @@ -60,7 +59,7 @@ void preCreateRaw(final BlockEntity blockEntity, final CallbackInfoReturnable<In
final MaterialManager manager =
shipMaterialManagers.computeIfAbsent(ship, k -> createMaterialManager());
final Vector3i c =
ship.getChunkClaim().getCenterBlockCoordinates(new LevelYRange(0, 0), new Vector3i());
ship.getChunkClaim().getCenterBlockCoordinates(VSGameUtilsKt.getYRange(nullableLevel), new Vector3i());
((InstancingEngineAccessor) manager).setOriginCoordinate(new BlockPos(c.x, c.y, c.z));

cir.setReturnValue(InstancedRenderRegistry.createInstance(manager, blockEntity));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
Expand Down Expand Up @@ -53,6 +55,7 @@
import org.valkyrienskies.mod.common.util.VSServerLevel;
import org.valkyrienskies.mod.common.util.VectorConversionsMCKt;
import org.valkyrienskies.mod.mixin.accessors.server.level.ChunkMapAccessor;
import org.valkyrienskies.mod.mixin.accessors.server.level.DistanceManagerAccessor;

@Mixin(ServerLevel.class)
public abstract class MixinServerLevel implements IShipObjectWorldServerProvider, VSServerLevel {
Expand All @@ -61,6 +64,10 @@ public abstract class MixinServerLevel implements IShipObjectWorldServerProvider
@Final
private ServerChunkCache chunkSource;

@Shadow
@Final
List<ServerPlayer> players;

@Shadow
@NotNull
public abstract MinecraftServer getServer();
Expand Down Expand Up @@ -119,6 +126,68 @@ private boolean includeShipsInParticleDistanceCheck(
return posInWorld.distanceSquared(player.getX(), player.getY(), player.getZ()) < distance * distance;
}

@Unique
private void loadChunk(@NotNull final ChunkAccess worldChunk, final List<TerrainUpdate> voxelShapeUpdates) {
if (!knownChunks.containsKey(worldChunk.getPos())) {
final List<Vector3ic> voxelChunkPositions = new ArrayList<>();

final int chunkX = worldChunk.getPos().x;
final int chunkZ = worldChunk.getPos().z;

final LevelChunkSection[] chunkSections = worldChunk.getSections();

for (int sectionY = 0; sectionY < chunkSections.length; sectionY++) {
final LevelChunkSection chunkSection = chunkSections[sectionY];
final Vector3ic chunkPos =
new Vector3i(chunkX, worldChunk.getSectionYFromSectionIndex(sectionY), chunkZ);
voxelChunkPositions.add(chunkPos);

if (chunkSection != null && !chunkSection.hasOnlyAir()) {
// Add this chunk to the ground rigid body
final TerrainUpdate voxelShapeUpdate =
VSGameUtilsKt.toDenseVoxelUpdate(chunkSection, chunkPos);
voxelShapeUpdates.add(voxelShapeUpdate);

// region Detect wings
final ServerLevel thisAsLevel = ServerLevel.class.cast(this);
final LoadedServerShip
ship = VSGameUtilsKt.getShipObjectManagingPos(thisAsLevel, chunkX, chunkZ);
if (ship != null) {
// Sussy cast, but I don't want to expose this directly through the vs-core api
final WingManager shipAsWingManager = ship.getAttachment(WingManager.class);
final MutableBlockPos mutableBlockPos = new MutableBlockPos();
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
final BlockState blockState = chunkSection.getBlockState(x, y, z);
final int posX = (chunkX << 4) + x;
final int posY = chunkSection.bottomBlockY() + y;
final int posZ = (chunkZ << 4) + z;
if (blockState.getBlock() instanceof WingBlock) {
mutableBlockPos.set(posX, posY, posZ);
final Wing wing =
((WingBlock) blockState.getBlock()).getWing(thisAsLevel,
mutableBlockPos, blockState);
if (wing != null) {
shipAsWingManager.setWing(shipAsWingManager.getFirstWingGroupId(),
posX, posY, posZ, wing);
}
}
}
}
}
}
// endregion
} else {
final TerrainUpdate emptyVoxelShapeUpdate = getVsCore()
.newEmptyVoxelShapeUpdate(chunkPos.x(), chunkPos.y(), chunkPos.z(), true);
voxelShapeUpdates.add(emptyVoxelShapeUpdate);
}
}
knownChunks.put(worldChunk.getPos(), voxelChunkPositions);
}
}

@Inject(method = "tick", at = @At("TAIL"))
private void postTick(final BooleanSupplier shouldKeepTicking, final CallbackInfo ci) {
final ServerLevel self = ServerLevel.class.cast(this);
Expand All @@ -129,77 +198,24 @@ private void postTick(final BooleanSupplier shouldKeepTicking, final CallbackInf
// Create DenseVoxelShapeUpdate for new loaded chunks
// Also mark the chunks as loaded in the ship objects
final List<TerrainUpdate> voxelShapeUpdates = new ArrayList<>();
final DistanceManagerAccessor distanceManagerAccessor = (DistanceManagerAccessor) chunkSource.chunkMap.getDistanceManager();

for (final ChunkHolder chunkHolder : chunkMapAccessor.callGetChunks()) {
final Optional<LevelChunk> worldChunkOptional =
chunkHolder.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).left();
if (worldChunkOptional.isPresent()) {
// Only load chunks that are present and that have tickets
if (worldChunkOptional.isPresent() && distanceManagerAccessor.getTickets().containsKey(chunkHolder.getPos().toLong())) {
// Only load chunks that have a ticket
final LevelChunk worldChunk = worldChunkOptional.get();
if (!knownChunks.containsKey(worldChunk.getPos())) {
final List<Vector3ic> voxelChunkPositions = new ArrayList<>();

final int chunkX = worldChunk.getPos().x;
final int chunkZ = worldChunk.getPos().z;

final LevelChunkSection[] chunkSections = worldChunk.getSections();

for (int sectionY = 0; sectionY < chunkSections.length; sectionY++) {
final LevelChunkSection chunkSection = chunkSections[sectionY];
final Vector3ic chunkPos =
new Vector3i(chunkX, worldChunk.getSectionYFromSectionIndex(sectionY), chunkZ);
voxelChunkPositions.add(chunkPos);

if (chunkSection != null && !chunkSection.hasOnlyAir()) {
// Add this chunk to the ground rigid body
final TerrainUpdate voxelShapeUpdate =
VSGameUtilsKt.toDenseVoxelUpdate(chunkSection, chunkPos);
voxelShapeUpdates.add(voxelShapeUpdate);

// region Detect wings
final ServerLevel thisAsLevel = ServerLevel.class.cast(this);
final LoadedServerShip
ship = VSGameUtilsKt.getShipObjectManagingPos(thisAsLevel, chunkX, chunkZ);
if (ship != null) {
// Sussy cast, but I don't want to expose this directly through the vs-core api
final WingManager shipAsWingManager = ship.getAttachment(WingManager.class);
final MutableBlockPos mutableBlockPos = new MutableBlockPos();
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
final BlockState blockState = chunkSection.getBlockState(x, y, z);
final int posX = (chunkX << 4) + x;
final int posY = chunkSection.bottomBlockY() + y;
final int posZ = (chunkZ << 4) + z;
if (blockState.getBlock() instanceof WingBlock) {
mutableBlockPos.set(posX, posY, posZ);
final Wing wing =
((WingBlock) blockState.getBlock()).getWing(thisAsLevel,
mutableBlockPos, blockState);
if (wing != null) {
shipAsWingManager.setWing(shipAsWingManager.getFirstWingGroupId(),
posX, posY, posZ, wing);
}
}
}
}
}
}
// endregion
} else {
final TerrainUpdate emptyVoxelShapeUpdate = getVsCore()
.newEmptyVoxelShapeUpdate(chunkPos.x(), chunkPos.y(), chunkPos.z(), true);
voxelShapeUpdates.add(emptyVoxelShapeUpdate);
}
}
knownChunks.put(worldChunk.getPos(), voxelChunkPositions);
}
loadChunk(worldChunk, voxelShapeUpdates);
}
}

final Iterator<Entry<ChunkPos, List<Vector3ic>>> knownChunkPosIterator = knownChunks.entrySet().iterator();
while (knownChunkPosIterator.hasNext()) {
final Entry<ChunkPos, List<Vector3ic>> knownChunkPosEntry = knownChunkPosIterator.next();
if (chunkMapAccessor.callGetVisibleChunkIfPresent(knownChunkPosEntry.getKey().toLong()) == null) {
// Unload chunks if they don't have tickets or if they're not in the visible chunks
if ((!distanceManagerAccessor.getTickets().containsKey(knownChunkPosEntry.getKey().toLong()) || chunkMapAccessor.callGetVisibleChunkIfPresent(knownChunkPosEntry.getKey().toLong()) == null)) {
// Delete this chunk
for (final Vector3ic unloadedChunk : knownChunkPosEntry.getValue()) {
final TerrainUpdate deleteVoxelShapeUpdate =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fun MinecraftServer.executeIf(condition: () -> Boolean, toExecute: Runnable) {
}
}

val Level.yRange get() = LevelYRange(minBuildHeight, maxBuildHeight)
val Level.yRange get() = LevelYRange(minBuildHeight, maxBuildHeight - 1)

fun Level.isTickingChunk(pos: ChunkPos) = isTickingChunk(pos.x, pos.z)
fun Level.isTickingChunk(chunkX: Int, chunkZ: Int) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ package org.valkyrienskies.mod.common.util

import net.minecraft.world.entity.player.Player
import org.joml.Vector3d
import org.joml.Vector3dc
import org.valkyrienskies.core.api.ships.properties.ShipId
import org.valkyrienskies.core.apigame.world.IPlayer
import org.valkyrienskies.core.apigame.world.PlayerState
import org.valkyrienskies.core.apigame.world.properties.DimensionId
import org.valkyrienskies.mod.common.dimensionId
import org.valkyrienskies.mod.common.getPassengerPos
import org.valkyrienskies.mod.common.getShipObjectEntityMountedTo
import org.valkyrienskies.mod.common.vsCore
import java.lang.ref.WeakReference
import java.util.UUID
Expand Down Expand Up @@ -34,6 +39,22 @@ class MinecraftPlayer(playerObject: Player) : IPlayer {
return dest.set(player.x, player.y, player.z)
}

override fun getPlayerState(): PlayerState {
var mountedShip: ShipId? = null
var mountedPos: Vector3dc? = null
player.level.getShipObjectEntityMountedTo(player)?.let {
mountedShip = it.id
mountedPos = player.vehicle!!.getPassengerPos(player.myRidingOffset, 0.0f)
}
return PlayerState(
Vector3d(player.x, player.y, player.z),
Vector3d(Vector3d(player.x - player.xo, player.y - player.yo, player.z - player.zo)),
dimension,
mountedShip,
mountedPos,
)
}

override fun hashCode(): Int {
return uuid.hashCode()
}
Expand Down
8 changes: 6 additions & 2 deletions forge/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,15 @@ dependencies {
transitive = false
}

forgeRuntimeLibrary shadowCommon("org.valkyrienskies:physics_api_krunch:1.0.0+2bfb3f8968") {
forgeRuntimeLibrary include("org.valkyrienskies.core:util:${rootProject.vs_core_version}") {
transitive = false
}

forgeRuntimeLibrary shadowCommon("org.valkyrienskies:physics_api:1.0.0+63b53cc647") {
forgeRuntimeLibrary shadowCommon("org.valkyrienskies:physics_api_krunch:1.0.0+c56602855f") {
transitive = false
}

forgeRuntimeLibrary shadowCommon("org.valkyrienskies:physics_api:1.0.0+94304c13aa") {
transitive = false
}

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fabric_loader_version=0.14.10
fabric_api_version=0.59.0+1.18.2
forge_version=1.18.2-40.1.69
create_fabric_version=0.5.0.i-934+1.18.2
vs_core_version=1.1.0+c366a39369
vs_core_version=1.1.0+6f373832e9
# Prevent kotlin from autoincluding stdlib as a dependency, which breaks
# gradle's composite builds (includeBuild) for some reason. We'll add it manually
kotlin.stdlib.default.dependency=false
Expand Down

0 comments on commit 939e4ee

Please sign in to comment.