Skip to content

Commit

Permalink
fixed sus
Browse files Browse the repository at this point in the history
  • Loading branch information
ThePlasticPotato committed May 28, 2024
1 parent 9316bbd commit 2a905f1
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 192 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ object ShipAssembler {
}


fun assembleToShip(level: Level, blocks: List<BlockPos>, removeOriginal: Boolean, scale: Double): Boolean {
fun assembleToShip(level: Level, blocks: List<BlockPos>, removeOriginal: Boolean, scale: Double): ServerShip {
assert(level is ServerLevel) { "Can't manage contraptions on client side!" }
val sLevel: ServerLevel = level as ServerLevel
if (blocks.isEmpty()) {
return false
throw IllegalArgumentException()
}

val existingShip = sLevel.getShipObjectManagingPos(blocks.find { !sLevel.getBlockState(it).isAir } ?: return false)
val existingShip = sLevel.getShipObjectManagingPos(blocks.find { !sLevel.getBlockState(it).isAir } ?: throw IllegalArgumentException())

var structureCornerMin: BlockPos = blocks[0]
var structureCornerMax: BlockPos = blocks[0]
Expand All @@ -52,7 +52,7 @@ object ShipAssembler {
hasSolids = true
}
}
if (!hasSolids) return false
if (!hasSolids) throw IllegalArgumentException("No solid blocks found in the structure")
val contraptionOGPos: Vector3ic = AssemblyUtil.getMiddle(structureCornerMin, structureCornerMax)
// Create new contraption at center of bounds
val contraptionWorldPos: Vector3i = if (existingShip != null) {
Expand Down Expand Up @@ -108,7 +108,7 @@ object ShipAssembler {
sLevel.server.shipObjectWorld
.teleportShip(newShip as ServerShip, ShipTeleportDataImpl(Vector3d(contraptionWorldPos.x.toDouble(),contraptionWorldPos.y.toDouble(),contraptionWorldPos.z.toDouble())))

return true
return newShip as ServerShip
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import org.valkyrienskies.core.impl.game.ships.ShipTransformImpl
import org.valkyrienskies.core.impl.networking.simple.sendToClient
import org.valkyrienskies.mod.common.dimensionId
import org.valkyrienskies.mod.common.executeIf
import org.valkyrienskies.mod.common.getShipManagingPos
import org.valkyrienskies.mod.common.isTickingChunk
import org.valkyrienskies.mod.common.networking.PacketRestartChunkUpdates
import org.valkyrienskies.mod.common.networking.PacketStopChunkUpdates
import org.valkyrienskies.mod.common.playerWrapper
import org.valkyrienskies.mod.common.shipObjectWorld
import org.valkyrienskies.mod.common.util.toBlockPos
import org.valkyrienskies.mod.common.util.toJOML
import org.valkyrienskies.mod.util.relocateBlock
import org.valkyrienskies.mod.util.updateBlock
Expand All @@ -26,84 +28,8 @@ fun createNewShipWithBlocks(
): ServerShip {
if (blocks.isEmpty()) throw IllegalArgumentException()

val ship = level.shipObjectWorld.createNewShipAtBlock(centerBlock.toJOML(), false, 1.0, level.dimensionId)
val blockList: MutableList<BlockPos> = mutableListOf()

val shipChunkX = ship.chunkClaim.xMiddle
val shipChunkZ = ship.chunkClaim.zMiddle

val worldChunkX = centerBlock.x shr 4
val worldChunkZ = centerBlock.z shr 4

val deltaX = worldChunkX - shipChunkX
val deltaZ = worldChunkZ - shipChunkZ

val chunksToBeUpdated = mutableMapOf<ChunkPos, Pair<ChunkPos, ChunkPos>>()
blocks.forEachChunk { x, _, z, _ ->
val sourcePos = ChunkPos(x, z)
val destPos = ChunkPos(x - deltaX, z - deltaZ)
chunksToBeUpdated[sourcePos] = Pair(sourcePos, destPos)
}
val chunkPairs = chunksToBeUpdated.values.toList()
val chunkPoses = chunkPairs.flatMap { it.toList() }
val chunkPosesJOML = chunkPoses.map { it.toJOML() }

// Send a list of all the chunks that we plan on updating to players, so that they
// defer all updates until assembly is finished
level.players().forEach { player ->
PacketStopChunkUpdates(chunkPosesJOML).sendToClient(player.playerWrapper)
}

// Use relocateBlock to copy all the blocks into the ship
blocks.forEachChunk { chunkX, chunkY, chunkZ, chunk ->
val sourceChunk = level.getChunk(chunkX, chunkZ)
val destChunk = level.getChunk(chunkX - deltaX, chunkZ - deltaZ)

chunk.forEach { x, y, z ->
val fromPos = BlockPos((sourceChunk.pos.x shl 4) + x, (chunkY shl 4) + y, (sourceChunk.pos.z shl 4) + z)
val toPos = BlockPos((destChunk.pos.x shl 4) + x, (chunkY shl 4) + y, (destChunk.pos.z shl 4) + z)

relocateBlock(sourceChunk, fromPos, destChunk, toPos, false, ship)
}
}

// Use updateBlock to update blocks after copying
blocks.forEachChunk { chunkX, chunkY, chunkZ, chunk ->
val sourceChunk = level.getChunk(chunkX, chunkZ)
val destChunk = level.getChunk(chunkX - deltaX, chunkZ - deltaZ)

chunk.forEach { x, y, z ->
val fromPos = BlockPos((sourceChunk.pos.x shl 4) + x, (chunkY shl 4) + y, (sourceChunk.pos.z shl 4) + z)
val toPos = BlockPos((destChunk.pos.x shl 4) + x, (chunkY shl 4) + y, (destChunk.pos.z shl 4) + z)

updateBlock(destChunk.level, fromPos, toPos, destChunk.getBlockState(toPos))
}
}

// Calculate the position of the block that the player clicked after it has been assembled
val centerInShip = Vector3d(
((shipChunkX shl 4) + (centerBlock.x and 15)).toDouble(),
centerBlock.y.toDouble(),
((shipChunkZ shl 4) + (centerBlock.z and 15)).toDouble()
)

// The ship's position has shifted from the center block since we assembled the ship, compensate for that
val centerBlockPosInWorld = ship.inertiaData.centerOfMassInShip.sub(centerInShip, Vector3d())
.add(ship.transform.positionInWorld)

// Put the ship into the compensated position, so that all the assembled blocks stay in the same place
// TODO: AAAAAAAAA THIS IS HORRIBLE how can the API support this?
(ship as ShipData).transform = (ship.transform as ShipTransformImpl).copy(positionInWorld = centerBlockPosInWorld)

level.server.executeIf(
// This condition will return true if all modified chunks have been both loaded AND
// chunk update packets were sent to players
{ chunkPoses.all(level::isTickingChunk) }
) {
// Once all the chunk updates are sent to players, we can tell them to restart chunk updates
level.players().forEach { player ->
PacketRestartChunkUpdates(chunkPosesJOML).sendToClient(player.playerWrapper)
}
}

return ship
blocks.toList().forEach { blockList.add(it.toBlockPos()) }
return ShipAssembler.assembleToShip(level, blockList, true, 1.0)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import org.valkyrienskies.mod.common.networking.PacketStopChunkUpdates
import org.valkyrienskies.mod.common.playerWrapper
import org.valkyrienskies.mod.common.shipObjectWorld
import org.valkyrienskies.mod.common.util.settings
import org.valkyrienskies.mod.common.util.toBlockPos
import org.valkyrienskies.mod.common.util.toJOML
import org.valkyrienskies.mod.common.util.toJOMLD
import org.valkyrienskies.mod.util.relocateBlock
Expand All @@ -29,113 +30,8 @@ import org.valkyrienskies.mod.util.updateBlock
fun splitShip(centerBlock: BlockPos, blocks: DenseBlockPosSet, level: ServerLevel, originalShip: ServerShip): ServerShip {
if (blocks.isEmpty()) throw IllegalArgumentException()

val ship = level.shipObjectWorld.createNewShipAtBlock(centerBlock.toJOML(), false, 1.0, level.dimensionId)
val blockList: MutableList<BlockPos> = mutableListOf()

val shipChunkX = ship.chunkClaim.xMiddle
val shipChunkZ = ship.chunkClaim.zMiddle

val worldChunkX = centerBlock.x shr 4
val worldChunkZ = centerBlock.z shr 4

val deltaX = worldChunkX - shipChunkX
val deltaZ = worldChunkZ - shipChunkZ

val chunksToBeUpdated = mutableMapOf<ChunkPos, Pair<ChunkPos, ChunkPos>>()
blocks.forEachChunk { x, _, z, _ ->
val sourcePos = ChunkPos(x, z)
val destPos = ChunkPos(x - deltaX, z - deltaZ)
chunksToBeUpdated[sourcePos] = Pair(sourcePos, destPos)
}
val chunkPairs = chunksToBeUpdated.values.toList()
val chunkPoses = chunkPairs.flatMap { it.toList() }
val chunkPosesJOML = chunkPoses.map { it.toJOML() }

// Send a list of all the chunks that we plan on updating to players, so that they
// defer all updates until assembly is finished
level.players().forEach { player ->
PacketStopChunkUpdates(chunkPosesJOML).sendToClient(player.playerWrapper)
}

// Use relocateBlock to copy all the blocks into the ship
blocks.forEachChunk { chunkX, chunkY, chunkZ, chunk ->
val sourceChunk = level.getChunk(chunkX, chunkZ)
val destChunk = level.getChunk(chunkX - deltaX, chunkZ - deltaZ)

chunk.forEach { x, y, z ->
val fromPos = BlockPos((sourceChunk.pos.x shl 4) + x, (chunkY shl 4) + y, (sourceChunk.pos.z shl 4) + z)
val toPos = BlockPos((destChunk.pos.x shl 4) + x, (chunkY shl 4) + y, (destChunk.pos.z shl 4) + z)

relocateBlock(sourceChunk, fromPos, destChunk, toPos, false, ship)
}
}

// Use updateBlock to update blocks after copying
blocks.forEachChunk { chunkX, chunkY, chunkZ, chunk ->
val sourceChunk = level.getChunk(chunkX, chunkZ)
val destChunk = level.getChunk(chunkX - deltaX, chunkZ - deltaZ)

chunk.forEach { x, y, z ->
val fromPos = BlockPos((sourceChunk.pos.x shl 4) + x, (chunkY shl 4) + y, (sourceChunk.pos.z shl 4) + z)
val toPos = BlockPos((destChunk.pos.x shl 4) + x, (chunkY shl 4) + y, (destChunk.pos.z shl 4) + z)

updateBlock(destChunk.level, fromPos, toPos, destChunk.getBlockState(toPos))
}
}

// Calculate the position of the block that the player clicked after it has been assembled
val centerInShip = Vector3d(
((shipChunkX shl 4) + (centerBlock.x and 15)).toDouble(),
centerBlock.y.toDouble(),
((shipChunkZ shl 4) + (centerBlock.z and 15)).toDouble()
)

// The ship's position has shifted from the center block since we assembled the ship, compensate for that
val centerBlockPosInWorld = ship.inertiaData.centerOfMassInShip.sub(centerInShip, Vector3d())
.add(ship.transform.positionInWorld)

// Put the ship into the compensated position, so that all the assembled blocks stay in the same place
// TODO: AAAAAAAAA THIS IS HORRIBLE how can the API support this?
(ship as ShipData).transform = (ship.transform as ShipTransformImpl).copy(positionInWorld = centerBlockPosInWorld)

level.server.executeIf(
// This condition will return true if all modified chunks have been both loaded AND
// chunk update packets were sent to players
{ chunkPoses.all(level::isTickingChunk) }
) {
// Once all the chunk updates are sent to players, we can tell them to restart chunk updates
level.players().forEach { player ->
PacketRestartChunkUpdates(chunkPosesJOML).sendToClient(player.playerWrapper)
}
}

val shipChunkXUpdated = ship.chunkClaim.xMiddle
val shipChunkZUpdated = ship.chunkClaim.zMiddle

val centerPosCentered = centerBlock.toJOMLD().add(0.5, 0.5, 0.5)

val centerInShipUpdated: Vector3dc = Vector3d(
((shipChunkXUpdated shl 4) + (centerBlock.x and 15).toDouble()),
centerBlock.y.toDouble(),
(shipChunkZUpdated shl 4) + (centerBlock.z and 15).toDouble()
)

val scaling = ship.transform.shipToWorldScaling
val offset: Vector3dc =
ship.inertiaData.centerOfMassInShip.sub(centerInShipUpdated, Vector3d())

val posInWorld = originalShip.transform.shipToWorld.transformPosition(centerPosCentered.add(offset, Vector3d()), Vector3d())
val rotInWorld = originalShip.transform.shipToWorldRotation
val velVec = Vector3d(originalShip.velocity)
val omegaVec = Vector3d(originalShip.omega)

val newShipTransform = ShipTransformImpl(posInWorld, ship.inertiaData.centerOfMassInShip, rotInWorld, scaling)

ship.transform = newShipTransform
ship.physicsData.linearVelocity = velVec
ship.physicsData.angularVelocity = omegaVec

val event = VSGameEvents.ShipSplitEvent(originalShip.id, ship.id, blocks)
VSGameEvents.shipSplit.emit(event)

return ship
blocks.toList().forEach { blockList.add(it.toBlockPos()) }
return ShipAssembler.assembleToShip(level, blockList, true, 1.0)
}

0 comments on commit 2a905f1

Please sign in to comment.