Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

[Help] Saving issues.

Newbie Spellweaver
Joined
Jul 30, 2012
Messages
59
Reaction score
15
Okay well, People in this community know me, I assume.

Okay so. I've never really had problems with the SaveToDB Function before, there's no bat errors or anything. Everything runs smoothly and perfectly. There's an issue with the Saving tho, Like if you forcibly close the client It'll roll you back to the last time you did save, Or if you log out, You'll automatically be stuck and you can log back in until a server restart, It'll just bring you back to the login screen after you click your character. Keep in mind there is no Bat file errors, so I have no clue where to look.


Code:
public void saveToDB(boolean update) {
        Connection con = DatabaseConnection.getConnection();
        try {
            con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
            con.setAutoCommit(false);
            PreparedStatement ps;
            if (update) {
                ps = con.prepareStatement("UPDATE characters SET level = ?, fame = ?, str = ?, dex = ?, luk = ?, `int` = ?, exp = ?, gachaexp = ?, hp = ?, mp = ?, expbonuses = ?, donatorpoints = ?, votepoints = ?, maxhp = ?, maxmp = ?, sp = ?, ap = ?, gm = ?, skincolor = ?, gender = ?, job = ?, hair = ?, face = ?, map = ?, meso = ?, hpMpUsed = ?, spawnpoint = ?, party = ?, buddyCapacity = ?, messengerid = ?, messengerposition = ?, mountlevel = ?, mountexp = ?, mounttiredness= ?, equipslots = ?, useslots = ?, setupslots = ?, etcslots = ?,  monsterbookcover = ?, vanquisherStage = ?, dojoPoints = ?, lastDojoStage = ?, finishedDojoTutorial = ?, vanquisherKills = ?, matchcardwins = ?, matchcardlosses = ?, matchcardties = ?, omokwins = ?, omoklosses = ?, omokties = ?, legend = ?, monstercount = ?, horntail_slyed = ?, pinkbeen_slyed = ?, occupation = ?  WHERE id = ?", Statement.RETURN_GENERATED_KEYS);
            } else {
                ps = con.prepareStatement("INSERT INTO characters (level, fame, str, dex, luk, `int`, exp, gachaexp, hp, mp, expbonuses, donatorpoints, votepoints, maxhp, maxmp, sp, ap, gm, skincolor, gender, job, hair, face, map, meso, hpMpUsed, spawnpoint, party, buddyCapacity, messengerid, messengerposition, mountlevel, mounttiredness, mountexp, equipslots, useslots, setupslots, etcslots, monsterbookcover, vanquisherStage, dojopoints, lastDojoStage, finishedDojoTutorial, vanquisherKills, matchcardwins, matchcardlosses, matchcardties, omokwins, omoklosses, omokties, legend, monstercount, horntail_slyed, pinkbeen_slyed, occupation, accountid, name, world) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
            }
            if (gmLevel < 1 && level > 199) {
                ps.setInt(1, isCygnus() ? 120 : 200);
            } else {
                ps.setInt(1, level);
            }
            ps.setInt(2, fame);
            ps.setInt(3, str);
            ps.setInt(4, dex);
            ps.setInt(5, luk);
            ps.setInt(6, int_);
            ps.setInt(7, Math.abs(exp.get()));
            ps.setInt(8, Math.abs(gachaexp.get()));
            ps.setInt(9, hp);
            ps.setInt(10, mp);
            ps.setInt(11, expbonuses);
            ps.setInt(12, DonatorPoints);
            ps.setInt(13, VotePoints);
            ps.setInt(14, maxhp);
            ps.setInt(15, maxmp);
            ps.setInt(16, remainingSp);
            ps.setInt(17, remainingAp);
            ps.setInt(18, gmLevel);
            ps.setInt(19, skinColor.getId());
            ps.setInt(20, gender);
            ps.setInt(21, job.getId());
            ps.setInt(22, hair);
            ps.setInt(23, face);
            if (map == null && getJob() == MapleJob.BEGINNER) {
                ps.setInt(24, 100000000);
            } else if (map == null && getJob() == MapleJob.NOBLESSE) {
                ps.setInt(24, 100000000);
            } else if (map == null && getJob() == MapleJob.LEGEND) {
                ps.setInt(24, 100000000);
            } else {
                if (map.getForcedReturnId() != 999999999) {
                    ps.setInt(24, map.getForcedReturnId());
                } else {
                    ps.setInt(24, map.getId());
                }
            }
            ps.setInt(25, meso.get());
            ps.setInt(26, hpMpApUsed);
            if (map == null || map.getId() == 610020000 || map.getId() == 610020001) {
                ps.setInt(27, 0);
            } else {
                MaplePortal closest = map.findClosestSpawnpoint(getPosition());
                if (closest != null) {
                    ps.setInt(27, closest.getId());
                } else {
                    ps.setInt(27, 0);
                }
            }
            if (party != null) {
                ps.setInt(28, party.getId());
            } else {
                ps.setInt(28, -1);
            }
            ps.setInt(29, buddylist.getCapacity());
            if (messenger != null) {
                ps.setInt(30, messenger.getId());
                ps.setInt(31, messengerposition);
            } else {
                ps.setInt(30, 0);
                ps.setInt(31, 4);
            }
            if (maplemount != null) {
                ps.setInt(32, maplemount.getLevel());
                ps.setInt(33, maplemount.getExp());
                ps.setInt(34, maplemount.getTiredness());
            } else {
                ps.setInt(32, 1);
                ps.setInt(33, 0);
                ps.setInt(34, 0);
            }
            for (int i = 1; i < 5; i++)
	          ps.setInt(i + 34, getSlots(i)); // gotta change the 32 if you add new values before it like expbonuses

            if (update) {
                monsterbook.saveCards(getId());
            }
            ps.setInt(39, bookCover);
            ps.setInt(40, vanquisherStage);
            ps.setInt(41, dojoPoints);
            ps.setInt(42, dojoStage);
            ps.setInt(43, finishedDojoTutorial ? 1 : 0);
            ps.setInt(44, vanquisherKills);
            ps.setInt(45, matchcardwins);
            ps.setInt(46, matchcardlosses);
            ps.setInt(47, matchcardties);
            ps.setInt(48, omokwins);
            ps.setInt(49, omoklosses);
            ps.setInt(50, omokties);
            ps.setInt(51, legend);
            ps.setInt(52, monstercount);
            ps.setInt(53, horntail_slyed);
            ps.setInt(54, pinkbeen_slyed);
            ps.setInt(55, occupation);
            if (update) {
                ps.setInt(56, id);
            } else {
                ps.setInt(56, accountid);
                ps.setString(57, name);
                ps.setInt(58, world);
            }
            
            int updateRows = ps.executeUpdate();
            if (!update) {
                ResultSet rs = ps.getGeneratedKeys();
                if (rs.next()) {
                    this.id = rs.getInt(1);
                } else {
                    throw new RuntimeException("Inserting char failed.");
                }
            } else if (updateRows < 1) {
                throw new RuntimeException("Character not in database (" + id + ") " + name);
            }
            for (int i = 0; i < 3; i++) {
                if (pets[i] != null) {
                    pets[i].saveToDb();
                }
            }
            deleteWhereCharacterId(con, "DELETE FROM keymap WHERE characterid = ?");
            ps = con.prepareStatement("INSERT INTO keymap (characterid, `key`, `type`, `action`) VALUES (?, ?, ?, ?)");
            ps.setInt(1, id);
            for (Entry<Integer, MapleKeyBinding> keybinding : keymap.entrySet()) {
                ps.setInt(2, keybinding.getKey().intValue());
                ps.setInt(3, keybinding.getValue().getType());
                ps.setInt(4, keybinding.getValue().getAction());
                ps.addBatch();
            }
            ps.executeBatch();
            deleteWhereCharacterId(con, "DELETE FROM skillmacros WHERE characterid = ?");
            ps = con.prepareStatement("INSERT INTO skillmacros (characterid, skill1, skill2, skill3, name, shout, position) VALUES (?, ?, ?, ?, ?, ?, ?)");
            ps.setInt(1, getId());
            for (int i = 0; i < 5; i++) {
                SkillMacro macro = skillMacros[i];
                if (macro != null) {
                    ps.setInt(2, macro.getSkill1());
                    ps.setInt(3, macro.getSkill2());
                    ps.setInt(4, macro.getSkill3());
                    ps.setString(5, macro.getName());
                    ps.setInt(6, macro.getShout());
                    ps.setInt(7, i);
                    ps.addBatch();
                }
            }
            ps.executeBatch();
            List<Pair<IItem, MapleInventoryType>> itemsWithType = new ArrayList<Pair<IItem, MapleInventoryType>>();

            for (MapleInventory iv : inventory) {
                for (IItem item : iv.list()) {
                    itemsWithType.add(new Pair<IItem, MapleInventoryType>(item, iv.getType()));
                }
            }

            ItemFactory.INVENTORY.saveItems(itemsWithType, id);
            deleteWhereCharacterId(con, "DELETE FROM skills WHERE characterid = ?");
            ps = con.prepareStatement("INSERT INTO skills (characterid, skillid, skilllevel, masterlevel, expiration) VALUES (?, ?, ?, ?, ?)");
            ps.setInt(1, id);
            for (Entry<ISkill, SkillEntry> skill : skills.entrySet()) {
                ps.setInt(2, skill.getKey().getId());
                ps.setInt(3, skill.getValue().skillevel);
                ps.setInt(4, skill.getValue().masterlevel);
                ps.setLong(5, skill.getValue().expiration);
                ps.addBatch();
            }
            ps.executeBatch();
            deleteWhereCharacterId(con, "DELETE FROM savedlocations WHERE characterid = ?");
            ps = con.prepareStatement("INSERT INTO savedlocations (characterid, `locationtype`, `map`, `portal`) VALUES (?, ?, ?, ?)");
            ps.setInt(1, id);
            for (SavedLocationType savedLocationType : SavedLocationType.values()) {
                if (savedLocations[savedLocationType.ordinal()] != null) {
                    ps.setString(2, savedLocationType.name());
                    ps.setInt(3, savedLocations[savedLocationType.ordinal()].getMapId());
                    ps.setInt(4, savedLocations[savedLocationType.ordinal()].getPortal());
                    ps.addBatch();
                }
            }
            ps.executeBatch();
            deleteWhereCharacterId(con, "DELETE FROM buddies WHERE characterid = ? AND pending = 0");
            ps = con.prepareStatement("INSERT INTO buddies (characterid, `buddyid`, `pending`, `group`) VALUES (?, ?, 0, ?)");
            ps.setInt(1, id);
            for (BuddylistEntry entry : buddylist.getBuddies()) {
                if (entry.isVisible()) {
                    ps.setInt(2, entry.getCharacterId());
                    ps.setString(3, entry.getGroup());
                    ps.addBatch();
                }
            }
            ps.executeBatch();
            deleteWhereCharacterId(con, "DELETE FROM queststatus WHERE characterid = ?");
            ps = con.prepareStatement("INSERT INTO queststatus (`queststatusid`, `characterid`, `quest`, `status`, `time`, `forfeited`) VALUES (DEFAULT, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
            PreparedStatement pse = con.prepareStatement("INSERT INTO queststatusmobs VALUES (DEFAULT, ?, ?, ?)");
            ps.setInt(1, id);
            for (MapleQuestStatus q : quests.values()) {
                ps.setInt(2, q.getQuest().getId());
                ps.setInt(3, q.getStatus().getId());
                ps.setInt(4, (int) (q.getCompletionTime() / 1000));
                ps.setInt(5, q.getForfeited());
                ps.executeUpdate();
                ResultSet rs = ps.getGeneratedKeys();
                rs.next();
                for (int mob : q.getMobKills().keySet()) {
                    pse.setInt(1, rs.getInt(1));
                    pse.setInt(2, mob);
                    pse.setInt(3, q.getMobKills(mob));
                    pse.addBatch();
                }
                pse.executeBatch();
                rs.close();
            }
            pse.close();
            ps = con.prepareStatement("UPDATE accounts SET gm = ? WHERE id = ?");
            ps.setInt(1, gmLevel);
            ps.setInt(2, client.getAccID());
            ps.executeUpdate();
            if (cashshop != null) {
                cashshop.save();
            }
            if (storage != null) {
                storage.saveToDB();
            }

            if (gmLevel > 1) {
                ps = con.prepareStatement("INSERT INTO gmlog (`cid`, `command`) VALUES (?, ?)");
                ps.setInt(1, id);
                for (String com : commands) {
                    ps.setString(2, com);
                    ps.addBatch();
                }
                ps.executeBatch();
            }
            ps.close();
            con.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                con.rollback();
            } catch (SQLException se) {
            }
        } finally {
            try {
                con.setAutoCommit(true);
                con.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
            } catch (Exception e) {
            }
        }
    }


Again I have no clue what could be wrong. It might not even be savetoDB it could be something completely different.
 
Junior Spellweaver
Joined
Jan 4, 2013
Messages
162
Reaction score
29
Have you try checking for saveToDB() in locations like "MapleClient.java --> disconnect()" or "ChangeMapHandler.java --> handlePacket()". Has this happen in the past with your source / repack? Do you also have a log file? I'm just thinking that it having issue saving somewhere like your character and maybe it just stuck in a loop, do you experience any lag on the server or sudden changes after disconnecting and being unable to log in again? Have you ever try to log in and log out with out using @save? If so, did you have issue logging back in?

Maybe try replacing this in your saveToDB()?

PHP:
 } catch (Exception e) {
     e.printStackTrace();
     try {
          con.rollback();
     } catch (SQLException se) {
     }

with this:

PHP:
} catch (SQLException | RuntimeException t) {
     System.out.println("Error saving " + name + " Level: " + level + " Job: " + job.getId());
     try {
          con.rollback();
      } catch (SQLException se) {
          System.out.println("Error trying to rollback " + name);
      }
 
Last edited:
Upvote 0
Newbie Spellweaver
Joined
Jul 30, 2012
Messages
59
Reaction score
15
Yes, every time I try logging back in when I log out, I need to restart the server in order to get in game. Otherwise I just disconnect at the character selection screen. BUT, as I've discovered this is only with Admin accounts. As on the server I'm working with the only people I've had on here were all Admins so it took me quite a while to figure that out. Lololol. But I'll try replacing it and thank you. c:

Edit.

I was completely wrong, It's not just admin accounts It's still doing it. Let me check the Uhh save to db in those places and try replacing that. I'll get back to you. Anyway, any more thoughts on this?
Also no lag when using the save command.
 
Last edited:
Upvote 0
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
Yes, every time I try logging back in when I log out, I need to restart the server in order to get in game. Otherwise I just disconnect at the character selection screen. BUT, as I've discovered this is only with Admin accounts. As on the server I'm working with the only people I've had on here were all Admins so it took me quite a while to figure that out. Lololol. But I'll try replacing it and thank you. c:

Edit.

I was completely wrong, It's not just admin accounts It's still doing it. Let me check the Uhh save to db in those places and try replacing that. I'll get back to you. Anyway, any more thoughts on this?
Also no lag when using the save command.

what happens when you try to log in again? id already logged in or when you click your character it returns unable to connect to the game server? I think the issue may lie in MapleClient's disconnect function as that's what should be saving your character and logging its instance out. If it's id already logged in, its not updating the login status upon logout like it should. If it's unable to connect, it's your playerstorage instance stuck ingame and won't duplicate itself so you dc.
 
Upvote 0
Newbie Spellweaver
Joined
Jul 30, 2012
Messages
59
Reaction score
15
Base is moople dev, And I get id already logged in, And I switch it out though mysql to logged in 2 to 0, and I can get to the character selection with that then it just goes back to the login screen and I can't log in unless I restart the server or make a new account.

Code:
public void disconnect() {
        if (player != null && isLoggedIn()) {
            if (player.getTrade() != null) {
                MapleTrade.cancelTrade(player);
            }
            player.saveCooldowns();
            MapleMiniGame game = player.getMiniGame();
            if (game != null) {
                player.setMiniGame(null);
                if (game.isOwner(player)) {
                    player.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(player));
                    game.broadcastToVisitor(MaplePacketCreator.getMiniGameClose());
                } else {
                    game.removeVisitor(player);
                }
            }
            player.cancelAllBuffs();
            if (player.getEventInstance() != null) {
                player.getEventInstance().playerDisconnected(player);
            }
            HiredMerchant merchant = player.getHiredMerchant();
            if (merchant != null) {
                if (merchant.isOwner(player)) {
                    merchant.setOpen(true);
                } else {
                    merchant.removeVisitor(player);
                }
                try {
                    merchant.saveItems();
                } catch (SQLException ex) {
                    System.out.println("Error while saving Hired Merchant items.");
                }
            }
            player.unequipAllPets();
            try {
                WorldChannelInterface wci = getChannelServer().getWorldInterface();
                if (player.getMessenger() != null) {
                    MapleMessengerCharacter messengerplayer = new MapleMessengerCharacter(player);
                    wci.leaveMessenger(player.getMessenger().getId(), messengerplayer);
                    player.setMessenger(null);
                }
            } catch (RemoteException e) {
                getChannelServer().reconnectWorld();
            }
            NPCScriptManager npcsm = NPCScriptManager.getInstance();
            if (npcsm != null) {
                npcsm.dispose(this);
            }
            if (!player.isAlive()) {
                player.setHp(50, true);
            }
            player.setMessenger(null);
            player.getExpirationTask().cancel(true);
            player.saveToDB(true);
            player.getMap().removePlayer(player);
            try {
                WorldChannelInterface wci = getChannelServer().getWorldInterface();
                if (player.getParty() != null) {
                    MaplePartyCharacter chrp = new MaplePartyCharacter(player);
                    chrp.setOnline(false);
                    wci.updateParty(player.getParty().getId(), PartyOperation.LOG_ONOFF, chrp);
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            try {
                WorldChannelInterface wci = getChannelServer().getWorldInterface();
                if (!this.serverTransition && isLoggedIn()) {
                    wci.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
                } else {
                    wci.loggedOn(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
                }
                if (player.getGuildId() > 0) {
                    wci.setGuildMemberOnline(player.getMGC(), false, -1);
                    int allianceId = player.getGuild().getAllianceId();
                    if (allianceId > 0) {
                        wci.allianceMessage(allianceId, MaplePacketCreator.allianceMemberOnline(player, false), player.getId(), -1);
                    }
                }
            } catch (RemoteException e) {
                getChannelServer().reconnectWorld();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (getChannelServer() != null) {
                    getChannelServer().removePlayer(player);
                }
                player = null;
                session.close(true);
            }
        }
        if (!this.serverTransition && isLoggedIn()) {
            this.updateLoginState(LOGIN_NOTLOGGEDIN);
        }
    }
 
Last edited:
Upvote 0
Newbie Spellweaver
Joined
Jul 30, 2012
Messages
59
Reaction score
15
It literally says "Chrotle caught an exception Java.lang" And that's it. Lol.
 
Upvote 0
Back
Top