/** * Copyright 2014 * SMEdit https://github.com/StarMade/SMEdit * SMTools https://github.com/StarMade/SMTools * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. **/ package jo.sm.ship.logic; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import jo.sm.data.BlockTypes; import jo.sm.data.CubeIterator; import jo.sm.data.SparseMatrix; import jo.sm.ship.data.Block; import jo.sm.ship.data.Chunk; import jo.sm.ship.data.Data; import jo.vecmath.Point3i; /** * @Auther Jo Jaquinta for SMEdit Classic - version 1.0 **/ public class ShipLogic { public static void getBounds(Data datum, Point3i lower, Point3i upper) { boolean first = true; for (Chunk c : datum.getChunks()) { Point3i pos = c.getPosition(); for (CubeIterator i = new CubeIterator(new Point3i(0, 0, 0), new Point3i(15, 15, 15)); i.hasNext();) { Point3i xyz = i.next(); if ((c.getBlocks()[xyz.x][xyz.y][xyz.z] == null) || (c.getBlocks()[xyz.x][xyz.y][xyz.z].getBlockID() <= 0)) { continue; } if (first) { lower.add(pos, xyz); upper.add(pos, xyz); first = false; } else { lower.x = Math.min(lower.x, pos.x + xyz.x); lower.y = Math.min(lower.y, pos.y + xyz.y); lower.z = Math.min(lower.z, pos.z + xyz.z); upper.x = Math.max(upper.x, pos.x + xyz.x); upper.y = Math.max(upper.y, pos.y + xyz.y); upper.z = Math.max(upper.z, pos.z + xyz.z); } } } } public static void getBounds(Map<Point3i, Data> data, Point3i lower, Point3i upper) { boolean first = true; for (Point3i o : data.keySet()) { Point3i l = new Point3i(); Point3i u = new Point3i(); Data datum = data.get(o); getBounds(datum, l, u); if (first) { lower.set(l); upper.set(u); first = false; } else { lower.x = Math.min(lower.x, l.x); lower.y = Math.min(lower.y, l.y); lower.z = Math.min(lower.z, l.z); upper.x = Math.max(upper.x, u.x); upper.y = Math.max(upper.y, u.y); upper.z = Math.max(upper.z, u.z); } } } public static void dumpChunks(Map<Point3i, Data> data) { for (Point3i p : data.keySet()) { Data datum = data.get(p); Point3i lower = new Point3i(); Point3i upper = new Point3i(); getBounds(datum, lower, upper); System.out.println("Datum: " + p + ", " + lower + " -- " + upper); for (Chunk c : datum.getChunks()) { System.out.println(" Chunk: " + c.getPosition() + ", type=" + c.getType()); } } } public static SparseMatrix<Block> getBlocks(Map<Point3i, Data> data) { SparseMatrix<Block> blocks = new SparseMatrix<>(); for (Point3i dataOrigin : data.keySet()) { Data datum = data.get(dataOrigin); for (Chunk c : datum.getChunks()) { Point3i p = c.getPosition(); //p.x += dataOrigin.x*256; //p.y += dataOrigin.y*256; //p.z += dataOrigin.z*256; for (CubeIterator i = new CubeIterator(new Point3i(0, 0, 0), new Point3i(15, 15, 15)); i.hasNext();) { Point3i xyz = i.next(); Block b = c.getBlocks()[xyz.x][xyz.y][xyz.z]; if ((b != null) && (b.getBlockID() > 0)) { blocks.set(p.x + xyz.x, p.y + xyz.y, p.z + xyz.z, b); } } } } return blocks; } public static Map<Point3i, Data> getData(SparseMatrix<Block> blocks) { long now = System.currentTimeMillis(); Map<Point3i, Map<Point3i, Chunk>> assemblies = new HashMap<>(); for (Iterator<Point3i> i = blocks.iteratorNonNull(); i.hasNext();) { Point3i universePoint = i.next(); Point3i superChunkIndex = getSuperChunkIndexFromPoint(universePoint); Point3i superChunkOrigin = getSuperChunkOriginFromIndex(superChunkIndex); Point3i superChunkLower = getSuperChunkLowerFromOrigin(superChunkOrigin); Map<Point3i, Chunk> assembly = assemblies.get(superChunkIndex); if (assembly == null) { assembly = new HashMap<>(); assemblies.put(superChunkIndex, assembly); } Point3i chunkIndex = new Point3i(universePoint); chunkIndex.sub(superChunkLower); chunkIndex.scale(1, 16); Point3i chunkPosition = getChunkPositionFromSuperchunkLowerAndChunkIndex(superChunkLower, chunkIndex); Chunk chunk = assembly.get(chunkIndex); if (chunk == null) { chunk = new Chunk(); chunk.setPosition(chunkPosition); chunk.setBlocks(new Block[16][16][16]); chunk.setTimestamp(now); chunk.setType(1); assembly.put(chunkIndex, chunk); } Point3i chunkOffset = new Point3i(universePoint.x - chunkPosition.x, universePoint.y - chunkPosition.y, universePoint.z - chunkPosition.z); try { chunk.getBlocks()[chunkOffset.x][chunkOffset.y][chunkOffset.z] = blocks.get(universePoint); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Universe Point: " + universePoint); System.out.println("Super Chunk Index: " + superChunkIndex); System.out.println("Super Chunk Origin: " + superChunkOrigin); System.out.println("Super Chunk Lower: " + superChunkLower); System.out.println("Chunk Index: " + chunkIndex); System.out.println("Chunk Position: " + chunkPosition); System.out.println("Chunk Offset: " + chunkOffset); e.printStackTrace(); } } Map<Point3i, Data> data = new HashMap<Point3i, Data>(); for (Point3i superChunkIndex : assemblies.keySet()) { Map<Point3i, Chunk> assembly = assemblies.get(superChunkIndex); Data datum = new Data(); datum.setChunks(assembly.values().toArray(new Chunk[0])); data.put(superChunkIndex, datum); } return data; /* long now = System.currentTimeMillis(); Map<Point3i, Data> data = new HashMap<Point3i, Data>(); Point3i lowerUniverse = new Point3i(); Point3i upperUniverse = new Point3i(); blocks.getBounds(lowerUniverse, upperUniverse); Point3i lowerData = getSuperChunkIndexFromPoint(lowerUniverse); Point3i upperData = getSuperChunkIndexFromPoint(upperUniverse); System.out.println("Universe: "+lowerUniverse+" -- "+upperUniverse); System.out.println("Superchunks: "+lowerData+" -- "+upperData); for (Iterator<Point3i> i = new CubeIterator(lowerData, upperData); i.hasNext(); ) { Point3i superChunkIndex = i.next(); Data datum = new Data(); Point3i superChunkOrigin = getSuperChunkOriginFromIndex(superChunkIndex); Point3i lowerSuperChunk = getSuperChunkLowerFromOrigin(superChunkOrigin); Point3i upperSuperChunk = getSuperChunkUpperFromOrigin(superChunkOrigin); System.out.println(" Index="+superChunkIndex+", origin="+superChunkOrigin+", lower="+lowerSuperChunk+", upper="+upperSuperChunk); List<Chunk> chunks = new ArrayList<Chunk>(); System.out.println("Splitting "+superChunkIndex+" -> "+lowerSuperChunk+" / "+upperSuperChunk); for (Iterator<Point3i> j = new CubeIterator(lowerSuperChunk, upperSuperChunk, new Point3i(16, 16, 16)); j.hasNext(); ) { Point3i chunkOrigin = j.next(); Point3i chunkPos = new Point3i(chunkOrigin); //chunkPos.sub(origin); Chunk chunk = new Chunk(); chunk.setPosition(chunkPos); chunk.setBlocks(new Block[16][16][16]); chunk.setTimestamp(now); chunk.setType(1); boolean doneAny = false; for (Iterator<Point3i> k = new CubeIterator(new Point3i(), new Point3i(15, 15, 15)); k.hasNext(); ) { Point3i chunkOffset = k.next(); Block b = blocks.get(chunkOrigin.x + chunkOffset.x, chunkOrigin.y + chunkOffset.y, chunkOrigin.z + chunkOffset.z); if (b == null) continue; chunk.getBlocks()[chunkOffset.x][chunkOffset.y][chunkOffset.z] = b; doneAny = true; } if (doneAny) chunks.add(chunk); } if (chunks.size() == 0) continue; datum.setChunks(chunks.toArray(new Chunk[0])); data.put(superChunkIndex, datum); } return data; */ } public static Point3i findCore(SparseMatrix<Block> grid) { Point3i p = new Point3i(8, 8, 8); Block b = grid.get(p); if ((b != null) && (b.getBlockID() == BlockTypes.CORE_ID)) { return p; } return findFirstBlock(grid, BlockTypes.CORE_ID); } public static Point3i findFirstBlock(SparseMatrix<Block> grid, short id) { List<Point3i> finds = findBlocks(grid, id, true); if (finds.isEmpty()) { return null; } else { return finds.get(0); } } public static List<Point3i> findBlocks(SparseMatrix<Block> grid, short id) { return findBlocks(grid, id, false); } public static List<Point3i> findBlocks(SparseMatrix<Block> grid, short id, boolean stopAfterFirst) { List<Point3i> finds = new ArrayList<>(); for (Iterator<Point3i> i = grid.iteratorNonNull(); i.hasNext();) { Point3i pp = i.next(); Block b = grid.get(pp); if (b.getBlockID() == id) { finds.add(pp); if (stopAfterFirst) { break; } } } return finds; } public static Point3i getSuperChunkOriginFromIndex(Point3i superChunkIndex) { Point3i superChunkOrigin = new Point3i(); if (superChunkIndex.x >= 0) { superChunkOrigin.x = superChunkIndex.x * 256; } else { superChunkOrigin.x = superChunkIndex.x * 256 + 16; } if (superChunkIndex.y >= 0) { superChunkOrigin.y = superChunkIndex.y * 256; } else { superChunkOrigin.y = superChunkIndex.y * 256 + 16; } if (superChunkIndex.z >= 0) { superChunkOrigin.z = superChunkIndex.z * 256; } else { superChunkOrigin.z = superChunkIndex.z * 256 + 16; } return superChunkOrigin; } public static Point3i getSuperChunkLowerFromOrigin(Point3i superChunkOrigin) { Point3i lowerSuperChunk = new Point3i(superChunkOrigin.x - 128, superChunkOrigin.y - 128, superChunkOrigin.z - 128); return lowerSuperChunk; } public static Point3i getSuperChunkUpperFromOrigin(Point3i superChunkOrigin) { Point3i upperSuperChunk = new Point3i(superChunkOrigin.x + 127, superChunkOrigin.y + 127, superChunkOrigin.z + 127); if (superChunkOrigin.x == -240) { upperSuperChunk.x = -129; } if (superChunkOrigin.y == -240) { upperSuperChunk.y = -129; } if (superChunkOrigin.z == -240) { upperSuperChunk.z = -129; } return upperSuperChunk; } public static Point3i getSuperChunkIndexFromPoint(Point3i universePoint) { Point3i superChunkIndex = new Point3i( getIndexFromAxis(universePoint.x), getIndexFromAxis(universePoint.y), getIndexFromAxis(universePoint.z) ); return superChunkIndex; } private static int getIndexFromAxis(int axis) { if (axis >= -128) { return (axis + 128) / 256; } if (axis < -368) { return -(143 - axis) / 256; } return -1; } public static Point3i getChunkPositionFromSuperchunkOriginAndChunkIndex( Point3i superChunkOrigin, Point3i chunkIndex) { Point3i chunkPosition = new Point3i(); if (superChunkOrigin.x >= 0) { chunkPosition.x = superChunkOrigin.x + (chunkIndex.x - 8) * 16; } else { chunkPosition.x = superChunkOrigin.x + (7 - chunkIndex.x) * 16; } if (superChunkOrigin.y >= 0) { chunkPosition.y = superChunkOrigin.y + (chunkIndex.y - 8) * 16; } else { chunkPosition.y = superChunkOrigin.y + (7 - chunkIndex.y) * 16; } if (superChunkOrigin.z >= 0) { chunkPosition.z = superChunkOrigin.z + (chunkIndex.z - 8) * 16; } else { chunkPosition.z = superChunkOrigin.z + (7 - chunkIndex.z) * 16; } return chunkPosition; } private static Point3i getChunkPositionFromSuperchunkLowerAndChunkIndex( Point3i superChunkLower, Point3i chunkIndex) { Point3i chunkPosition = new Point3i(chunkIndex); chunkPosition.scale(16); chunkPosition.add(superChunkLower); return chunkPosition; } public static Point3i getChunkIndexFromSuperchunkOriginAndChunkPosition( Point3i superChunkOrigin, Point3i chunkPosition) { Point3i chunkIndex = new Point3i(); if (superChunkOrigin.x >= 0) { chunkIndex.x = (chunkPosition.x - superChunkOrigin.x) / 16 + 8; } else { chunkIndex.x = (superChunkOrigin.x - chunkPosition.x) / 16 + 7; } if (superChunkOrigin.y >= 0) { chunkIndex.y = (chunkPosition.y - superChunkOrigin.y) / 16 + 8; } else { chunkIndex.y = (superChunkOrigin.y - chunkPosition.y) / 16 + 7; } if (superChunkOrigin.z >= 0) { chunkIndex.z = (chunkPosition.z - superChunkOrigin.z) / 16 + 8; } else { chunkIndex.z = (superChunkOrigin.z - chunkPosition.z) / 16 + 7; } return chunkIndex; } public static void ensureCore(SparseMatrix<Block> grid) { Point3i core = findCore(grid); if ((core != null) && (core.x == 8) && (core.y == 8) && (core.z == 8)) { return; } if (core != null) { grid.set(core, null); } List<Point3i> cores = findBlocks(grid, BlockTypes.CORE_ID); for (Point3i p : cores) { grid.set(p, null); } grid.set(8, 8, 8, new Block(BlockTypes.CORE_ID)); } }