Java tutorial
/* * This program 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. * * This program 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.l2jfree.gameserver.instancemanager; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.parsers.DocumentBuilderFactory; import javolution.util.FastMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import com.l2jfree.Config; import com.l2jfree.gameserver.gameobjects.L2Creature; import com.l2jfree.gameserver.gameobjects.L2Npc; import com.l2jfree.gameserver.gameobjects.L2Player; import com.l2jfree.gameserver.model.Location; import com.l2jfree.gameserver.model.clan.L2Clan; import com.l2jfree.gameserver.model.entity.Castle; import com.l2jfree.gameserver.model.entity.ClanHall; import com.l2jfree.gameserver.model.entity.Fort; import com.l2jfree.gameserver.model.entity.FortSiege; import com.l2jfree.gameserver.model.entity.Instance; import com.l2jfree.gameserver.model.entity.Siege; import com.l2jfree.gameserver.model.entity.Town; import com.l2jfree.gameserver.model.mapregion.L2MapArea; import com.l2jfree.gameserver.model.mapregion.L2MapRegion; import com.l2jfree.gameserver.model.mapregion.L2MapRegionRestart; import com.l2jfree.gameserver.model.mapregion.L2SpecialMapRegion; import com.l2jfree.gameserver.model.mapregion.TeleportWhereType; import com.l2jfree.gameserver.model.world.L2World; import com.l2jfree.gameserver.model.world.L2WorldRegion; import com.l2jfree.gameserver.model.zone.L2Zone; import com.l2jfree.gameserver.util.Util; import com.l2jfree.util.L2Collections; import com.l2jfree.util.LookupTable; /** * @author Noctarius */ public final class MapRegionManager { private static final Log _log = LogFactory.getLog(MapRegionManager.class); private final LookupTable<L2MapRegionRestart> _mapRegionRestart = new LookupTable<L2MapRegionRestart>(); public static MapRegionManager getInstance() { return SingletonHolder._instance; } private MapRegionManager() { load(); } private void load() { for (File xml : Util.getDatapackFiles("mapregion", ".xml")) { Document doc = null; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); factory.setIgnoringComments(true); doc = factory.newDocumentBuilder().parse(xml); } catch (Exception e) { _log.warn("MapRegionManager: Error while loading XML definition: " + xml.getName() + e, e); return; } try { parseDocument(doc); } catch (Exception e) { _log.warn("MapRegionManager: Error in XML definition: " + xml.getName() + e, e); return; } } } public void reload() { // Get the world regions for (L2WorldRegion[] finalWorldRegion : L2World.getInstance().getAllWorldRegions()) { for (L2WorldRegion finalElement : finalWorldRegion) { finalElement.clearMapRegions(); } } load(); } private void parseDocument(Document doc) throws Exception { final Map<Integer, L2MapRegionRestart> restarts = new FastMap<Integer, L2MapRegionRestart>(); final List<L2MapRegion> specialMapRegions = new ArrayList<L2MapRegion>(); final List<L2MapArea> mapAreas = new ArrayList<L2MapArea>(); final Set<Integer> restartAreas = new HashSet<Integer>(); for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling()) { if ("mapregion".equalsIgnoreCase(n.getNodeName())) { for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling()) { if ("regions".equalsIgnoreCase(d.getNodeName())) { for (Node f = d.getFirstChild(); f != null; f = f.getNextSibling()) { if ("region".equalsIgnoreCase(f.getNodeName())) { specialMapRegions.add(new L2SpecialMapRegion(f)); } } } else if ("restartpoints".equalsIgnoreCase(d.getNodeName())) { for (Node f = d.getFirstChild(); f != null; f = f.getNextSibling()) { if ("restartpoint".equalsIgnoreCase(f.getNodeName())) { L2MapRegionRestart restart = new L2MapRegionRestart(f); if (!restarts.containsKey(restart.getRestartId())) restarts.put(restart.getRestartId(), restart); else throw new Exception( "Duplicate restartpointId: " + restart.getRestartId() + "."); } } } else if ("restartareas".equalsIgnoreCase(d.getNodeName())) { for (Node f = d.getFirstChild(); f != null; f = f.getNextSibling()) { if ("restartarea".equalsIgnoreCase(f.getNodeName())) { final int restartId = Integer .parseInt(f.getAttributes().getNamedItem("restartId").getNodeValue()); restartAreas.add(restartId); for (Node r = f.getFirstChild(); r != null; r = r.getNextSibling()) { if ("map".equalsIgnoreCase(r.getNodeName())) { int X = Integer .parseInt(r.getAttributes().getNamedItem("X").getNodeValue()); int Y = Integer .parseInt(r.getAttributes().getNamedItem("Y").getNodeValue()); mapAreas.add(new L2MapArea(restartId, X, Y)); } } } } } } } } final L2WorldRegion[][] worldRegions = L2World.getInstance().getAllWorldRegions(); for (L2MapRegion mapregion : L2Collections.concatenatedIterable(specialMapRegions, mapAreas)) { // Register the mapregions to any intersecting world region for (int x = 0; x < worldRegions.length; x++) { for (int y = 0; y < worldRegions[x].length; y++) { int ax = (x - L2World.OFFSET_X) << L2World.SHIFT_BY; int bx = ((x + 1) - L2World.OFFSET_X) << L2World.SHIFT_BY; int ay = (y - L2World.OFFSET_Y) << L2World.SHIFT_BY; int by = ((y + 1) - L2World.OFFSET_Y) << L2World.SHIFT_BY; if (mapregion.intersectsRectangle(ax, bx, ay, by)) worldRegions[x][y].addMapRegion(mapregion); } } } _mapRegionRestart.clear(false); for (Map.Entry<Integer, L2MapRegionRestart> entry : restarts.entrySet()) _mapRegionRestart.set(entry.getKey(), entry.getValue()); int redirectCount = 0; for (L2MapRegionRestart restart : _mapRegionRestart) { if (restart.getBannedRace() != null) redirectCount++; } _log.info("MapRegionManager: Loaded " + _mapRegionRestart.size() + " restartpoint(s)."); _log.info("MapRegionManager: Loaded " + restartAreas.size() + " restartareas with " + mapAreas.size() + " arearegion(s)."); _log.info("MapRegionManager: Loaded " + specialMapRegions.size() + " zoneregion(s)."); _log.info("MapRegionManager: Loaded " + redirectCount + " race depending redirects."); } public L2MapRegionRestart getRestartLocation(L2Player activeChar) { L2MapRegion region = getRegion(activeChar); // Temporary fix for new hunting grounds if (region == null) return _mapRegionRestart.get(Config.ALT_DEFAULT_RESTARTTOWN); else return _mapRegionRestart.get(region.getRestartId(activeChar)); } public L2MapRegionRestart getRestartLocation(int restartId) { return _mapRegionRestart.get(restartId); } public Location getRestartPoint(int restartId, L2Player activeChar) { L2MapRegionRestart restart = _mapRegionRestart.get(restartId); if (restart == null) restart = _mapRegionRestart.get(Config.ALT_DEFAULT_RESTARTTOWN); return restart.getRandomRestartPoint(activeChar); } public Location getChaoticRestartPoint(int restartId, L2Player activeChar) { L2MapRegionRestart restart = _mapRegionRestart.get(restartId); if (restart == null) restart = _mapRegionRestart.get(Config.ALT_DEFAULT_RESTARTTOWN); return restart.getRandomChaoticRestartPoint(activeChar); } public L2MapRegion getRegion(L2Creature activeChar) { return getRegion(activeChar.getX(), activeChar.getY(), activeChar.getZ()); } public L2MapRegion getRegion(int x, int y, int z) { return L2World.getInstance().getRegion(x, y).getMapRegion(x, y, z); } public L2MapRegion getRegion(int x, int y) { return getRegion(x, y, -1); } //TODO: Needs to be clean rewritten public Location getTeleToLocation(L2Player player, TeleportWhereType teleportWhere) { L2Clan clan = player.getClan(); // Checking if in Dimensinal Gap if (DimensionalRiftManager.getInstance().checkIfInRiftZone(player.getX(), player.getY(), player.getZ(), true)) // true -> ignore waiting room :) { if (player.isInParty() && player.getParty().isInDimensionalRift()) { player.getParty().getDimensionalRift().usedTeleport(player); } return DimensionalRiftManager.getInstance().getWaitingRoomTeleport(); } // Checking if in an instance if (player.isInInstance()) { Instance inst = InstanceManager.getInstance().getInstance(player.getInstanceId()); if (inst != null) { Location loc = inst.getSpawnLoc(); if (loc != null) return loc; } } // Checking if in arena L2Zone arena = ZoneManager.getInstance().isInsideZone(L2Zone.ZoneType.Arena, player.getX(), player.getY()); if (arena != null && arena.isInsideZone(player)) { Location loc = arena.getRestartPoint(L2Zone.RestartType.OWNER); if (loc == null) loc = arena.getRandomLocation(); return loc; } if (clan != null && !player.isFlyingMounted() && !player.isFlying()) // flying players in gracia cant use teleports to aden continent { // If teleport to clan hall if (teleportWhere == TeleportWhereType.ClanHall) { ClanHall clanhall = ClanHallManager.getInstance().getClanHallByOwner(clan); if (clanhall != null) { L2Zone zone = clanhall.getZone(); if (zone != null) { Location loc = zone.getRestartPoint(L2Zone.RestartType.OWNER); if (loc == null) loc = zone.getRandomLocation(); return loc; } } } else if (teleportWhere == TeleportWhereType.Castle) { Castle castle = CastleManager.getInstance().getCastleByOwner(clan); if (castle != null) { L2Zone zone = castle.getZone(); if (zone != null) { if (castle.getSiege().getIsInProgress() && player.isChaotic()) { // Karma player respawns out of siege zone (only during sieges ? o.O ) return zone.getRestartPoint(L2Zone.RestartType.CHAOTIC); } return zone.getRestartPoint(L2Zone.RestartType.OWNER); } } } else if (teleportWhere == TeleportWhereType.Fortress) { Fort fort = FortManager.getInstance().getFortByOwner(clan); if (fort != null) { L2Zone zone = fort.getZone(); if (zone != null) { // If is on castle with siege and player's clan is defender if (fort.getSiege().getIsInProgress() && player.isChaotic()) { // Karma player respawns out of siege zone (only during sieges ? o.O ) return zone.getRestartPoint(L2Zone.RestartType.CHAOTIC); } return zone.getRestartPoint(L2Zone.RestartType.OWNER); } } } else if (teleportWhere == TeleportWhereType.SiegeFlag) { Siege siege = SiegeManager.getInstance().getSiege(clan); FortSiege fsiege = FortSiegeManager.getInstance().getSiege(clan); // Check if player's clan is attacker if (siege != null && fsiege == null && siege.checkIsAttacker(clan) && siege.checkIfInZone(player)) { // Karma player respawns out of siege zone if (player.isChaotic()) { L2Zone zone = siege.getCastle().getZone(); if (zone != null) { return zone.getRestartPoint(L2Zone.RestartType.CHAOTIC); } } // get nearest flag L2Npc flag = siege.getClosestFlag(player); // spawn to flag if (flag != null) return flag.getLoc(); } else if (siege == null && fsiege != null && fsiege.checkIsAttacker(clan) && fsiege.checkIfInZone(player)) { // Karma player respawns out of siege zone if (player.isChaotic()) { L2Zone zone = fsiege.getFort().getZone(); if (zone != null) { return zone.getRestartPoint(L2Zone.RestartType.CHAOTIC); } } // Get nearest flag L2Npc flag = fsiege.getClosestFlag(player); // Spawn to flag if (flag != null) return flag.getLoc(); } } } // TeleportWhereType.Town, and other TeleportWhereTypes where the condition was not met L2MapRegionRestart restart = getRestartLocation(player); Location loc = null; // Karma player land out of city if (player.isChaotic()) loc = restart.getRandomChaoticRestartPoint(player); if (loc == null) loc = restart.getRandomRestartPoint(player); if (loc != null) return loc; // teleport to default town if nothing else will work return getRestartPoint(Config.ALT_DEFAULT_RESTARTTOWN, player); } public int getAreaCastle(L2Creature activeChar) { Town town = TownManager.getInstance().getClosestTown(activeChar); if (town == null) return 5; return town.getCastleId(); } /** * < 1, 8, > 15 - Empty<BR>1 - Talking island<BR>2 - Gludio<BR> * 3 - Dark elven<BR>4 - Elven<BR>5 - Dion<BR>6 - Giran<BR> * 7 - Neutral zone<BR>9 - Schuttgart<BR>10 - Oren<BR> * 11 - Hunters Village<BR>12 - Innadril<BR>13 - Aden<BR> * 14 - Rune<BR>15 - Goddard * @param player a player * @return L2 region used in partymatching */ public int getL2Region(L2Player player) { L2MapRegion region = getRegion(player); int locName = -1; if (region != null) { int restartId = region.getRestartId(); L2MapRegionRestart restart = getRestartLocation(restartId); locName = restart.getLocName(); } return convertLocNameToL2Region(locName); } public int convertLocNameToL2Region(int locName) { switch (locName) { case 910: // TI return 1; case 911: // Gludin case 912: // Gludio case 2190: // Southern wastelands case 2710: // Keucereus case 2711: // inside SoI case 2712: // outside SoI case 2716: // inside Cleft return 2; case 913: // Neutral zone return 7; case 914: // Elven village return 4; case 915: // DE village return 3; case 916: // Dion case 917: // Floran return 5; case 918: // Giran case 919: // Harbor return 6; case 920: // Orc village case 921: // Dwarven village case 1714: // Schuttgart return 9; case 922: // Oren return 10; case 923: // Hunters village return 11; case 924: // Aden case 925: // Coliseum case 2189: // Kamael Village return 13; case 926: // Heine return 12; case 1537: // Rune case 1924: // Primeval Isle case 2259: // Fantasy Isle return 14; case 1538: // Goddard return 15; default: // TODO: Epilogue locations return 0; // no name } } @SuppressWarnings("synthetic-access") private static class SingletonHolder { protected static final MapRegionManager _instance = new MapRegionManager(); } }