/*
* This file is part of the OdinMS MapleStory Private Server
* Copyright (C) 2011 Patrick Huy and Matthias Butz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package server;
import client.CardData;
import constants.GameConstants;
import database.DatabaseConnection;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import tools.Pair;
import tools.Triple;
/**
*
* @author AlphaEta
*/
public class CharacterCardFactory {
private final static CharacterCardFactory instance = new CharacterCardFactory();
private final MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Etc.wz"));
private final Map<Integer, Integer> cardEffects = new HashMap<>(); // cardid, skillid
private final Map<Integer, List<Integer>> uniqueEffects = new HashMap<>(); // skillid, cardids
public static CharacterCardFactory getInstance() {
return instance;
}
public void initialize() {
final MapleData b = data.getData("CharacterCard.img");
for (MapleData c : b.getChildByPath("Card")) {
int skillId = MapleDataTool.getIntConvert("skillID", c, 0);
if (skillId > 0) {
cardEffects.put(Integer.parseInt(c.getName()), skillId);
}
}
for (MapleData c : b.getChildByPath("Deck")) {
boolean uniqueEffect = MapleDataTool.getIntConvert("uniqueEffect", c, 0) > 0;
int skillId = MapleDataTool.getIntConvert("skillID", c, 0);
if (uniqueEffect) {
final List<Integer> ids = new LinkedList<>();
for (MapleData z : c.getChildByPath("reqCardID")) {
ids.add(MapleDataTool.getIntConvert(z));
}
if (skillId > 0 && !ids.isEmpty()) {
uniqueEffects.put(skillId, ids);
}
}
}
//System.out.println("Loaded " + (cardEffects.size() + uniqueEffects.size()) + " card effects");
}
public final Triple<Integer, Integer, Integer> getCardSkill(final int job, final int level) { // cardid, skillid, skilllevel
final int skillid = cardEffects.get(job / 10);
if (skillid <= 0) {
return null;
}
return new Triple<>((skillid - 71000000), skillid, GameConstants.getSkillLevel(level));
}
public final List<Integer> getUniqueSkills(final List<Integer> special) {
final List<Integer> uis = new LinkedList<>();
for (Entry<Integer, List<Integer>> m : uniqueEffects.entrySet()) {
if (m.getValue().contains(special.get(0)) && m.getValue().contains(special.get(1)) && m.getValue().contains(special.get(2))) {
uis.add(m.getKey());
}
}
return uis;
}
public final int getRankSkill(final int level) {
return (GameConstants.getSkillLevel(level) + 71001099);
}
public final boolean canHaveCard(final int level, final int job) {
if (level < 30) {
return false;
}
return cardEffects.get(job / 10) != null;
}
public final Map<Integer, CardData> loadCharacterCards(final int accId, final int serverId) {
Map<Integer, CardData> cards = new LinkedHashMap<>(); // order
Map<Integer, Pair<Short, Short>> inf = loadCharactersInfo(accId, serverId);
try {
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM `character_cards` WHERE `accid` = ?")) {
ps.setInt(1, accId);
try (ResultSet rs = ps.executeQuery()) {
int deck1 = 0, deck2 = 3;
while (rs.next()) {
final int cid = rs.getInt("characterid");
final Pair<Short, Short> x = inf.get(cid);
if (x == null || !canHaveCard(x.getLeft(), x.getRight())) { // we don't need to delete them as it'll be there till the user reupdate the char cards
continue;
}
final int position = rs.getInt("position");
if (position < 4) {
deck1++;
cards.put(deck1, new CardData(cid, x.getLeft(), x.getRight()));
} else {
deck2++;
cards.put(deck2, new CardData(cid, x.getLeft(), x.getRight()));
}
}
}
}
} catch (SQLException sqlE) {
System.out.println("Failed to load character cards. Reason: " + sqlE.toString());
}
for (int i = 1; i <= 6; i++) {
if (cards.get(i) == null) {
cards.put(i, new CardData(0, (short) 0, (short) 0)); // fill it in
}
}
return cards;
}
public Map<Integer, Pair<Short, Short>> loadCharactersInfo(int accId, int serverId) {
Map<Integer, Pair<Short, Short>> chars = new HashMap<>();
try {
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT id, level, job FROM characters WHERE accountid = ? AND world = ?")) {
ps.setInt(1, accId);
ps.setInt(2, serverId);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
chars.put(rs.getInt("id"), new Pair<>(rs.getShort("level"), rs.getShort("job")));
}
}
}
} catch (SQLException e) {
System.err.println("error loading characters info. reason: " + e.toString());
}
return chars;
}
}