1 package de.lathanda.eos.robot;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6 import java.util.Iterator;
7 import java.util.LinkedList;
8 import java.util.Map.Entry;
9 import java.util.Random;
10 import java.util.TreeMap;
12 import javax.swing.JFrame;
13 import javax.xml.parsers.DocumentBuilder;
14 import javax.xml.parsers.DocumentBuilderFactory;
15 import javax.xml.parsers.ParserConfigurationException;
16 import javax.xml.transform.OutputKeys;
17 import javax.xml.transform.Transformer;
18 import javax.xml.transform.TransformerException;
19 import javax.xml.transform.TransformerFactory;
20 import javax.xml.transform.dom.DOMSource;
21 import javax.xml.transform.stream.StreamResult;
23 import org.w3c.dom.DOMException;
24 import org.w3c.dom.Document;
25 import org.w3c.dom.Element;
26 import org.w3c.dom.Node;
27 import org.w3c.dom.NodeList;
28 import org.xml.sax.SAXException;
30 import de.lathanda.eos.base.MutableColor;
31 import de.lathanda.eos.base.ResourceLoader;
32 import de.lathanda.eos.base.event.CleanupListener;
33 import de.lathanda.eos.base.util.Direction;
34 import de.lathanda.eos.robot.exceptions.CubeImmutableException;
35 import de.lathanda.eos.robot.exceptions.RobotEntranceMissingException;
36 import de.lathanda.eos.robot.exceptions.RobotException;
37 import de.lathanda.eos.robot.exceptions.RobotNoSpaceException;
38 import de.lathanda.eos.robot.exceptions.UnknownWorldVersionException;
39 import de.lathanda.eos.robot.exceptions.WorldLoadFailedException;
40 import de.lathanda.eos.robot.exceptions.WorldNotFoundException;
41 import de.lathanda.eos.robot.gui.Camera;
42 import de.lathanda.eos.robot.gui.WorldFrame;
55 private final TreeMap<Coordinate, Column> columns =
new TreeMap<Coordinate, Column>();
59 private final LinkedList<Entrance> entrances =
new LinkedList<Entrance>();
63 private final LinkedList<Robot> robots =
new LinkedList<Robot>();
87 private boolean showCursor =
false;
93 private Random random =
new Random();
123 }
catch (IOException fnfe) {
138 synchronized (columns) {
141 synchronized (entrances) {
144 synchronized (robots) {
150 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
152 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
154 doc = dBuilder.parse(worldStream);
155 Element world = doc.getDocumentElement();
157 switch (Integer.parseInt(world.getAttribute(
"version"))) {
159 parseVersion1(world);
162 parseVersion2(world);
167 }
catch (SAXException | IOException | ParserConfigurationException |
RobotException e) {
178 if (world.hasAttribute(
"minx")) {
179 minX = Integer.parseInt(world.getAttribute(
"minx"));
183 if (world.hasAttribute(
"maxx")) {
184 maxX = Integer.parseInt(world.getAttribute(
"maxx"));
188 if (world.hasAttribute(
"miny")) {
189 minY = Integer.parseInt(world.getAttribute(
"miny"));
193 if (world.hasAttribute(
"maxy")) {
194 maxY = Integer.parseInt(world.getAttribute(
"maxy"));
198 NodeList nodes = world.getChildNodes();
199 for (
int i = 0; i < nodes.getLength(); i++) {
200 Node node = nodes.item(i);
201 if (node.getNodeType() == Node.ELEMENT_NODE) {
202 Element element = (Element) node;
203 switch (node.getNodeName()) {
205 synchronized (entrances) {
206 int x = Integer.parseInt(element.getAttribute(
"x"));
207 int y = Integer.parseInt(element.getAttribute(
"y"));
208 int z = Integer.parseInt(element.getAttribute(
"z"));
209 Direction d = Direction.getDirection(Integer.parseInt(element.getAttribute(
"direction")));
211 entrances.add(
new Entrance(x, y, z, d));
216 Coordinate coordinate =
new Coordinate(Integer.parseInt(element.getAttribute(
"x")),
217 Integer.parseInt(element.getAttribute(
"y")));
219 column.setMark(Integer.parseInt(element.getAttribute(
"mark")) == 1);
221 NodeList cubeNodes = node.getChildNodes();
222 for (
int j = 0; j < cubeNodes.getLength(); j++) {
223 Node cubeNode = cubeNodes.item(j);
224 if (cubeNode.getNodeType() == Node.ELEMENT_NODE && cubeNode.getNodeName().equals(
"cube")) {
225 Element cubeElement = (Element) cubeNode;
226 Cube cube = Cube.createCube(Integer.parseInt(cubeElement.getAttribute(
"type")),
227 new MutableColor(Integer.parseInt(cubeElement.getAttribute(
"color"))));
228 int level = Integer.parseInt(cubeElement.getAttribute(
"index"));
230 column.setCube(level, cube);
245 private void parseVersion2(Element world)
throws RobotException {
246 if (world.hasAttribute(
"minx")) {
247 minX = Integer.parseInt(world.getAttribute(
"minx"));
251 if (world.hasAttribute(
"maxx")) {
252 maxX = Integer.parseInt(world.getAttribute(
"maxx"));
256 if (world.hasAttribute(
"miny")) {
257 minY = Integer.parseInt(world.getAttribute(
"miny"));
261 if (world.hasAttribute(
"maxy")) {
262 maxY = Integer.parseInt(world.getAttribute(
"maxy"));
267 if (world.hasAttribute(
"camerapositionx")) {
270 if (world.hasAttribute(
"camerapositiony")) {
273 if (world.hasAttribute(
"camerapositionz")) {
276 if (world.hasAttribute(
"camerarotationx")) {
279 if (world.hasAttribute(
"camerarotationz")) {
283 NodeList nodes = world.getChildNodes();
284 for (
int i = 0; i < nodes.getLength(); i++) {
285 Node node = nodes.item(i);
286 if (node.getNodeType() == Node.ELEMENT_NODE) {
287 Element element = (Element) node;
288 switch (node.getNodeName()) {
290 synchronized (entrances) {
291 int x = Integer.parseInt(element.getAttribute(
"x"));
292 int y = Integer.parseInt(element.getAttribute(
"y"));
293 int z = Integer.parseInt(element.getAttribute(
"z"));
294 Direction d = Direction.getDirection(Integer.parseInt(element.getAttribute(
"direction")));
296 entrances.add(
new Entrance(x, y, z, d));
301 Coordinate coordinate =
new Coordinate(Integer.parseInt(element.getAttribute(
"x")),
302 Integer.parseInt(element.getAttribute(
"y")));
304 if (element.hasAttribute(
"mark")) {
305 column.setMark(
new MutableColor(Integer.parseInt(element.getAttribute(
"mark"))));
307 NodeList cubeNodes = node.getChildNodes();
308 for (
int j = 0; j < cubeNodes.getLength(); j++) {
309 Node cubeNode = cubeNodes.item(j);
310 if (cubeNode.getNodeType() == Node.ELEMENT_NODE && cubeNode.getNodeName().equals(
"cube")) {
311 Element cubeElement = (Element) cubeNode;
312 Cube cube = Cube.createCube(Integer.parseInt(cubeElement.getAttribute(
"type")),
313 new MutableColor(Integer.parseInt(cubeElement.getAttribute(
"color"))));
314 int level = Integer.parseInt(cubeElement.getAttribute(
"index"));
316 column.setCube(level, cube);
335 public void save(OutputStream targetStream)
throws ParserConfigurationException, TransformerException,
RobotException {
336 Document world = buildDocumentVersion2();
337 DOMSource worldSource =
new DOMSource(world);
338 TransformerFactory tf = TransformerFactory.newInstance();
339 StreamResult target =
new StreamResult(targetStream);
340 Transformer serializer = tf.newTransformer();
341 serializer.setOutputProperty(OutputKeys.ENCODING,
"UTF-8");
342 serializer.setOutputProperty(OutputKeys.INDENT,
"yes");
343 serializer.transform(worldSource, target);
353 private Document buildDocumentVersion2() throws ParserConfigurationException, DOMException,
RobotException {
354 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
355 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
356 Document doc = dBuilder.newDocument();
359 Element world = doc.createElement(
"world");
360 world.setAttribute(
"version",
"2");
362 world.setAttribute(
"minx", Integer.toString(minX));
365 world.setAttribute(
"maxx", Integer.toString(maxX));
368 world.setAttribute(
"miny", Integer.toString(minY));
371 world.setAttribute(
"maxy", Integer.toString(maxY));
380 doc.appendChild(world);
381 synchronized (entrances) {
382 for (Entrance entrance : entrances) {
383 Element entranceElement = doc.createElement(
"entrance");
384 entranceElement.setAttribute(
"x",
"" + entrance.x);
385 entranceElement.setAttribute(
"y",
"" + entrance.y);
386 entranceElement.setAttribute(
"z",
"" + entrance.z);
387 entranceElement.setAttribute(
"direction",
"" + entrance.d.index);
388 world.appendChild(entranceElement);
391 synchronized (columns) {
392 for (Entry<Coordinate, Column> col : this.columns.entrySet()) {
393 Element columnElement = doc.createElement(
"column");
394 Column column = col.getValue();
395 Coordinate coordinate = col.getKey();
396 columnElement.setAttribute(
"x",
"" + coordinate.getX());
397 columnElement.setAttribute(
"y",
"" + coordinate.getY());
398 if (column.isMarked()) {
399 columnElement.setAttribute(
"mark",
"" + column.getMark().getRGB());
402 boolean saveColumn = column.isMarked();
403 for (Cube cube : column.getCubes()) {
404 if (!cube.isEmpty()) {
405 Element cubeElement = doc.createElement(
"cube");
406 cubeElement.setAttribute(
"index",
"" + index);
407 cubeElement.setAttribute(
"color",
"" + cube.getColor().getRGB());
408 cubeElement.setAttribute(
"type",
"" + cube.getType());
409 columnElement.appendChild(cubeElement);
415 world.appendChild(columnElement);
438 for (
int x = left; x <= right; x++) {
439 next:
for (
int y = bottom; y <= top; y++) {
440 if (random.nextDouble() <= density) {
441 for (
Robot robot : robots) {
442 if (robot.getX() == x && robot.getY() == y) {
447 if (e.x == x && e.y == y) {
472 if (minX !=
null && co.
getX() < minX) {
475 if (minY !=
null && co.
getY() < minY) {
478 if (maxX !=
null && co.
getX() > maxX) {
481 if (maxY !=
null && co.
getY() > maxY) {
485 synchronized (columns) {
503 synchronized (entrances) {
504 if (entrances.size() == 0) {
511 r.initialize(
this, e.
x, e.
y, e.
z, e.
d);
512 entrances.removeFirst();
514 synchronized(robots) {
527 synchronized (entrances) {
529 Iterator<Entrance> i = entrances.iterator();
530 while (i.hasNext()) {
532 if (e.
x == x && e.
y == y && e.
z == z) {
537 entrances.add(
new Entrance(x, y, z, d));
544 synchronized (entrances) {
546 Iterator<Entrance> i = entrances.iterator();
547 while (i.hasNext()) {
549 if (e.
x == cursorX && e.
y == cursorY && e.
z == cursorZ) {
615 return this.stoneColor;
629 return this.markColor;
671 synchronized (entrances) {
673 Iterator<Entrance> i = entrances.iterator();
674 while (i.hasNext()) {
676 if (e.
x == cursorX && e.
y == cursorY && e.
z == cursorZ) {
741 public static class IntRange implements Iterable<Integer> {
766 public void extend(
int value,
int radius) {
767 if (value - radius < min) {
768 min = value - radius;
770 if (value + radius > max) {
771 max = value + radius;
780 return max - min + 1;
785 return this.
new IntRangeIterator();
793 private class IntRangeIterator
implements Iterator<Integer> {
802 public IntRangeIterator() {
807 public boolean hasNext() {
812 public Integer next() {
827 this.showCursor = showCursor;
877 synchronized (columns) {
880 synchronized(entrances) {
883 synchronized(robots) {
888 return robots.size();
891 return entrances.size();
894 public void setRange(Integer minX, Integer maxX, Integer minY, Integer maxY) {
static final MutableColor RED
static final MutableColor YELLOW
static InputStream getResourceAsStream(String filename)
boolean isFree(int level, int size)
void setMark(boolean mark)
void dropCube(int level, Cube cube)
void setCube(int level, Cube cube)
void removeCube(int level)
static Cube createStone(MutableColor stoneColor)
static Cube createRock(MutableColor stoneColor)
IntRange(int min, int max)
void extend(int value, int radius)
Iterator< Integer > iterator()
void dropStone(int x, int y)
void load(String filename)
void setStoneColor(MutableColor c)
void fillRandom(int left, int top, int right, int bottom, double density)
LinkedList< Entrance > getEntrances()
void setRange(Integer minX, Integer maxX, Integer minY, Integer maxY)
Column getColumn(Coordinate co)
void setStone(int x, int y, int z)
void setMark(int x, int y, MutableColor c)
void setStone(int x, int y, int z, MutableColor c)
void setShowCursor(boolean showCursor)
LinkedList< Robot > getRobots()
void load(InputStream worldStream)
void setCursor(int x, int y, int z)
void setMarkColor(MutableColor c)
Column getColumn(int x, int y)
void save(OutputStream targetStream)
MutableColor getMarkColor()
void removeStone(int x, int y, int z)
TreeMap< Coordinate, Column > getColumns()
void setRock(int x, int y, int z)
void pickupStone(int x, int y)
void dropStone(int x, int y, MutableColor c)
void toggleEntrance(int x, int y, int z, Direction d)
MutableColor getStoneColor()
double getCameraPositionX()
double getCameraRotationX()
double getCameraPositionY()
void setCameraPositionY(double cameraPositionY)
void setCameraPositionZ(double cameraPositionZ)
void setCameraRotationX(double cameraRotationX)
double getCameraPositionZ()
double getCameraRotationZ()
void setCameraPositionX(double cameraPositionX)
void setCameraRotationZ(double cameraRotationZ)