Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Splitting to 1.20.1 #731

Open
wants to merge 2 commits into
base: 1.20.1/main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.valkyrienskies.mod.mixin.mod_compat.create.accessors;

import com.simibubi.create.content.logistics.chute.ChuteBlockEntity;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;

@Mixin(ChuteBlockEntity.class)
public interface ChuteBlockEntityAccessor {
@Accessor("bottomPullDistance")
float getBottomPullDistance();

@Invoker
boolean callCanAcceptItem(ItemStack item);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.valkyrienskies.mod.mixin.mod_compat.create.blockentity;

import com.simibubi.create.content.logistics.chute.ChuteBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.joml.Vector3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.At.Shift;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import org.valkyrienskies.core.api.ships.ServerShip;
import org.valkyrienskies.mod.common.VSGameUtilsKt;
import org.valkyrienskies.mod.mixin.mod_compat.create.accessors.ChuteBlockEntityAccessor;

@Mixin(ChuteBlockEntity.class)
public class MixinChuteBlockEntity {
@Inject(method = "findEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/AABB;<init>(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;)V", shift = Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, remap = false)
private void preFindEntities(float itemSpeed, CallbackInfo ci, Vec3 center) {
if (((ChuteBlockEntity) (Object) this).getLevel() != null) {

final ChuteBlockEntity be = (ChuteBlockEntity) (Object) this;
final ChuteBlockEntityAccessor bea = (ChuteBlockEntityAccessor) be;
Level level = ((ChuteBlockEntity) (Object) this).getLevel();

BlockPos pos = be.getBlockPos();

AABB searchArea = new AABB(center.add(0, -bea.getBottomPullDistance() - 0.5, 0), center.add(0, -0.5, 0)).inflate(.45f);

if (VSGameUtilsKt.getShipObjectManagingPos(level, pos) instanceof ServerShip ship) {
Vector3d searchAreaMin = new Vector3d(searchArea.minX, searchArea.minY, searchArea.minZ);
Vector3d searchAreaMax = new Vector3d(searchArea.maxX, searchArea.maxY, searchArea.maxZ);

Vector3d searchAreaReturnMin = new Vector3d();
Vector3d searchAreaReturnMax = new Vector3d();

ship.getTransform().getShipToWorld().transformAab(searchAreaMin, searchAreaMax, searchAreaReturnMin, searchAreaReturnMax);

searchArea = new AABB(searchAreaReturnMin.x, searchAreaReturnMin.y, searchAreaReturnMin.z, searchAreaReturnMax.x, searchAreaReturnMax.y, searchAreaReturnMax.z);

for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, searchArea)) {
if (!itemEntity.isAlive())
continue;
ItemStack entityItem = itemEntity.getItem();
if (!bea.callCanAcceptItem(entityItem))
continue;
be.setItem(entityItem.copy(), (float) (itemEntity.getBoundingBox()
.getCenter().y - be.getBlockPos().getY()));
itemEntity.discard();
break;
}
ci.cancel();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -40,10 +41,13 @@
import org.valkyrienskies.core.api.ships.LoadedServerShip;
import org.valkyrienskies.core.api.ships.Wing;
import org.valkyrienskies.core.api.ships.WingManager;
import org.valkyrienskies.core.api.ships.datastructures.ShipConnDataAttachment;
import org.valkyrienskies.core.apigame.world.ServerShipWorldCore;
import org.valkyrienskies.core.apigame.world.chunks.TerrainUpdate;
import org.valkyrienskies.core.util.datastructures.Breakage;
import org.valkyrienskies.mod.common.IShipObjectWorldServerProvider;
import org.valkyrienskies.mod.common.VSGameUtilsKt;
import org.valkyrienskies.mod.common.assembly.SubShipAssemblyKt;
import org.valkyrienskies.mod.common.block.WingBlock;
import org.valkyrienskies.mod.common.util.VSServerLevel;
import org.valkyrienskies.mod.common.util.VectorConversionsMCKt;
Expand Down Expand Up @@ -231,6 +235,24 @@ private void postTick(final BooleanSupplier shouldKeepTicking, final CallbackInf
VSGameUtilsKt.getDimensionId(self),
voxelShapeUpdates
);

// Process pending ship breakages
for (final LoadedServerShip loadedShip : shipObjectWorld.getLoadedShips()) {
if (loadedShip.getAttachment(ShipConnDataAttachment.class) instanceof ShipConnDataAttachment) {
ShipConnDataAttachment connData = loadedShip.getAttachment(ShipConnDataAttachment.class);
assert connData != null;
HashSet<Object> shipBreakages = (HashSet<Object>) connData.getBreakages();
Iterator<Object> breakageIterator = shipBreakages.iterator();

while (breakageIterator.hasNext()) {
Object breakage = breakageIterator.next();
if (breakage instanceof Breakage breaking) {
SubShipAssemblyKt.splitShip(VectorConversionsMCKt.toBlockPos(breaking.component1()), breaking.component2(), self, loadedShip);
breakageIterator.remove();
}
}
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ object DefaultBlockStateInfoProvider : BlockStateInfoProvider {
val block = blockState.block
if (block is LiquidBlock)
return if (block == Blocks.LAVA) vsCore.blockTypes.lava else vsCore.blockTypes.water
return if (blockState.isSolid) vsCore.blockTypes.solid else vsCore.blockTypes.air
return if (blockState.isSolid) vsCore.blockTypes.solid else vsCore.blockTypes.noCollision
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
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.joml.Vector3dc
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.impl.networking.simple.sendToClient
import org.valkyrienskies.core.util.datastructures.DenseBlockPosSet
import org.valkyrienskies.core.util.x
import org.valkyrienskies.mod.common.dimensionId
import org.valkyrienskies.mod.common.executeIf
import org.valkyrienskies.mod.common.hooks.VSGameEvents
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.settings
import org.valkyrienskies.mod.common.util.toJOML
import org.valkyrienskies.mod.common.util.toJOMLD
import org.valkyrienskies.mod.util.relocateBlock
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 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
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import net.minecraft.client.renderer.LevelRenderer.RenderChunkInfo
import net.minecraft.client.renderer.RenderType
import org.joml.Matrix4f
import org.valkyrienskies.core.api.ships.ClientShip
import org.valkyrienskies.core.api.ships.properties.ShipId
import org.valkyrienskies.core.impl.util.events.EventEmitterImpl
import org.valkyrienskies.core.util.datastructures.DenseBlockPosSet

object VSGameEvents {

Expand All @@ -18,6 +20,8 @@ object VSGameEvents {
val postRenderShip = EventEmitterImpl<ShipRenderEvent>()
val shipsStartRendering = EventEmitterImpl<ShipStartRenderEvent>()

val shipSplit = EventEmitterImpl<ShipSplitEvent>()

data class ShipStartRenderEvent(
val renderer: LevelRenderer,
val renderType: RenderType,
Expand All @@ -35,5 +39,11 @@ object VSGameEvents {
val ship: ClientShip,
val chunks: ObjectList<RenderChunkInfo>
)

data class ShipSplitEvent(
val ship: ShipId,
val newShip: ShipId,
val blocks: DenseBlockPosSet
)
}

2 changes: 2 additions & 0 deletions common/src/main/resources/valkyrienskies-common.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"mod_compat.create.MixinEntityLauncher",
"mod_compat.create.MixinRedstoneLinkNetworkHandler",
"mod_compat.create.MixinSharedDepotBlockMethods",
"mod_compat.create.accessors.ChuteBlockEntityAccessor",
"mod_compat.create.accessors.Matrix3dAccessor",
"mod_compat.create.accessors.OutlineParamsAccessor",
"mod_compat.create.behaviour.MixinBlockBreakingMovementBehaviour",
Expand All @@ -73,6 +74,7 @@
"mod_compat.create.block.MixinRedstoneContactBlock",
"mod_compat.create.block.MixinStickerBlock",
"mod_compat.create.blockentity.IMixinMechanicalBearingTileEntity",
"mod_compat.create.blockentity.MixinChuteBlockEntity",
"mod_compat.create.blockentity.MixinCrushingWheelControllerTileEntity",
"mod_compat.create.blockentity.MixinEjectorTileEntity",
"mod_compat.create.blockentity.MixinEncasedFanTileEntity",
Expand Down
2 changes: 1 addition & 1 deletion forge/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ loader_platform=Forge
loom.platform=forge
kotlin.stdlib.default.dependency=false
#Deps
kotlin_version = 3.12.0
kotlin_version = 4.3.0
cloth_config_version = 11.1.106

#Compat
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ flywheel_version_fabric=0.6.9-6
# https://modrinth.com/mod/create-big-cannons/versions
createbigcannons_version= 0.5.2.a

vs_core_version=1.1.0+b19b27c4a4
vs_core_version=1.1.0+7dbd2ee63a
# Prevent kotlin from autoincluding stdlib as a dependency, which breaks
# gradle's composite builds (includeBuild) for some reason. We'll add it manually
kotlin.stdlib.default.dependency=false
Expand Down
Loading