Autosave feature + Pet Ignore fix

Added experimental autosaver feature. Fixed pet ignore feature not
saving/loading data in some cases. Added concurrency protection for
inventory classes and monster book.
This commit is contained in:
ronancpl
2017-09-11 16:53:40 -03:00
parent e064d5cbfa
commit f387d589b2
55 changed files with 568 additions and 248 deletions

View File

@@ -30,6 +30,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import provider.MapleData;
import provider.MapleDataProvider;
@@ -43,6 +45,7 @@ import client.inventory.ItemFactory;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import constants.ItemConstants;
import java.util.Collections;
/*
* @author Flav
@@ -99,12 +102,13 @@ public class CashShop {
item = new Item(itemId, (byte) 0, count, petid);
}
if (ItemConstants.EXPIRING_ITEMS)
if(itemId == 5211048 || itemId == 5360042) { // 4 Hour 2X coupons, the period is 1, but we don't want them to last a day.
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 4));
} else {
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 24 * period));
}
if (ItemConstants.EXPIRING_ITEMS) {
if(itemId == 5211048 || itemId == 5360042) { // 4 Hour 2X coupons, the period is 1, but we don't want them to last a day.
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 4));
} else {
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 24 * period));
}
}
item.setSN(sn);
return item;
}
@@ -237,6 +241,7 @@ public class CashShop {
private List<Item> inventory = new ArrayList<>();
private List<Integer> wishList = new ArrayList<>();
private int notes = 0;
private Lock lock = new ReentrantLock();
public CashShop(int accountId, int characterId, int jobType) throws SQLException {
this.accountId = accountId;
@@ -325,13 +330,18 @@ public class CashShop {
}
public List<Item> getInventory() {
return inventory;
lock.lock();
try {
return Collections.unmodifiableList(inventory);
} finally {
lock.unlock();
}
}
public Item findByCashId(int cashId) {
boolean isRing = false;
Equip equip = null;
for (Item item : inventory) {
for (Item item : getInventory()) {
if (item.getType() == 1) {
equip = (Equip) item;
isRing = equip.getRingId() > -1;
@@ -345,11 +355,21 @@ public class CashShop {
}
public void addToInventory(Item item) {
inventory.add(item);
lock.lock();
try {
inventory.add(item);
} finally {
lock.unlock();
}
}
public void removeFromInventory(Item item) {
inventory.remove(item);
lock.lock();
try {
inventory.remove(item);
} finally {
lock.unlock();
}
}
public List<Integer> getWishList() {
@@ -458,7 +478,8 @@ public class CashShop {
ps.close();
List<Pair<Item, MapleInventoryType>> itemsWithType = new ArrayList<>();
for (Item item : inventory) {
List<Item> inv = getInventory();
for (Item item : inv) {
itemsWithType.add(new Pair<>(item, MapleItemInformationProvider.getInstance().getInventoryType(item.getItemId())));
}
@@ -466,7 +487,7 @@ public class CashShop {
ps = con.prepareStatement("DELETE FROM `wishlists` WHERE `charid` = ?");
ps.setInt(1, characterId);
ps.executeUpdate();
ps.close();
ps.close();
ps = con.prepareStatement("INSERT INTO `wishlists` VALUES (DEFAULT, ?, ?)");
ps.setInt(1, characterId);

View File

@@ -36,6 +36,8 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
import tools.Pair;
@@ -47,10 +49,11 @@ import tools.Pair;
public class MapleStorage {
private int id;
private List<Item> items;
private int meso;
private byte slots;
private Map<MapleInventoryType, List<Item>> typeItems = new HashMap<>();
private List<Item> items;
private Lock lock = new ReentrantLock();
private MapleStorage(int id, byte slots, int meso) {
this.id = id;
@@ -135,7 +138,8 @@ public class MapleStorage {
}
List<Pair<Item, MapleInventoryType>> itemsWithType = new ArrayList<>();
for (Item item : items) {
List<Item> list = getItems();
for (Item item : list) {
itemsWithType.add(new Pair<>(item, MapleItemInformationProvider.getInstance().getInventoryType(item.getItemId())));
}
@@ -146,30 +150,56 @@ public class MapleStorage {
}
public Item getItem(byte slot) {
return items.get(slot);
lock.lock();
try {
return items.get(slot);
} finally {
lock.unlock();
}
}
public Item takeOut(byte slot) {
Item ret = items.remove(slot);
Item ret;
lock.lock();
try {
ret = items.remove(slot);
} finally {
lock.unlock();
}
MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(ret.getItemId());
typeItems.put(type, new ArrayList<>(filterItems(type)));
return ret;
}
public void store(Item item) {
items.add(item);
lock.lock();
try {
items.add(item);
} finally {
lock.unlock();
}
MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(item.getItemId());
typeItems.put(type, new ArrayList<>(filterItems(type)));
}
public List<Item> getItems() {
return Collections.unmodifiableList(items);
lock.lock();
try {
return Collections.unmodifiableList(items);
} finally {
lock.unlock();
}
}
private List<Item> filterItems(MapleInventoryType type) {
List<Item> storageItems = getItems();
List<Item> ret = new LinkedList<>();
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
for (Item item : items) {
for (Item item : storageItems) {
if (ii.getInventoryType(item.getItemId()) == type) {
ret.add(item);
}
@@ -179,7 +209,8 @@ public class MapleStorage {
public byte getSlot(MapleInventoryType type, byte slot) {
byte ret = 0;
for (Item item : items) {
List<Item> storageItems = getItems();
for (Item item : storageItems) {
if (item == typeItems.get(type).get(slot)) {
return ret;
}
@@ -190,21 +221,29 @@ public class MapleStorage {
public void sendStorage(MapleClient c, int npcId) {
final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Collections.sort(items, new Comparator<Item>() {
@Override
public int compare(Item o1, Item o2) {
if (ii.getInventoryType(o1.getItemId()).getType() < ii.getInventoryType(o2.getItemId()).getType()) {
return -1;
} else if (ii.getInventoryType(o1.getItemId()) == ii.getInventoryType(o2.getItemId())) {
return 0;
lock.lock();
try {
Collections.sort(items, new Comparator<Item>() {
@Override
public int compare(Item o1, Item o2) {
if (ii.getInventoryType(o1.getItemId()).getType() < ii.getInventoryType(o2.getItemId()).getType()) {
return -1;
} else if (ii.getInventoryType(o1.getItemId()) == ii.getInventoryType(o2.getItemId())) {
return 0;
}
return 1;
}
return 1;
}
});
for (MapleInventoryType type : MapleInventoryType.values()) {
typeItems.put(type, new ArrayList<>(items));
});
} finally {
lock.unlock();
}
c.announce(MaplePacketCreator.getStorage(npcId, slots, items, meso));
List<Item> storageItems = getItems();
for (MapleInventoryType type : MapleInventoryType.values()) {
typeItems.put(type, new ArrayList<>(storageItems));
}
c.announce(MaplePacketCreator.getStorage(npcId, slots, storageItems, meso));
}
public void sendStored(MapleClient c, MapleInventoryType type) {
@@ -231,7 +270,12 @@ public class MapleStorage {
}
public boolean isFull() {
return items.size() >= slots;
lock.lock();
try {
return items.size() >= slots;
} finally {
lock.unlock();
}
}
public void close() {

View File

@@ -55,100 +55,107 @@ public class MapleLifeFactory {
}
public static MapleMonster getMonster(int mid) {
MapleMonsterStats stats = monsterStats.get(Integer.valueOf(mid));
if (stats == null) {
MapleData monsterData = data.getData(StringUtil.getLeftPaddedStr(Integer.toString(mid) + ".img", '0', 11));
if (monsterData == null) {
return null;
}
MapleData monsterInfoData = monsterData.getChildByPath("info");
stats = new MapleMonsterStats();
stats.setHp(MapleDataTool.getIntConvert("maxHP", monsterInfoData));
stats.setFriendly(MapleDataTool.getIntConvert("damagedByMob", monsterInfoData, 0) == 1);
stats.setPADamage(MapleDataTool.getIntConvert("PADamage", monsterInfoData));
stats.setPDDamage(MapleDataTool.getIntConvert("PDDamage", monsterInfoData));
stats.setMADamage(MapleDataTool.getIntConvert("MADamage", monsterInfoData));
stats.setMDDamage(MapleDataTool.getIntConvert("MDDamage", monsterInfoData));
stats.setMp(MapleDataTool.getIntConvert("maxMP", monsterInfoData, 0));
stats.setExp(MapleDataTool.getIntConvert("exp", monsterInfoData, 0));
stats.setLevel(MapleDataTool.getIntConvert("level", monsterInfoData));
stats.setRemoveAfter(MapleDataTool.getIntConvert("removeAfter", monsterInfoData, 0));
stats.setBoss(MapleDataTool.getIntConvert("boss", monsterInfoData, 0) > 0);
stats.setExplosiveReward(MapleDataTool.getIntConvert("explosiveReward", monsterInfoData, 0) > 0);
stats.setFfaLoot(MapleDataTool.getIntConvert("publicReward", monsterInfoData, 0) > 0);
stats.setUndead(MapleDataTool.getIntConvert("undead", monsterInfoData, 0) > 0);
stats.setName(MapleDataTool.getString(mid + "/name", mobStringData, "MISSINGNO"));
stats.setBuffToGive(MapleDataTool.getIntConvert("buff", monsterInfoData, -1));
stats.setCP(MapleDataTool.getIntConvert("getCP", monsterInfoData, 0));
stats.setRemoveOnMiss(MapleDataTool.getIntConvert("removeOnMiss", monsterInfoData, 0) > 0);
MapleData special = monsterInfoData.getChildByPath("coolDamage");
if (special != null) {
int coolDmg = MapleDataTool.getIntConvert("coolDamage", monsterInfoData);
int coolProb = MapleDataTool.getIntConvert("coolDamageProb", monsterInfoData, 0);
stats.setCool(new Pair<>(coolDmg, coolProb));
}
special = monsterInfoData.getChildByPath("loseItem");
if (special != null) {
for (MapleData liData : special.getChildren()) {
stats.addLoseItem(new loseItem(MapleDataTool.getInt(liData.getChildByPath("id")), (byte) MapleDataTool.getInt(liData.getChildByPath("prop")), (byte) MapleDataTool.getInt(liData.getChildByPath("x"))));
try {
MapleMonsterStats stats = monsterStats.get(Integer.valueOf(mid));
if (stats == null) {
MapleData monsterData = data.getData(StringUtil.getLeftPaddedStr(Integer.toString(mid) + ".img", '0', 11));
if (monsterData == null) {
return null;
}
}
special = monsterInfoData.getChildByPath("selfDestruction");
if (special != null) {
stats.setSelfDestruction(new selfDestruction((byte) MapleDataTool.getInt(special.getChildByPath("action")), MapleDataTool.getIntConvert("removeAfter", special, -1), MapleDataTool.getIntConvert("hp", special, -1)));
}
MapleData firstAttackData = monsterInfoData.getChildByPath("firstAttack");
int firstAttack = 0;
if (firstAttackData != null) {
if (firstAttackData.getType() == MapleDataType.FLOAT) {
firstAttack = Math.round(MapleDataTool.getFloat(firstAttackData));
} else {
firstAttack = MapleDataTool.getInt(firstAttackData);
}
}
stats.setFirstAttack(firstAttack > 0);
stats.setDropPeriod(MapleDataTool.getIntConvert("dropItemPeriod", monsterInfoData, 0) * 10000);
stats.setTagColor(MapleDataTool.getIntConvert("hpTagColor", monsterInfoData, 0));
stats.setTagBgColor(MapleDataTool.getIntConvert("hpTagBgcolor", monsterInfoData, 0));
MapleData monsterInfoData = monsterData.getChildByPath("info");
stats = new MapleMonsterStats();
stats.setHp(MapleDataTool.getIntConvert("maxHP", monsterInfoData));
stats.setFriendly(MapleDataTool.getIntConvert("damagedByMob", monsterInfoData, 0) == 1);
stats.setPADamage(MapleDataTool.getIntConvert("PADamage", monsterInfoData));
stats.setPDDamage(MapleDataTool.getIntConvert("PDDamage", monsterInfoData));
stats.setMADamage(MapleDataTool.getIntConvert("MADamage", monsterInfoData));
stats.setMDDamage(MapleDataTool.getIntConvert("MDDamage", monsterInfoData));
stats.setMp(MapleDataTool.getIntConvert("maxMP", monsterInfoData, 0));
stats.setExp(MapleDataTool.getIntConvert("exp", monsterInfoData, 0));
stats.setLevel(MapleDataTool.getIntConvert("level", monsterInfoData));
stats.setRemoveAfter(MapleDataTool.getIntConvert("removeAfter", monsterInfoData, 0));
stats.setBoss(MapleDataTool.getIntConvert("boss", monsterInfoData, 0) > 0);
stats.setExplosiveReward(MapleDataTool.getIntConvert("explosiveReward", monsterInfoData, 0) > 0);
stats.setFfaLoot(MapleDataTool.getIntConvert("publicReward", monsterInfoData, 0) > 0);
stats.setUndead(MapleDataTool.getIntConvert("undead", monsterInfoData, 0) > 0);
stats.setName(MapleDataTool.getString(mid + "/name", mobStringData, "MISSINGNO"));
stats.setBuffToGive(MapleDataTool.getIntConvert("buff", monsterInfoData, -1));
stats.setCP(MapleDataTool.getIntConvert("getCP", monsterInfoData, 0));
stats.setRemoveOnMiss(MapleDataTool.getIntConvert("removeOnMiss", monsterInfoData, 0) > 0);
for (MapleData idata : monsterData) {
if (!idata.getName().equals("info")) {
int delay = 0;
for (MapleData pic : idata.getChildren()) {
delay += MapleDataTool.getIntConvert("delay", pic, 0);
MapleData special = monsterInfoData.getChildByPath("coolDamage");
if (special != null) {
int coolDmg = MapleDataTool.getIntConvert("coolDamage", monsterInfoData);
int coolProb = MapleDataTool.getIntConvert("coolDamageProb", monsterInfoData, 0);
stats.setCool(new Pair<>(coolDmg, coolProb));
}
special = monsterInfoData.getChildByPath("loseItem");
if (special != null) {
for (MapleData liData : special.getChildren()) {
stats.addLoseItem(new loseItem(MapleDataTool.getInt(liData.getChildByPath("id")), (byte) MapleDataTool.getInt(liData.getChildByPath("prop")), (byte) MapleDataTool.getInt(liData.getChildByPath("x"))));
}
stats.setAnimationTime(idata.getName(), delay);
}
}
MapleData reviveInfo = monsterInfoData.getChildByPath("revive");
if (reviveInfo != null) {
List<Integer> revives = new LinkedList<>();
for (MapleData data_ : reviveInfo) {
revives.add(MapleDataTool.getInt(data_));
special = monsterInfoData.getChildByPath("selfDestruction");
if (special != null) {
stats.setSelfDestruction(new selfDestruction((byte) MapleDataTool.getInt(special.getChildByPath("action")), MapleDataTool.getIntConvert("removeAfter", special, -1), MapleDataTool.getIntConvert("hp", special, -1)));
}
stats.setRevives(revives);
}
decodeElementalString(stats, MapleDataTool.getString("elemAttr", monsterInfoData, ""));
MapleData monsterSkillData = monsterInfoData.getChildByPath("skill");
if (monsterSkillData != null) {
int i = 0;
List<Pair<Integer, Integer>> skills = new ArrayList<>();
while (monsterSkillData.getChildByPath(Integer.toString(i)) != null) {
skills.add(new Pair<>(Integer.valueOf(MapleDataTool.getInt(i + "/skill", monsterSkillData, 0)), Integer.valueOf(MapleDataTool.getInt(i + "/level", monsterSkillData, 0))));
i++;
MapleData firstAttackData = monsterInfoData.getChildByPath("firstAttack");
int firstAttack = 0;
if (firstAttackData != null) {
if (firstAttackData.getType() == MapleDataType.FLOAT) {
firstAttack = Math.round(MapleDataTool.getFloat(firstAttackData));
} else {
firstAttack = MapleDataTool.getInt(firstAttackData);
}
}
stats.setSkills(skills);
stats.setFirstAttack(firstAttack > 0);
stats.setDropPeriod(MapleDataTool.getIntConvert("dropItemPeriod", monsterInfoData, 0) * 10000);
stats.setTagColor(MapleDataTool.getIntConvert("hpTagColor", monsterInfoData, 0));
stats.setTagBgColor(MapleDataTool.getIntConvert("hpTagBgcolor", monsterInfoData, 0));
for (MapleData idata : monsterData) {
if (!idata.getName().equals("info")) {
int delay = 0;
for (MapleData pic : idata.getChildren()) {
delay += MapleDataTool.getIntConvert("delay", pic, 0);
}
stats.setAnimationTime(idata.getName(), delay);
}
}
MapleData reviveInfo = monsterInfoData.getChildByPath("revive");
if (reviveInfo != null) {
List<Integer> revives = new LinkedList<>();
for (MapleData data_ : reviveInfo) {
revives.add(MapleDataTool.getInt(data_));
}
stats.setRevives(revives);
}
decodeElementalString(stats, MapleDataTool.getString("elemAttr", monsterInfoData, ""));
MapleData monsterSkillData = monsterInfoData.getChildByPath("skill");
if (monsterSkillData != null) {
int i = 0;
List<Pair<Integer, Integer>> skills = new ArrayList<>();
while (monsterSkillData.getChildByPath(Integer.toString(i)) != null) {
skills.add(new Pair<>(Integer.valueOf(MapleDataTool.getInt(i + "/skill", monsterSkillData, 0)), Integer.valueOf(MapleDataTool.getInt(i + "/level", monsterSkillData, 0))));
i++;
}
stats.setSkills(skills);
}
MapleData banishData = monsterInfoData.getChildByPath("ban");
if (banishData != null) {
stats.setBanishInfo(new BanishInfo(MapleDataTool.getString("banMsg", banishData), MapleDataTool.getInt("banMap/0/field", banishData, -1), MapleDataTool.getString("banMap/0/portal", banishData, "sp")));
}
monsterStats.put(Integer.valueOf(mid), stats);
}
MapleData banishData = monsterInfoData.getChildByPath("ban");
if (banishData != null) {
stats.setBanishInfo(new BanishInfo(MapleDataTool.getString("banMsg", banishData), MapleDataTool.getInt("banMap/0/field", banishData, -1), MapleDataTool.getString("banMap/0/portal", banishData, "sp")));
}
monsterStats.put(Integer.valueOf(mid), stats);
MapleMonster ret = new MapleMonster(mid, stats);
return ret;
} catch(NullPointerException npe) {
System.out.println("[SEVERE] MOB " + mid + " failed to load. Issue: " + npe.getMessage() + "\n\n");
npe.printStackTrace();
return null;
}
MapleMonster ret = new MapleMonster(mid, stats);
return ret;
}
private static void decodeElementalString(MapleMonsterStats stats, String elemAttr) {

View File

@@ -2325,11 +2325,11 @@ public class MapleMap {
}
public void setMapPointBoundings(int px, int py, int h, int w) {
mapArea.setBounds(px, py, w, h);
mapArea.setBounds(px + 7, py, w - 14, h);
}
public void setMapLineBoundings(int vrTop, int vrBottom, int vrLeft, int vrRight) {
mapArea.setBounds(vrLeft, vrTop, vrRight - vrLeft, vrBottom - vrTop);
mapArea.setBounds(vrLeft + 7, vrTop, vrRight - vrLeft - 14, vrBottom - vrTop);
}
/**