Rewrite MonsterBook, touch up chr loading
Temporarily disabled loading monster cards from db
This commit is contained in:
@@ -1901,8 +1901,8 @@ public class Character extends AbstractCharacterObject {
|
||||
ii.getItemEffect(itemId).applyTo(this);
|
||||
}
|
||||
|
||||
if (itemId / 10000 == 238) {
|
||||
this.getMonsterBook().addCard(client, itemId);
|
||||
if (ItemId.isMonsterCard(itemId)) {
|
||||
monsterbook.addCard(itemId, client);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -6743,7 +6743,7 @@ public class Character extends AbstractCharacterObject {
|
||||
}
|
||||
}
|
||||
|
||||
public static Character loadCharacterEntryFromDB(ResultSet rs, List<Item> equipped) {
|
||||
public static Character loadCharacterViewFromDB(ResultSet rs, List<Item> equipped) {
|
||||
Character ret = new Character();
|
||||
|
||||
try {
|
||||
@@ -6794,7 +6794,7 @@ public class Character extends AbstractCharacterObject {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Character generateCharacterEntry() {
|
||||
public Character createCharacterView() {
|
||||
Character ret = new Character();
|
||||
|
||||
ret.accountid = this.getAccountID();
|
||||
@@ -6854,10 +6854,16 @@ public class Character extends AbstractCharacterObject {
|
||||
updateRemainingSp(remainingSp, GameConstants.getSkillBook(job.getId()));
|
||||
}
|
||||
|
||||
public static Character loadCharFromDB(final int charid, Client client, boolean channelserver) throws SQLException {
|
||||
@Deprecated
|
||||
public static Character loadCharFromDB(int chrId, Client client, boolean channelServer) throws SQLException {
|
||||
return loadCharFromDB(chrId, client, channelServer, new MonsterBook(Collections.emptyList()));
|
||||
}
|
||||
|
||||
public static Character loadCharFromDB(final int chrId, Client client, boolean channelServer,
|
||||
MonsterBook monsterBook) throws SQLException {
|
||||
Character ret = new Character();
|
||||
ret.client = client;
|
||||
ret.id = charid;
|
||||
ret.id = chrId;
|
||||
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
final int mountexp;
|
||||
@@ -6867,7 +6873,7 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
// Character info
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM characters WHERE id = ?")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (!rs.next()) {
|
||||
@@ -6925,8 +6931,7 @@ public class Character extends AbstractCharacterObject {
|
||||
ret.allianceRank = rs.getInt("allianceRank");
|
||||
ret.familyId = rs.getInt("familyId");
|
||||
ret.bookCover = rs.getInt("monsterbookcover");
|
||||
ret.monsterbook = new MonsterBook();
|
||||
ret.monsterbook.loadCards(charid);
|
||||
ret.monsterbook = monsterBook;
|
||||
ret.vanquisherStage = rs.getInt("vanquisherStage");
|
||||
ret.ariantPoints = rs.getInt("ariantPoints");
|
||||
ret.dojoPoints = rs.getInt("dojoPoints");
|
||||
@@ -6946,7 +6951,7 @@ public class Character extends AbstractCharacterObject {
|
||||
ret.getInventory(InventoryType.ETC).setSlotLimit(rs.getByte("etcslots"));
|
||||
|
||||
short sandboxCheck = 0x0;
|
||||
for (Pair<Item, InventoryType> item : ItemFactory.INVENTORY.loadItems(ret.id, !channelserver)) {
|
||||
for (Pair<Item, InventoryType> item : ItemFactory.INVENTORY.loadItems(ret.id, !channelServer)) {
|
||||
sandboxCheck |= item.getLeft().getFlag();
|
||||
|
||||
ret.getInventory(item.getRight()).addItemFromDB(item.getLeft());
|
||||
@@ -6993,7 +6998,7 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
// Items excluded from pet loot
|
||||
try (PreparedStatement psPet = con.prepareStatement("SELECT petid FROM inventoryitems WHERE characterid = ? AND petid > -1")) {
|
||||
psPet.setInt(1, charid);
|
||||
psPet.setInt(1, chrId);
|
||||
|
||||
try (ResultSet rsPet = psPet.executeQuery()) {
|
||||
while (rsPet.next()) {
|
||||
@@ -7016,7 +7021,7 @@ public class Character extends AbstractCharacterObject {
|
||||
ret.commitExcludedItems();
|
||||
|
||||
|
||||
if (channelserver) {
|
||||
if (channelServer) {
|
||||
MapManager mapManager = client.getChannelServer().getMapFactory();
|
||||
ret.map = mapManager.getMap(ret.mapid);
|
||||
|
||||
@@ -7054,7 +7059,7 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
// Teleport rocks
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT mapid,vip FROM trocklocations WHERE characterid = ? LIMIT 15")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
byte vip = 0;
|
||||
@@ -7125,7 +7130,7 @@ public class Character extends AbstractCharacterObject {
|
||||
// Blessing of the Fairy
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT name, level FROM characters WHERE accountid = ? AND id != ? ORDER BY level DESC limit 1")) {
|
||||
ps.setInt(1, ret.accountid);
|
||||
ps.setInt(2, charid);
|
||||
ps.setInt(2, chrId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
@@ -7135,12 +7140,12 @@ public class Character extends AbstractCharacterObject {
|
||||
}
|
||||
}
|
||||
|
||||
if (channelserver) {
|
||||
if (channelServer) {
|
||||
final Map<Integer, QuestStatus> loadedQuestStatus = new LinkedHashMap<>();
|
||||
|
||||
// Quest status
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM queststatus WHERE characterid = ?")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
@@ -7167,7 +7172,7 @@ public class Character extends AbstractCharacterObject {
|
||||
// Quest progress
|
||||
// opportunity for improvement on questprogress/medalmaps calls to DB
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM questprogress WHERE characterid = ?")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
try (ResultSet rsProgress = ps.executeQuery()) {
|
||||
while (rsProgress.next()) {
|
||||
QuestStatus status = loadedQuestStatus.get(rsProgress.getInt("queststatusid"));
|
||||
@@ -7180,7 +7185,7 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
// Medal map visit progress
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM medalmaps WHERE characterid = ?")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
try (ResultSet rsMedalMaps = ps.executeQuery()) {
|
||||
while (rsMedalMaps.next()) {
|
||||
QuestStatus status = loadedQuestStatus.get(rsMedalMaps.getInt("queststatusid"));
|
||||
@@ -7195,7 +7200,7 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
// Skills
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT skillid,skilllevel,masterlevel,expiration FROM skills WHERE characterid = ?")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
@@ -7265,7 +7270,7 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
// Skill macros
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM skillmacros WHERE characterid = ?")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
@@ -7278,7 +7283,7 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
// Key config
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT `key`,`type`,`action` FROM keymap WHERE characterid = ?")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
@@ -7292,7 +7297,7 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
// Saved locations
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT `locationtype`,`map`,`portal` FROM savedlocations WHERE characterid = ?")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
@@ -7303,7 +7308,7 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
// Fame history
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT `characterid_to`,`when` FROM famelog WHERE characterid = ? AND DATEDIFF(NOW(),`when`) < 30")) {
|
||||
ps.setInt(1, charid);
|
||||
ps.setInt(1, chrId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
ret.lastfametime = 0;
|
||||
@@ -7315,7 +7320,7 @@ public class Character extends AbstractCharacterObject {
|
||||
}
|
||||
}
|
||||
|
||||
ret.buddylist.loadFromDb(charid);
|
||||
ret.buddylist.loadFromDb(chrId);
|
||||
ret.storage = wserv.getAccountStorage(ret.accountid);
|
||||
|
||||
/* Double-check storage incase player is first time on server
|
||||
|
||||
@@ -1,190 +1,106 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||
Matthias Butz <matze@odinms.de>
|
||||
Jan Christian Meyer <vimes@odinms.de>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package client;
|
||||
|
||||
import tools.DatabaseConnection;
|
||||
import database.monsterbook.MonsterCard;
|
||||
import net.jcip.annotations.ThreadSafe;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class MonsterBook {
|
||||
private int specialCard = 0;
|
||||
private int normalCard = 0;
|
||||
private int bookLevel = 1;
|
||||
private final Map<Integer, Integer> cards = new LinkedHashMap<>();
|
||||
private final Lock lock = new ReentrantLock();
|
||||
// TODO: add tests
|
||||
@ThreadSafe
|
||||
public class MonsterBook {
|
||||
private final Map<Integer, MonsterCard> cards;
|
||||
private int bookLevel;
|
||||
|
||||
public void addCard(final Client c, final int cardid) {
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), PacketCreator.showForeignCardEffect(c.getPlayer().getId()), false);
|
||||
public MonsterBook(List<MonsterCard> monsterCards) {
|
||||
this.cards = monsterCards.stream()
|
||||
.collect(Collectors.toMap(MonsterCard::cardId, Function.identity()));
|
||||
}
|
||||
|
||||
Integer qty;
|
||||
lock.lock();
|
||||
try {
|
||||
qty = cards.get(cardid);
|
||||
public synchronized List<MonsterCard> getCards() {
|
||||
return new ArrayList<>(cards.values());
|
||||
}
|
||||
|
||||
if (qty != null) {
|
||||
if (qty < 5) {
|
||||
cards.put(cardid, qty + 1);
|
||||
}
|
||||
} else {
|
||||
cards.put(cardid, 1);
|
||||
qty = 0;
|
||||
|
||||
if (cardid / 1000 >= 2388) {
|
||||
specialCard++;
|
||||
} else {
|
||||
normalCard++;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
public synchronized void addCard(int cardId, Client client) {
|
||||
var monsterCard = cards.get(cardId);
|
||||
if (monsterCard != null && monsterCard.isMaxLevel()) {
|
||||
client.sendPacket(PacketCreator.addMonsterCardAlreadyFull());
|
||||
return;
|
||||
}
|
||||
|
||||
if (qty < 5) {
|
||||
if (qty == 0) { // leveling system only accounts unique cards
|
||||
calculateLevel();
|
||||
}
|
||||
|
||||
c.sendPacket(PacketCreator.addCard(false, cardid, qty + 1));
|
||||
c.sendPacket(PacketCreator.showGainCard());
|
||||
boolean isNewCard = monsterCard == null;
|
||||
final MonsterCard card;
|
||||
if (isNewCard) {
|
||||
card = new MonsterCard(cardId, (byte) 1);
|
||||
cards.put(cardId, card);
|
||||
calculateAndSetLevel();
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.addCard(true, cardid, 5));
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateLevel() {
|
||||
lock.lock();
|
||||
try {
|
||||
int collectionExp = (normalCard + specialCard);
|
||||
|
||||
int level = 0, expToNextlevel = 1;
|
||||
do {
|
||||
level++;
|
||||
expToNextlevel += level * 10;
|
||||
} while (collectionExp >= expToNextlevel);
|
||||
|
||||
bookLevel = level; // thanks IxianMace for noticing book level differing between book UI and character info UI
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int getBookLevel() {
|
||||
lock.lock();
|
||||
try {
|
||||
return bookLevel;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<Integer, Integer> getCards() {
|
||||
lock.lock();
|
||||
try {
|
||||
return Collections.unmodifiableMap(cards);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int getTotalCards() {
|
||||
lock.lock();
|
||||
try {
|
||||
return specialCard + normalCard;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int getNormalCard() {
|
||||
lock.lock();
|
||||
try {
|
||||
return normalCard;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int getSpecialCard() {
|
||||
lock.lock();
|
||||
try {
|
||||
return specialCard;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadCards(final int charid) throws SQLException {
|
||||
lock.lock();
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT cardid, level FROM monsterbook WHERE charid = ? ORDER BY cardid ASC")) {
|
||||
ps.setInt(1, charid);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
int cardid;
|
||||
int level;
|
||||
while (rs.next()) {
|
||||
cardid = rs.getInt("cardid");
|
||||
level = rs.getInt("level");
|
||||
if (cardid / 1000 >= 2388) {
|
||||
specialCard++;
|
||||
} else {
|
||||
normalCard++;
|
||||
}
|
||||
cards.put(cardid, level);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
card = new MonsterCard(cardId, (byte) (monsterCard.level() + 1));
|
||||
cards.put(cardId, card);
|
||||
}
|
||||
|
||||
calculateLevel();
|
||||
var chr = client.getPlayer();
|
||||
chr.sendPacket(PacketCreator.addMonsterCard(card));
|
||||
chr.sendPacket(PacketCreator.showMonsterCardEffect());
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.showForeignMonsterCardEffect(chr.getId()), false);
|
||||
}
|
||||
|
||||
public void saveCards(Connection con, int chrId) throws SQLException {
|
||||
private synchronized void calculateAndSetLevel() {
|
||||
int collectionExp = getTotalCards();
|
||||
|
||||
int level = 0;
|
||||
int expToNextLevel = 1;
|
||||
do {
|
||||
level++;
|
||||
expToNextLevel += level * 10;
|
||||
} while (collectionExp >= expToNextLevel);
|
||||
|
||||
this.bookLevel = level;
|
||||
}
|
||||
|
||||
public synchronized int getBookLevel() {
|
||||
return bookLevel;
|
||||
}
|
||||
|
||||
public synchronized int getNormalCards() {
|
||||
return (int) cards.values().stream()
|
||||
.filter(Predicate.not(MonsterCard::isSpecial))
|
||||
.count();
|
||||
}
|
||||
|
||||
public synchronized int getSpecialCards() {
|
||||
return (int) cards.values().stream()
|
||||
.filter(MonsterCard::isSpecial)
|
||||
.count();
|
||||
}
|
||||
|
||||
public synchronized int getTotalCards() {
|
||||
return cards.size();
|
||||
}
|
||||
|
||||
public synchronized void saveCards(Connection con, int chrId) throws SQLException {
|
||||
final String query = """
|
||||
INSERT INTO monsterbook (charid, cardid, level)
|
||||
VALUES (?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE level = ?;
|
||||
""";
|
||||
try (final PreparedStatement ps = con.prepareStatement(query)) {
|
||||
for (Map.Entry<Integer, Integer> cardAndLevel : cards.entrySet()) {
|
||||
final int card = cardAndLevel.getKey();
|
||||
final int level = cardAndLevel.getValue();
|
||||
for (MonsterCard card : cards.values()) {
|
||||
// insert
|
||||
ps.setInt(1, chrId);
|
||||
ps.setInt(2, card);
|
||||
ps.setInt(3, level);
|
||||
ps.setInt(2, card.cardId());
|
||||
ps.setInt(3, card.level());
|
||||
|
||||
// update
|
||||
ps.setInt(4, level);
|
||||
ps.setInt(4, card.level());
|
||||
|
||||
ps.addBatch();
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package database.monsterbook;
|
||||
|
||||
import constants.id.ItemId;
|
||||
|
||||
public record MonsterCard(int cardId, byte level) {
|
||||
private static final int MAX_LEVEL = 5;
|
||||
|
||||
public MonsterCard {
|
||||
if (cardId / 10_000 != 238) {
|
||||
if (!ItemId.isMonsterCard(cardId)) {
|
||||
throw new IllegalArgumentException("Invalid monster card id: %d".formatted(cardId));
|
||||
}
|
||||
if (level < 0 || level > 5) {
|
||||
if (level < 0 || level > MAX_LEVEL) {
|
||||
throw new IllegalArgumentException("Invalid monster card level: %d".formatted(level));
|
||||
}
|
||||
}
|
||||
@@ -14,4 +17,8 @@ public record MonsterCard(int cardId, byte level) {
|
||||
public boolean isSpecial() {
|
||||
return cardId / 1000 == 2388;
|
||||
}
|
||||
|
||||
public boolean isMaxLevel() {
|
||||
return level == MAX_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1432,7 +1432,7 @@ public class Server {
|
||||
}
|
||||
|
||||
public void updateCharacterEntry(Character chr) {
|
||||
Character chrView = chr.generateCharacterEntry();
|
||||
Character chrView = chr.createCharacterView();
|
||||
|
||||
lgnWLock.lock();
|
||||
try {
|
||||
@@ -1457,7 +1457,7 @@ public class Server {
|
||||
|
||||
worldChars.put(chrid, world);
|
||||
|
||||
Character chrView = chr.generateCharacterEntry();
|
||||
Character chrView = chr.createCharacterView();
|
||||
|
||||
World wserv = this.getWorld(chrView.getWorld());
|
||||
if (wserv != null) {
|
||||
@@ -1488,47 +1488,6 @@ public class Server {
|
||||
}
|
||||
}
|
||||
|
||||
public void transferWorldCharacterEntry(Character chr, Integer toWorld) { // used before setting the new worldid on the character object
|
||||
lgnWLock.lock();
|
||||
try {
|
||||
Integer chrid = chr.getId(), accountid = chr.getAccountID(), world = worldChars.get(chr.getId());
|
||||
if (world != null) {
|
||||
World wserv = this.getWorld(world);
|
||||
if (wserv != null) {
|
||||
wserv.unregisterAccountCharacterView(accountid, chrid);
|
||||
}
|
||||
}
|
||||
|
||||
worldChars.put(chrid, toWorld);
|
||||
|
||||
Character chrView = chr.generateCharacterEntry();
|
||||
|
||||
World wserv = this.getWorld(toWorld);
|
||||
if (wserv != null) {
|
||||
wserv.registerAccountCharacterView(chrView.getAccountID(), chrView);
|
||||
}
|
||||
} finally {
|
||||
lgnWLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public void deleteAccountEntry(Integer accountid) { is this even a thing?
|
||||
lgnWLock.lock();
|
||||
try {
|
||||
accountCharacterCount.remove(accountid);
|
||||
accountChars.remove(accountid);
|
||||
} finally {
|
||||
lgnWLock.unlock();
|
||||
}
|
||||
|
||||
for (World wserv : this.getWorlds()) {
|
||||
wserv.clearAccountCharacterView(accountid);
|
||||
wserv.unregisterAccountStorage(accountid);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public SortedMap<Integer, List<Character>> loadAccountCharlist(int accountId, int visibleWorlds) {
|
||||
List<World> worlds = this.getWorlds();
|
||||
if (worlds.size() > visibleWorlds) {
|
||||
@@ -1558,11 +1517,11 @@ public class Server {
|
||||
return worldChrs;
|
||||
}
|
||||
|
||||
private static Pair<Short, List<List<Character>>> loadAccountCharactersViewFromDb(int accId, int wlen) {
|
||||
short characterCount = 0;
|
||||
List<List<Character>> wchars = new ArrayList<>(wlen);
|
||||
for (int i = 0; i < wlen; i++) {
|
||||
wchars.add(i, new LinkedList<>());
|
||||
private static Pair<Short, List<List<Character>>> loadAccountCharactersViewFromDb(int accId, int worlds) {
|
||||
short chrCount = 0;
|
||||
List<List<Character>> worldChrs = new ArrayList<>(worlds);
|
||||
for (int i = 0; i < worlds; i++) {
|
||||
worldChrs.add(i, new LinkedList<>());
|
||||
}
|
||||
|
||||
List<Character> chars = new LinkedList<>();
|
||||
@@ -1587,32 +1546,32 @@ public class Server {
|
||||
ps.setInt(1, accId);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
characterCount++;
|
||||
chrCount++;
|
||||
|
||||
int cworld = rs.getByte("world");
|
||||
if (cworld >= wlen) {
|
||||
if (cworld >= worlds) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cworld > curWorld) {
|
||||
wchars.add(curWorld, chars);
|
||||
worldChrs.add(curWorld, chars);
|
||||
|
||||
curWorld = cworld;
|
||||
chars = new LinkedList<>();
|
||||
}
|
||||
|
||||
Integer cid = rs.getInt("id");
|
||||
chars.add(Character.loadCharacterEntryFromDB(rs, accPlayerEquips.get(cid)));
|
||||
chars.add(Character.loadCharacterViewFromDB(rs, accPlayerEquips.get(cid)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wchars.add(curWorld, chars);
|
||||
worldChrs.add(curWorld, chars);
|
||||
} catch (SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
|
||||
return new Pair<>(characterCount, wchars);
|
||||
return new Pair<>(chrCount, worldChrs);
|
||||
}
|
||||
|
||||
public void loadAllAccountsCharactersView() {
|
||||
|
||||
@@ -451,18 +451,6 @@ public class World {
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAccountCharacterView(Integer accountId) {
|
||||
accountCharsLock.lock();
|
||||
try {
|
||||
SortedMap<Integer, Character> accChars = accountChars.remove(accountId);
|
||||
if (accChars != null) {
|
||||
accChars.clear();
|
||||
}
|
||||
} finally {
|
||||
accountCharsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadAccountStorage(Integer accountId) {
|
||||
if (getAccountStorage(accountId) == null) {
|
||||
registerAccountStorage(accountId);
|
||||
|
||||
@@ -40,6 +40,7 @@ import constants.inventory.ItemConstants;
|
||||
import constants.skills.Buccaneer;
|
||||
import constants.skills.Corsair;
|
||||
import constants.skills.ThunderBreaker;
|
||||
import database.monsterbook.MonsterCard;
|
||||
import net.encryption.InitializationVector;
|
||||
import net.opcodes.SendOpcode;
|
||||
import net.packet.ByteBufOutPacket;
|
||||
@@ -526,12 +527,12 @@ public class PacketCreator {
|
||||
private static void addMonsterBookInfo(OutPacket p, Character chr) {
|
||||
p.writeInt(chr.getMonsterBookCover()); // cover
|
||||
p.writeByte(0);
|
||||
Map<Integer, Integer> cards = chr.getMonsterBook().getCards();
|
||||
List<MonsterCard> cards = chr.getMonsterBook().getCards();
|
||||
p.writeShort(cards.size());
|
||||
for (Entry<Integer, Integer> all : cards.entrySet()) {
|
||||
p.writeShort(all.getKey() % 10000); // Id
|
||||
p.writeByte(all.getValue()); // Level
|
||||
}
|
||||
cards.forEach(card -> {
|
||||
p.writeShort(card.cardId() % 10000);
|
||||
p.writeByte(card.level());
|
||||
});
|
||||
}
|
||||
|
||||
public static Packet sendGuestTOS() {
|
||||
@@ -2734,8 +2735,8 @@ public class PacketCreator {
|
||||
|
||||
MonsterBook book = chr.getMonsterBook();
|
||||
p.writeInt(book.getBookLevel());
|
||||
p.writeInt(book.getNormalCard());
|
||||
p.writeInt(book.getSpecialCard());
|
||||
p.writeInt(book.getNormalCards());
|
||||
p.writeInt(book.getSpecialCards());
|
||||
p.writeInt(book.getTotalCards());
|
||||
p.writeInt(chr.getMonsterBookCover() > 0 ? ItemInformationProvider.getInstance().getCardMobId(chr.getMonsterBookCover()) : 0);
|
||||
Item medal = chr.getInventory(InventoryType.EQUIPPED).getItem((short) -49);
|
||||
@@ -5978,13 +5979,29 @@ public class PacketCreator {
|
||||
return p;
|
||||
}
|
||||
|
||||
public static Packet showGainCard() {
|
||||
public static Packet addMonsterCard(MonsterCard monsterCard) {
|
||||
OutPacket p = OutPacket.create(SendOpcode.MONSTER_BOOK_SET_CARD);
|
||||
p.writeBool(true);
|
||||
p.writeInt(monsterCard.cardId());
|
||||
p.writeInt(monsterCard.level());
|
||||
return p;
|
||||
}
|
||||
|
||||
public static Packet addMonsterCardAlreadyFull() {
|
||||
OutPacket p = OutPacket.create(SendOpcode.MONSTER_BOOK_SET_CARD);
|
||||
p.writeBool(false);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Packet showMonsterCardEffect() {
|
||||
OutPacket p = OutPacket.create(SendOpcode.SHOW_ITEM_GAIN_INCHAT);
|
||||
p.writeByte(0x0D);
|
||||
return p;
|
||||
}
|
||||
|
||||
public static Packet showForeignCardEffect(int id) {
|
||||
public static Packet showForeignMonsterCardEffect(int id) {
|
||||
OutPacket p = OutPacket.create(SendOpcode.SHOW_FOREIGN_EFFECT);
|
||||
p.writeInt(id);
|
||||
p.writeByte(0x0D);
|
||||
|
||||
@@ -38,6 +38,20 @@ class MonsterCardTest {
|
||||
assertFalse(normalCard.isSpecial());
|
||||
}
|
||||
|
||||
@Test
|
||||
void notMaxLevel() {
|
||||
var nonMaxedCard = new MonsterCard(validCardId(), (byte) 4);
|
||||
|
||||
assertFalse(nonMaxedCard.isMaxLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isMaxLevel() {
|
||||
var maxedCard = new MonsterCard(validCardId(), (byte) 5);
|
||||
|
||||
assertTrue(maxedCard.isMaxLevel());
|
||||
}
|
||||
|
||||
private int validCardId() {
|
||||
return 2380000;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user