20 package net.sf.gridarta.model.io;
22 import java.awt.Point;
23 import java.io.BufferedReader;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.List;
29 import java.util.Map.Entry;
37 import org.apache.log4j.Category;
38 import org.apache.log4j.Logger;
39 import org.jetbrains.annotations.NotNull;
40 import org.jetbrains.annotations.Nullable;
81 public G
load(@NotNull
final BufferedReader reader, @Nullable
final Collection<G> objects)
throws IOException {
82 final String line = reader.readLine();
87 return load(reader, line, objects);
96 public G
load(@NotNull
final BufferedReader reader, @NotNull
final String firstLine, @Nullable
final Collection<G> objects)
throws IOException {
98 if (archName == null) {
106 final String thisLine2 = reader.readLine();
107 if (thisLine2 == null) {
108 throw new IOException(
"unexpected end of file while reading 'arch " + archName +
"'");
110 final String thisLine = thisLine2.trim();
112 if (thisLine.startsWith(
"arch ")) {
113 final G invItem =
load(reader, thisLine, objects);
114 assert invItem != null :
"invItem must not be null here.";
115 gameObject.addLast(invItem);
116 }
else if (thisLine.equals(
"end")) {
117 if (objects != null) {
118 objects.add(gameObject);
121 }
else if (thisLine.equals(
"msg")) {
122 gameObject.setMsgText(
"");
124 final String thisLine3 = reader.readLine();
125 if (thisLine3 == null) {
126 throw new IOException(
"unexpected end of file while reading 'arch " + archName +
"'");
129 if (thisLine3.trim().equals(
"endmsg")) {
133 gameObject.addMsgTextLine(thisLine3);
135 }
else if (
parseLine(thisLine, gameObject)) {
137 }
else if (thisLine.startsWith(
"x ")) {
138 gameObject.setMapX(Integer.parseInt(thisLine.substring(2)));
139 }
else if (thisLine.startsWith(
"y ")) {
140 gameObject.setMapY(Integer.parseInt(thisLine.substring(2)));
142 gameObject.addObjectText(thisLine);
155 protected boolean parseLine(@NotNull
final String line, @NotNull
final G gameObject) {
169 private static String
readArchName(@NotNull
final BufferedReader reader, @NotNull
final String firstLine)
throws IOException {
170 for (String thisLine2 = firstLine; thisLine2 != null; thisLine2 = reader.readLine()) {
171 final String thisLine = thisLine2.trim();
172 if (thisLine.startsWith(
"arch ")) {
173 return thisLine.substring(5).trim();
174 }
else if (!thisLine.isEmpty() && !thisLine.startsWith(
"#")) {
175 throw new IOException(
"unexpected first line of game object: '" + thisLine +
"', expected 'arch ...'");
183 final Collection<G> tailList =
new ArrayList<>();
185 for (
final G gameObject : objects) {
186 if (!gameObject.isInContainer()) {
191 objects.addAll(tailList);
195 public void save(@NotNull
final Appendable appendable, @NotNull
final G gameObject)
throws IOException {
198 appendable.append(
"arch ");
199 appendable.append(gameObject.getArchetype().getArchetypeName());
200 appendable.append(
"\n");
201 for (
final Entry<String, String> entry : fields.entrySet()) {
202 final String key = entry.getKey();
203 appendable.append(key);
204 if (key.equals(
"msg")) {
205 appendable.append(
"\n");
206 appendable.append(entry.getValue());
207 appendable.append(
"endmsg\n");
209 appendable.append(
" ");
210 appendable.append(entry.getValue());
211 appendable.append(
"\n");
215 for (
final G inventoryItem : gameObject) {
216 save(appendable, inventoryItem);
219 appendable.append(
"end\n");
223 public void addModifiedFields(@NotNull
final G gameObject, @NotNull
final Map<String, String> fields) {
226 final String msgText = gameObject.getMsgText();
227 final String archMsgText = archetype.
getMsgText();
228 if (msgText != null && !msgText.equals(archMsgText == null ?
"" : archMsgText)) {
229 fields.put(
"msg", msgText);
232 final CharSequence objText = gameObject.getObjectText();
233 if (objText.length() != 0) {
236 if (line.length == 2) {
237 fields.put(line[0], line[1]);
239 LOG.warn(
"writeMapArch: ignoring invalid arch line: " + aTmp);
245 if (gameObject.getMapX() != 0) {
246 fields.put(
"x", Integer.toString(gameObject.getMapX()));
248 if (gameObject.getMapY() != 0) {
249 fields.put(
"y", Integer.toString(gameObject.getMapY()));
264 private void expandMulti(@NotNull
final G gameObject, @NotNull
final Collection<G> objects) {
267 if (!archetype.
isMulti() || gameObject.getMultiRefCount() > 1) {
271 if (gameObject.isInContainer()) {
272 LOG.warn(
"Multi-part expansion for a GameObject inside a container requested.");
277 final Point pos = gameObject.getMapLocation();
278 for (R oldPart = archetype.
getMultiNext(); oldPart != null; oldPart = oldPart.getMultiNext()) {
280 tailGameObject.setMapX(pos.x + oldPart.getMultiX());
281 tailGameObject.setMapY(pos.y + oldPart.getMultiY());
282 objects.add(tailGameObject);
G createGameObject(@NotNull R archetype)
Creates a new GameObject from an Archetype.
Utility class for string manipulation.
T getMultiNext()
Returns the next of this multi-part object.
R getOrCreateArchetype(@NotNull String archetypeName)
Returns an archetype by its name.
Interface for classes that read or write GameObject instances.
void addModifiedFields(@NotNull final G gameObject, @NotNull final Map< String, String > fields)
static final Pattern PATTERN_SPACES
The pattern that matches a non-empty sequence of spaces.
Map< String, String > getModifiedFields( @NotNull G gameObject)
Returns the modified fields of a GameObject.
final ArchetypeSet< G, A, R > archetypeSet
The ArchetypeSet for looking up archetypes.
void save(@NotNull final Appendable appendable, @NotNull final G gameObject)
Base package of all Gridarta classes.
void collectTempList(@NotNull final List< G > objects)
Reflects a game object (object on a map).
AbstractGameObjectParser(@NotNull final GameObjectFactory< G, A, R > gameObjectFactory, @NotNull final ArchetypeSet< G, A, R > archetypeSet)
Create a new instance.
Abstract factory for creating GameObject instances.
G load(@NotNull final BufferedReader reader, @NotNull final String firstLine, @Nullable final Collection< G > objects)
GameObjects are the objects based on Archetypes found on maps.
String getMsgText()
Returns the message bound to this object.
R getArchetype()
Returns the Archetype this GameObject is based on.
static final Pattern PATTERN_END_OF_LINE
The pattern to match end of line characters separating lines.
static String readArchName(@NotNull final BufferedReader reader, @NotNull final String firstLine)
Read an archetype name.
boolean parseLine(@NotNull final String line, @NotNull final G gameObject)
Parse one line.
Interface that captures similarities between different ArchetypeSet implementations.
G load(@NotNull final BufferedReader reader, @Nullable final Collection< G > objects)
boolean isMulti()
Returns whether this Archetype is a multi-part object.
final GameObjectFactory< G, A, R > gameObjectFactory
The game object factory for creating new game object instances.
static final Category LOG
The Logger for printing log messages.
Abstract base class for classes implementing GameObjectParsers.
void expandMulti(@NotNull final G gameObject, @NotNull final Collection< G > objects)
If the given gameObject is a multi-part head, we generate the appropriate tail (from the archetype st...
Interface for MapArchObjects.
G createGameObjectPart(@NotNull R archetype, @Nullable G head)
Creates a new GameObject from an Archetype.