Skip to content

Commit

Permalink
basic cardholic support
Browse files Browse the repository at this point in the history
  • Loading branch information
hex-agon committed Aug 23, 2023
1 parent 5453af9 commit dc2344c
Show file tree
Hide file tree
Showing 18 changed files with 442 additions and 4 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ This emulator only works with the PangYa GB.852 client, if you browse around the
In order to run the client it is highly recommended that you use [RugBurn](https://github.com/pangbox/rugburn).

## Running the servers
Each server requires a configuration file to be present in the working directory, see the readme of each server for a configuration file template:

### Dependencies
[Login Server Config](login-server/README.md)

[Game Server Config](game-server/README.md)

### Dependencies
Before running the login & game server you'll need the following extra services:

* A redis instance
* A postgres instance

Expand Down
10 changes: 9 additions & 1 deletion database/migrations/V0001__base-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,12 @@ CREATE TABLE player_achievement_milestone (
completed_at timestamptz
);

CREATE UNIQUE INDEX idx_player_achievement_milestone ON player_achievement_milestone (player_achievement_uid, iff_id);
CREATE UNIQUE INDEX idx_player_achievement_milestone ON player_achievement_milestone (player_achievement_uid, iff_id);

CREATE TABLE player_inventory_card (
uid serial PRIMARY KEY,
account_uid int NOT NULL
CONSTRAINT fk_player_inventory_item__account REFERENCES account (uid) ON DELETE CASCADE,
iff_id int NOT NULL,
quantity int
);
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import work.fking.pangya.discovery.HeartbeatPublisher
import work.fking.pangya.discovery.ServerType.GAME
import work.fking.pangya.game.persistence.JooqAchievementsRepository
import work.fking.pangya.game.persistence.JooqCaddieRepository
import work.fking.pangya.game.persistence.JooqCardInventory
import work.fking.pangya.game.persistence.JooqCharacterRepository
import work.fking.pangya.game.persistence.JooqEquipmentRepository
import work.fking.pangya.game.persistence.JooqInventoryRepository
Expand Down Expand Up @@ -62,6 +63,7 @@ object Bootstrap {
characterRepository = JooqCharacterRepository(),
caddieRepository = JooqCaddieRepository(),
inventoryRepository = JooqInventoryRepository(),
cardRepository = JooqCardInventory(),
equipmentRepository = JooqEquipmentRepository(),
statisticsRepository = JooqStatisticsRepository(),
achievementsRepository = JooqAchievementsRepository()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.slf4j.LoggerFactory
import work.fking.pangya.game.net.ServerChannelInitializer
import work.fking.pangya.game.persistence.PersistenceContext
import work.fking.pangya.game.player.CaddieRoster
import work.fking.pangya.game.player.CardInventory
import work.fking.pangya.game.player.CharacterRoster
import work.fking.pangya.game.player.Equipment
import work.fking.pangya.game.player.Inventory
Expand Down Expand Up @@ -55,9 +56,10 @@ class GameServer(
characterRoster: CharacterRoster,
caddieRoster: CaddieRoster,
inventory: Inventory,
cardInventory: CardInventory,
equipment: Equipment,
statistics: PlayerStatistics,
achievements: PlayerAchievements
achievements: PlayerAchievements,
): Player {
val player = Player(
channel = channel,
Expand All @@ -69,6 +71,7 @@ class GameServer(
characterRoster = characterRoster,
caddieRoster = caddieRoster,
inventory = inventory,
cardInventory = cardInventory,
equipment = equipment,
statistics = statistics,
achievements = achievements,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const val IFF_TYPE_BALL = 20
const val IFF_TYPE_EQUIPITEM_ITEM = 24
const val IFF_TYPE_NOEQUIP_ITEM = 26
const val IFF_TYPE_CADDIE = 28
const val IFF_TYPE_CARD = 124

interface IffObject {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package work.fking.pangya.game.packet.outbound

import work.fking.pangya.game.player.CardInventory
import work.fking.pangya.networking.protocol.OutboundPacket

object CardholicReplies {

fun inventory(cards: CardInventory): OutboundPacket {
return OutboundPacket { buffer ->
buffer.writeShortLE(0x138)

buffer.writeIntLE(0)
buffer.writeShortLE(cards.entries.size)

cards.entries.forEach { it.encode(buffer) }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package work.fking.pangya.game.persistence

import org.jooq.RecordMapper
import work.fking.pangya.game.persistence.jooq.keys.PLAYER_INVENTORY_CARD_PKEY
import work.fking.pangya.game.persistence.jooq.tables.records.PlayerInventoryCardRecord
import work.fking.pangya.game.persistence.jooq.tables.references.PLAYER_INVENTORY_CARD
import work.fking.pangya.game.player.Card
import work.fking.pangya.game.player.CardInventory
import java.util.concurrent.atomic.AtomicInteger

interface CardRepository {
fun load(txCtx: TransactionalContext, playerUid: Int): CardInventory
fun saveCard(txCtx: TransactionalContext, playerUid: Int, card: Card): Card
fun deleteCard(txCtx: TransactionalContext, playerUid: Int, card: Card)
}

class InMemoryCardRepository : CardRepository {
private val uidSequence = AtomicInteger(1)
private val cardInventories = mutableMapOf<Int, MutableList<Card>>()

private fun findCardInventory(playerUid: Int): MutableList<Card> = cardInventories.computeIfAbsent(playerUid) {
mutableListOf()
}

override fun load(txCtx: TransactionalContext, playerUid: Int): CardInventory {
return CardInventory(findCardInventory(playerUid))
}

override fun saveCard(txCtx: TransactionalContext, playerUid: Int, card: Card): Card {
val persistedCard = card.copy(uid = uidSequence.get())
findCardInventory(playerUid).add(persistedCard)
return persistedCard
}

override fun deleteCard(txCtx: TransactionalContext, playerUid: Int, card: Card) {
findCardInventory(playerUid).remove(card)
}
}

class JooqCardInventory : CardRepository {
private val cardMapper = RecordMapper<PlayerInventoryCardRecord, Card> {
Card(
uid = it.uid!!,
iffId = it.iffId,
quantity = it.quantity ?: 1
)
}

override fun load(txCtx: TransactionalContext, playerUid: Int): CardInventory {
val cards = txCtx.jooq().selectFrom(PLAYER_INVENTORY_CARD)
.where(PLAYER_INVENTORY_CARD.ACCOUNT_UID.eq(playerUid))
.fetch(cardMapper)
return CardInventory(cards)
}

override fun saveCard(txCtx: TransactionalContext, playerUid: Int, card: Card): Card {
val insert = txCtx.jooq().insertInto(PLAYER_INVENTORY_CARD)

if (card.uid != -1) insert.set(PLAYER_INVENTORY_CARD.UID, card.uid)

val uid = insert
.set(PLAYER_INVENTORY_CARD.ACCOUNT_UID, playerUid)
.set(PLAYER_INVENTORY_CARD.IFF_ID, card.iffId)
.set(PLAYER_INVENTORY_CARD.QUANTITY, card.quantity)
.onConflict(PLAYER_INVENTORY_CARD_PKEY.fields)
.doUpdate()
.set(PLAYER_INVENTORY_CARD.QUANTITY, card.quantity)
.returningResult(PLAYER_INVENTORY_CARD.UID)
.fetchOneInto(Int::class.java)

return card.copy(
uid = uid!!
)
}

override fun deleteCard(txCtx: TransactionalContext, playerUid: Int, card: Card) {
txCtx.jooq().deleteFrom(PLAYER_INVENTORY_CARD)
.where(PLAYER_INVENTORY_CARD.UID.eq(card.uid))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ data class PersistenceContext(
val characterRepository: CharacterRepository = InMemoryCharacterRepository(),
val caddieRepository: CaddieRepository = InMemoryCaddieRepository(),
val inventoryRepository: InventoryRepository = InMemoryInventoryRepository(),
val cardRepository: CardRepository = InMemoryCardRepository(),
val equipmentRepository: EquipmentRepository = InMemoryEquipmentRepository(),
val statisticsRepository: StatisticsRepository = InMemoryStatisticsRepository(),
val achievementsRepository: AchievementsRepository = InMemoryAchievementsRepository()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import work.fking.pangya.game.persistence.jooq.tables.PlayerAchievementMilestone
import work.fking.pangya.game.persistence.jooq.tables.PlayerCaddie
import work.fking.pangya.game.persistence.jooq.tables.PlayerCharacter
import work.fking.pangya.game.persistence.jooq.tables.PlayerEquipment
import work.fking.pangya.game.persistence.jooq.tables.PlayerInventoryCard
import work.fking.pangya.game.persistence.jooq.tables.PlayerInventoryItem
import work.fking.pangya.game.persistence.jooq.tables.PlayerStatistics

Expand Down Expand Up @@ -81,6 +82,11 @@ open class Public : SchemaImpl("public", DefaultCatalog.DEFAULT_CATALOG) {
*/
val PLAYER_EQUIPMENT: PlayerEquipment get() = PlayerEquipment.PLAYER_EQUIPMENT

/**
* The table <code>public.player_inventory_card</code>.
*/
val PLAYER_INVENTORY_CARD: PlayerInventoryCard get() = PlayerInventoryCard.PLAYER_INVENTORY_CARD

/**
* The table <code>public.player_inventory_item</code>.
*/
Expand All @@ -103,6 +109,7 @@ open class Public : SchemaImpl("public", DefaultCatalog.DEFAULT_CATALOG) {
PlayerCaddie.PLAYER_CADDIE,
PlayerCharacter.PLAYER_CHARACTER,
PlayerEquipment.PLAYER_EQUIPMENT,
PlayerInventoryCard.PLAYER_INVENTORY_CARD,
PlayerInventoryItem.PLAYER_INVENTORY_ITEM,
PlayerStatistics.PLAYER_STATISTICS
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import work.fking.pangya.game.persistence.jooq.tables.PlayerAchievementMilestone
import work.fking.pangya.game.persistence.jooq.tables.PlayerCaddie
import work.fking.pangya.game.persistence.jooq.tables.PlayerCharacter
import work.fking.pangya.game.persistence.jooq.tables.PlayerEquipment
import work.fking.pangya.game.persistence.jooq.tables.PlayerInventoryCard
import work.fking.pangya.game.persistence.jooq.tables.PlayerInventoryItem
import work.fking.pangya.game.persistence.jooq.tables.PlayerStatistics
import work.fking.pangya.game.persistence.jooq.tables.records.AccountRecord
Expand All @@ -29,6 +30,7 @@ import work.fking.pangya.game.persistence.jooq.tables.records.PlayerAchievementR
import work.fking.pangya.game.persistence.jooq.tables.records.PlayerCaddieRecord
import work.fking.pangya.game.persistence.jooq.tables.records.PlayerCharacterRecord
import work.fking.pangya.game.persistence.jooq.tables.records.PlayerEquipmentRecord
import work.fking.pangya.game.persistence.jooq.tables.records.PlayerInventoryCardRecord
import work.fking.pangya.game.persistence.jooq.tables.records.PlayerInventoryItemRecord
import work.fking.pangya.game.persistence.jooq.tables.records.PlayerStatisticsRecord

Expand All @@ -47,6 +49,7 @@ val PLAYER_ACHIEVEMENT_MILESTONE_PKEY: UniqueKey<PlayerAchievementMilestoneRecor
val PLAYER_CADDIE_PKEY: UniqueKey<PlayerCaddieRecord> = Internal.createUniqueKey(PlayerCaddie.PLAYER_CADDIE, DSL.name("player_caddie_pkey"), arrayOf(PlayerCaddie.PLAYER_CADDIE.UID), true)
val PLAYER_CHARACTER_PKEY: UniqueKey<PlayerCharacterRecord> = Internal.createUniqueKey(PlayerCharacter.PLAYER_CHARACTER, DSL.name("player_character_pkey"), arrayOf(PlayerCharacter.PLAYER_CHARACTER.UID), true)
val PLAYER_EQUIPMENT_PKEY: UniqueKey<PlayerEquipmentRecord> = Internal.createUniqueKey(PlayerEquipment.PLAYER_EQUIPMENT, DSL.name("player_equipment_pkey"), arrayOf(PlayerEquipment.PLAYER_EQUIPMENT.ACCOUNT_UID), true)
val PLAYER_INVENTORY_CARD_PKEY: UniqueKey<PlayerInventoryCardRecord> = Internal.createUniqueKey(PlayerInventoryCard.PLAYER_INVENTORY_CARD, DSL.name("player_inventory_card_pkey"), arrayOf(PlayerInventoryCard.PLAYER_INVENTORY_CARD.UID), true)
val PLAYER_INVENTORY_ITEM_PKEY: UniqueKey<PlayerInventoryItemRecord> = Internal.createUniqueKey(PlayerInventoryItem.PLAYER_INVENTORY_ITEM, DSL.name("player_inventory_item_pkey"), arrayOf(PlayerInventoryItem.PLAYER_INVENTORY_ITEM.UID), true)
val PLAYER_STATISTICS_PKEY: UniqueKey<PlayerStatisticsRecord> = Internal.createUniqueKey(PlayerStatistics.PLAYER_STATISTICS, DSL.name("player_statistics_pkey"), arrayOf(PlayerStatistics.PLAYER_STATISTICS.ACCOUNT_UID), true)

Expand All @@ -60,5 +63,6 @@ val PLAYER_ACHIEVEMENT_MILESTONE__FK_PLAYER_ACHIEVEMENT_MILESTONE__PLAYER_ACHIEV
val PLAYER_CADDIE__FK_PLAYER_CADDIE__ACCOUNT: ForeignKey<PlayerCaddieRecord, AccountRecord> = Internal.createForeignKey(PlayerCaddie.PLAYER_CADDIE, DSL.name("fk_player_caddie__account"), arrayOf(PlayerCaddie.PLAYER_CADDIE.ACCOUNT_UID), work.fking.pangya.game.persistence.jooq.keys.ACCOUNT_PKEY, arrayOf(Account.ACCOUNT.UID), true)
val PLAYER_CHARACTER__FK_PLAYER_CHARACTER__ACCOUNT: ForeignKey<PlayerCharacterRecord, AccountRecord> = Internal.createForeignKey(PlayerCharacter.PLAYER_CHARACTER, DSL.name("fk_player_character__account"), arrayOf(PlayerCharacter.PLAYER_CHARACTER.ACCOUNT_UID), work.fking.pangya.game.persistence.jooq.keys.ACCOUNT_PKEY, arrayOf(Account.ACCOUNT.UID), true)
val PLAYER_EQUIPMENT__FK_PLAYER_STATISTICS__ACCOUNT: ForeignKey<PlayerEquipmentRecord, AccountRecord> = Internal.createForeignKey(PlayerEquipment.PLAYER_EQUIPMENT, DSL.name("fk_player_statistics__account"), arrayOf(PlayerEquipment.PLAYER_EQUIPMENT.ACCOUNT_UID), work.fking.pangya.game.persistence.jooq.keys.ACCOUNT_PKEY, arrayOf(Account.ACCOUNT.UID), true)
val PLAYER_INVENTORY_CARD__FK_PLAYER_INVENTORY_ITEM__ACCOUNT: ForeignKey<PlayerInventoryCardRecord, AccountRecord> = Internal.createForeignKey(PlayerInventoryCard.PLAYER_INVENTORY_CARD, DSL.name("fk_player_inventory_item__account"), arrayOf(PlayerInventoryCard.PLAYER_INVENTORY_CARD.ACCOUNT_UID), work.fking.pangya.game.persistence.jooq.keys.ACCOUNT_PKEY, arrayOf(Account.ACCOUNT.UID), true)
val PLAYER_INVENTORY_ITEM__FK_PLAYER_INVENTORY_ITEM__ACCOUNT: ForeignKey<PlayerInventoryItemRecord, AccountRecord> = Internal.createForeignKey(PlayerInventoryItem.PLAYER_INVENTORY_ITEM, DSL.name("fk_player_inventory_item__account"), arrayOf(PlayerInventoryItem.PLAYER_INVENTORY_ITEM.ACCOUNT_UID), work.fking.pangya.game.persistence.jooq.keys.ACCOUNT_PKEY, arrayOf(Account.ACCOUNT.UID), true)
val PLAYER_STATISTICS__FK_PLAYER_STATISTICS__ACCOUNT: ForeignKey<PlayerStatisticsRecord, AccountRecord> = Internal.createForeignKey(PlayerStatistics.PLAYER_STATISTICS, DSL.name("fk_player_statistics__account"), arrayOf(PlayerStatistics.PLAYER_STATISTICS.ACCOUNT_UID), work.fking.pangya.game.persistence.jooq.keys.ACCOUNT_PKEY, arrayOf(Account.ACCOUNT.UID), true)
Loading

0 comments on commit dc2344c

Please sign in to comment.