/******************************************************************************* * Rhythos Editor is a game editor and project management tool for making RPGs on top of the Rhythos Game system. * * Copyright (C) 2013 David Maletz * * 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 mrpg.world; import java.awt.Image; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import javax.swing.JOptionPane; import mrpg.editor.MapEditor; import mrpg.editor.resource.Project; import mrpg.export.WorldIO; public class World { private ArrayList<Cell> cells; private int width, height; public boolean wrapX = false, wrapY = false; public Image background = null; public World(int _width, int _height){ width = _width; height = _height; cells = new ArrayList<Cell>(width*height); cells.addAll(Collections.nCopies(width*height, (Cell)null)); } private World(int _width, int _height, boolean b){width = _width; height = _height; cells = new ArrayList<Cell>(width*height);} public World(World w){ width = w.width; height = w.height; int sz = width*height; cells = new ArrayList<Cell>(sz); wrapX = w.wrapX; wrapY = w.wrapY; background = w.background; for(int i=0; i<sz; i++){ Cell c = w.cells.get(i); cells.add((c == null)?null:new Cell(c, this)); } } public void refresh(Project p){refresh(p, false);} public void refresh(Project p, boolean prompt_add){ PromptAdd prompt = (prompt_add)?new PromptAdd():null; boolean u = false; for(Cell c : cells) if(c != null) u |= c.refresh(p, prompt); if(u) updateNeighbors(); } public static class PromptAdd { private static final int PROMPT=0, DONT_ADD=1, ADD=2; private int state = PROMPT; public boolean copyTileset(){ if(state == PROMPT){ int i = JOptionPane.showConfirmDialog(MapEditor.instance, "The project you are moving this map to is missing tilesets the map needs. Do you wish to copy the tilesets over?", "Moving Map", JOptionPane.YES_NO_OPTION); state = (i == JOptionPane.YES_OPTION)?ADD:DONT_ADD; } return state == ADD; } } public int getWidth(){return width;} public int getHeight(){return height;} private final Cell OOB = new Cell(this, -1, -1); public Cell getCell(int x, int y){ boolean oob = false; if(wrapX){x = x%width; if(x < 0) x += width;} else oob = oob || x < 0 || x >= width; if(wrapY){y = y%height; if(y < 0) y += height;} else oob = oob || y < 0 || y >= height; return (oob)?OOB:cells.get(y*width+x); } public Cell addCell(int x, int y){ if(x < 0 || y < 0 || x >= width || y >= height) return null; Cell c = new Cell(this, x, y); cells.set(y*width+x, c); return c; } public boolean isNeighbor(int x, int y, Tile tile, int level){ Cell c = getCell(x, y); return c == OOB || (c != null && c.getTile(level).info.map == tile.info.map); } public int getNeighbors(int x, int y, Tile tile, int level){ int neighbors = Direction.NONE; if(isNeighbor(x-1, y, tile, level)) neighbors |= Direction.LEFT; if(isNeighbor(x+1, y, tile, level)) neighbors |= Direction.RIGHT; if(isNeighbor(x, y-1, tile, level)) neighbors |= Direction.UP; if(isNeighbor(x, y+1, tile, level)) neighbors |= Direction.DOWN; if(isNeighbor(x-1, y-1, tile, level)) neighbors |= Direction.UPPER_LEFT; if(isNeighbor(x+1, y-1, tile, level)) neighbors |= Direction.UPPER_RIGHT; if(isNeighbor(x-1, y+1, tile, level)) neighbors |= Direction.LOWER_LEFT; if(isNeighbor(x+1, y+1, tile, level)) neighbors |= Direction.LOWER_RIGHT; return neighbors; } public void updateNeighbors(){ for(int _y = 0; _y<height; _y++) for(int _x=0; _x<width; _x++){ Cell c = getCell(_x, _y); if(c == null) continue; int level = 0; for(Tile t : c){ if(t == Tile.empty || !t.info.map.indexNeighbors()){level++; continue;} int neighbors = getNeighbors(_x, _y, t, level); c.tiles.set(level, t.info.map.getTile(neighbors)); level++; } } } public void updateAdjacent(int x, int y, Tile tile, int level){ for(int _y = y-1; _y<=y+1; _y++) for(int _x=x-1; _x<=x+1; _x++){ Cell c = getCell(_x, _y); if(c == null) continue; Tile t = c.getTile(level); if(t == Tile.empty || !t.info.map.indexNeighbors()) continue; int neighbors = getNeighbors(_x, _y, t, level); c.tiles.set(level, t.info.map.getTile(neighbors)); } } public void resize(int _width, int _height){ ArrayList<Cell> _cells = new ArrayList<Cell>(_width*_height); for(int y=0; y<_height; y++) for(int x=0; x<_width; x++) _cells.add(getCell(x,y)); width = _width; height = _height; cells = _cells; } public void write(WorldIO tileIO) throws IOException { tileIO.writeShort(width); tileIO.writeShort(height); int wrap = 0; if(wrapX) wrap |= 1; if(wrapY) wrap |= 2; tileIO.write(wrap); for(int i=0; i<width*height; i++){ Cell c = cells.get(i); if(c == null) tileIO.write(0); else { int ct = 0; for(Tile t : c) if(t != Tile.empty) ct++; tileIO.write(ct); ct = 0; for(Tile t : c){ if(t != Tile.empty){tileIO.write(ct); t.write(tileIO);} ct++; } } } } public static World read(WorldIO tileIO) throws IOException { int width = tileIO.readShort(); int height = tileIO.readShort(); World w = new World(width, height, true); int wrap = tileIO.read(); w.wrapX = (wrap & 1) != 0; w.wrapY = (wrap & 2) != 0; for(int y=0; y<height; y++) for(int x=0; x<width; x++){ int tiles = tileIO.read(); if(tiles == 0) w.cells.add(null); else{ Cell c = new Cell(w, x, y); w.cells.add(c); for(int t=0; t<tiles; t++){ int level = tileIO.read(); c.setTile(Tile.read(tileIO), level, false); } } } w.updateNeighbors(); return w; } }