123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- /*
- * Copyright (C) 2004-2015 L2J Server
- *
- * This file is part of L2J Server.
- *
- * L2J Server 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.
- *
- * L2J Server 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 com.l2jserver.gameserver.data.sql.impl;
- import java.io.File;
- import java.nio.file.Files;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- import java.util.HashSet;
- import java.util.Map;
- import java.util.Set;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.atomic.AtomicInteger;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- import com.l2jserver.Config;
- import com.l2jserver.commons.database.pool.impl.ConnectionFactory;
- import com.l2jserver.gameserver.model.L2Clan;
- import com.l2jserver.gameserver.model.L2Crest;
- import com.l2jserver.gameserver.model.L2Crest.CrestType;
- import com.l2jserver.util.file.filter.BMPFilter;
- /**
- * Loads and saves crests from database.
- * @author NosBit
- */
- public final class CrestTable
- {
- private static final Logger LOGGER = Logger.getLogger(CrestTable.class.getName());
-
- private final Map<Integer, L2Crest> _crests = new ConcurrentHashMap<>();
- private final AtomicInteger _nextId = new AtomicInteger(1);
-
- protected CrestTable()
- {
- load();
- }
-
- public synchronized void load()
- {
- _crests.clear();
- Set<Integer> crestsInUse = new HashSet<>();
- for (L2Clan clan : ClanTable.getInstance().getClans())
- {
- if (clan.getCrestId() != 0)
- {
- crestsInUse.add(clan.getCrestId());
- }
-
- if (clan.getCrestLargeId() != 0)
- {
- crestsInUse.add(clan.getCrestLargeId());
- }
-
- if (clan.getAllyCrestId() != 0)
- {
- crestsInUse.add(clan.getAllyCrestId());
- }
- }
-
- try (Connection con = ConnectionFactory.getInstance().getConnection();
- Statement statement = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
- ResultSet rs = statement.executeQuery("SELECT `crest_id`, `data`, `type` FROM `crests` ORDER BY `crest_id` DESC"))
- {
- while (rs.next())
- {
- int id = rs.getInt("crest_id");
-
- if (_nextId.get() <= id)
- {
- _nextId.set(id + 1);
- }
-
- // delete all unused crests except the last one we dont want to reuse
- // a crest id because client will display wrong crest if its reused
- if (!crestsInUse.contains(id) && (id != (_nextId.get() - 1)))
- {
- rs.deleteRow();
- continue;
- }
-
- byte[] data = rs.getBytes("data");
- CrestType crestType = CrestType.getById(rs.getInt("type"));
- if (crestType != null)
- {
- _crests.put(id, new L2Crest(id, data, crestType));
- }
- else
- {
- LOGGER.warning("Unknown crest type found in database. Type:" + rs.getInt("type"));
- }
- }
-
- }
- catch (SQLException e)
- {
- LOGGER.log(Level.WARNING, "There was an error while loading crests from database:", e);
- }
-
- moveOldCrestsToDb(crestsInUse);
-
- LOGGER.info(getClass().getSimpleName() + ": Loaded " + _crests.size() + " Crests.");
-
- for (L2Clan clan : ClanTable.getInstance().getClans())
- {
- if (clan.getCrestId() != 0)
- {
- if (getCrest(clan.getCrestId()) == null)
- {
- LOGGER.info("Removing non-existent crest for clan " + clan.getName() + " [" + clan.getId() + "], crestId:" + clan.getCrestId());
- clan.setCrestId(0);
- clan.changeClanCrest(0);
- }
- }
-
- if (clan.getCrestLargeId() != 0)
- {
- if (getCrest(clan.getCrestLargeId()) == null)
- {
- LOGGER.info("Removing non-existent large crest for clan " + clan.getName() + " [" + clan.getId() + "], crestLargeId:" + clan.getCrestLargeId());
- clan.setCrestLargeId(0);
- clan.changeLargeCrest(0);
- }
- }
-
- if (clan.getAllyCrestId() != 0)
- {
- if (getCrest(clan.getAllyCrestId()) == null)
- {
- LOGGER.info("Removing non-existent ally crest for clan " + clan.getName() + " [" + clan.getId() + "], allyCrestId:" + clan.getAllyCrestId());
- clan.setAllyCrestId(0);
- clan.changeAllyCrest(0, true);
- }
- }
- }
- }
-
- /**
- * Moves old crests from data/crests folder to database and deletes crest folder<br>
- * <b>TODO:</b> remove it after some time
- * @param crestsInUse the set of crests in use
- */
- private void moveOldCrestsToDb(Set<Integer> crestsInUse)
- {
- final File crestDir = new File(Config.DATAPACK_ROOT, "data/crests/");
- if (crestDir.exists())
- {
- final File[] files = crestDir.listFiles(new BMPFilter());
- if (files == null)
- {
- return;
- }
-
- for (File file : files)
- {
- try
- {
- final byte[] data = Files.readAllBytes(file.toPath());
- if (file.getName().startsWith("Crest_Large_"))
- {
- final int crestId = Integer.parseInt(file.getName().substring(12, file.getName().length() - 4));
- if (crestsInUse.contains(crestId))
- {
- final L2Crest crest = createCrest(data, CrestType.PLEDGE_LARGE);
- if (crest != null)
- {
- for (L2Clan clan : ClanTable.getInstance().getClans())
- {
- if (clan.getCrestLargeId() == crestId)
- {
- clan.setCrestLargeId(0);
- clan.changeLargeCrest(crest.getId());
- }
- }
- }
- }
- }
- else if (file.getName().startsWith("Crest_"))
- {
- final int crestId = Integer.parseInt(file.getName().substring(6, file.getName().length() - 4));
- if (crestsInUse.contains(crestId))
- {
- final L2Crest crest = createCrest(data, CrestType.PLEDGE);
- if (crest != null)
- {
- for (L2Clan clan : ClanTable.getInstance().getClans())
- {
- if (clan.getCrestId() == crestId)
- {
- clan.setCrestId(0);
- clan.changeClanCrest(crest.getId());
- }
- }
- }
- }
- }
- else if (file.getName().startsWith("AllyCrest_"))
- {
- final int crestId = Integer.parseInt(file.getName().substring(10, file.getName().length() - 4));
- if (crestsInUse.contains(crestId))
- {
- final L2Crest crest = createCrest(data, CrestType.ALLY);
- if (crest != null)
- {
- for (L2Clan clan : ClanTable.getInstance().getClans())
- {
- if (clan.getAllyCrestId() == crestId)
- {
- clan.setAllyCrestId(0);
- clan.changeAllyCrest(crest.getId(), false);
- }
- }
- }
- }
- }
- file.delete();
- }
- catch (Exception e)
- {
- LOGGER.log(Level.WARNING, "There was an error while moving crest file " + file.getName() + " to database:", e);
- }
- }
- crestDir.delete();
- }
- }
-
- /**
- * @param crestId The crest id
- * @return {@code L2Crest} if crest is found, {@code null} if crest was not found.
- */
- public L2Crest getCrest(int crestId)
- {
- return _crests.get(crestId);
- }
-
- /**
- * Creates a {@code L2Crest} object and inserts it in database and cache.
- * @param data
- * @param crestType
- * @return {@code L2Crest} on success, {@code null} on failure.
- */
- public L2Crest createCrest(byte[] data, CrestType crestType)
- {
- try (Connection con = ConnectionFactory.getInstance().getConnection();
- PreparedStatement statement = con.prepareStatement("INSERT INTO `crests`(`crest_id`, `data`, `type`) VALUES(?, ?, ?)"))
- {
- final L2Crest crest = new L2Crest(getNextId(), data, crestType);
- statement.setInt(1, crest.getId());
- statement.setBytes(2, crest.getData());
- statement.setInt(3, crest.getType().getId());
- statement.executeUpdate();
- _crests.put(crest.getId(), crest);
- return crest;
- }
- catch (SQLException e)
- {
- LOGGER.log(Level.WARNING, "There was an error while saving crest in database:", e);
- }
- return null;
- }
-
- /**
- * Removes crest from database and cache.
- * @param crestId the id of crest to be removed.
- */
- public void removeCrest(int crestId)
- {
- _crests.remove(crestId);
-
- // avoid removing last crest id we dont want to lose index...
- // because client will display wrong crest if its reused
- if (crestId == (_nextId.get() - 1))
- {
- return;
- }
-
- try (Connection con = ConnectionFactory.getInstance().getConnection();
- PreparedStatement statement = con.prepareStatement("DELETE FROM `crests` WHERE `crest_id` = ?"))
- {
- statement.setInt(1, crestId);
- statement.executeUpdate();
- }
- catch (SQLException e)
- {
- LOGGER.log(Level.WARNING, "There was an error while deleting crest from database:", e);
- }
- }
-
- /**
- * @return The next crest id.
- */
- public int getNextId()
- {
- return _nextId.getAndIncrement();
- }
-
- public static CrestTable getInstance()
- {
- return SingletonHolder._instance;
- }
-
- private static class SingletonHolder
- {
- protected static final CrestTable _instance = new CrestTable();
- }
- }
|