Skip to content

Commit

Permalink
hole collectibles
Browse files Browse the repository at this point in the history
  • Loading branch information
hex-agon committed Jul 18, 2023
1 parent 88a0e24 commit 57f7d97
Show file tree
Hide file tree
Showing 20 changed files with 2,903 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ fun giveTestStuff(player: Player) {
inventory.add(Item(iffId = 402653230, quantity = 100)) // Double Strength Boost
inventory.add(Item(iffId = 402653228, quantity = 100)) // Silent Nerve Stabilizer
inventory.add(Item(iffId = 436207680, quantity = 1000)) // Auto Caliper
inventory.add(Item(iffId = 436207633, quantity = 1000)) // Time booster

luciaItems.forEach { inventory.add(Item(iffId = it)) }
arinItems.forEach { inventory.add(Item(iffId = it)) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import work.fking.pangya.game.packet.handler.RareShopOpenPacketHandler
import work.fking.pangya.game.packet.handler.SelectChannelPacketHandler
import work.fking.pangya.game.packet.handler.UpdateChatMacrosPacketHandler
import work.fking.pangya.game.packet.handler.UserProfileRequestPacketHandler
import work.fking.pangya.game.packet.handler.match.MatchFinalStatsPacketHandler
import work.fking.pangya.game.packet.handler.match.MatchFinishPlayerPreviewPacketHandler
import work.fking.pangya.game.packet.handler.match.MatchHoleStartPacketHandler
import work.fking.pangya.game.packet.handler.match.MatchPlayerHoleFinishPacketHandler
Expand All @@ -24,6 +25,7 @@ import work.fking.pangya.game.packet.handler.match.MatchPlayerShotStartPacketHan
import work.fking.pangya.game.packet.handler.match.MatchPlayerShotSyncPacketHandler
import work.fking.pangya.game.packet.handler.match.MatchPlayerTurnEndPacketHandler
import work.fking.pangya.game.packet.handler.match.MatchPlayerUseItemPacketHandler
import work.fking.pangya.game.packet.handler.match.MatchPlayerUseTimeBoosterPacketHandler
import work.fking.pangya.game.packet.handler.match.MatchTourneyShotPacketHandler
import work.fking.pangya.game.packet.handler.match.StartGamePacketHandler
import work.fking.pangya.game.packet.handler.room.CreateRoomPacketHandler
Expand All @@ -36,7 +38,7 @@ enum class ClientPacketType(
private val handler: ClientPacketHandler = ClientPacketHandler { _, _, _ -> }
) {
SELECT_CHANNEL(0x4, SelectChannelPacketHandler()),
MATCH_FINAL_STATS(0x6),
MATCH_FINAL_STATS(0x6, MatchFinalStatsPacketHandler()),
ROOM_CREATE(0x8, CreateRoomPacketHandler()),
ROOM_JOIN(0x9, JoinRoomHandler()),
ROOM_SETTINGS_UPDATE(0xa, RoomSettingsUpdatePacketHandler()),
Expand All @@ -62,6 +64,7 @@ enum class ClientPacketType(
MATCH_PLAYER_SHOT_ARROW(0x42),
PLAYER_LOAD_PROGRESS(0x48),
LOUNGE_USER_ACTION(0x63),
MATCH_PLAYER_USE_TIME_BOOSTER(0x65, MatchPlayerUseTimeBoosterPacketHandler()),
UPDATE_MACROS(0x69, UpdateChatMacrosPacketHandler()),
JOIN_LOBBY(0x81, JoinLobbyPacketHandler()),
LEAVE_LOBBY(0x82, LeaveLobbyPacketHandler()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ class UserProfileRequestPacketHandler : ClientPacketHandler {

override fun handle(server: GameServer, player: Player, packet: ByteBuf) {
val playerUid = packet.readIntLE()
val type = packet.readByte()
val type = packet.readByte().toInt()

if (type.toInt() == 5) {
player.write(UserStatisticsReplies.username(type.toInt(), player))
if (type == 5) {
player.write(UserStatisticsReplies.username(type, player))
player.write(UserStatisticsReplies.character(player))
player.write(UserStatisticsReplies.equipment(type.toInt(), player))
player.write(UserStatisticsReplies.equipment(type, player))
}
player.write(UserStatisticsReplies.userStatistic(type.toInt(), playerUid))
player.write(UserStatisticsReplies.courseStatistic(type.toInt(), playerUid))
player.write(UserStatisticsReplies.trophies(type.toInt(), playerUid))
player.write(UserStatisticsReplies.ack(true, type.toInt(), playerUid))
player.write(UserStatisticsReplies.userStatistic(type, playerUid, player.statistics))
player.write(UserStatisticsReplies.courseStatistic(type, playerUid))
player.write(UserStatisticsReplies.trophies(type, playerUid))
player.write(UserStatisticsReplies.ack(true, type, playerUid))
player.flush()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package work.fking.pangya.game.packet.handler.match

import io.netty.buffer.ByteBuf
import work.fking.pangya.game.GameServer
import work.fking.pangya.game.net.ClientPacketHandler
import work.fking.pangya.game.player.Player
import work.fking.pangya.game.player.readStatistics
import work.fking.pangya.game.room.match.PlayerMatchFinishEvent

class MatchFinalStatsPacketHandler : ClientPacketHandler {
override fun handle(server: GameServer, player: Player, packet: ByteBuf) {
val room = player.currentRoom ?: throw IllegalStateException("Player ${player.nickname} finished a match but is not in a room")
val roomPlayer = room.findSelf(player)
val statistics = packet.readStatistics()
room.handleMatchEvent(PlayerMatchFinishEvent(roomPlayer, statistics))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class MatchHoleStartPacketHandler : ClientPacketHandler {
val teeCoord = Coord2D(packet.readFloatLE(), packet.readFloatLE())
val holeCoord = Coord2D(packet.readFloatLE(), packet.readFloatLE())


room.handleMatchEvent(
PlayerHoleStartEvent(
player = roomPlayer,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package work.fking.pangya.game.packet.handler.match

import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufUtil
import work.fking.pangya.game.GameServer
import work.fking.pangya.game.net.ClientPacketHandler
import work.fking.pangya.game.player.Player
import work.fking.pangya.game.player.readStatistics
import work.fking.pangya.game.room.match.PlayerHoleFinishEvent

class MatchPlayerHoleFinishPacketHandler : ClientPacketHandler {
override fun handle(server: GameServer, player: Player, packet: ByteBuf) {
val room = player.currentRoom ?: throw IllegalStateException("Player ${player.nickname} finished a hole but is not in a room")
val roomPlayer = room.findSelf(player)
room.handleMatchEvent(PlayerHoleFinishEvent(roomPlayer))
val statistics = packet.readStatistics()
room.handleMatchEvent(PlayerHoleFinishEvent(roomPlayer, statistics))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class MatchPlayerShotSyncPacketHandler : ClientPacketHandler {
player = roomPlayer,
x = x,
z = z,
pang = pang,
bonusPang = bonusPang,
shotFlags = shotFlags,
frames = shotFrames
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package work.fking.pangya.game.packet.handler.match

import io.netty.buffer.ByteBuf
import work.fking.pangya.game.GameServer
import work.fking.pangya.game.net.ClientPacketHandler
import work.fking.pangya.game.packet.outbound.MatchReplies
import work.fking.pangya.game.player.Player

class MatchPlayerUseTimeBoosterPacketHandler : ClientPacketHandler {
override fun handle(server: GameServer, player: Player, packet: ByteBuf) {
val room = player.currentRoom ?: throw IllegalStateException("Player ${player.nickname} tried to use a time booster but is not in a room")
val roomPlayer = room.findSelf(player)
val boostValue = packet.readFloatLE()

roomPlayer.writeAndFlush(MatchReplies.useTimeBoosterAck(roomPlayer, boostValue))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package work.fking.pangya.game.packet.outbound

import work.fking.pangya.game.player.Player
import work.fking.pangya.game.player.PlayerBasicInfo
import work.fking.pangya.game.player.PlayerStatistic
import work.fking.pangya.game.player.PlayerStatistics
import work.fking.pangya.game.player.PlayerTrophies
import work.fking.pangya.game.player.write
import work.fking.pangya.game.room.Course
Expand Down Expand Up @@ -57,7 +57,7 @@ object HandoverReplies {
PlayerBasicInfo().encode(buffer, player)

// Player Statistics (verified ok by comparing with struct sent on hole end)
buffer.write(PlayerStatistic())
buffer.write(player.statistics)

// trophies (verified ok by checking my room trophies and confirming there's 1 ama 6 gold trophy and 1 bronze pro 7 trophy)
PlayerTrophies().encode(buffer)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package work.fking.pangya.game.packet.outbound

import work.fking.pangya.game.Rand
import work.fking.pangya.game.model.write
import work.fking.pangya.game.player.Player
import work.fking.pangya.game.room.Room
import work.fking.pangya.game.room.RoomPlayer
import work.fking.pangya.game.room.mapHoleCollectibles
import work.fking.pangya.game.room.match.Hole
import work.fking.pangya.game.room.match.MatchState
import work.fking.pangya.game.room.match.ShotCommitData
Expand Down Expand Up @@ -55,8 +58,23 @@ object MatchReplies {
buffer.writeIntLE(matchState.gameTimeMs)
matchState.holes.forEach { buffer.write(it) }
buffer.writeIntLE(matchState.randSeed) // it seems like the original server can only generate short random values
// collectibles, each byte is the count for each hole
buffer.writeZero(18)

val mapHoleCollectibles = mapHoleCollectibles[matchState.course] ?: Array(18) { emptyArray() }

for ((holeIdx, holeCollectibles) in mapHoleCollectibles.withIndex()) {
buffer.writeByte(holeCollectibles.size)
for (collectible in holeCollectibles) {
buffer.writeIntLE(collectible.type.ordinal)
buffer.writeIntLE(Rand.nextInt())
buffer.writeIntLE(0)
buffer.writeIntLE(matchState.course.ordinal)
buffer.writeByte(holeIdx + 1)
buffer.writeByte(holeIdx)
buffer.writeShortLE(0)
buffer.write(collectible.position)
buffer.writeIntLE(collectible.type.ordinal)
}
}
}
}

Expand All @@ -78,7 +96,7 @@ object MatchReplies {
}
}

fun gamePlayerUseItem(player: RoomPlayer, itemIffId: Int, randSeed: Int): OutboundPacket {
fun playerUseItem(player: RoomPlayer, itemIffId: Int, randSeed: Int): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0x5a)
buffer.writeIntLE(itemIffId)
Expand All @@ -90,14 +108,14 @@ object MatchReplies {
/**
* Tells the client to play the player intro & start music
*/
fun gamePlayerStartHole(player: RoomPlayer): OutboundPacket {
fun playerStartHole(player: RoomPlayer): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0x53)
buffer.writeIntLE(player.connectionId)
}
}

fun gameFinishPlayerPreviewAck(): OutboundPacket {
fun finishPlayerPreviewAck(): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0x90)
}
Expand Down Expand Up @@ -141,7 +159,7 @@ object MatchReplies {
}

// used for drawing the white dots across the map
fun gameTourneyShotGhost(player: RoomPlayer, x: Float, z: Float, shotFlags: Int, frames: Int): OutboundPacket {
fun tourneyShotGhost(player: RoomPlayer, x: Float, z: Float, shotFlags: Int, frames: Int): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0x6e)
buffer.writeIntLE(player.connectionId)
Expand All @@ -156,7 +174,7 @@ object MatchReplies {
}
}

fun gameTourneyShotAck(player: RoomPlayer, tourneyShotData: TourneyShotData): OutboundPacket {
fun tourneyShotAck(player: RoomPlayer, tourneyShotData: TourneyShotData): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0x1f7)
buffer.writeIntLE(player.connectionId)
Expand All @@ -165,7 +183,7 @@ object MatchReplies {
}
}

fun gameTourneyEndingScore(): OutboundPacket {
fun tourneyEndingScore(): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0x79)
buffer.writeIntLE(4) // experience
Expand All @@ -180,32 +198,37 @@ object MatchReplies {
}
}

fun gameTourneyWinnings(): OutboundPacket {
fun tourneyWinnings(itemIffIds: List<Int>): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0xce)
buffer.writeByte(0)
buffer.writeShortLE(1) // count

repeat(1) {
buffer.writeIntLE(402653195) // item iffIds
}
buffer.writeShortLE(itemIffIds.size)
itemIffIds.forEach { buffer.writeIntLE(it) }
}
}

fun gameTourneyTimeout(): OutboundPacket {
fun tourneyTimeout(): OutboundPacket {
return OutboundPacket { buffer -> buffer.writeShortLE(0x8c) }
}

fun gameTourneyUpdatePlayerProgress(player: RoomPlayer): OutboundPacket {
fun tourneyUpdatePlayerProgress(player: RoomPlayer): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0x6d)
buffer.writeIntLE(player.connectionId)
buffer.writeByte(player.currentHole) // hole
buffer.writeByte(3) // total strokes?
buffer.writeIntLE(-1) // score
buffer.writeLongLE(30) // pang
buffer.writeLongLE(1) // bonus pang
buffer.writeByte(1) // finished the hole 1 or 0 not
buffer.writeLongLE(player.pang.toLong()) // pang
buffer.writeLongLE(player.bonusPang.toLong()) // bonus pang
buffer.writeByte(1) // finished the hole, 1 or 0 not
}
}

fun useTimeBoosterAck(player: RoomPlayer, boostValue: Float): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0xC7)
buffer.writeFloatLE(boostValue)
buffer.writeIntLE(player.connectionId)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package work.fking.pangya.game.packet.outbound

import work.fking.pangya.game.player.Player
import work.fking.pangya.game.player.PlayerBasicInfo
import work.fking.pangya.game.player.PlayerStatistic
import work.fking.pangya.game.player.PlayerStatistics
import work.fking.pangya.game.player.PlayerTrophies
import work.fking.pangya.game.player.write
import work.fking.pangya.game.room.Course
Expand Down Expand Up @@ -38,12 +38,12 @@ object UserStatisticsReplies {
}
}

fun userStatistic(requestType: Int, playerUid: Int): OutboundPacket {
fun userStatistic(requestType: Int, playerUid: Int, statistics: PlayerStatistics): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0x158)
buffer.writeByte(requestType)
buffer.writeIntLE(playerUid)
buffer.write(PlayerStatistic())
buffer.write(statistics)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,16 @@ class Player(
val connectionId: Int,
val username: String,
val nickname: String,
val achievements: PlayerAchievements = createPlayerAchievements()
val achievements: PlayerAchievements = createPlayerAchievements(),
var statistics: PlayerStatistics = PlayerStatistics(
level = 70
)
) {
val inventory = Inventory()
val equipment = Equipment(this)
val characterRoster = CharacterRoster()
val caddieRoster = CaddieRoster()

var rank = 0
private set
var experience = 0
set(value) {
require(value >= 0) { "Cannot add negative experience" }
field += value
}

var pangBalance = 10000
set(value) {
field = max(0, value)
Expand Down
Loading

0 comments on commit 57f7d97

Please sign in to comment.