package net.sourceforge.pain.logic.transform.rom24support;
import net.sourceforge.pain.util.*;
import java.io.*;
import java.util.*;
public class Rom24AreaLoader {
private final Rom24AreaModel model = new Rom24AreaModel();
public static Rom24AreaModel loadArea(String fileName) throws Exception {
Rom24AreaLoader loader = new Rom24AreaLoader(fileName);
loader._load();
return loader.model;
}
private Rom24AreaLoader(String fileName) {
if (fileName == null) {
throw new NullPointerException("area file name is null");
}
model.fileName = fileName;
}
private void _load() throws Exception {
Log.info("opening file:" + model.fileName);
BufferedReader reader = new BufferedReader(new FileReader(model.fileName), 50 * 1000);
Log.info("opened");
try {
do {
String state = getState(reader);
if (state == null) {
break;
} else if (state.equals("#AREA")) {
loadAreaHeaders(reader);
} else if (state.equals("#RESETMESSAGE")) {
loadResetMessage(reader);
} else if (state.equals("#FLAG")) {
loadFlags(reader);
} else if (state.equals("#MOBILES")) {
loadMobiles(reader);
} else if (state.equals("#OBJECTS")) {
loadObjects(reader);
} else if (state.equals("#ROOMS")) {
loadRooms(reader);
} else if (state.equals("#RESETS")) {
loadResets(reader);
} else if (state.equals("#SHOPS")) {
loadShops(reader);
} else if (state.equals("#SPECIALS")) {
loadSpecials(reader);
} else if (state.equals("#PRACTICERS")) {
loadPracticers(reader);
} else if (state.equals("#OMPROGS")) {
loadMobProgs(reader);
} else if (state.equals("#OLIMITS")) {
loadLimits(reader);
} else {
Log.warn("unknown state:" + state + " - ignoring");
}
} while (true);
} finally {
reader.close();
}
// System.out.println("time:" + (System.currentTimeMillis() - starttime));
}
private void loadAreaHeaders(BufferedReader reader) throws Exception {
reader.readLine();// fileName
String tmp = reader.readLine().trim();
model.areaName = tmp.substring(0, tmp.length() - 1);
model.levelRange = reader.readLine();
model.vnumRange = reader.readLine();
}
private void loadResetMessage(BufferedReader reader) throws Exception {
model.resetMessage = reader.readLine().split("~")[0];
}
private void loadFlags(BufferedReader reader) throws Exception {
model.flags = reader.readLine();
}
private void loadMobiles(BufferedReader reader) throws Exception {
Log.info("loading mobiles...");
String line;
while ((line = findLineStarted(reader, "#", false)) != null) {
String id = line.substring(1).trim();
if (Integer.parseInt(id) == 0) {
break;
}
// ok its room and we have id;
Log.info("mobile found, id =" + id);
ROMMobile mobile = new ROMMobile(id);
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
mobile.nameList = line.split(" ");
for (int i = 0; i < mobile.nameList.length; i++) {
mobile.nameList[i] = mobile.nameList[i].toLowerCase();
}
// Log.debug("namelist:" + mobile.nameList[0]);
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
mobile.shortDesc = line;
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
mobile.longDesc = line;
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
mobile.lookDesc = line;
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
mobile.race = line;
reader.readLine(); // \n
line = reader.readLine();
StringTokenizer st = new StringTokenizer(line, " \t");
if (st.countTokens() != 4) {
throw new IllegalArgumentException("wrong: VII. Act, Affect, Alignment and group:" + line);
}
mobile.act = st.nextToken();
mobile.affect = st.nextToken();
mobile.alignment = st.nextToken();
mobile.group = st.nextToken();
line = reader.readLine();
st = new StringTokenizer(line, " \t");
if (st.countTokens() < 5) {
throw new IllegalArgumentException("wrong: Level, hit bonus, hit dice, mana dice, damage, damtype: " + line);
}
mobile.level = Integer.parseInt(st.nextToken());
mobile.hitBonus = Integer.parseInt(st.nextToken());
mobile.hitDice = parseDice(st.nextToken());
mobile.manaDice = parseDice(st.nextToken());
mobile.damDice = parseDice(st.nextToken());
mobile.damType = (st.hasMoreTokens() ? st.nextToken() : Rom24AreaModel.defaultDamType);
line = reader.readLine();
st = new StringTokenizer(line, " \t");
if (st.countTokens() < 4) {
throw new IllegalArgumentException("wrong: armor:" + line);
}
mobile.armor = new int[4];
mobile.armor[0] = Integer.parseInt(st.nextToken());
mobile.armor[1] = Integer.parseInt(st.nextToken());
mobile.armor[2] = Integer.parseInt(st.nextToken());
mobile.armor[3] = Integer.parseInt(st.nextToken());
line = reader.readLine();
st = new StringTokenizer(line, " \t");
if (st.countTokens() != 4) {
throw new IllegalArgumentException("wrong: offence, immune, resist, vuln:" + line);
}
mobile.offenses = st.nextToken();
mobile.immunities = st.nextToken();
mobile.resistances = st.nextToken();
mobile.vulnerabilities = st.nextToken();
// line = reader.readLine();
// st = new StringTokenizer(line, " \t");
// mobile.offenses = st.nextToken();
// mobile.immunities = st.nextToken();
// mobile.resistances = st.nextToken();
// mobile.vulnerabilities = st.nextToken();
line = reader.readLine();
if (line.length() == 0) {
line = reader.readLine(); // cells.are contains empty line
}
st = new StringTokenizer(line, " \t");
mobile.position1 = st.nextToken();
mobile.position2 = st.nextToken();
mobile.gender = st.nextToken();
mobile.treasure = Integer.parseInt(st.nextToken());
// form, parst sizes - ignored;
model.mobiles.put(mobile.vnum, mobile);
}
}
private void loadObjects(BufferedReader reader) throws Exception {
Log.info("loading objects...");
String line;
while ((line = findLineStarted(reader, "#", false)) != null) {
String id = line.substring(1).trim();
if (Integer.parseInt(id) == 0) {
break;
}
// ok its room and we have id;
Log.info("object found, id =" + id);
ROMObject obj = new ROMObject(id);
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
obj.nameList = line.split(" ");
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
obj.shortDesc = line;
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
obj.longDesc = line;
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
obj.material = line;
reader.readLine(); // \n
line = reader.readLine();
StringTokenizer st = new StringTokenizer(line, " \t");
if (st.countTokens() != 3) {
throw new IllegalArgumentException("wrong: Flags, Extras, Wear locations:" + line);
}
obj.typeFlags = st.nextToken();
obj.extraFlags = st.nextToken();
obj.wearFlags = st.nextToken();
line = reader.readLine();
String complexTokens[] = parseComplexTokens(line);
if (complexTokens.length != 5) {
throw new IllegalArgumentException("wrong: V0 through V4:" + line);
}
obj.value[0] = complexTokens[0];
obj.value[1] = complexTokens[1];
;
obj.value[2] = complexTokens[2];
;
obj.value[3] = complexTokens[3];
;
obj.value[4] = complexTokens[4];
;
line = reader.readLine();
st = new StringTokenizer(line, " \t");
if (st.countTokens() != 4) {
throw new IllegalArgumentException("wrong: <level> <weight> <cost> <cond>:" + line);
}
obj.level = Integer.parseInt(st.nextToken());
obj.weight = Integer.parseInt(st.nextToken());
obj.cost = Integer.parseInt(st.nextToken());
obj.condition = st.nextToken();
// + applies
// + extraDescs
model.objects.put(obj.vnum, obj);
}
}
private void loadResets(BufferedReader reader) throws Exception {
if (model.rooms.size() == 0 /*|| (mobiles.size() == 0 && objects.size() == 0)*/) { // offcol.are: rooms and resets!
if (reader.readLine().trim().equals("S")) {
return;
}
throw new RuntimeException("cant load resets before rooms, objects and mobiles!");
}
Log.info("loading resets...");
// only MOB and OBJ reset loading implemented
do {
String line = reader.readLine();
String comment = "";
int commentStart = line.indexOf('*');
if (commentStart > 0) {
comment = line.substring(commentStart + 1);
line = line.substring(0, commentStart - 1);
}
if (line.startsWith("O")) {
Log.info("reading reset:" + line);
StringTokenizer st = new StringTokenizer(line, " \t");
if (st.countTokens() < 5) {
Log.warn("IGNORING: wrong reset:" + line);
continue;
}
ROMObjectReset reset = new ROMObjectReset();
reset.comment = comment;
st.nextToken();
st.nextToken();
reset.obj = (ROMObject) model.objects.get(st.nextToken());
if (reset.obj == null) {
Log.warn("IGNORING: can't find object for reset:" + line);
continue;
}
reset.count = Integer.parseInt(st.nextToken());
if (reset.count < 1 && reset.count != -1) {
Log.warn("IGNORING: wrong reset count:" + line);
continue;
}
// String tmp = st.nextToken();
ROMRoom room = (ROMRoom) model.rooms.get(st.nextToken());
if (room == null) {
Log.warn("IGNORING: can't find room for reset:" + line);
continue;
}
room.resets.add(reset);
} else if (line.startsWith("M")) {
Log.info("reading reset:" + line);
StringTokenizer st = new StringTokenizer(line, " \t");
if (st.countTokens() < 6) {
Log.warn("IGNORING: wrong reset:" + line);
continue;
}
ROMMobileReset reset = new ROMMobileReset();
reset.comment = comment;
st.nextToken();
st.nextToken();
reset.mob = (ROMMobile) model.mobiles.get(st.nextToken());
if (reset.mob == null) {
Log.warn("IGNORING: can't find mobile for reset:" + line);
continue;
}
int limit = Integer.parseInt(st.nextToken());
if (reset.mob.limit != 0 && reset.mob.limit != limit) {
if (reset.mob.limit < limit) {
Log.warn("Mobile limit changed from:" + reset.mob.limit + " to:" + limit);
} else {
Log.warn("Mobile already has higher limit:" + reset.mob.limit + ". Ignoring" + limit);
}
}
reset.mob.limit = limit;
ROMRoom room = (ROMRoom) model.rooms.get(st.nextToken());
if (room == null) {
Log.warn("IGNORING: can't find room for reset:" + line);
continue;
}
String countStr = st.nextToken();
int commentIndex = countStr.indexOf("*");
if (commentIndex > -1) { // there is values like '1*' / mount the doom
countStr = countStr.substring(0, commentIndex);
}
reset.count = Integer.parseInt(countStr);
if (reset.count < 1) {
Log.warn("IGNORING: wrong reset count:" + line);
continue;
}
room.resets.add(reset);
} else if (line.startsWith("S")) {
break;
} else {
Log.info("ignoring unsupported reset:" + line);
continue;
}
} while (true);
}
private void loadShops(BufferedReader reader) {
}
private void loadSpecials(BufferedReader reader) {
}
private void loadPracticers(BufferedReader reader) {
}
private void loadMobProgs(BufferedReader reader) {
}
private void loadLimits(BufferedReader reader) {
}
private void loadRooms(BufferedReader reader) throws Exception {
Log.info("loading rooms...");
String line;
while ((line = findLineStarted(reader, "#", false)) != null) {
String id = line.substring(1).trim();
if (Integer.parseInt(id) == 0) {
break;
}
// ok its room and we have id;
Log.info("room found, id =" + id);
ROMRoom room = new ROMRoom(id);
// reading name
readUntilToken(reader, "~", true);
line = model.tmpBuffer.toString().trim();
room.name = line;
// reading name
if (readUntilToken(reader, "~", false)) {
room.desc = model.tmpBuffer.toString().trim();
}
// Log.info("loading exits for room");
// ok now load exits
// String[] roomExits = new String[6];
do {
line = reader.readLine().trim().toUpperCase();
if (line.length() == 2 && line.charAt(0) == 'D') { // ok its exit
int direction = line.charAt(1) - '0';
readUntilToken(reader, "~", true);
String exitDescr = model.tmpBuffer.toString();
readUntilToken(reader, "~", true);
reader.readLine(); // \r\n
line = reader.readLine().trim();
line = line.substring(line.lastIndexOf(' ') + 1, line.length());
room.exits[direction] = line;
room.exitsDescs[direction] = exitDescr;
}
} while (!line.equals("S"));
model.rooms.put(room.vnum, room);
// Log.info("------------------------");
// Log.info("room added: rom24support id=" + id);
// Log.info(" name=" + room.desc);
// Log.info(" desc=" + room.name);
}
Log.info("rooms loaded OK");
}
private static String findLineStarted(BufferedReader reader, String token, boolean required) throws Exception {
// int c1 = token.charAt(token.length() - 1);
String line;
do {
line = reader.readLine();
if (line == null) {
break;
}
if (line.startsWith(token)) {
return line;
}
} while (true);
if (required) {
throw new Exception("required linestart not found:" + token);
}
return null;
}
private boolean readUntilToken(BufferedReader reader, String token, boolean required) throws Exception {
if (model.tmpBuffer.length() > 0) {
model.tmpBuffer = new StringBuffer();
}
final int tokenLen = token.length();
final int c1 = token.charAt(tokenLen - 1);
int bufLen;
while (true) {
int c2 = reader.read();
if (c2 == -1) {
if (required) {
Log.info("Buffer before error:" + model.tmpBuffer.toString());
throw new Exception("required token not found:" + token);
} else {
return false;
}
}
model.tmpBuffer.append((char) c2);
if (c2 == c1 && (bufLen = model.tmpBuffer.length()) >= tokenLen) {
boolean match = true;
for (int i = 2; i <= tokenLen; i++) {
if (model.tmpBuffer.charAt(bufLen - i) != token.charAt(tokenLen - i)) {
match = false;
}
}
if (match) {
model.tmpBuffer.setLength(bufLen - tokenLen);
break;
}
}
}
return true;
}
private static String getState(BufferedReader reader) throws Exception {
String state;
do {
state = reader.readLine();
if (state == null) {
return null;
}
if (state.startsWith("#")) {
state = state.trim().toUpperCase();
if (state.equals("#$")) {
return null;
}
return state;
}
} while (true);
}
private static int[] parseDice(String dice) {
dice = dice.toUpperCase();
int indexD = dice.indexOf("D");
if (indexD < 0) {
throw new IllegalArgumentException("wrong dice:" + dice);
}
int indexA = dice.indexOf("+", indexD);
if (indexA < 0) {
throw new IllegalArgumentException("wrong dice:" + dice);
}
int dices[] = new int[3];
dices[0] = Integer.parseInt(dice.substring(0, indexD));
dices[1] = Integer.parseInt(dice.substring(indexD + 1, indexA));
dices[2] = Integer.parseInt(dice.substring(indexA + 1));
return dices;
}
private String[] parseComplexTokens(String line) {
if (model.tmpBuffer.length() > 0) {
model.tmpBuffer = new StringBuffer();
}
ArrayList list = new ArrayList();
boolean outQuote = true;
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if ((c == ' ' || c == '\t') && outQuote) {
if (model.tmpBuffer.length() > 0) {
list.add(model.tmpBuffer.toString());
model.tmpBuffer = new StringBuffer();
}
} else if (c == '\'') {
if (model.tmpBuffer.length() > 0) {
list.add(model.tmpBuffer.toString());
model.tmpBuffer = new StringBuffer();
} else {
if (!outQuote) { // '' exp
list.add(null);
}
}
outQuote = !outQuote;
} else {
model.tmpBuffer.append(c);
}
}
if (model.tmpBuffer.length() > 0) {
list.add(model.tmpBuffer.toString());
model.tmpBuffer = new StringBuffer();
}
String result[] = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = (String) list.get(i);
}
return result;
}
}