Files
sweetgum-server/src/server/maps/MapleMapFactory.java
ronancpl 67af338f8a Fix map spawn
Fix map failing to spawn in some cases.
2017-04-06 10:07:14 -03:00

311 lines
15 KiB
Java

/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package server.maps;
import java.awt.Point;
import java.awt.Rectangle;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataTool;
import server.PortalFactory;
import server.life.AbstractLoadedMapleLife;
import server.life.MapleLifeFactory;
import server.life.MapleMonster;
import tools.DatabaseConnection;
import tools.StringUtil;
public class MapleMapFactory {
private MapleDataProvider source;
private MapleData nameData;
private Map<Integer, MapleMap> maps = new HashMap<>();
private int channel, world;
public MapleMapFactory(MapleDataProvider source, MapleDataProvider stringSource, int world, int channel) {
this.source = source;
this.nameData = stringSource.getData("Map.img");
this.world = world;
this.channel = channel;
}
public MapleMap getMap(int mapid) {
Integer omapid = Integer.valueOf(mapid);
MapleMap map = maps.get(omapid);
if (map == null) {
synchronized (this) {
map = maps.get(omapid);
if (map != null) {
return map;
}
String mapName = getMapName(mapid);
MapleData mapData = source.getData(mapName);
String link = MapleDataTool.getString(mapData.getChildByPath("info/link"), "");
if (!link.equals("")) { //nexon made hundreds of dojo maps so to reduce the size they added links.
mapName = getMapName(Integer.parseInt(link));
mapData = source.getData(mapName);
}
float monsterRate = 0;
MapleData mobRate = mapData.getChildByPath("info/mobRate");
if (mobRate != null) {
monsterRate = ((Float) mobRate.getData()).floatValue();
}
map = new MapleMap(mapid, world, channel, MapleDataTool.getInt("info/returnMap", mapData), monsterRate);
String onFirstEnter = MapleDataTool.getString(mapData.getChildByPath("info/onFirstUserEnter"), String.valueOf(mapid));
map.setOnFirstUserEnter(onFirstEnter.equals("") ? String.valueOf(mapid) : onFirstEnter);
String onEnter = MapleDataTool.getString(mapData.getChildByPath("info/onUserEnter"), String.valueOf(mapid));
map.setOnUserEnter(onEnter.equals("") ? String.valueOf(mapid) : onEnter);
map.setFieldLimit(MapleDataTool.getInt(mapData.getChildByPath("info/fieldLimit"), 0));
map.setMobInterval((short) MapleDataTool.getInt(mapData.getChildByPath("info/createMobInterval"), 5000));
PortalFactory portalFactory = new PortalFactory();
for (MapleData portal : mapData.getChildByPath("portal")) {
map.addPortal(portalFactory.makePortal(MapleDataTool.getInt(portal.getChildByPath("pt")), portal));
}
MapleData timeMob = mapData.getChildByPath("info/timeMob");
if (timeMob != null) {
map.timeMob(MapleDataTool.getInt(timeMob.getChildByPath("id")),
MapleDataTool.getString(timeMob.getChildByPath("message")));
}
List<MapleFoothold> allFootholds = new LinkedList<>();
Point lBound = new Point();
Point uBound = new Point();
for (MapleData footRoot : mapData.getChildByPath("foothold")) {
for (MapleData footCat : footRoot) {
for (MapleData footHold : footCat) {
int x1 = MapleDataTool.getInt(footHold.getChildByPath("x1"));
int y1 = MapleDataTool.getInt(footHold.getChildByPath("y1"));
int x2 = MapleDataTool.getInt(footHold.getChildByPath("x2"));
int y2 = MapleDataTool.getInt(footHold.getChildByPath("y2"));
MapleFoothold fh = new MapleFoothold(new Point(x1, y1), new Point(x2, y2), Integer.parseInt(footHold.getName()));
fh.setPrev(MapleDataTool.getInt(footHold.getChildByPath("prev")));
fh.setNext(MapleDataTool.getInt(footHold.getChildByPath("next")));
if (fh.getX1() < lBound.x) {
lBound.x = fh.getX1();
}
if (fh.getX2() > uBound.x) {
uBound.x = fh.getX2();
}
if (fh.getY1() < lBound.y) {
lBound.y = fh.getY1();
}
if (fh.getY2() > uBound.y) {
uBound.y = fh.getY2();
}
allFootholds.add(fh);
}
}
}
MapleFootholdTree fTree = new MapleFootholdTree(lBound, uBound);
for (MapleFoothold fh : allFootholds) {
fTree.insert(fh);
}
map.setFootholds(fTree);
if (mapData.getChildByPath("area") != null) {
for (MapleData area : mapData.getChildByPath("area")) {
int x1 = MapleDataTool.getInt(area.getChildByPath("x1"));
int y1 = MapleDataTool.getInt(area.getChildByPath("y1"));
int x2 = MapleDataTool.getInt(area.getChildByPath("x2"));
int y2 = MapleDataTool.getInt(area.getChildByPath("y2"));
map.addMapleArea(new Rectangle(x1, y1, (x2 - x1), (y2 - y1)));
}
}
try { try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("SELECT * FROM playernpcs WHERE map = ?")) {
ps.setInt(1, omapid);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
map.addMapObject(new PlayerNPCs(rs));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
for (MapleData life : mapData.getChildByPath("life")) {
String id = MapleDataTool.getString(life.getChildByPath("id"));
String type = MapleDataTool.getString(life.getChildByPath("type"));
if (id.equals("9001105")) {
id = "9001108";//soz
}
AbstractLoadedMapleLife myLife = loadLife(life, id, type);
if (myLife instanceof MapleMonster) {
MapleMonster monster = (MapleMonster) myLife;
int mobTime = MapleDataTool.getInt("mobTime", life, 0);
int team = MapleDataTool.getInt("team", life, -1);
if (mobTime == -1) { //does not respawn, force spawn once
map.spawnMonster(monster);
} else {
map.addMonsterSpawn(monster, mobTime, team);
}
//should the map be reseted, use allMonsterSpawn list of monsters to spawn them again
map.addAllMonsterSpawn(monster, mobTime, team);
} else {
map.addMapObject(myLife);
}
}
if (mapData.getChildByPath("reactor") != null) {
for (MapleData reactor : mapData.getChildByPath("reactor")) {
String id = MapleDataTool.getString(reactor.getChildByPath("id"));
if (id != null) {
MapleReactor newReactor = loadReactor(reactor, id);
map.spawnReactor(newReactor);
}
}
}
try {
map.setMapName(MapleDataTool.getString("mapName", nameData.getChildByPath(getMapStringName(omapid)), ""));
map.setStreetName(MapleDataTool.getString("streetName", nameData.getChildByPath(getMapStringName(omapid)), ""));
} catch (Exception e) {
e.printStackTrace();
System.err.println("Not found mapid " + omapid);
map.setMapName("");
map.setStreetName("");
}
map.setClock(mapData.getChildByPath("clock") != null);
map.setEverlast(mapData.getChildByPath("everlast") != null);
map.setTown(mapData.getChildByPath("info/town") != null);
map.setHPDec(MapleDataTool.getIntConvert("info/decHP", mapData, 0));
map.setHPDecProtect(MapleDataTool.getIntConvert("info/protectItem", mapData, 0));
map.setForcedReturnMap(MapleDataTool.getInt(mapData.getChildByPath("info/forcedReturn"), 999999999));
map.setBoat(mapData.getChildByPath("shipObj") != null);
map.setTimeLimit(MapleDataTool.getIntConvert("timeLimit", mapData.getChildByPath("info"), -1));
map.setFieldType(MapleDataTool.getIntConvert("info/fieldType", mapData, 0));
map.setMobCapacity(MapleDataTool.getIntConvert("fixedMobCapacity", mapData.getChildByPath("info"), 500));//Is there a map that contains more than 500 mobs?
HashMap<Integer, Integer> backTypes = new HashMap<>();
try {
for (MapleData layer : mapData.getChildByPath("back")) { // yolo
int layerNum = Integer.parseInt(layer.getName());
int type = MapleDataTool.getInt(layer.getChildByPath("type"), 0);
backTypes.put(layerNum, type);
}
} catch (Exception e) {
e.printStackTrace();
// swallow cause I'm cool
}
map.setBackgroundTypes(backTypes);
maps.put(omapid, map);
}
}
return map;
}
public boolean isMapLoaded(int mapId) {
return maps.containsKey(mapId);
}
private AbstractLoadedMapleLife loadLife(MapleData life, String id, String type) {
AbstractLoadedMapleLife myLife = MapleLifeFactory.getLife(Integer.parseInt(id), type);
myLife.setCy(MapleDataTool.getInt(life.getChildByPath("cy")));
MapleData dF = life.getChildByPath("f");
if (dF != null) {
myLife.setF(MapleDataTool.getInt(dF));
}
myLife.setFh(MapleDataTool.getInt(life.getChildByPath("fh")));
myLife.setRx0(MapleDataTool.getInt(life.getChildByPath("rx0")));
myLife.setRx1(MapleDataTool.getInt(life.getChildByPath("rx1")));
int x = MapleDataTool.getInt(life.getChildByPath("x"));
int y = MapleDataTool.getInt(life.getChildByPath("y"));
myLife.setPosition(new Point(x, y));
int hide = MapleDataTool.getInt("hide", life, 0);
if (hide == 1) {
myLife.setHide(true);
}
return myLife;
}
private MapleReactor loadReactor(MapleData reactor, String id) {
MapleReactor myReactor = new MapleReactor(MapleReactorFactory.getReactor(Integer.parseInt(id)), Integer.parseInt(id));
int x = MapleDataTool.getInt(reactor.getChildByPath("x"));
int y = MapleDataTool.getInt(reactor.getChildByPath("y"));
myReactor.setPosition(new Point(x, y));
myReactor.setDelay(MapleDataTool.getInt(reactor.getChildByPath("reactorTime")) * 1000);
myReactor.setState((byte) 0);
myReactor.setName(MapleDataTool.getString(reactor.getChildByPath("name"), ""));
return myReactor;
}
private String getMapName(int mapid) {
String mapName = StringUtil.getLeftPaddedStr(Integer.toString(mapid), '0', 9);
StringBuilder builder = new StringBuilder("Map/Map");
int area = mapid / 100000000;
builder.append(area);
builder.append("/");
builder.append(mapName);
builder.append(".img");
mapName = builder.toString();
return mapName;
}
private String getMapStringName(int mapid) {
StringBuilder builder = new StringBuilder();
if (mapid < 100000000) {
builder.append("maple");
} else if (mapid >= 100000000 && mapid < 200000000) {
builder.append("victoria");
} else if (mapid >= 200000000 && mapid < 300000000) {
builder.append("ossyria");
} else if (mapid >= 540000000 && mapid < 560000000) {
builder.append("singapore");
} else if (mapid >= 600000000 && mapid < 620000000) {
builder.append("MasteriaGL");
} else if (mapid >= 670000000 && mapid < 682000000) {
builder.append("weddingGL");
} else if (mapid >= 682000000 && mapid < 683000000) {
builder.append("HalloweenGL");
} else if (mapid >= 800000000 && mapid < 900000000) {
builder.append("jp");
} else {
builder.append("etc");
}
builder.append("/").append(mapid);
return builder.toString();
}
public void setChannel(int channel) {
this.channel = channel;
}
public void setWorld(int world) {
this.channel = world;
}
public Map<Integer, MapleMap> getMaps() {
return maps;
}
}