From d437831a280f170d81d2dda22a41b17bf5ca23b1 Mon Sep 17 00:00:00 2001 From: theplasticpotato Date: Sat, 19 Oct 2024 13:22:57 -0400 Subject: [PATCH 1/9] Initial --- .../mod/common/BlockStateInfoProvider.kt | 21 +++++++++++++++++++ .../mod/common/assembly/AssemblyUtil.kt | 4 ++-- .../mod/common/assembly/ShipAssembler.kt | 2 +- .../mod/common/assembly/ShipAssembly.kt | 17 +-------------- gradle.properties | 2 +- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt index 129d47e3a..dd5384c63 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt @@ -3,6 +3,7 @@ package org.valkyrienskies.mod.common import com.mojang.serialization.Lifecycle import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap import net.minecraft.core.BlockPos +import net.minecraft.core.Direction import net.minecraft.core.MappedRegistry import net.minecraft.core.Registry import net.minecraft.resources.ResourceKey @@ -134,5 +135,25 @@ object BlockStateInfo { x, y, z, level.dimensionId, prevBlockType, newBlockType, prevBlockMass, newBlockMass ) + + if (level is ServerLevel) { + if (!prevBlockState.isAir && newBlockState.isAir){ + val blockNeighbors: HashSet = HashSet() + for (dir in Direction.entries) { + val neighborPos = BlockPos(x, y, z).relative(dir) + val neighborState = level.getBlockState(neighborPos) + if (!neighborState.isAir) { + blockNeighbors.add(neighborPos) + } + } + for (neighborPos in blockNeighbors) { + for (otherNeighborPos in blockNeighbors) { + if (neighborPos != otherNeighborPos) { + + } + } + } + } + } } } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/AssemblyUtil.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/AssemblyUtil.kt index 78199a624..2f3b7e397 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/AssemblyUtil.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/AssemblyUtil.kt @@ -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) @@ -29,7 +29,7 @@ object AssemblyUtil { setBlock(level, pos, Blocks.AIR.defaultBlockState()) } - 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) diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt index 7ee1c79b1..c7af8af27 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt @@ -79,7 +79,7 @@ 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 } } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembly.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembly.kt index b3ea1c640..e297942fc 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembly.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembly.kt @@ -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 { diff --git a/gradle.properties b/gradle.properties index 8f0f19c5d..b2a85647c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ forge_version=1.18.2-40.2.4 create_fabric_version=0.5.1-f-build.1333+mc1.18.2 flywheel_version_fabric=0.6.9-38 createbigcannons_version= 0.5.2-nightly-e815ca4 -vs_core_version=1.1.0+cf7b0d3c5b +vs_core_version=1.1.0+2e644a6fea # 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 From cf815ca370c001e71990658b7d0883e3150ea712 Mon Sep 17 00:00:00 2001 From: StewStrong Date: Thu, 24 Oct 2024 22:12:35 -0700 Subject: [PATCH 2/9] Fixed DenseBlockPosSet.iterator() --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8f0f19c5d..e1e2e5bb4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ forge_version=1.18.2-40.2.4 create_fabric_version=0.5.1-f-build.1333+mc1.18.2 flywheel_version_fabric=0.6.9-38 createbigcannons_version= 0.5.2-nightly-e815ca4 -vs_core_version=1.1.0+cf7b0d3c5b +vs_core_version=1.1.0+bf19ff814e # 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 From 68764a2de7aa820fdda2517845309845be1c2f1b Mon Sep 17 00:00:00 2001 From: theplasticpotato Date: Fri, 25 Oct 2024 14:30:34 -0400 Subject: [PATCH 3/9] Spliterating --- .../mod/common/BlockStateInfoProvider.kt | 176 ++++++++++++++++-- .../mod/common/ValkyrienSkiesMod.kt | 1 + .../mod/common/item/ConnectionCheckerItem.kt | 64 +++++++ .../assets/valkyrienskies/lang/en_us.json | 1 + .../models/item/connection_checker.json | 6 + .../fabric/common/ValkyrienSkiesModFabric.kt | 10 + .../forge/common/ValkyrienSkiesModForge.kt | 11 ++ gradle.properties | 2 +- 8 files changed, 259 insertions(+), 12 deletions(-) create mode 100644 common/src/main/kotlin/org/valkyrienskies/mod/common/item/ConnectionCheckerItem.kt create mode 100644 common/src/main/resources/assets/valkyrienskies/models/item/connection_checker.json diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt index dd5384c63..471c709de 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt @@ -6,6 +6,7 @@ import net.minecraft.core.BlockPos import net.minecraft.core.Direction import net.minecraft.core.MappedRegistry import net.minecraft.core.Registry +import net.minecraft.core.Vec3i import net.minecraft.resources.ResourceKey import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerLevel @@ -14,10 +15,15 @@ import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.state.BlockState import org.valkyrienskies.core.api.ships.Wing import org.valkyrienskies.core.api.ships.WingManager +import org.valkyrienskies.core.api.world.connectivity.ConnectionStatus.CONNECTED +import org.valkyrienskies.core.api.world.connectivity.ConnectionStatus.DISCONNECTED import org.valkyrienskies.core.apigame.world.chunks.BlockType +import org.valkyrienskies.core.util.expand +import org.valkyrienskies.mod.common.assembly.ShipAssembler import org.valkyrienskies.mod.common.block.WingBlock import org.valkyrienskies.mod.common.config.MassDatapackResolver import org.valkyrienskies.mod.common.hooks.VSGameEvents +import org.valkyrienskies.mod.common.util.toJOML import java.util.function.IntFunction // Other mods can then provide weights and types based on their added content @@ -137,19 +143,167 @@ object BlockStateInfo { ) if (level is ServerLevel) { - if (!prevBlockState.isAir && newBlockState.isAir){ - val blockNeighbors: HashSet = HashSet() - for (dir in Direction.entries) { - val neighborPos = BlockPos(x, y, z).relative(dir) - val neighborState = level.getBlockState(neighborPos) - if (!neighborState.isAir) { - blockNeighbors.add(neighborPos) + val loadedShip = level.getShipObjectManagingPos(x shr 4, z shr 4) + if (loadedShip != null) { + if (!prevBlockState.isAir && newBlockState.isAir){ + val blockNeighbors: HashSet = HashSet() + for (dir in Direction.entries) { + val shipBox = loadedShip.shipAABB?.expand(1) ?: continue + val neighborPos = BlockPos(x, y, z).relative(dir) + val neighborState = level.getBlockState(neighborPos) + if (!neighborState.isAir && neighborPos != BlockPos(x, y, z) && shipBox.containsPoint(neighborPos.toJOML())) { + blockNeighbors.add(neighborPos) + } + if (true) { //later: check block edge connectivity config + for (secondDir in Direction.entries) { + if (dir.axis != secondDir.axis) { + val secondNeighborPos = neighborPos.relative(secondDir) + val secondNeighborState = level.getBlockState(secondNeighborPos) + if (!secondNeighborState.isAir && secondNeighborPos != BlockPos(x, y, z) && shipBox.containsPoint(neighborPos.toJOML())) { + blockNeighbors.add(secondNeighborPos) + } + if (true) { //later: check block corner connectivity config + for (thirdDir in Direction.entries) { + if (dir.axis != secondDir.axis && dir.axis != thirdDir.axis && secondDir.axis != thirdDir.axis) { + val thirdNeighborPos = secondNeighborPos.relative(thirdDir) + val thirdNeighborState = level.getBlockState(thirdNeighborPos) + if (!thirdNeighborState.isAir && thirdNeighborPos != BlockPos(x, y, z) && shipBox.containsPoint(neighborPos.toJOML())) { + blockNeighbors.add(thirdNeighborPos) + } + } + } + } + } + } + } } - } - for (neighborPos in blockNeighbors) { - for (otherNeighborPos in blockNeighbors) { - if (neighborPos != otherNeighborPos) { + if (blockNeighbors.isNotEmpty()) { + //find largest remaining component + var largestComponentNode: BlockPos = blockNeighbors.first() + var largestComponentSize: Long = -1 + + for (neighborPos in blockNeighbors) { + print(level.shipObjectWorld.isIsolatedSolid(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId)) + if (level.shipObjectWorld.isIsolatedSolid(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) == DISCONNECTED) { + val size = level.shipObjectWorld.getSolidComponentSize(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) + if (size > largestComponentSize) { + largestComponentNode = neighborPos + largestComponentSize = size + } + } + } + + if (largestComponentSize == -1L) { + return + } + + blockNeighbors.remove(largestComponentNode) + + // use largest as base + + //find all disconnected components + + val disconnected = HashSet() + for (neighborPos in blockNeighbors) { + if (level.shipObjectWorld.isIsolatedSolid(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) == DISCONNECTED) { + if (neighborPos != largestComponentNode) { + if (level.shipObjectWorld.isConnectedBySolid(largestComponentNode.x, largestComponentNode.y, largestComponentNode.z, neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) == DISCONNECTED) { + val component = HashSet() + disconnected.add(neighborPos) + } + println("this is " + level.shipObjectWorld.isConnectedBySolid(largestComponentNode.x, largestComponentNode.y, largestComponentNode.z, neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId).toString()) + } + } + } + + //check if any disconnected components are connected + val toIgnore: HashSet = HashSet() + for (component in disconnected) { + for (otherComponent in disconnected) { + if (component == otherComponent) { + continue + } + if (level.shipObjectWorld.isConnectedBySolid(component.x, component.y, component.z, otherComponent.x, otherComponent.y, otherComponent.z, level.dimensionId) == CONNECTED) { + if (!toIgnore.contains(otherComponent) && !toIgnore.contains(component)) { + toIgnore.add(component) + } + } + } + } + + disconnected.removeAll(toIgnore) + + if (disconnected.isEmpty()) { + return + } + + //begin the DFSing + + val offsetsToCheck: ArrayList = arrayListOf( + Vec3i(1, 0, 0), + Vec3i(-1, 0, 0), + Vec3i(0, 1, 0), + Vec3i(0, -1, 0), + Vec3i(0, 0, 1), + Vec3i(0, 0, -1) + ) + if (true) { //later: check block edge connectivity config + offsetsToCheck.add(Vec3i(1, 1, 0)) + offsetsToCheck.add(Vec3i(1, -1, 0)) + offsetsToCheck.add(Vec3i(-1, 1, 0)) + offsetsToCheck.add(Vec3i(-1, -1, 0)) + offsetsToCheck.add(Vec3i(1, 0, 1)) + offsetsToCheck.add(Vec3i(1, 0, -1)) + offsetsToCheck.add(Vec3i(-1, 0, 1)) + offsetsToCheck.add(Vec3i(-1, 0, -1)) + offsetsToCheck.add(Vec3i(0, 1, 1)) + offsetsToCheck.add(Vec3i(0, 1, -1)) + offsetsToCheck.add(Vec3i(0, -1, 1)) + offsetsToCheck.add(Vec3i(0, -1, -1)) + } + if (true) { //later: check block corner connectivity config + offsetsToCheck.add(Vec3i(1, 1, 1)) + offsetsToCheck.add(Vec3i(1, 1, -1)) + offsetsToCheck.add(Vec3i(1, -1, 1)) + offsetsToCheck.add(Vec3i(1, -1, -1)) + offsetsToCheck.add(Vec3i(-1, 1, 1)) + offsetsToCheck.add(Vec3i(-1, 1, -1)) + offsetsToCheck.add(Vec3i(-1, -1, 1)) + offsetsToCheck.add(Vec3i(-1, -1, -1)) + } + + val toAssemble = HashSet>() + + for (starter in disconnected) { + val visited = HashSet() + val queuedPositions = HashSet() + queuedPositions.add(starter) + + while (queuedPositions.isNotEmpty()) { + val current = queuedPositions.first() + queuedPositions.remove(current) + visited.add(current) + val toCheck = HashSet() + for (offset in offsetsToCheck) { + toCheck.add(BlockPos(current.x + offset.x, current.y + offset.y, current.z + offset.z)) + } + for (check in toCheck) { + if (!visited.contains(check) && !level.getBlockState(check).isAir) { + queuedPositions.add(check) + } + } + } + //if we have visited all blocks in the component, we can split it + toAssemble.add(visited.toList()) + } + + if (toAssemble.isEmpty()) { + return + } + + for (component in toAssemble) { + ShipAssembler.assembleToShip(level, component, true, 1.0) } } } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt index f5f20b0b7..8adf43287 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt @@ -24,6 +24,7 @@ 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 diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ConnectionCheckerItem.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ConnectionCheckerItem.kt new file mode 100644 index 000000000..db86a4a09 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ConnectionCheckerItem.kt @@ -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) + } +} diff --git a/common/src/main/resources/assets/valkyrienskies/lang/en_us.json b/common/src/main/resources/assets/valkyrienskies/lang/en_us.json index ddd33df22..49a430a42 100644 --- a/common/src/main/resources/assets/valkyrienskies/lang/en_us.json +++ b/common/src/main/resources/assets/valkyrienskies/lang/en_us.json @@ -7,6 +7,7 @@ "block.valkyrienskies.test_flap": "Debug Flap", "block.valkyrienskies.test_wing": "Debug Wing", "item.valkyrienskies.ship_creator": "Ship Creator", + "item.valkyrienskies.connection_checker": "Connection Checker", "item.valkyrienskies.ship_creator_smaller": "Mini Ship Creator", "item.valkyrienskies.physics_entity_creator": "Physics Entity Creator", "argument.valkyrienskies.ship.no_found": "Ship not found", diff --git a/common/src/main/resources/assets/valkyrienskies/models/item/connection_checker.json b/common/src/main/resources/assets/valkyrienskies/models/item/connection_checker.json new file mode 100644 index 000000000..f0dc3b971 --- /dev/null +++ b/common/src/main/resources/assets/valkyrienskies/models/item/connection_checker.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "minecraft:item/stick" + } +} \ No newline at end of file diff --git a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt index 5ae9cea1f..55484159c 100644 --- a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt +++ b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt @@ -42,6 +42,7 @@ import org.valkyrienskies.mod.common.entity.ShipMountingEntity import org.valkyrienskies.mod.common.entity.VSPhysicsEntity import org.valkyrienskies.mod.common.entity.handling.VSEntityManager import org.valkyrienskies.mod.common.hooks.VSGameEvents +import org.valkyrienskies.mod.common.item.ConnectionCheckerItem import org.valkyrienskies.mod.common.item.PhysicsEntityCreatorItem import org.valkyrienskies.mod.common.item.ShipAssemblerItem import org.valkyrienskies.mod.common.item.ShipCreatorItem @@ -63,6 +64,11 @@ class ValkyrienSkiesModFabric : ModInitializer { ValkyrienSkiesMod.TEST_FLAP = TestFlapBlock ValkyrienSkiesMod.TEST_WING = TestWingBlock ValkyrienSkiesMod.TEST_SPHERE = TestSphereBlock + ValkyrienSkiesMod.CONNECTION_CHECKER_ITEM = ConnectionCheckerItem( + Properties().tab(CreativeModeTab.TAB_MISC), + { 1.0 }, + { VSGameConfig.SERVER.minScaling } + ) ValkyrienSkiesMod.SHIP_CREATOR_ITEM = ShipCreatorItem( Properties().tab(CreativeModeTab.TAB_MISC), { 1.0 }, @@ -114,6 +120,10 @@ class ValkyrienSkiesModFabric : ModInitializer { registerBlockAndItem("test_flap", ValkyrienSkiesMod.TEST_FLAP) registerBlockAndItem("test_wing", ValkyrienSkiesMod.TEST_WING) registerBlockAndItem("test_sphere", ValkyrienSkiesMod.TEST_SPHERE) + Registry.register( + Registry.ITEM, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "connection_checker"), + ValkyrienSkiesMod.CONNECTION_CHECKER_ITEM + ) Registry.register( Registry.ITEM, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "ship_assembler"), ValkyrienSkiesMod.SHIP_ASSEMBLER_ITEM diff --git a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt index b72fa2397..601c4dd57 100644 --- a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt +++ b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt @@ -46,6 +46,7 @@ import org.valkyrienskies.mod.common.entity.ShipMountingEntity import org.valkyrienskies.mod.common.entity.VSPhysicsEntity import org.valkyrienskies.mod.common.entity.handling.VSEntityManager import org.valkyrienskies.mod.common.hooks.VSGameEvents +import org.valkyrienskies.mod.common.item.ConnectionCheckerItem import org.valkyrienskies.mod.common.item.PhysicsEntityCreatorItem import org.valkyrienskies.mod.common.item.ShipAssemblerItem import org.valkyrienskies.mod.common.item.ShipCreatorItem @@ -62,6 +63,7 @@ class ValkyrienSkiesModForge { private val TEST_FLAP_REGISTRY: RegistryObject private val TEST_WING_REGISTRY: RegistryObject private val TEST_SPHERE_REGISTRY: RegistryObject + private val CONNECTION_CHECKER_ITEM_REGISTRY: RegistryObject private val SHIP_CREATOR_ITEM_REGISTRY: RegistryObject private val SHIP_CREATOR_SMALLER_ITEM_REGISTRY: RegistryObject private val PHYSICS_ENTITY_CREATOR_ITEM_REGISTRY: RegistryObject @@ -119,6 +121,14 @@ class ValkyrienSkiesModForge { { 1.0 }, { VSGameConfig.SERVER.minScaling }) } + CONNECTION_CHECKER_ITEM_REGISTRY = + ITEMS.register("connection_checker") { + ConnectionCheckerItem( + Properties().tab(CreativeModeTab.TAB_MISC), + { 1.0 }, + { VSGameConfig.SERVER.minScaling } + ) + } SHIP_CREATOR_SMALLER_ITEM_REGISTRY = ITEMS.register("ship_creator_smaller") { ShipCreatorItem( @@ -206,5 +216,6 @@ class ValkyrienSkiesModForge { ValkyrienSkiesMod.PHYSICS_ENTITY_TYPE = PHYSICS_ENTITY_TYPE_REGISTRY.get() ValkyrienSkiesMod.SHIP_ASSEMBLER_ITEM = SHIP_ASSEMBLER_ITEM_REGISTRY.get() ValkyrienSkiesMod.TEST_HINGE_BLOCK_ENTITY_TYPE = TEST_HINGE_BLOCK_ENTITY_TYPE_REGISTRY.get() + ValkyrienSkiesMod.CONNECTION_CHECKER_ITEM = CONNECTION_CHECKER_ITEM_REGISTRY.get() } } diff --git a/gradle.properties b/gradle.properties index b2a85647c..d496f87d5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ forge_version=1.18.2-40.2.4 create_fabric_version=0.5.1-f-build.1333+mc1.18.2 flywheel_version_fabric=0.6.9-38 createbigcannons_version= 0.5.2-nightly-e815ca4 -vs_core_version=1.1.0+2e644a6fea +vs_core_version=1.1.0+9d576c0e71 # 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 From 7c6b8b6561549ebf954402fedbbac86e104a63d7 Mon Sep 17 00:00:00 2001 From: theplasticpotato Date: Fri, 25 Oct 2024 19:54:48 -0400 Subject: [PATCH 4/9] Added area assembler, fixed splitting --- .../mod/common/BlockStateInfoProvider.kt | 176 +---------------- .../mod/common/ValkyrienSkiesMod.kt | 10 + .../mod/common/assembly/AssemblyUtil.kt | 4 +- .../mod/common/assembly/ShipAssembler.kt | 36 +++- .../mod/common/item/AreaAssemblerItem.kt | 88 +++++++++ .../mod/common/item/ConnectionCheckerItem.kt | 2 +- .../mod/common/util/SplitHandler.kt | 181 ++++++++++++++++++ .../util/SplittingDisablerAttachment.kt | 15 ++ .../assets/valkyrienskies/lang/en_us.json | 1 + .../models/item/area_assembler.json | 6 + .../fabric/common/ValkyrienSkiesModFabric.kt | 10 + .../forge/common/ValkyrienSkiesModForge.kt | 11 +- gradle.properties | 2 +- 13 files changed, 355 insertions(+), 187 deletions(-) create mode 100644 common/src/main/kotlin/org/valkyrienskies/mod/common/item/AreaAssemblerItem.kt create mode 100644 common/src/main/kotlin/org/valkyrienskies/mod/common/util/SplitHandler.kt create mode 100644 common/src/main/kotlin/org/valkyrienskies/mod/common/util/SplittingDisablerAttachment.kt create mode 100644 common/src/main/resources/assets/valkyrienskies/models/item/area_assembler.json diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt index 471c709de..c88be2f65 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt @@ -3,10 +3,8 @@ package org.valkyrienskies.mod.common import com.mojang.serialization.Lifecycle import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap import net.minecraft.core.BlockPos -import net.minecraft.core.Direction import net.minecraft.core.MappedRegistry import net.minecraft.core.Registry -import net.minecraft.core.Vec3i import net.minecraft.resources.ResourceKey import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerLevel @@ -15,15 +13,10 @@ import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.state.BlockState import org.valkyrienskies.core.api.ships.Wing import org.valkyrienskies.core.api.ships.WingManager -import org.valkyrienskies.core.api.world.connectivity.ConnectionStatus.CONNECTED -import org.valkyrienskies.core.api.world.connectivity.ConnectionStatus.DISCONNECTED import org.valkyrienskies.core.apigame.world.chunks.BlockType -import org.valkyrienskies.core.util.expand -import org.valkyrienskies.mod.common.assembly.ShipAssembler import org.valkyrienskies.mod.common.block.WingBlock import org.valkyrienskies.mod.common.config.MassDatapackResolver import org.valkyrienskies.mod.common.hooks.VSGameEvents -import org.valkyrienskies.mod.common.util.toJOML import java.util.function.IntFunction // Other mods can then provide weights and types based on their added content @@ -142,172 +135,9 @@ object BlockStateInfo { newBlockMass ) - if (level is ServerLevel) { - val loadedShip = level.getShipObjectManagingPos(x shr 4, z shr 4) - if (loadedShip != null) { - if (!prevBlockState.isAir && newBlockState.isAir){ - val blockNeighbors: HashSet = HashSet() - for (dir in Direction.entries) { - val shipBox = loadedShip.shipAABB?.expand(1) ?: continue - val neighborPos = BlockPos(x, y, z).relative(dir) - val neighborState = level.getBlockState(neighborPos) - if (!neighborState.isAir && neighborPos != BlockPos(x, y, z) && shipBox.containsPoint(neighborPos.toJOML())) { - blockNeighbors.add(neighborPos) - } - if (true) { //later: check block edge connectivity config - for (secondDir in Direction.entries) { - if (dir.axis != secondDir.axis) { - val secondNeighborPos = neighborPos.relative(secondDir) - val secondNeighborState = level.getBlockState(secondNeighborPos) - if (!secondNeighborState.isAir && secondNeighborPos != BlockPos(x, y, z) && shipBox.containsPoint(neighborPos.toJOML())) { - blockNeighbors.add(secondNeighborPos) - } - if (true) { //later: check block corner connectivity config - for (thirdDir in Direction.entries) { - if (dir.axis != secondDir.axis && dir.axis != thirdDir.axis && secondDir.axis != thirdDir.axis) { - val thirdNeighborPos = secondNeighborPos.relative(thirdDir) - val thirdNeighborState = level.getBlockState(thirdNeighborPos) - if (!thirdNeighborState.isAir && thirdNeighborPos != BlockPos(x, y, z) && shipBox.containsPoint(neighborPos.toJOML())) { - blockNeighbors.add(thirdNeighborPos) - } - } - } - } - } - } - } - } - - if (blockNeighbors.isNotEmpty()) { - //find largest remaining component - var largestComponentNode: BlockPos = blockNeighbors.first() - var largestComponentSize: Long = -1 - - for (neighborPos in blockNeighbors) { - print(level.shipObjectWorld.isIsolatedSolid(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId)) - if (level.shipObjectWorld.isIsolatedSolid(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) == DISCONNECTED) { - val size = level.shipObjectWorld.getSolidComponentSize(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) - if (size > largestComponentSize) { - largestComponentNode = neighborPos - largestComponentSize = size - } - } - } - - if (largestComponentSize == -1L) { - return - } - - blockNeighbors.remove(largestComponentNode) - - // use largest as base - - //find all disconnected components - - val disconnected = HashSet() - for (neighborPos in blockNeighbors) { - if (level.shipObjectWorld.isIsolatedSolid(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) == DISCONNECTED) { - if (neighborPos != largestComponentNode) { - if (level.shipObjectWorld.isConnectedBySolid(largestComponentNode.x, largestComponentNode.y, largestComponentNode.z, neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) == DISCONNECTED) { - val component = HashSet() - disconnected.add(neighborPos) - } - println("this is " + level.shipObjectWorld.isConnectedBySolid(largestComponentNode.x, largestComponentNode.y, largestComponentNode.z, neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId).toString()) - } - } - } - - //check if any disconnected components are connected - val toIgnore: HashSet = HashSet() - for (component in disconnected) { - for (otherComponent in disconnected) { - if (component == otherComponent) { - continue - } - if (level.shipObjectWorld.isConnectedBySolid(component.x, component.y, component.z, otherComponent.x, otherComponent.y, otherComponent.z, level.dimensionId) == CONNECTED) { - if (!toIgnore.contains(otherComponent) && !toIgnore.contains(component)) { - toIgnore.add(component) - } - } - } - } - - disconnected.removeAll(toIgnore) - - if (disconnected.isEmpty()) { - return - } - - //begin the DFSing - - val offsetsToCheck: ArrayList = arrayListOf( - Vec3i(1, 0, 0), - Vec3i(-1, 0, 0), - Vec3i(0, 1, 0), - Vec3i(0, -1, 0), - Vec3i(0, 0, 1), - Vec3i(0, 0, -1) - ) - if (true) { //later: check block edge connectivity config - offsetsToCheck.add(Vec3i(1, 1, 0)) - offsetsToCheck.add(Vec3i(1, -1, 0)) - offsetsToCheck.add(Vec3i(-1, 1, 0)) - offsetsToCheck.add(Vec3i(-1, -1, 0)) - offsetsToCheck.add(Vec3i(1, 0, 1)) - offsetsToCheck.add(Vec3i(1, 0, -1)) - offsetsToCheck.add(Vec3i(-1, 0, 1)) - offsetsToCheck.add(Vec3i(-1, 0, -1)) - offsetsToCheck.add(Vec3i(0, 1, 1)) - offsetsToCheck.add(Vec3i(0, 1, -1)) - offsetsToCheck.add(Vec3i(0, -1, 1)) - offsetsToCheck.add(Vec3i(0, -1, -1)) - } - if (true) { //later: check block corner connectivity config - offsetsToCheck.add(Vec3i(1, 1, 1)) - offsetsToCheck.add(Vec3i(1, 1, -1)) - offsetsToCheck.add(Vec3i(1, -1, 1)) - offsetsToCheck.add(Vec3i(1, -1, -1)) - offsetsToCheck.add(Vec3i(-1, 1, 1)) - offsetsToCheck.add(Vec3i(-1, 1, -1)) - offsetsToCheck.add(Vec3i(-1, -1, 1)) - offsetsToCheck.add(Vec3i(-1, -1, -1)) - } - - val toAssemble = HashSet>() - - for (starter in disconnected) { - val visited = HashSet() - val queuedPositions = HashSet() - queuedPositions.add(starter) - - while (queuedPositions.isNotEmpty()) { - val current = queuedPositions.first() - queuedPositions.remove(current) - visited.add(current) - val toCheck = HashSet() - for (offset in offsetsToCheck) { - toCheck.add(BlockPos(current.x + offset.x, current.y + offset.y, current.z + offset.z)) - } - for (check in toCheck) { - if (!visited.contains(check) && !level.getBlockState(check).isAir) { - queuedPositions.add(check) - } - } - } - //if we have visited all blocks in the component, we can split it - toAssemble.add(visited.toList()) - } - - if (toAssemble.isEmpty()) { - return - } - - for (component in toAssemble) { - ShipAssembler.assembleToShip(level, component, true, 1.0) - } - } - } - } + // todo check if splitting is enabled, dolt + if (true) { + ValkyrienSkiesMod.splitHandler.split(level, x, y, z, prevBlockState, newBlockState) } } } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt index 8adf43287..312af3a0d 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt @@ -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" @@ -28,6 +30,7 @@ object ValkyrienSkiesMod { 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 lateinit var PHYSICS_ENTITY_TYPE: EntityType @@ -42,6 +45,9 @@ object ValkyrienSkiesMod { @JvmStatic val vsCoreClient get() = vsCore as VSCoreClient + @JvmStatic + lateinit var splitHandler: SplitHandler + fun init(core: VSCore) { this.vsCore = core @@ -50,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)) } } } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/AssemblyUtil.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/AssemblyUtil.kt index 2f3b7e397..326c333ea 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/AssemblyUtil.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/AssemblyUtil.kt @@ -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) { 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)) { diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt index c7af8af27..31f00fd00 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt @@ -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 { @@ -31,11 +36,11 @@ object ShipAssembler { } - fun assembleToShip(level: Level, blocks: List, removeOriginal: Boolean, scale: Double): ServerShip { - assert(level is ServerLevel) { "Can't manage contraptions on client side!" } + fun assembleToShip(level: Level, blocks: List, 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()) @@ -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()?.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()) @@ -84,9 +92,9 @@ object ShipAssembler { } // 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) { @@ -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()?.enableSplitting() + } return newShip as ServerShip } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/item/AreaAssemblerItem.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/AreaAssemblerItem.kt new file mode 100644 index 000000000..51c64bdc4 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/AreaAssemblerItem.kt @@ -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() + + 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) + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ConnectionCheckerItem.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ConnectionCheckerItem.kt index db86a4a09..4c141aa5d 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ConnectionCheckerItem.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ConnectionCheckerItem.kt @@ -53,7 +53,7 @@ class ConnectionCheckerItem( putInt("firstPosY", blockPos.y) putInt("firstPosZ", blockPos.z) } - ctx.player?.sendMessage(TextComponent("First block selected: (${blockPos.x}, ${blockPos.y}, ${blockPos.z}"), Util.NIL_UUID) + ctx.player?.sendMessage(TextComponent("First block selected: (${blockPos.x}, ${blockPos.y}, ${blockPos.z})"), Util.NIL_UUID) } } } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/SplitHandler.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/SplitHandler.kt new file mode 100644 index 000000000..48f34c8ee --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/SplitHandler.kt @@ -0,0 +1,181 @@ +package org.valkyrienskies.mod.common.util + +import net.minecraft.core.BlockPos +import net.minecraft.core.Vec3i +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.state.BlockState +import org.joml.primitives.AABBi +import org.valkyrienskies.core.api.ships.getAttachment +import org.valkyrienskies.core.api.world.connectivity.ConnectionStatus.CONNECTED +import org.valkyrienskies.core.api.world.connectivity.ConnectionStatus.DISCONNECTED +import org.valkyrienskies.core.util.expand +import org.valkyrienskies.mod.common.assembly.ShipAssembler +import org.valkyrienskies.mod.common.dimensionId +import org.valkyrienskies.mod.common.getShipObjectManagingPos +import org.valkyrienskies.mod.common.shipObjectWorld + +class SplitHandler(private val doEdges: Boolean, private val doCorners: Boolean) { + + fun split(level: Level, x: Int, y: Int, z: Int, prevBlockState: BlockState, newBlockState: BlockState) { + if (level is ServerLevel) { + val loadedShip = level.getShipObjectManagingPos(x shr 4, z shr 4) + if (loadedShip != null && loadedShip.getAttachment()?.canSplit() != false) { + if (!prevBlockState.isAir && newBlockState.isAir) { + val blockNeighbors: HashSet = HashSet() + + val shipBox = loadedShip.shipAABB?.expand(1, AABBi()) ?: return + + for (neighborOffset in getOffsets(doEdges, doCorners)) { + val neighborPos = BlockPos(x + neighborOffset.x, y + neighborOffset.y, z + neighborOffset.z) + val neighborState = level.getBlockState(neighborPos) + if (!neighborState.isAir && neighborPos != BlockPos(x, y, z) && shipBox.containsPoint(neighborPos.toJOML())) { + blockNeighbors.add(neighborPos) + } + } + + if (blockNeighbors.isNotEmpty()) { + //find largest remaining component + var largestComponentNode: BlockPos = blockNeighbors.first() + var largestComponentSize: Long = -1 + + for (neighborPos in blockNeighbors) { + if (level.shipObjectWorld.isIsolatedSolid(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) == DISCONNECTED) { + val size = level.shipObjectWorld.getSolidComponentSize(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) + if (size > largestComponentSize) { + largestComponentNode = neighborPos + largestComponentSize = size + } + } + } + + if (largestComponentSize == -1L) { + return + } + + blockNeighbors.remove(largestComponentNode) + + // use largest as base + + //find all disconnected components + + val disconnected = HashSet() + for (neighborPos in blockNeighbors) { + if (level.shipObjectWorld.isIsolatedSolid(neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) == DISCONNECTED) { + if (neighborPos != largestComponentNode) { + if (level.shipObjectWorld.isConnectedBySolid(largestComponentNode.x, largestComponentNode.y, largestComponentNode.z, neighborPos.x, neighborPos.y, neighborPos.z, level.dimensionId) == DISCONNECTED) { + disconnected.add(neighborPos) + } + } + } + } + + //check if any disconnected components are connected + val toIgnore: HashSet = HashSet() + toIgnore.add(BlockPos(x, y, z)) + for (component in disconnected) { + for (otherComponent in disconnected) { + if (component == otherComponent) { + continue + } + if (level.shipObjectWorld.isConnectedBySolid(component.x, component.y, component.z, otherComponent.x, otherComponent.y, otherComponent.z, level.dimensionId) == CONNECTED) { + if (!toIgnore.contains(otherComponent) && !toIgnore.contains(component)) { + toIgnore.add(component) + } + } + } + } + + disconnected.removeAll(toIgnore) + + if (disconnected.isEmpty()) { + return + } else { + loadedShip.getAttachment(SplittingDisablerAttachment::class.java)?.disableSplitting() + } + + //begin the DFSing + + val toAssemble = HashSet>() + + for (starter in disconnected) { + val visited = HashSet() + val queuedPositions = HashSet() + queuedPositions.add(starter) + + while (queuedPositions.isNotEmpty()) { + val current = queuedPositions.first() + queuedPositions.remove(current) + visited.add(current) + val toCheck = HashSet() + for (offset in getOffsets(doEdges, doCorners)) { + toCheck.add( + BlockPos(current.x + offset.x, current.y + offset.y, current.z + offset.z) + ) + } + for (check in toCheck) { + if (!visited.contains(check) && !level.getBlockState(check).isAir) { + queuedPositions.add(check) + } + } + } + //if we have visited all blocks in the component, we can split it + toAssemble.add(visited.toList()) + } + + if (toAssemble.isEmpty()) { + loadedShip.getAttachment(SplittingDisablerAttachment::class.java)?.enableSplitting() + return + } + + for (component in toAssemble) { + ShipAssembler.assembleToShip(level, component, true, 1.0, true) + } + + loadedShip.getAttachment(SplittingDisablerAttachment::class.java)?.enableSplitting() + } + } + } + } + } + + companion object { + val offsetsToCheck: ArrayList = arrayListOf( + Vec3i(1, 0, 0), + Vec3i(-1, 0, 0), + Vec3i(0, 1, 0), + Vec3i(0, -1, 0), + Vec3i(0, 0, 1), + Vec3i(0, 0, -1) + ) + + fun getOffsets(doEdges: Boolean, doCorners: Boolean): ArrayList { + val list = ArrayList(offsetsToCheck) + if (doEdges) { //later: check block edge connectivity config + list.add(Vec3i(1, 1, 0)) + list.add(Vec3i(1, -1, 0)) + list.add(Vec3i(-1, 1, 0)) + list.add(Vec3i(-1, -1, 0)) + list.add(Vec3i(1, 0, 1)) + list.add(Vec3i(1, 0, -1)) + list.add(Vec3i(-1, 0, 1)) + list.add(Vec3i(-1, 0, -1)) + list.add(Vec3i(0, 1, 1)) + list.add(Vec3i(0, 1, -1)) + list.add(Vec3i(0, -1, 1)) + list.add(Vec3i(0, -1, -1)) + } + if (doCorners) { //later: check block corner connectivity config + list.add(Vec3i(1, 1, 1)) + list.add(Vec3i(1, 1, -1)) + list.add(Vec3i(1, -1, 1)) + list.add(Vec3i(1, -1, -1)) + list.add(Vec3i(-1, 1, 1)) + list.add(Vec3i(-1, 1, -1)) + list.add(Vec3i(-1, -1, 1)) + list.add(Vec3i(-1, -1, -1)) + } + return list + } + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/SplittingDisablerAttachment.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/SplittingDisablerAttachment.kt new file mode 100644 index 000000000..42959258a --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/SplittingDisablerAttachment.kt @@ -0,0 +1,15 @@ +package org.valkyrienskies.mod.common.util + +data class SplittingDisablerAttachment(private var splitt: Boolean) { + fun enableSplitting() { + splitt = true + } + + fun disableSplitting() { + splitt = false + } + + fun canSplit(): Boolean { + return splitt + } +} diff --git a/common/src/main/resources/assets/valkyrienskies/lang/en_us.json b/common/src/main/resources/assets/valkyrienskies/lang/en_us.json index 49a430a42..96ccb3af3 100644 --- a/common/src/main/resources/assets/valkyrienskies/lang/en_us.json +++ b/common/src/main/resources/assets/valkyrienskies/lang/en_us.json @@ -7,6 +7,7 @@ "block.valkyrienskies.test_flap": "Debug Flap", "block.valkyrienskies.test_wing": "Debug Wing", "item.valkyrienskies.ship_creator": "Ship Creator", + "item.valkyrienskies.area_assembler": "Area Assembler", "item.valkyrienskies.connection_checker": "Connection Checker", "item.valkyrienskies.ship_creator_smaller": "Mini Ship Creator", "item.valkyrienskies.physics_entity_creator": "Physics Entity Creator", diff --git a/common/src/main/resources/assets/valkyrienskies/models/item/area_assembler.json b/common/src/main/resources/assets/valkyrienskies/models/item/area_assembler.json new file mode 100644 index 000000000..f0dc3b971 --- /dev/null +++ b/common/src/main/resources/assets/valkyrienskies/models/item/area_assembler.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "minecraft:item/stick" + } +} \ No newline at end of file diff --git a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt index 55484159c..cdee8650b 100644 --- a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt +++ b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt @@ -42,6 +42,7 @@ import org.valkyrienskies.mod.common.entity.ShipMountingEntity import org.valkyrienskies.mod.common.entity.VSPhysicsEntity import org.valkyrienskies.mod.common.entity.handling.VSEntityManager import org.valkyrienskies.mod.common.hooks.VSGameEvents +import org.valkyrienskies.mod.common.item.AreaAssemblerItem import org.valkyrienskies.mod.common.item.ConnectionCheckerItem import org.valkyrienskies.mod.common.item.PhysicsEntityCreatorItem import org.valkyrienskies.mod.common.item.ShipAssemblerItem @@ -75,6 +76,11 @@ class ValkyrienSkiesModFabric : ModInitializer { { VSGameConfig.SERVER.minScaling } ) ValkyrienSkiesMod.SHIP_ASSEMBLER_ITEM = ShipAssemblerItem(Properties().tab(CreativeModeTab.TAB_MISC)) + ValkyrienSkiesMod.AREA_ASSEMBLER_ITEM = AreaAssemblerItem( + Properties().tab(CreativeModeTab.TAB_MISC), + { 1.0 }, + { VSGameConfig.SERVER.minScaling } + ) ValkyrienSkiesMod.SHIP_CREATOR_ITEM_SMALLER = ShipCreatorItem( Properties().tab(CreativeModeTab.TAB_MISC), { VSGameConfig.SERVER.miniShipSize }, @@ -124,6 +130,10 @@ class ValkyrienSkiesModFabric : ModInitializer { Registry.ITEM, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "connection_checker"), ValkyrienSkiesMod.CONNECTION_CHECKER_ITEM ) + Registry.register( + Registry.ITEM, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "area_assembler"), + ValkyrienSkiesMod.AREA_ASSEMBLER_ITEM + ) Registry.register( Registry.ITEM, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "ship_assembler"), ValkyrienSkiesMod.SHIP_ASSEMBLER_ITEM diff --git a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt index 601c4dd57..438bfec90 100644 --- a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt +++ b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt @@ -46,6 +46,7 @@ import org.valkyrienskies.mod.common.entity.ShipMountingEntity import org.valkyrienskies.mod.common.entity.VSPhysicsEntity import org.valkyrienskies.mod.common.entity.handling.VSEntityManager import org.valkyrienskies.mod.common.hooks.VSGameEvents +import org.valkyrienskies.mod.common.item.AreaAssemblerItem import org.valkyrienskies.mod.common.item.ConnectionCheckerItem import org.valkyrienskies.mod.common.item.PhysicsEntityCreatorItem import org.valkyrienskies.mod.common.item.ShipAssemblerItem @@ -66,6 +67,7 @@ class ValkyrienSkiesModForge { private val CONNECTION_CHECKER_ITEM_REGISTRY: RegistryObject private val SHIP_CREATOR_ITEM_REGISTRY: RegistryObject private val SHIP_CREATOR_SMALLER_ITEM_REGISTRY: RegistryObject + private val AREA_ASSEMBLER_ITEM_REGISTRY: RegistryObject private val PHYSICS_ENTITY_CREATOR_ITEM_REGISTRY: RegistryObject private val SHIP_MOUNTING_ENTITY_REGISTRY: RegistryObject> private val PHYSICS_ENTITY_TYPE_REGISTRY: RegistryObject> @@ -137,7 +139,13 @@ class ValkyrienSkiesModForge { { VSGameConfig.SERVER.minScaling } ) } - + AREA_ASSEMBLER_ITEM_REGISTRY = ITEMS.register("area_assembler") { + AreaAssemblerItem( + Properties().tab(CreativeModeTab.TAB_MISC), + { 1.0 }, + { VSGameConfig.SERVER.minScaling } + ) + } PHYSICS_ENTITY_CREATOR_ITEM_REGISTRY = ITEMS.register("physics_entity_creator") { PhysicsEntityCreatorItem( @@ -217,5 +225,6 @@ class ValkyrienSkiesModForge { ValkyrienSkiesMod.SHIP_ASSEMBLER_ITEM = SHIP_ASSEMBLER_ITEM_REGISTRY.get() ValkyrienSkiesMod.TEST_HINGE_BLOCK_ENTITY_TYPE = TEST_HINGE_BLOCK_ENTITY_TYPE_REGISTRY.get() ValkyrienSkiesMod.CONNECTION_CHECKER_ITEM = CONNECTION_CHECKER_ITEM_REGISTRY.get() + ValkyrienSkiesMod.AREA_ASSEMBLER_ITEM = AREA_ASSEMBLER_ITEM_REGISTRY.get() } } diff --git a/gradle.properties b/gradle.properties index d496f87d5..0396b7a8c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ forge_version=1.18.2-40.2.4 create_fabric_version=0.5.1-f-build.1333+mc1.18.2 flywheel_version_fabric=0.6.9-38 createbigcannons_version= 0.5.2-nightly-e815ca4 -vs_core_version=1.1.0+9d576c0e71 +vs_core_version=1.1.0+6df41559a1 # 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 From 8450cfc531b7d9797e1cac45856270466dffa337 Mon Sep 17 00:00:00 2001 From: theplasticpotato Date: Fri, 25 Oct 2024 20:28:42 -0400 Subject: [PATCH 5/9] Update VSCore --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0396b7a8c..7c52e1b13 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ forge_version=1.18.2-40.2.4 create_fabric_version=0.5.1-f-build.1333+mc1.18.2 flywheel_version_fabric=0.6.9-38 createbigcannons_version= 0.5.2-nightly-e815ca4 -vs_core_version=1.1.0+6df41559a1 +vs_core_version=1.1.0+13b73ea871 # 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 From 78a95356935170753a800c21fb5bf6ebe61fe915 Mon Sep 17 00:00:00 2001 From: theplasticpotato Date: Fri, 25 Oct 2024 20:37:32 -0400 Subject: [PATCH 6/9] Missed a tiny bit --- .../mod/common/hooks/CommonHooksImpl.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/hooks/CommonHooksImpl.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/hooks/CommonHooksImpl.kt index 980a24c0d..490f306f5 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/hooks/CommonHooksImpl.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/hooks/CommonHooksImpl.kt @@ -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) { From 1edb9df58c028811d00f884d2ccdc20b62d7a386 Mon Sep 17 00:00:00 2001 From: theplasticpotato Date: Fri, 25 Oct 2024 20:40:46 -0400 Subject: [PATCH 7/9] Another quick miss --- .../org/valkyrienskies/mod/common/BlockStateInfoProvider.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt index c88be2f65..9178dfb7a 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt @@ -135,8 +135,7 @@ object BlockStateInfo { newBlockMass ) - // todo check if splitting is enabled, dolt - if (true) { + if (ValkyrienSkiesMod.vsCore.hooks.enableConnectivity) { ValkyrienSkiesMod.splitHandler.split(level, x, y, z, prevBlockState, newBlockState) } } From a0517bae1e11bf69695d92c0230dd139241ba37b Mon Sep 17 00:00:00 2001 From: StewStrong Date: Mon, 28 Oct 2024 01:34:00 -0700 Subject: [PATCH 8/9] Fixed ShipAssembler.assembleToShip() --- .../mixin/server/MixinMinecraftServer.java | 1 + .../mod/common/assembly/ShipAssembler.kt | 28 ++++++++++--------- gradle.properties | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java index c5642f5f3..c3ff37678 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java @@ -305,6 +305,7 @@ private void shipChangeDimension(@NotNull final ServerLevel srcLevel, @NotNull f new Vector3d(), new Vector3d(), VSGameUtilsKt.getDimensionId(destLevel), + null, null ); shipWorld.teleportShip(shipObject, shipTeleportData); diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt index 31f00fd00..6ee1d6579 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembler.kt @@ -3,10 +3,8 @@ package org.valkyrienskies.mod.common.assembly import net.minecraft.core.BlockPos import net.minecraft.server.level.ServerLevel 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 @@ -18,8 +16,6 @@ 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 { @@ -45,20 +41,25 @@ object ShipAssembler { val existingShip = sLevel.getShipObjectManagingPos(blocks.find { !sLevel.getBlockState(it).isAir } ?: throw IllegalArgumentException()) - var structureCornerMin: BlockPos = blocks[0] - var structureCornerMax: BlockPos = blocks[0] + var structureCornerMin: BlockPos? = null + var structureCornerMax: BlockPos? = null var hasSolids = false // Calculate bounds of the area containing all blocks adn check for solids and invalid blocks for (itPos in blocks) { if (isValidShipBlock(level.getBlockState(itPos))) { - structureCornerMin = AssemblyUtil.getMinCorner(structureCornerMin, itPos) - structureCornerMax = AssemblyUtil.getMaxCorner(structureCornerMax, itPos) + if (structureCornerMin == null) { + structureCornerMin = itPos + structureCornerMax = itPos + } else { + structureCornerMin = AssemblyUtil.getMinCorner(structureCornerMin!!, itPos) + structureCornerMax = AssemblyUtil.getMaxCorner(structureCornerMax!!, itPos) + } hasSolids = true } } if (!hasSolids) throw IllegalArgumentException("No solid blocks found in the structure") - val contraptionOGPos: Vector3ic = AssemblyUtil.getMiddle(structureCornerMin, structureCornerMax) + val contraptionOGPos: Vector3ic = AssemblyUtil.getMiddle(structureCornerMin!!, structureCornerMax!!) // Create new contraption at center of bounds val contraptionWorldPos: Vector3i = if (existingShip != null) { val doubleVer = existingShip.shipToWorld.transformPosition(Vector3d(contraptionOGPos)).floor() @@ -112,15 +113,16 @@ 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) - + val shipCenterPos = ((newShip as ServerShip).inertiaData.centerOfMassInShip).add(0.5, 0.5, 0.5, Vector3d()) + // This is giga sus, but whatever + val shipPos = Vector3d(contraptionOGPos).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)) + .teleportShip(newShip as ServerShip, ShipTeleportDataImpl(existingShip.shipToWorld.transformPosition(shipPos, Vector3d()), existingShip.transform.shipToWorldRotation, existingShip.velocity, existingShip.omega, existingShip.chunkClaimDimension, newScale = existingShip.transform.shipToWorldScaling.x(), newPosInShip = shipCenterPos)) } else { sLevel.server.shipObjectWorld - .teleportShip(newShip as ServerShip, ShipTeleportDataImpl(spawnWorldPos)) + .teleportShip(newShip as ServerShip, ShipTeleportDataImpl(newPos = shipPos, newPosInShip = shipCenterPos)) } if (shouldDisableSplitting) { level.shipObjectWorld.loadedShips.getById(newShip.id)?.getAttachment()?.enableSplitting() diff --git a/gradle.properties b/gradle.properties index 7c52e1b13..868595b10 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ forge_version=1.18.2-40.2.4 create_fabric_version=0.5.1-f-build.1333+mc1.18.2 flywheel_version_fabric=0.6.9-38 createbigcannons_version= 0.5.2-nightly-e815ca4 -vs_core_version=1.1.0+13b73ea871 +vs_core_version=1.1.0+2a62e6a823 # 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 From cf1ea8631c237f79702b5ddd63a0de91ced6753c Mon Sep 17 00:00:00 2001 From: StewStrong Date: Mon, 28 Oct 2024 01:54:31 -0700 Subject: [PATCH 9/9] Fix create forge not working --- .../mixin/compat/create/client/MixinTrackBlockOutline.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinTrackBlockOutline.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinTrackBlockOutline.java index 599b00336..362177c3b 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinTrackBlockOutline.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinTrackBlockOutline.java @@ -28,7 +28,7 @@ import org.valkyrienskies.mod.common.VSGameUtilsKt; import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; -@Mixin(value = TrackBlockOutline.class, remap = false) +@Mixin(value = TrackBlockOutline.class) public class MixinTrackBlockOutline { @Unique private static Vec3 valkyrienskies$cameraVec3; @@ -37,7 +37,7 @@ public class MixinTrackBlockOutline { @Unique private static Vec3 valkyrienskies$angles; - @Inject(method = "drawCurveSelection", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/trains/track/TrackBlockOutline$BezierPointSelection;angles()Lnet/minecraft/world/phys/Vec3;"), locals = LocalCapture.CAPTURE_FAILHARD) + @Inject(method = "drawCurveSelection", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/trains/track/TrackBlockOutline$BezierPointSelection;angles()Lnet/minecraft/world/phys/Vec3;"), locals = LocalCapture.CAPTURE_FAILHARD, remap = false) private static void harvestDrawCurveSelection(final PoseStack ms, final MultiBufferSource buffer, final Vec3 camera, final CallbackInfo ci, final Minecraft mc, final BezierPointSelection result, final VertexConsumer vb, final Vec3 vec) { @@ -48,7 +48,8 @@ private static void harvestDrawCurveSelection(final PoseStack ms, final MultiBuf @ModifyArg(method = "drawCurveSelection", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/trains/track/TrackBlockOutline;renderShape(Lnet/minecraft/world/phys/shapes/VoxelShape;Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;Ljava/lang/Boolean;)V"), - index = 1) + index = 1, + remap = false) private static PoseStack redirectTransformStackTranslate(final PoseStack ms) { final Level level = Minecraft.getInstance().level;