make it work a bit better in multiplayer

still needs work but at least the essential stuff works
This commit is contained in:
りき萌 2023-05-03 19:49:31 +02:00
parent 849f12d907
commit c72730f1a2
9 changed files with 120 additions and 36 deletions

View file

@ -1,5 +1,7 @@
package net.liquidev.dawd3.mixin;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.liquidev.dawd3.events.DebugHudEvents;
import net.minecraft.client.gui.hud.DebugHud;
import org.spongepowered.asm.mixin.Mixin;
@ -9,6 +11,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
@Environment(EnvType.CLIENT)
@Mixin(DebugHud.class)
public class DebugHudMixin {
@Inject(at = @At("RETURN"), method = "getLeftText")

View file

@ -1,5 +1,7 @@
package net.liquidev.dawd3.mixin;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.liquidev.dawd3.events.D3ClientEvents;
import net.minecraft.client.MinecraftClient;
import org.objectweb.asm.Opcodes;
@ -8,6 +10,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Environment(EnvType.CLIENT)
@Mixin(MinecraftClient.class)
public class PauseMixin {
@Inject(

View file

@ -1,7 +1,10 @@
package net.liquidev.dawd3.block.device
import net.fabricmc.fabric.api.networking.v1.PlayerLookup
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
import net.liquidev.dawd3.common.*
import net.liquidev.dawd3.item.PatchCableItem
import net.liquidev.dawd3.net.DisconnectPort
import net.liquidev.dawd3.ui.Rack
import net.minecraft.block.*
import net.minecraft.block.entity.BlockEntity
@ -110,6 +113,21 @@ class DeviceBlock(private val descriptor: AnyDeviceBlockDescriptor) :
}
if (usedPortName != null && player.isSneaking) {
return if (blockEntity.severConnectionsInPort(usedPortName)) {
if (!world.isClient) {
val witnesses = PlayerLookup.tracking(blockEntity)
for (witness in witnesses) {
if (witness != player) {
ServerPlayNetworking.send(
witness,
DisconnectPort.id,
DisconnectPort(
pos,
usedPortName.id
).serialize()
)
}
}
}
ActionResult.success(world.isClient)
} else {
ActionResult.PASS

View file

@ -185,11 +185,14 @@ class DeviceBlockEntity(
val world = world ?: return false
val clientState = clientState
val severedConnections = if (clientState != null) {
var severedAnyConnections = false
severedAnyConnections = severedAnyConnections or if (clientState != null) {
val resolvedPortName =
if (portName is OutputPortName) portName.resolveInstance() else portName
Devices.severAllConnectionsInPort(clientState.logicalDevice, resolvedPortName)
} else 0
Devices.severAllConnectionsInPort(clientState.logicalDevice, resolvedPortName) > 0
} else {
false
}
when (portName) {
is InputPortName -> {
@ -199,6 +202,7 @@ class DeviceBlockEntity(
if (blockEntity is DeviceBlockEntity) {
blockEntity.outputConnections.remove(inputConnection.outputPortName)
}
severedAnyConnections = true
}
}
is OutputPortName -> {
@ -208,10 +212,11 @@ class DeviceBlockEntity(
if (blockEntity is DeviceBlockEntity) {
blockEntity.inputConnections.values.removeAll { it.outputPortName == portName }
}
severedAnyConnections = true
}
}
}
return severedConnections != 0
return severedAnyConnections
}
companion object {

View file

@ -109,7 +109,7 @@ class DeviceBlockEntityRenderer(context: BlockEntityRendererFactory.Context) : B
matrixStack.push()
rotateToFaceFront(blockState, matrixStack)
for ((_, connection) in PatchCableItem.ongoingConnectionsServer) {
for ((_, connection) in PatchCableItem.ongoingConnectionsClient) {
if (connection.blockPosition == blockEntity.pos) {
val port = blockEntity.descriptor.portLayout[connection.portName]
if (port != null) {

View file

@ -21,14 +21,16 @@ class PatchCableItem(settings: Settings, val color: Byte) : BasicItem(settings)
override fun useOnBlock(context: ItemUsageContext): ActionResult {
if (context.player?.isSneaking != true) {
val blockEntity = context.world.getBlockEntity(context.blockPos)
if (!context.world.isClient && blockEntity is DeviceBlockEntity) {
if (blockEntity is DeviceBlockEntity) {
val portName =
DeviceBlockInteractions.findUsedPort(context.hitResult, blockEntity.descriptor)
if (portName != null) {
useOnPort(context, portName)
}
return ActionResult.success(context.world.isClient)
} else {
return ActionResult.PASS
}
return ActionResult.success(context.world.isClient)
} else {
return context.world.getBlockState(context.blockPos)
.onUse(context.world, context.player, context.hand, context.hitResult)
@ -36,41 +38,46 @@ class PatchCableItem(settings: Settings, val color: Byte) : BasicItem(settings)
}
private fun useOnPort(context: ItemUsageContext, portName: PortName) {
val player = context.player
if (player == null || player !is ServerPlayerEntity) {
return
}
val isClient = context.world.isClient
val player = context.player ?: return
val ongoingConnection = ongoingConnectionsServer[player]
val ongoingConnection =
if (isClient) ongoingConnectionsClient[player] else ongoingConnectionsServer[player]
if (ongoingConnection == null) {
// Do this action both on the client and the server, such that the player visually
// sees that a port is being connected.
startConnecting(player, OngoingConnection(context.blockPos, portName, color))
ServerPlayNetworking.send(
player,
StartConnectingPorts.id,
StartConnectingPorts(context.blockPos, portName.toString(), color).serialize()
)
if (player is ServerPlayerEntity) {
ServerPlayNetworking.send(
player,
StartConnectingPorts.id,
StartConnectingPorts(context.blockPos, portName.toString(), color).serialize()
)
}
} else {
if (portName.direction != ongoingConnection.portName.direction) {
val world = context.world as ServerWorld
val world = context.world
val fromPosition = ongoingConnection.blockPosition
val fromPort = ongoingConnection.portName
val toPosition = context.blockPos
val witnesses = PlayerLookup.tracking(world, fromPosition).toHashSet()
witnesses.addAll(PlayerLookup.tracking(world, toPosition))
for (witness in witnesses) {
ServerPlayNetworking.send(
witness,
ConnectPorts.id,
ConnectPorts(
fromPosition,
fromPort.id.toString(),
toPosition,
portName.id.toString(),
ongoingConnection.color,
).serialize()
)
if (world is ServerWorld) {
val witnesses = PlayerLookup.tracking(world, fromPosition).toHashSet()
witnesses.addAll(PlayerLookup.tracking(world, toPosition))
for (witness in witnesses) {
ServerPlayNetworking.send(
witness,
ConnectPorts.id,
ConnectPorts(
fromPosition,
fromPort.id.toString(),
toPosition,
portName.id.toString(),
ongoingConnection.color,
).serialize()
)
}
}
val fromBlockEntity = world.getBlockEntity(fromPosition)
@ -105,8 +112,10 @@ class PatchCableItem(settings: Settings, val color: Byte) : BasicItem(settings)
internal val ongoingConnectionsClient = hashMapOf<ClientPlayerEntity, OngoingConnection>()
private fun clearOngoingConnection(player: PlayerEntity) {
ongoingConnectionsServer.remove(player)
ongoingConnectionsClient.remove(player)
when (player) {
is ServerPlayerEntity -> ongoingConnectionsServer.remove(player)
is ClientPlayerEntity -> ongoingConnectionsClient.remove(player)
}
}
internal fun removeAllConnectionsAtBlock(blockPosition: BlockPos) {

View file

@ -0,0 +1,43 @@
package net.liquidev.dawd3.net
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
import net.liquidev.dawd3.Mod
import net.liquidev.dawd3.audio.device.PortName
import net.liquidev.dawd3.block.device.DeviceBlockEntity
import net.minecraft.network.PacketByteBuf
import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
/** S2C packet notifying clients about a client disconnecting the cables from a port. */
data class DisconnectPort(
val position: BlockPos,
val port: Identifier,
) {
companion object {
val id = Identifier(Mod.id, "disconnect_port")
fun registerClientReceiver() {
ClientPlayNetworking.registerGlobalReceiver(id) { client, _, buffer, _ ->
val packet = deserialize(buffer)
client.execute {
val world = client.world ?: return@execute
val blockEntity = world.getBlockEntity(packet.position) as? DeviceBlockEntity
?: return@execute
val portName = PortName.fromString(packet.port.toString()) ?: return@execute
blockEntity.severConnectionsInPort(portName)
}
}
}
private fun deserialize(buffer: PacketByteBuf) =
DisconnectPort(
position = buffer.readBlockPos(),
port = buffer.readIdentifier(),
)
}
fun serialize() = PacketByteBufs.create()
.writeBlockPos(position)
.writeIdentifier(port)
}

View file

@ -4,6 +4,7 @@ object Packets {
fun registerClientReceivers() {
StartConnectingPorts.registerClientReceiver()
ConnectPorts.registerClientReceiver()
DisconnectPort.registerClientReceiver()
TweakControl.registerClientReceiver()
}

View file

@ -6,8 +6,10 @@
"defaultRequire": 1
},
"mixins": [
"DebugHudMixin",
"PauseMixin",
"PlayerItemSwitchMixin"
],
"client": [
"DebugHudMixin",
"PauseMixin"
]
}