PlayerSkillSaveDAOMySQLImpl.java 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * Copyright © 2004-2019 L2J Server
  3. *
  4. * This file is part of L2J Server.
  5. *
  6. * L2J Server is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J Server is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.l2jserver.gameserver.dao.impl.mysql;
  20. import static com.l2jserver.gameserver.config.Configuration.character;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.Map.Entry;
  25. import org.slf4j.Logger;
  26. import org.slf4j.LoggerFactory;
  27. import com.l2jserver.commons.database.ConnectionFactory;
  28. import com.l2jserver.gameserver.dao.PlayerSkillSaveDAO;
  29. import com.l2jserver.gameserver.datatables.SkillData;
  30. import com.l2jserver.gameserver.model.TimeStamp;
  31. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  32. import com.l2jserver.gameserver.model.skills.AbnormalType;
  33. import com.l2jserver.gameserver.model.skills.BuffInfo;
  34. import com.l2jserver.gameserver.model.skills.Skill;
  35. /**
  36. * Player Skill Save DAO MySQL implementation.
  37. * @author Zoey76
  38. */
  39. public class PlayerSkillSaveDAOMySQLImpl implements PlayerSkillSaveDAO {
  40. private static final Logger LOG = LoggerFactory.getLogger(PlayerSkillSaveDAOMySQLImpl.class);
  41. private static final String INSERT = "INSERT INTO character_skills_save (charId,skill_id,skill_level,remaining_time,reuse_delay,systime,restore_type,class_index,buff_index) VALUES (?,?,?,?,?,?,?,?,?)";
  42. private static final String SELECT = "SELECT skill_id,skill_level,remaining_time, reuse_delay, systime, restore_type FROM character_skills_save WHERE charId=? AND class_index=? ORDER BY buff_index ASC";
  43. private static final String DELETE = "DELETE FROM character_skills_save WHERE charId=? AND class_index=?";
  44. @Override
  45. public void delete(L2PcInstance player, int classIndex) {
  46. try (var con = ConnectionFactory.getInstance().getConnection();
  47. var ps = con.prepareStatement(DELETE)) {
  48. ps.setInt(1, player.getObjectId());
  49. ps.setInt(2, classIndex);
  50. ps.execute();
  51. } catch (Exception e) {
  52. LOG.error("Could not delete all effect data!", player, e);
  53. }
  54. }
  55. @Override
  56. public void delete(L2PcInstance player) {
  57. delete(player, player.getClassIndex());
  58. }
  59. @Override
  60. public void insert(L2PcInstance player, boolean storeEffects) {
  61. try (var con = ConnectionFactory.getInstance().getConnection();
  62. var ps = con.prepareStatement(INSERT)) {
  63. int buff_index = 0;
  64. final List<Integer> storedSkills = new ArrayList<>();
  65. // Store all effect data along with calculated remaining
  66. // reuse delays for matching skills. 'restore_type'= 0.
  67. if (storeEffects) {
  68. for (BuffInfo info : player.getEffectList().getEffects()) {
  69. if (info == null) {
  70. continue;
  71. }
  72. final Skill skill = info.getSkill();
  73. // Do not save heals.
  74. if (skill.getAbnormalType() == AbnormalType.LIFE_FORCE_OTHERS) {
  75. continue;
  76. }
  77. if (skill.isToggle()) {
  78. continue;
  79. }
  80. // Dances and songs are not kept in retail.
  81. if (skill.isDance() && !character().storeDances()) {
  82. continue;
  83. }
  84. if (storedSkills.contains(skill.getReuseHashCode())) {
  85. continue;
  86. }
  87. storedSkills.add(skill.getReuseHashCode());
  88. ps.setInt(1, player.getObjectId());
  89. ps.setInt(2, skill.getId());
  90. ps.setInt(3, skill.getLevel());
  91. ps.setInt(4, info.getTime());
  92. final TimeStamp t = player.getSkillReuseTimeStamp(skill.getReuseHashCode());
  93. ps.setLong(5, (t != null) && t.hasNotPassed() ? t.getReuse() : 0);
  94. ps.setLong(6, (t != null) && t.hasNotPassed() ? t.getStamp() : 0);
  95. ps.setInt(7, 0); // Store type 0, active buffs/debuffs.
  96. ps.setInt(8, player.getClassIndex());
  97. ps.setInt(9, ++buff_index);
  98. ps.execute();
  99. }
  100. }
  101. // Skills under reuse.
  102. final Map<Integer, TimeStamp> reuseTimeStamps = player.getSkillReuseTimeStamps();
  103. if (reuseTimeStamps != null) {
  104. for (Entry<Integer, TimeStamp> ts : reuseTimeStamps.entrySet()) {
  105. final int hash = ts.getKey();
  106. if (storedSkills.contains(hash)) {
  107. continue;
  108. }
  109. final TimeStamp t = ts.getValue();
  110. if ((t != null) && t.hasNotPassed()) {
  111. storedSkills.add(hash);
  112. ps.setInt(1, player.getObjectId());
  113. ps.setInt(2, t.getSkillId());
  114. ps.setInt(3, t.getSkillLvl());
  115. ps.setInt(4, -1);
  116. ps.setLong(5, t.getReuse());
  117. ps.setLong(6, t.getStamp());
  118. ps.setInt(7, 1); // Restore type 1, skill reuse.
  119. ps.setInt(8, player.getClassIndex());
  120. ps.setInt(9, ++buff_index);
  121. ps.execute();
  122. }
  123. }
  124. }
  125. } catch (Exception e) {
  126. LOG.error("Could not store {} effect data!", player, e);
  127. }
  128. }
  129. @Override
  130. public void load(L2PcInstance player) {
  131. try (var con = ConnectionFactory.getInstance().getConnection();
  132. var ps = con.prepareStatement(SELECT)) {
  133. ps.setInt(1, player.getObjectId());
  134. ps.setInt(2, player.getClassIndex());
  135. try (var rs = ps.executeQuery()) {
  136. while (rs.next()) {
  137. int remainingTime = rs.getInt("remaining_time");
  138. long reuseDelay = rs.getLong("reuse_delay");
  139. long systime = rs.getLong("systime");
  140. int restoreType = rs.getInt("restore_type");
  141. final Skill skill = SkillData.getInstance().getSkill(rs.getInt("skill_id"), rs.getInt("skill_level"));
  142. if (skill == null) {
  143. continue;
  144. }
  145. final long time = systime - System.currentTimeMillis();
  146. if (time > 10) {
  147. player.disableSkill(skill, time);
  148. player.addTimeStamp(skill, reuseDelay, systime);
  149. }
  150. // Restore Type 1 The remaining skills lost effect upon logout but were still under a high reuse delay.
  151. if (restoreType > 0) {
  152. continue;
  153. }
  154. // Restore Type 0 These skill were still in effect on the character upon logout.
  155. // Some of which were self casted and might still have had a long reuse delay which also is restored.
  156. skill.applyEffects(player, player, false, remainingTime);
  157. }
  158. }
  159. } catch (Exception e) {
  160. LOG.error("Could not restore {} active effect data!", player, e);
  161. }
  162. }
  163. }