Здравствуйте! Сборка: Please login or register to view links Клиент: Установлены: MySQL 5.5 и Navicat for MySQL No-ip: Спойлер Please login or register to view links - Please login or register to view links 1. Проблема в том, что квесты не сохраняются. Открываю новый акк, захожу в игру, делаю пару квестов, апаю лвл беру дроп. После перезахода в игру лвл и дроп стоит на месте, персонаж тоже там где остался, но вот Квесты все пропали до нуля. При повторном входе, заново идёт ролик который показывается когда открываешь нового перса (Квест Вступление). Спойлер При это в консоли ГС ничего такого нету (помоему). Спойлер 2. Захожу в Navicat даю админ права через account_data (Пишу там значение 3 или 5). Захожу в игру, выбираю персонажа, после загрузки экрана игры вылетает. Спойлер Скрин логов ГС при ошибке клиента: Спойлер Конкретная ошибка в логах: Спойлер Код: 2019-06-13 19:00:50,610 ERROR [ReadWrite-0 Dispatcher] com.aionemu.commons.network.Dispatcher [Dispatcher.java:111] Dispatcher error! java.lang.StringIndexOutOfBoundsException: String index out of range: -1 java.lang.StringIndexOutOfBoundsException: String index out of range: -1 at java.lang.String.substring(String.java:1937) ~[na:1.6.0_45] at com.aionemu.gameserver.model.gameobjects.player.Player.getCustomTag(Player.java:2272) ~[free_game.jar:na] at com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_INFO.writeImpl(SM_PLAYER_INFO.java:110) ~[free_game.jar:na] at com.aionemu.gameserver.network.aion.AionServerPacket.write(AionServerPacket.java:69) ~[free_game.jar:na] at com.aionemu.gameserver.network.aion.AionConnection.writeData(AionConnection.java:250) ~[free_game.jar:na] at com.aionemu.commons.network.Dispatcher.write(Dispatcher.java:287) ~[al-commons-1.3.jar:na] at com.aionemu.commons.network.AcceptReadWriteDispatcherImpl.dispatch(AcceptReadWriteDispatcherImpl.java:81) ~[al-commons-1.3.jar:na] at com.aionemu.commons.network.Dispatcher.run(Dispatcher.java:105) ~[al-commons-1.3.jar:na] Если кто то знает помоги плиз что за ошибка? В клиенте что то не так или в сборке? Замучился
Player.getCustomTag отключи админ теги для начала (в конфигах админки), на тэги ругается. Далее по коду ошибки пакет SM_PLAYER_INFO строка 110, надо смотреть что в ней у тебя.
Спасибо за быстрый отзыв, действительно краш клиента из за админ тэгов, в пакете SM_PLAYER_INFO строка 110 тоже именно про админ тегов. Извиняюсь, за то, что не посмотрел внимательно логи. Спасибо за отзыв! Извиняюсь за тупость, но я не так уж хорошо понимаю в сборке. Подскажите пожалуйся где именно смотреть? какие скрипты?
MySQL5PlayerQuestListDAO.java Спойлер Код: package mysql5; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; import java.util.Collection; import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.aionemu.commons.database.DatabaseFactory; import com.aionemu.commons.utils.GenericValidator; import com.aionemu.gameserver.dao.MySQL5DAOUtils; import com.aionemu.gameserver.dao.PlayerQuestListDAO; import com.aionemu.gameserver.model.gameobjects.PersistentState; import com.aionemu.gameserver.model.gameobjects.player.Player; import com.aionemu.gameserver.model.gameobjects.player.QuestStateList; import com.aionemu.gameserver.questEngine.model.QuestState; import com.aionemu.gameserver.questEngine.model.QuestStatus; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; /** * @author MrPoke * @modified vlog, Rolandas */ public class MySQL5PlayerQuestListDAO extends PlayerQuestListDAO { private static final Logger log = LoggerFactory.getLogger(MySQL5PlayerQuestListDAO.class); public static final String SELECT_QUERY = "SELECT `quest_id`, `status`, `quest_vars`, `complete_count`, `next_repeat_time`, `reward`, `complete_time` FROM `player_quests` WHERE `player_id`=?"; public static final String UPDATE_QUERY = "UPDATE `player_quests` SET `status`=?, `quest_vars`=?, `complete_count`=?, `next_repeat_time`=?, `reward`=?, `complete_time`=? WHERE `player_id`=? AND `quest_id`=?"; public static final String DELETE_QUERY = "DELETE FROM `player_quests` WHERE `player_id`=? AND `quest_id`=?"; public static final String INSERT_QUERY = "INSERT INTO `player_quests` (`player_id`, `quest_id`, `status`, `quest_vars`, `complete_count`, `next_repeat_time`, `reward`, `complete_time`) VALUES (?,?,?,?,?,?,?,?)"; private static final Predicate<QuestState> questsToAddPredicate = new Predicate<QuestState>() { @Override public boolean apply(@Nullable QuestState input) { return input != null && PersistentState.NEW == input.getPersistentState(); } }; private static final Predicate<QuestState> questsToUpdatePredicate = new Predicate<QuestState>() { @Override public boolean apply(@Nullable QuestState input) { return input != null && PersistentState.UPDATE_REQUIRED == input.getPersistentState(); } }; private static final Predicate<QuestState> questsToDeletePredicate = new Predicate<QuestState>() { @Override public boolean apply(@Nullable QuestState input) { return input != null && PersistentState.DELETED == input.getPersistentState(); } }; @Override public QuestStateList load(final Player player) { QuestStateList questStateList = new QuestStateList(); Connection con = null; PreparedStatement stmt = null; try { con = DatabaseFactory.getConnection(); stmt = con.prepareStatement(SELECT_QUERY); stmt.setInt(1, player.getObjectId()); ResultSet rset = stmt.executeQuery(); while (rset.next()) { int questId = rset.getInt("quest_id"); int questVars = rset.getInt("quest_vars"); int completeCount = rset.getInt("complete_count"); Timestamp nextRepeatTime = rset.getTimestamp("next_repeat_time"); Integer reward = rset.getInt("reward"); if (rset.wasNull()) reward = 0; Timestamp completeTime = rset.getTimestamp("complete_time"); QuestStatus status = QuestStatus.valueOf(rset.getString("status")); QuestState questState = new QuestState(questId, status, questVars, completeCount, nextRepeatTime, reward, completeTime); questState.setPersistentState(PersistentState.UPDATED); questStateList.addQuest(questId, questState); } rset.close(); } catch (Exception e) { log.error( "Could not restore QuestStateList data for player: " + player.getObjectId() + " from DB: " + e.getMessage(), e); } finally { DatabaseFactory.close(stmt, con); } return questStateList; } @Override public void store(Player player) { Collection<QuestState> qsList = player.getQuestStateList().getAllQuestState(); if (GenericValidator.isBlankOrNull(qsList)) { return; } Connection con = null; try { con = DatabaseFactory.getConnection(); con.setAutoCommit(false); deleteQuest(con, player.getObjectId(), qsList); addQuests(con, player.getObjectId(), qsList); updateQuests(con, player.getObjectId(), qsList); } catch (SQLException e) { log.error("Can't save quests for player " + player.getObjectId(), e); } finally { DatabaseFactory.close(con); } for (QuestState qs : qsList) { qs.setPersistentState(PersistentState.UPDATED); } } private void addQuests(Connection con, int playerId, Collection<QuestState> states) { states = Collections2.filter(states, questsToAddPredicate); if (GenericValidator.isBlankOrNull(states)) { return; } PreparedStatement ps = null; try { ps = con.prepareStatement(INSERT_QUERY); for (QuestState qs : states) { ps.setInt(1, playerId); ps.setInt(2, qs.getQuestId()); ps.setString(3, qs.getStatus().toString()); ps.setInt(4, qs.getQuestVars().getQuestVars()); ps.setInt(5, qs.getCompleteCount()); if (qs.getNextRepeatTime() != null) { ps.setTimestamp(6, qs.getNextRepeatTime()); } else { ps.setNull(6, Types.TIMESTAMP); } if (qs.getReward() == null) { ps.setNull(7, Types.INTEGER); } else { ps.setInt(7, qs.getReward()); } if (qs.getCompleteTime() == null) ps.setNull(8, Types.TIMESTAMP); else ps.setTimestamp(8, qs.getCompleteTime()); ps.addBatch(); } ps.executeBatch(); con.commit(); } catch (SQLException e) { log.error("Failed to insert new quests for player " + playerId); } finally { DatabaseFactory.close(ps); } } private void updateQuests(Connection con, int playerId, Collection<QuestState> states) { states = Collections2.filter(states, questsToUpdatePredicate); if (GenericValidator.isBlankOrNull(states)) { return; } PreparedStatement ps = null; try { ps = con.prepareStatement(UPDATE_QUERY); for (QuestState qs : states) { ps.setString(1, qs.getStatus().toString()); ps.setInt(2, qs.getQuestVars().getQuestVars()); ps.setInt(3, qs.getCompleteCount()); if (qs.getNextRepeatTime() != null) { ps.setTimestamp(4, qs.getNextRepeatTime()); } else { ps.setNull(4, Types.TIMESTAMP); } if (qs.getReward() == null) { ps.setNull(5, Types.SMALLINT); } else { ps.setInt(5, qs.getReward()); } if (qs.getCompleteTime() == null) ps.setNull(6, Types.TIMESTAMP); else ps.setTimestamp(6, qs.getCompleteTime()); ps.setInt(7, playerId); ps.setInt(8, qs.getQuestId()); ps.addBatch(); } ps.executeBatch(); con.commit(); } catch (SQLException e) { log.error("Failed to update existing quests for player " + playerId); } finally { DatabaseFactory.close(ps); } } private void deleteQuest(Connection con, int playerId, Collection<QuestState> states) { states = Collections2.filter(states, questsToDeletePredicate); if (GenericValidator.isBlankOrNull(states)) { return; } PreparedStatement ps = null; try { ps = con.prepareStatement(DELETE_QUERY); for (QuestState qs : states) { ps.setInt(1, playerId); ps.setInt(2, qs.getQuestId()); ps.addBatch(); } ps.executeBatch(); con.commit(); } catch (SQLException e) { log.error("Failed to delete existing quests for player " + playerId); } finally { DatabaseFactory.close(ps); } } /** * {@inheritDoc} */ @Override public boolean supports(String s, int i, int i1) { return MySQL5DAOUtils.supports(s, i, i1); } } Я хотел сказать в самой игре все квесты падают до нуля, т.е. до квеста Вступления. А в БД я вижу только таблицу "player_quests", и там у меня это Спойлер После несколько тестов, понял что в данную таблицу идут записи тех квестов которые начаты и ещё не выполнены. А те квесты которые я выполнил тут нету. В консоле сервера при выполнении квеста пишет: Спойлер Код: 2019-06-13 22:21:45,725 INFO [PacketProcessor:1] com.aionemu.gameserver.services.QuestService [QuestService.java:290] [QUEST]Player: Testcomplete quest Id: 1000 2019-06-13 22:21:45,826 INFO [PacketProcessor:2] com.aionemu.gameserver.taskmanager.AbstractPeriodicTaskManager [AbstractPeriodicTaskManager.java:41] PlayerMoveTaskManager: Initialized. 2019-06-13 22:22:49,235 INFO [PacketProcessor:3] com.aionemu.gameserver.services.QuestService [QuestService.java:290] [QUEST]Player: Testcomplete quest Id: 1101 2019-06-13 22:23:45,896 INFO [PacketProcessor:2] com.aionemu.gameserver.services.QuestService [QuestService.java:290] [QUEST]Player: Testcomplete quest Id: 1102 2019-06-13 22:24:21,270 INFO [pool-3-thread-11] com.aionemu.gameserver.services.GameTimeService [GameTimeService.java:52] Sending current game time to all players 2019-06-13 22:24:21,270 INFO [pool-3-thread-11] com.aionemu.gameserver.utils.gametime.GameTimeManager [GameTimeManager.java:74] Game time saved... 2019-06-13 22:24:44,758 INFO [PacketProcessor:2] com.aionemu.gameserver.services.QuestService [QuestService.java:290] [QUEST]Player: Testcomplete quest Id: 1103 2019-06-13 22:25:16,739 INFO [PacketProcessor:1] com.aionemu.gameserver.services.QuestService [QuestService.java:290] [QUEST]Player: Testcomplete quest Id: 1205 2019-06-13 22:25:26,752 INFO [PacketProcessor:2] com.aionemu.gameserver.services.QuestService [QuestService.java:290] [QUEST]Player: Testcomplete quest Id: 1100 2019-06-13 22:27:21,272 INFO [pool-3-thread-8] com.aionemu.gameserver.services.GameTimeService [GameTimeService.java:52] Sending current game time to all players 2019-06-13 22:27:21,272 INFO [pool-3-thread-8] com.aionemu.gameserver.utils.gametime.GameTimeManager [GameTimeManager.java:74] Game time saved... 2019-06-13 22:28:23,513 INFO [PacketProcessor:1] com.aionemu.gameserver.services.QuestService [QuestService.java:290] [QUEST]Player: Testcomplete quest Id: 1001 Я извиняюсь, но я даже не знаю что там смотреть QuestState.java Спойлер Код: package com.aionemu.gameserver.questEngine.model; import java.sql.Timestamp; import java.util.Calendar; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.aionemu.gameserver.dataholders.DataManager; import com.aionemu.gameserver.model.gameobjects.PersistentState; import com.aionemu.gameserver.model.templates.QuestTemplate; import com.aionemu.gameserver.model.templates.quest.QuestCategory; /** * @author MrPoke * @modified vlog, Rolandas */ public class QuestState { private final int questId; private QuestVars questVars; private QuestStatus status; private int completeCount; private Timestamp completeTime; private Timestamp nextRepeatTime; private Integer reward; private PersistentState persistentState; private static final Logger log = LoggerFactory.getLogger(QuestState.class); public QuestState(int questId, QuestStatus status, int questVars, int completeCount, Timestamp nextRepeatTime, Integer reward, Timestamp completeTime) { this.questId = questId; this.status = status; this.questVars = new QuestVars(questVars); this.completeCount = completeCount; this.nextRepeatTime = nextRepeatTime; this.reward = reward; this.completeTime = completeTime; this.persistentState = PersistentState.NEW; } public QuestVars getQuestVars() { return questVars; } /** * @param id * @param var */ public void setQuestVarById(int id, int var) { questVars.setVarById(id, var); setPersistentState(PersistentState.UPDATE_REQUIRED); } /** * @param id * @return Quest var by id. */ public int getQuestVarById(int id) { return questVars.getVarById(id); } public void setQuestVar(int var) { questVars.setVar(var); setPersistentState(PersistentState.UPDATE_REQUIRED); } public QuestStatus getStatus() { return status; } public void setStatus(QuestStatus status) { if (status == QuestStatus.COMPLETE && this.status != QuestStatus.COMPLETE) updateCompleteTime(); this.status = status; setPersistentState(PersistentState.UPDATE_REQUIRED); } public Timestamp getCompleteTime() { return completeTime; } public void setCompleteTime(Timestamp time) { completeTime = time; } public void updateCompleteTime() { completeTime = new Timestamp(Calendar.getInstance().getTimeInMillis()); } public int getQuestId() { return questId; } public void setCompleteCount(int completeCount) { this.completeCount = completeCount; setPersistentState(PersistentState.UPDATE_REQUIRED); } public int getCompleteCount() { return completeCount; } public void setNextRepeatTime(Timestamp nextRepeatTime) { this.nextRepeatTime = nextRepeatTime; } public Timestamp getNextRepeatTime() { return nextRepeatTime; } public void setReward(Integer reward) { this.reward = reward; setPersistentState(PersistentState.UPDATE_REQUIRED); } public Integer getReward() { if (reward == null) { log.warn("No reward for the quest " + String.valueOf(questId)); } else { return reward; } return 0; } public boolean canRepeat() { QuestTemplate template = DataManager.QUEST_DATA.getQuestById(questId); if (status == QuestStatus.COMPLETE && template.getCategory() == QuestCategory.EVENT) return true; if (status != QuestStatus.NONE && (status != QuestStatus.COMPLETE || (completeCount >= template.getMaxRepeatCount() && template.getMaxRepeatCount() != 255))) { return false; } if (questVars.getQuestVars() != 0) { return false; } if (template.isTimeBased() && nextRepeatTime != null) { Timestamp currentTime = new Timestamp(System.currentTimeMillis()); if (currentTime.before(nextRepeatTime)) { return false; } } return true; } /** * @return the pState */ public PersistentState getPersistentState() { return persistentState; } /** * @param persistentState * the pState to set */ public void setPersistentState(PersistentState persistentState) { switch (persistentState) { case DELETED: if (this.persistentState == PersistentState.NEW) break; default: this.persistentState = persistentState; } } } QuestStateList.java Спойлер Код: package com.aionemu.gameserver.model.gameobjects.player; import java.util.ArrayList; import java.util.Collection; import java.util.SortedMap; import java.util.TreeMap; import javolution.util.FastList; import org.slf4j.LoggerFactory; import org.slf4j.Logger; import com.aionemu.gameserver.dataholders.DataManager; import com.aionemu.gameserver.dataholders.QuestsData; import com.aionemu.gameserver.model.templates.quest.QuestCategory; import com.aionemu.gameserver.questEngine.model.QuestState; import com.aionemu.gameserver.questEngine.model.QuestStatus; /** * @author MrPoke */ public class QuestStateList { private static final Logger log = LoggerFactory.getLogger(QuestStateList.class); private final SortedMap<Integer, QuestState> _quests; private QuestsData _questData = DataManager.QUEST_DATA; /** * Creates an empty quests list */ public QuestStateList() { _quests = new TreeMap<Integer, QuestState>(); } public synchronized boolean addQuest(int questId, QuestState questState) { if (_quests.containsKey(questId)) { log.warn("Duplicate quest. "); return false; } _quests.put(questId, questState); return true; } public synchronized boolean removeQuest(int questId) { if (_quests.containsKey(questId)) { _quests.remove(questId); return true; } return false; } public QuestState getQuestState(int questId) { return _quests.get(questId); } public Collection<QuestState> getAllQuestState() { return _quests.values(); } public FastList<QuestState> getAllFinishedQuests() { FastList<QuestState> completeQuestList = FastList.newInstance(); for (QuestState qs : _quests.values()) { if (qs.getStatus() == QuestStatus.COMPLETE) { completeQuestList.add(qs); } } return completeQuestList; } /* * Issue #13 fix Used by the QuestService to check the amount of normal quests in the player's list * @author vlog */ public int getNormalQuestListSize() { return this.getNormalQuests().size(); } /* * Issue #13 fix Returns the list of normal quests * @author vlog */ public Collection<QuestState> getNormalQuests() { Collection<QuestState> l = new ArrayList<QuestState>(); for (QuestState qs : this.getAllQuestState()) { QuestCategory qc = _questData.getQuestById(qs.getQuestId()).getCategory(); String name = _questData.getQuestById(qs.getQuestId()).getName(); QuestStatus s = qs.getStatus(); if (s != QuestStatus.COMPLETE && s != QuestStatus.LOCKED && s != QuestStatus.NONE && qc == QuestCategory.QUEST && !name.startsWith("[Event]")) { l.add(qs); } } return l; } /* * Returns true if there is a quest in the list with this id Used by the QuestService * @author vlog */ public boolean hasQuest(int questId) { return _quests.containsKey(questId); } /* * Change the old value of the quest status to the new one Used by the QuestService * @author vlog */ public void changeQuestStatus(Integer key, QuestStatus newStatus) { _quests.get(key).setStatus(newStatus); } public int size() { return this._quests.size(); } public SortedMap<Integer, QuestState> getQuests() { return this._quests; } } Помогите пожалуйста..
возьми другую сборку где всё норм и сравни пакеты и так далее, в общем всё что связанно с квестами и найдёшь проблему