cables better

"symulator kładzenia światłowodu" ~ ezioleq, 2022
This commit is contained in:
りき萌 2022-11-28 21:44:56 +01:00
parent 337c9d08e1
commit 2939b76e83
13 changed files with 137 additions and 51 deletions

View file

@ -0,0 +1,21 @@
package net.liquidev.dawd3.events;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
public class PlayerEvents {
public static Event<PlayerItemSwitch> ITEM_SWITCHED = EventFactory.createArrayBacked(
PlayerItemSwitch.class,
context -> {},
callbacks -> context -> {
for (PlayerItemSwitch callback : callbacks) {
callback.itemSwitched(context);
}
}
);
public interface PlayerItemSwitch {
void itemSwitched(PlayerEntity playerEntity);
}
}

View file

@ -0,0 +1,24 @@
package net.liquidev.dawd3.mixin;
import net.liquidev.dawd3.events.PlayerEvents;
import net.minecraft.entity.player.PlayerEntity;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PlayerEntity.class)
public class PlayerItemSwitchMixin {
@Inject(
method = "tick",
at = @At(
value = "FIELD",
target = "Lnet/minecraft/entity/player/PlayerEntity;selectedItem:Lnet/minecraft/item/ItemStack;",
opcode = Opcodes.PUTFIELD
)
)
private void fireItemSwitchedCallback(CallbackInfo callbackInfo) {
PlayerEvents.ITEM_SWITCHED.invoker().itemSwitched((PlayerEntity) (Object) this);
}
}

View file

@ -9,6 +9,7 @@ import net.liquidev.dawd3.block.Blocks
import net.liquidev.dawd3.block.entity.registerClientBlockEntityEvents
import net.liquidev.dawd3.item.Items
import net.liquidev.dawd3.net.Packets
import net.liquidev.dawd3.render.Textures
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@ -27,7 +28,7 @@ object Mod : ModInitializer, ClientModInitializer {
override fun onInitializeClient() {
logger.info("booting up sound engine")
D3r.load()
Audio.forceInitializationNow()
Audio.initializeClient()
ClientLifecycleEvents.CLIENT_STOPPING.register {
logger.info("shutting down sound engine")
@ -36,6 +37,7 @@ object Mod : ModInitializer, ClientModInitializer {
}
registerClientBlockEntityEvents()
Textures.initializeClient()
Blocks.initializeClient()
Packets.registerClientReceivers()
}

View file

@ -30,7 +30,10 @@ object Audio {
D3r.startPlayback(outputStreamId)
}
fun forceInitializationNow() {}
fun initializeClient() {
// Stubbed out; this is called explicitly to force the otherwise lazy initialization
// of Audio.
}
fun deinitialize() {
D3r.closeOutputStream(outputStreamId)

View file

@ -25,7 +25,6 @@ class DeviceInstance(val state: Device) {
fun process(sampleCount: Int, channels: Int, processingState: ProcessingState) {
if (this !in processingState.processedDevices) {
println("processing $this")
processingState.processedDevices.add(this)
for ((_, port) in inputPortsByName) {
port.connectedOutput?.owningDevice?.process(sampleCount, channels, processingState)

View file

@ -51,7 +51,7 @@ class DeviceBlock(private val descriptor: AnyDeviceBlockDescriptor) :
newState: BlockState,
moved: Boolean,
) {
PatchCableItem.onBlockDestroyed(position)
PatchCableItem.removeAllConnectionsAtBlock(position)
@Suppress("DEPRECATION")
super.onStateReplaced(state, world, position, newState, moved)

View file

@ -42,6 +42,8 @@ class DeviceBlockEntityRenderer(context: BlockEntityRendererFactory.Context) : B
)
val renderLayerFactory = Function<Identifier, RenderLayer> { renderLayer }
const val cableProtrusionAmount = 0.69f // nice
const val cableThickness = 0.03f
const val cableSegmentCount = 6
const val cableSag = 0.2f
@ -82,6 +84,7 @@ class DeviceBlockEntityRenderer(context: BlockEntityRendererFactory.Context) : B
vertexConsumers,
overlay
)
renderCables(world, blockState, blockEntity, matrixStack, vertexConsumers, tickDelta)
}
private fun rotateToFaceFront(
@ -107,7 +110,7 @@ class DeviceBlockEntityRenderer(context: BlockEntityRendererFactory.Context) : B
matrixStack.push()
rotateToFaceFront(blockState, matrixStack)
for ((_, connection) in PatchCableItem.ongoingConnections) {
for ((_, connection) in PatchCableItem.ongoingConnectionsServer) {
if (connection.blockPosition == blockEntity.pos) {
val port = blockEntity.descriptor.portLayout[connection.portName]
if (port != null) {
@ -157,6 +160,42 @@ class DeviceBlockEntityRenderer(context: BlockEntityRendererFactory.Context) : B
matrixStack.pop()
}
}
}
private fun renderCables(
world: World,
blockState: BlockState,
blockEntity: DeviceBlockEntity,
matrixStack: MatrixStack,
vertexConsumers: VertexConsumerProvider,
tickDelta: Float,
) {
val facing = HorizontalDirection.fromDirection(blockState[Properties.HORIZONTAL_FACING])!!
// println(PatchCableItem.ongoingConnections)
for ((player, connection) in PatchCableItem.ongoingConnectionsClient) {
if (connection.blockPosition == blockEntity.pos) {
val port = blockEntity.descriptor.portLayout[connection.portName]
if (port != null) {
val worldFrom = blockEntity.pos.toVec3d()
val forward = player.getRotationVec(tickDelta)
val playerPosition =
player.getCameraPosVec(tickDelta) + forward + Vec3d(0.0, -0.1, 0.0)
val delta = (playerPosition - worldFrom).toVec3f()
val start = port.blockCablePosition(facing, cableProtrusionAmount)
renderCable(
world,
matrixStack,
vertexConsumers,
worldFrom,
start,
delta,
connection.color.toFloat(),
)
}
}
}
for ((inputPortName, connection) in blockEntity.inputConnections) {
val startAbsolute = blockEntity.pos.toVec3d()
@ -173,9 +212,8 @@ class DeviceBlockEntityRenderer(context: BlockEntityRendererFactory.Context) : B
world.getBlockEntity(connection.blockPosition) as DeviceBlockEntity
val outputPort = outputBlockEntity.descriptor.portLayout[connection.outputPortName]!!
val protrusionAmount = 0.69f // nice
val start = inputPort.blockCablePosition(facing, protrusionAmount)
val end = outputPort.blockCablePosition(outputBlockFacing, protrusionAmount)
val start = inputPort.blockCablePosition(facing, cableProtrusionAmount)
val end = outputPort.blockCablePosition(outputBlockFacing, cableProtrusionAmount)
val delta = (endAbsolute - startAbsolute).toVec3f() + end
renderCable(

View file

@ -8,8 +8,10 @@ import net.liquidev.dawd3.block.device.DeviceBlockEntity
import net.liquidev.dawd3.block.device.PhysicalPort
import net.liquidev.dawd3.common.*
import net.liquidev.dawd3.datagen.device.DeviceBlockModel
import net.liquidev.dawd3.events.PlayerEvents
import net.liquidev.dawd3.net.ConnectPorts
import net.liquidev.dawd3.net.StartConnectingPorts
import net.minecraft.client.network.ClientPlayerEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemUsageContext
import net.minecraft.server.network.ServerPlayerEntity
@ -64,7 +66,7 @@ class PatchCableItem(settings: Settings, val color: Byte) : BasicItem(settings)
return
}
val ongoingConnection = ongoingConnections[player]
val ongoingConnection = ongoingConnectionsServer[player]
if (ongoingConnection == null) {
startConnecting(player, OngoingConnection(context.blockPos, portName, color))
ServerPlayNetworking.send(
@ -124,18 +126,33 @@ class PatchCableItem(settings: Settings, val color: Byte) : BasicItem(settings)
companion object {
private var logger = Mod.logger<PatchCableItem>()
internal val ongoingConnections = hashMapOf<PlayerEntity, OngoingConnection>()
internal val ongoingConnectionsServer = hashMapOf<ServerPlayerEntity, OngoingConnection>()
internal val ongoingConnectionsClient = hashMapOf<ClientPlayerEntity, OngoingConnection>()
private fun clearOngoingConnection(player: PlayerEntity) {
ongoingConnections.remove(player)
ongoingConnectionsServer.remove(player)
ongoingConnectionsClient.remove(player)
}
internal fun onBlockDestroyed(blockPosition: BlockPos) {
ongoingConnections.values.removeAll { it.blockPosition == blockPosition }
internal fun removeAllConnectionsAtBlock(blockPosition: BlockPos) {
ongoingConnectionsServer.values.removeAll { it.blockPosition == blockPosition }
ongoingConnectionsClient.values.removeAll { it.blockPosition == blockPosition }
}
fun startConnecting(player: PlayerEntity, connection: OngoingConnection) {
ongoingConnections[player] = connection
when (player) {
is ServerPlayerEntity -> ongoingConnectionsServer[player] = connection
is ClientPlayerEntity -> ongoingConnectionsClient[player] = connection
else -> {
logger.warn("player of unexpected class found")
}
}
}
init {
PlayerEvents.ITEM_SWITCHED.register { player ->
clearOngoingConnection(player)
}
}
}
}

View file

@ -1,27 +0,0 @@
package net.liquidev.dawd3.mixin
import net.liquidev.dawd3.render.Textures
import net.minecraft.client.render.TexturedRenderLayers
import net.minecraft.client.util.SpriteIdentifier
import org.spongepowered.asm.mixin.Mixin
import org.spongepowered.asm.mixin.injection.At
import org.spongepowered.asm.mixin.injection.Inject
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo
import java.util.function.Consumer
@Suppress("UNUSED")
@Mixin(TexturedRenderLayers::class)
abstract class NonModelTextures {
private companion object {
@Inject(
method = ["addDefaultTextures(Ljava/util/function/Consumer;)V"],
at = [At(value = "TAIL")]
)
@JvmStatic
private fun addDefaultTextures(adder: Consumer<SpriteIdentifier>, ci: CallbackInfo) {
for (texture in Textures.nonModel) {
adder.accept(texture)
}
}
}
}

View file

@ -5,7 +5,7 @@ import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
import net.liquidev.dawd3.Mod
import net.liquidev.dawd3.audio.device.PortName
import net.liquidev.dawd3.item.PatchCableItem
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.client.network.ClientPlayerEntity
import net.minecraft.network.PacketByteBuf
import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
@ -47,13 +47,14 @@ class StartConnectingPorts(val blockPosition: BlockPos, val portName: String, va
return buffer
}
private fun handleForPlayer(player: PlayerEntity) {
private fun handleForPlayer(player: ClientPlayerEntity) {
val portName = PortName.fromString(portName)
if (portName == null) {
logger.warn("invalid port name ${this.portName}")
return
}
println("[PLAYER] Started connecting ports $player")
PatchCableItem.startConnecting(
player,
PatchCableItem.OngoingConnection(blockPosition, portName, color)

View file

@ -1,7 +1,7 @@
package net.liquidev.dawd3.render
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback
import net.liquidev.dawd3.Mod
import net.minecraft.client.util.SpriteIdentifier
import net.minecraft.screen.PlayerScreenHandler
import net.minecraft.util.Identifier
@ -10,10 +10,16 @@ object Textures {
* The set of textures that are not referenced by models but need to be loaded into the
* block atlas.
*/
val nonModel = setOf(
SpriteIdentifier(
PlayerScreenHandler.BLOCK_ATLAS_TEXTURE,
Identifier(Mod.id, "device/cable")
)
private val nonModel = arrayOf(
Identifier(Mod.id, "device/cable"),
)
fun initializeClient() {
ClientSpriteRegistryCallback.event(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE)
.register { _, registry ->
for (id in nonModel) {
registry.register(id)
}
}
}
}

View file

@ -16,5 +16,7 @@
"item.dawd3.green_patch_cable": "Green Patch Cable",
"item.dawd3.red_patch_cable": "Red Patch Cable",
"item.dawd3.black_patch_cable": "Black Patch Cable",
"block.dawd3.speaker": "Speaker"
"block.dawd3.speaker": "Speaker",
"block.dawd3.sine_oscillator": "Sine Oscillator",
"block.dawd3.fader": "Fader"
}

View file

@ -6,6 +6,6 @@
"defaultRequire": 1
},
"mixins": [
"NonModelTextures"
"PlayerItemSwitchMixin"
]
}