Skip to content

Commit

Permalink
Implement `/replay view camera reset command
Browse files Browse the repository at this point in the history
  • Loading branch information
senseiwells committed Nov 22, 2024
1 parent e80acae commit 9934633
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/main/kotlin/me/senseiwells/replay/viewer/ReplayViewer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import com.replaymod.replaystudio.replay.ZipReplayFile
import com.replaymod.replaystudio.studio.ReplayStudio
import it.unimi.dsi.fastutil.ints.IntArrayList
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
import it.unimi.dsi.fastutil.ints.IntSets
import it.unimi.dsi.fastutil.longs.LongOpenHashSet
import it.unimi.dsi.fastutil.longs.LongSets
import kotlinx.coroutines.*
import me.senseiwells.replay.ServerReplay
import me.senseiwells.replay.ducks.PackTracker
Expand Down Expand Up @@ -44,6 +46,7 @@ import net.minecraft.server.network.ServerGamePacketListenerImpl
import net.minecraft.world.BossEvent.BossBarColor
import net.minecraft.world.BossEvent.BossBarOverlay
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.PositionMoveRotation
import net.minecraft.world.level.ChunkPos
import net.minecraft.world.level.GameType
import net.minecraft.world.phys.Vec3
Expand Down Expand Up @@ -76,8 +79,9 @@ class ReplayViewer internal constructor(

private var tickSpeed = 20.0F
private var tickFrozen = false
private val chunks = Collections.synchronizedCollection(LongOpenHashSet())
private val entities = Collections.synchronizedCollection(IntOpenHashSet())

private val chunks = LongSets.synchronize(LongOpenHashSet())
private val entities = IntSets.synchronize(IntOpenHashSet())
private val players = Collections.synchronizedList(ArrayList<UUID>())
private val objectives = Collections.synchronizedCollection(ArrayList<String>())

Expand All @@ -92,6 +96,8 @@ class ReplayViewer internal constructor(

private var target = Duration.ZERO

private var position = Vec3.ZERO

val server: MinecraftServer
get() = this.player.server

Expand Down Expand Up @@ -239,6 +245,12 @@ class ReplayViewer internal constructor(
return this.replay.getResourcePack(hash).orNull()
}

fun resetCamera() {
this.send(ClientboundPlayerPositionPacket(
0, PositionMoveRotation(this.position, Vec3.ZERO, 0.0F, 0.0F), setOf()
))
}

private fun readMarkers(): Multimap<String?, Marker> {
val markers = this.replay.markers.orNull()
if (markers.isNullOrEmpty()) {
Expand Down Expand Up @@ -462,6 +474,7 @@ class ReplayViewer internal constructor(
return when (packet) {
is ClientboundGameEventPacket -> packet.event != CHANGE_GAME_MODE
is ClientboundPlayerPositionPacket -> {
this.position = packet.change.position
// We want the client to teleport to the first initial position
// subsequent positions will teleport the viewer which we don't want
val teleported = this.teleported
Expand All @@ -477,7 +490,6 @@ class ReplayViewer internal constructor(
when (packet) {
is ClientboundLevelChunkWithLightPacket -> this.chunks.add(ChunkPos.asLong(packet.x, packet.z))
is ClientboundForgetLevelChunkPacket -> this.chunks.remove(packet.pos.toLong())
is ClientboundAddEntityPacket -> this.entities.add(packet.id)
is ClientboundRemoveEntitiesPacket -> this.entities.removeAll(packet.entityIds)
is ClientboundSetObjectivePacket -> {
if (packet.method == ClientboundSetObjectivePacket.METHOD_REMOVE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ object ReplayViewerCommands {
).then(
Commands.literal("hide").executes(::hideReplayProgress)
)
).then(
Commands.literal("camera").then(
Commands.literal("reset").executes(::resetCamera)
)
).then(
Commands.literal("jump").then(
Commands.literal("to").then(
Expand Down Expand Up @@ -157,6 +161,15 @@ object ReplayViewerCommands {
return 0
}

private fun resetCamera(context: CommandContext<CommandSourceStack>): Int {
val viewer = context.source.getReplayViewer()
viewer.resetCamera()
context.source.sendSuccess({
Component.literal("Successfully reset camera")
}, false)
return Command.SINGLE_SUCCESS
}

private fun jumpToMarker(
context: CommandContext<CommandSourceStack>,
name: String? = StringArgumentType.getString(context, "name"),
Expand Down

0 comments on commit 9934633

Please sign in to comment.