Skip to content

Commit

Permalink
Merge pull request #993 from ValkyrienSkies/1.18.x/Splitting-3
Browse files Browse the repository at this point in the history
1.18.x/splitting 3
  • Loading branch information
ThePlasticPotato authored Oct 26, 2024
2 parents cf815ca + 1edb9df commit ed0ef81
Show file tree
Hide file tree
Showing 16 changed files with 469 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,9 @@ object BlockStateInfo {
x, y, z, level.dimensionId, prevBlockType, newBlockType, prevBlockMass,
newBlockMass
)

if (ValkyrienSkiesMod.vsCore.hooks.enableConnectivity) {
ValkyrienSkiesMod.splitHandler.split(level, x, y, z, prevBlockState, newBlockState)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import org.valkyrienskies.mod.common.entity.ShipMountingEntity
import org.valkyrienskies.mod.common.entity.VSPhysicsEntity
import org.valkyrienskies.mod.common.networking.VSGamePackets
import org.valkyrienskies.mod.common.util.GameTickForceApplier
import org.valkyrienskies.mod.common.util.SplitHandler
import org.valkyrienskies.mod.common.util.SplittingDisablerAttachment

object ValkyrienSkiesMod {
const val MOD_ID = "valkyrienskies"
Expand All @@ -24,9 +26,11 @@ object ValkyrienSkiesMod {
lateinit var TEST_FLAP: Block
lateinit var TEST_WING: Block
lateinit var TEST_SPHERE: Block
lateinit var CONNECTION_CHECKER_ITEM: Item
lateinit var SHIP_CREATOR_ITEM: Item
lateinit var SHIP_ASSEMBLER_ITEM: Item
lateinit var SHIP_CREATOR_ITEM_SMALLER: Item
lateinit var AREA_ASSEMBLER_ITEM: Item
lateinit var PHYSICS_ENTITY_CREATOR_ITEM: Item
lateinit var SHIP_MOUNTING_ENTITY_TYPE: EntityType<ShipMountingEntity>
lateinit var PHYSICS_ENTITY_TYPE: EntityType<VSPhysicsEntity>
Expand All @@ -41,6 +45,9 @@ object ValkyrienSkiesMod {
@JvmStatic
val vsCoreClient get() = vsCore as VSCoreClient

@JvmStatic
lateinit var splitHandler: SplitHandler

fun init(core: VSCore) {
this.vsCore = core

Expand All @@ -49,8 +56,12 @@ object ValkyrienSkiesMod {
VSGamePackets.registerHandlers()

core.registerConfigLegacy("vs", VSGameConfig::class.java)

splitHandler = SplitHandler(this.vsCore.hooks.enableBlockEdgeConnectivity, this.vsCore.hooks.enableBlockCornerConnectivity)

VSEvents.ShipLoadEvent.on { event ->
event.ship.setAttachment(GameTickForceApplier())
event.ship.setAttachment(SplittingDisablerAttachment(true))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import org.joml.Vector3i
private val AIR = Blocks.AIR.defaultBlockState()
object AssemblyUtil {

fun setBlock(level: Level, pos: BlockPos, state: BlockState?) {
fun setBlock(level: Level, pos: BlockPos, state: BlockState) {
val chunk = level.getChunk(pos) as LevelChunk
val section = chunk.getSection(chunk.getSectionIndex(pos.y))
val oldState = level.getBlockState(pos)
Expand All @@ -26,13 +26,13 @@ object AssemblyUtil {

fun removeBlock(level: Level, pos: BlockPos) {
level.removeBlockEntity(pos)
setBlock(level, pos, Blocks.AIR.defaultBlockState())
level.getChunk(pos).setBlockState(pos, Blocks.AIR.defaultBlockState(), false)
}

fun copyBlock(level: Level, from: BlockPos?, to: BlockPos) {
fun copyBlock(level: Level, from: BlockPos, to: BlockPos) {
val state = level.getBlockState(from)
val blockentity = level.getBlockEntity(from)
setBlock(level, to, state)
level.getChunk(to).setBlockState(to, state, false)

// Transfer pending schedule-ticks
if (level.blockTicks.hasScheduledTick(from, state.block)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@ import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.level.block.state.BlockState
import org.joml.Vector3d
import org.joml.Vector3dc
import org.joml.Vector3i
import org.joml.Vector3ic
import org.valkyrienskies.core.api.ships.ServerShip
import org.valkyrienskies.core.api.ships.Ship
import org.valkyrienskies.core.api.ships.getAttachment
import org.valkyrienskies.core.impl.game.ShipTeleportDataImpl
import org.valkyrienskies.mod.common.BlockStateInfo.onSetBlock
import org.valkyrienskies.mod.common.dimensionId
import org.valkyrienskies.mod.common.getShipObjectManagingPos
import org.valkyrienskies.mod.common.shipObjectWorld
import org.valkyrienskies.mod.common.util.SplittingDisablerAttachment
import org.valkyrienskies.mod.common.util.toJOMLD
import org.valkyrienskies.mod.util.logger

object ShipAssembler {

Expand All @@ -31,11 +36,11 @@ object ShipAssembler {
}


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

val existingShip = sLevel.getShipObjectManagingPos(blocks.find { !sLevel.getBlockState(it).isAir } ?: throw IllegalArgumentException())
Expand Down Expand Up @@ -66,7 +71,10 @@ object ShipAssembler {
val newShip: Ship = (level as ServerLevel).server.shipObjectWorld
.createNewShipAtBlock(contraptionWorldPos, false, scale, level.dimensionId)

// Stone for safety reasons
if (shouldDisableSplitting) {
level.shipObjectWorld.loadedShips.getById(newShip.id)?.getAttachment<SplittingDisablerAttachment>()?.disableSplitting()

}

val contraptionShipPos = newShip.worldToShip.transformPosition(Vector3d(contraptionWorldPos.x.toDouble(),contraptionWorldPos.y.toDouble(),contraptionWorldPos.z.toDouble()))
val contraptionBlockPos = BlockPos(contraptionShipPos.x.toInt(),contraptionShipPos.y.toInt(),contraptionShipPos.z.toInt())
Expand All @@ -79,14 +87,14 @@ object ShipAssembler {
val relative: BlockPos = itPos.subtract( BlockPos(contraptionOGPos.x(),contraptionOGPos.y(),contraptionOGPos.z()))
val shipPos: BlockPos = contraptionBlockPos.offset(relative)
AssemblyUtil.copyBlock(level, itPos, shipPos)
if (relative == BlockPos.ZERO) centerBlockReplaced = true
if (relative.equals(BlockPos.ZERO)) centerBlockReplaced = true
}
}

// If center block got not replaced, remove the stone block
if (!centerBlockReplaced) {
level.setBlock(contraptionBlockPos, Blocks.AIR.defaultBlockState(), 3)
}
// if (!centerBlockReplaced) {
// level.setBlock(contraptionBlockPos, Blocks.AIR.defaultBlockState(), 3)
// }

// Remove original blocks
if (removeOriginal) {
Expand All @@ -104,9 +112,19 @@ object ShipAssembler {
AssemblyUtil.updateBlock(level,itPos,shipPos,level.getBlockState(shipPos))
}

val spawnWorldPos: Vector3dc = AssemblyUtil.getMiddle(structureCornerMin.toJOMLD(), structureCornerMax.toJOMLD()).add(0.5, 0.5, 0.5)

if (existingShip != null) {
sLevel.server.shipObjectWorld
.teleportShip(newShip as ServerShip, ShipTeleportDataImpl(existingShip.shipToWorld.transformPosition(spawnWorldPos, Vector3d()), existingShip.transform.shipToWorldRotation, existingShip.velocity, existingShip.omega, existingShip.chunkClaimDimension))

sLevel.server.shipObjectWorld
.teleportShip(newShip as ServerShip, ShipTeleportDataImpl(Vector3d(contraptionWorldPos.x.toDouble(),contraptionWorldPos.y.toDouble(),contraptionWorldPos.z.toDouble())))
} else {
sLevel.server.shipObjectWorld
.teleportShip(newShip as ServerShip, ShipTeleportDataImpl(spawnWorldPos))
}
if (shouldDisableSplitting) {
level.shipObjectWorld.loadedShips.getById(newShip.id)?.getAttachment<SplittingDisablerAttachment>()?.enableSplitting()
}

return newShip as ServerShip
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,11 @@ package org.valkyrienskies.mod.common.assembly

import net.minecraft.core.BlockPos
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.level.ChunkPos
import org.joml.Vector3d
import org.valkyrienskies.core.api.ships.ServerShip
import org.valkyrienskies.core.impl.game.ships.ShipData
import org.valkyrienskies.core.impl.game.ships.ShipTransformImpl
import org.valkyrienskies.core.util.datastructures.DenseBlockPosSet
import org.valkyrienskies.mod.common.dimensionId
import org.valkyrienskies.mod.common.executeIf
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.common.vsCore
import org.valkyrienskies.mod.util.relocateBlock
import org.valkyrienskies.mod.util.updateBlock

@Deprecated("Use ShipAssembler.assembleToShip instead")
@Deprecated("Use [ShipAssembler.assembleToShip] instead")
fun createNewShipWithBlocks(
centerBlock: BlockPos, blocks: DenseBlockPosSet, level: ServerLevel
): ServerShip {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,26 @@ import org.valkyrienskies.core.apigame.hooks.PlayState.CLIENT_TITLESCREEN
import org.valkyrienskies.core.apigame.hooks.PlayState.SERVERSIDE
import org.valkyrienskies.mod.common.ValkyrienSkiesMod
import org.valkyrienskies.mod.common.shipObjectWorld
import org.valkyrienskies.mod.common.vsCore

abstract class CommonHooksImpl : CoreHooksOut {

override var enableBlockEdgeConnectivity: Boolean
get() = vsCore.hooks.enableBlockEdgeConnectivity
set(value) {}

override var enableBlockCornerConnectivity: Boolean
get() = vsCore.hooks.enableBlockCornerConnectivity
set(value) {}

override var enableConnectivity: Boolean
get() = vsCore.hooks.enableConnectivity
set(value) {}

override var enableWorldConnectivity: Boolean
get() = vsCore.hooks.enableWorldConnectivity
set(value) {}

override val playState: PlayState
get() {
if (!isPhysicalClient) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.valkyrienskies.mod.common.item

import net.minecraft.Util
import net.minecraft.core.BlockPos
import net.minecraft.core.Vec3i
import net.minecraft.network.chat.TextComponent
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.InteractionResult
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.context.UseOnContext
import net.minecraft.world.level.block.state.BlockState
import org.joml.primitives.AABBi
import org.valkyrienskies.mod.common.assembly.ShipAssembler
import org.valkyrienskies.mod.common.dimensionId
import org.valkyrienskies.mod.common.getShipManagingPos
import org.valkyrienskies.mod.common.getShipObjectManagingPos
import org.valkyrienskies.mod.common.shipObjectWorld
import org.valkyrienskies.mod.common.util.toJOML
import java.util.function.DoubleSupplier

class AreaAssemblerItem(
properties: Properties, private val scale: DoubleSupplier, private val minScaling: DoubleSupplier
) : Item(properties) {

override fun isFoil(stack: ItemStack): Boolean {
return true
}

override fun useOn(ctx: UseOnContext): InteractionResult {
val level = ctx.level as? ServerLevel ?: return super.useOn(ctx)
val blockPos = ctx.clickedPos
val blockState: BlockState = level.getBlockState(blockPos)
val item = ctx.itemInHand

if (item.item !is AreaAssemblerItem) {
return InteractionResult.FAIL
}

if (!level.isClientSide) {
if (!blockState.isAir) {
// Make a ship
val dimensionId = level.dimensionId

if (item.tag != null && item.tag!!.contains("firstPosX")) {
val firstPosX = item.tag!!.getInt("firstPosX")
val firstPosY = item.tag!!.getInt("firstPosY")
val firstPosZ = item.tag!!.getInt("firstPosZ")
if (level.shipObjectWorld.isBlockInShipyard(blockPos.x, blockPos.y, blockPos.z, dimensionId) != level.shipObjectWorld.isBlockInShipyard(firstPosX, firstPosY, firstPosZ, dimensionId)) {
ctx.player?.sendMessage(TextComponent("Cannot assemble between ship and world!"), Util.NIL_UUID)
} else if (level.getShipObjectManagingPos(blockPos) != level.getShipObjectManagingPos(Vec3i(firstPosX, firstPosY, firstPosZ))) {
ctx.player?.sendMessage(TextComponent("Cannot assemble something between two ships!"), Util.NIL_UUID)
} else {
val blockAABB = AABBi(blockPos.toJOML(), Vec3i(firstPosX, firstPosY, firstPosZ).toJOML())
blockAABB.correctBounds()
val blocks = ArrayList<BlockPos>()

for (x in blockAABB.minX..blockAABB.maxX) {
for (y in blockAABB.minY..blockAABB.maxY) {
for (z in blockAABB.minZ..blockAABB.maxZ) {
if (level.getBlockState(BlockPos(x, y, z)).isAir) {
continue
}
blocks.add(BlockPos(x, y, z))
}
}
}
ctx.player?.sendMessage(TextComponent("Assembling (${blockPos.x}, ${blockPos.y}, ${blockPos.z}) to ($firstPosX, $firstPosY, $firstPosZ)!"), Util.NIL_UUID)
ShipAssembler.assembleToShip(level, blocks, true, scale.asDouble)
}
item.tag!!.remove("firstPosX")
item.tag!!.remove("firstPosY")
item.tag!!.remove("firstPosZ")
} else {
item.tag = item.orCreateTag.apply {
putInt("firstPosX", blockPos.x)
putInt("firstPosY", blockPos.y)
putInt("firstPosZ", blockPos.z)
}
ctx.player?.sendMessage(
TextComponent("First block selected: (${blockPos.x}, ${blockPos.y}, ${blockPos.z})"), Util.NIL_UUID)
}
}
}

return super.useOn(ctx)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.valkyrienskies.mod.common.item

import net.minecraft.Util
import net.minecraft.network.chat.TextComponent
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.InteractionResult
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.context.UseOnContext
import net.minecraft.world.level.block.state.BlockState
import org.valkyrienskies.mod.common.dimensionId
import org.valkyrienskies.mod.common.getShipManagingPos
import org.valkyrienskies.mod.common.shipObjectWorld
import java.util.function.DoubleSupplier

class ConnectionCheckerItem(
properties: Properties, private val scale: DoubleSupplier, private val minScaling: DoubleSupplier
) : Item(properties) {

override fun isFoil(stack: ItemStack): Boolean {
return true
}

override fun useOn(ctx: UseOnContext): InteractionResult {
val level = ctx.level as? ServerLevel ?: return super.useOn(ctx)
val blockPos = ctx.clickedPos
val blockState: BlockState = level.getBlockState(blockPos)
val item = ctx.itemInHand

if (item.item !is ConnectionCheckerItem) {
return InteractionResult.FAIL
}

if (!level.isClientSide) {
val parentShip = ctx.level.getShipManagingPos(blockPos)
if (!blockState.isAir) {
// Make a ship
val dimensionId = level.dimensionId

if (parentShip != null) {
if (item.tag != null && item.tag!!.contains("firstPosX")) {
val firstPosX = item.tag!!.getInt("firstPosX")
val firstPosY = item.tag!!.getInt("firstPosY")
val firstPosZ = item.tag!!.getInt("firstPosZ")
val connected = level.shipObjectWorld.isConnectedBySolid(blockPos.x, blockPos.y, blockPos.z, firstPosX, firstPosY, firstPosZ, dimensionId)
ctx.player?.sendMessage(TextComponent("Connected: $connected"), Util.NIL_UUID)
item.tag!!.remove("firstPosX")
item.tag!!.remove("firstPosY")
item.tag!!.remove("firstPosZ")
} else {
item.tag = item.orCreateTag.apply {
putInt("firstPosX", blockPos.x)
putInt("firstPosY", blockPos.y)
putInt("firstPosZ", blockPos.z)
}
ctx.player?.sendMessage(TextComponent("First block selected: (${blockPos.x}, ${blockPos.y}, ${blockPos.z})"), Util.NIL_UUID)
}
}
}
}

return super.useOn(ctx)
}
}
Loading

0 comments on commit ed0ef81

Please sign in to comment.