/* * Copyright 2016 Nathan Howard * * This file is part of OpenGrave * * OpenGrave 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. * * OpenGrave 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 OpenGrave. If not, see <http://www.gnu.org/licenses/>. */ package com.opengrave.og.engine; import java.util.ArrayList; import java.util.HashMap; import java.util.UUID; import com.opengrave.common.world.*; import com.opengrave.og.Util; import com.opengrave.og.light.Shadow; import com.opengrave.og.terrain.TerrainArea; import com.opengrave.og.terrain.TerrainWorld; import com.opengrave.og.util.Matrix4f; public class ObjectStorageNode extends Node { HashMap<CommonAreaLoc, ArrayList<BaseObject>> objects = new HashMap<CommonAreaLoc, ArrayList<BaseObject>>(); HashMap<CommonAreaLoc, EmptyNode> areas = new HashMap<CommonAreaLoc, EmptyNode>(); ArrayList<CommonAreaLoc> lastLoaded = new ArrayList<CommonAreaLoc>(); Matrix4f matrix = new Matrix4f(); @Override public Matrix4f getMatrix() { return Util.createMatrixFor(new Location(), null, null, context); } @Override public void doUpdate(float delta) { } @Override public void doRender(Matrix4f parent) { } @Override public void doRenderShadows(Matrix4f parent, Shadow shadow) { } @Override public void doRenderForPicking(Matrix4f parent) { } @Override public void doRenderSemiTransparent(Matrix4f parent) { } public BaseObject createObject(CommonObject cobj) { removeObject(cobj.getUUID()); BaseObject obj = BaseObject.createObject(cobj); MaterialList mList = cobj.getMaterialList(); obj.setMaterialList(mList); obj.setLocation(cobj.getLocation()); addObject(obj); return obj; } /** * Used in TerrainEditor only, Bypasses the need for a Server, Connection, and Servers control over what areas you can see * * @param cw * @param tw */ public void fillFrom(CommonWorld cw, TerrainWorld tw) { // Will end up holding a list of any newly unloaded areas. ArrayList<CommonAreaLoc> areasUnloaded = new ArrayList<CommonAreaLoc>(); areasUnloaded.addAll(lastLoaded); // Will end up holding a list of any newly loaded areas. ArrayList<CommonAreaLoc> areasLoaded = new ArrayList<CommonAreaLoc>(); // Will end up holding next frames "lastLoaded" ArrayList<CommonAreaLoc> nextLoaded = new ArrayList<CommonAreaLoc>(); for (Node node : tw.children) { if (node instanceof TerrainArea) { TerrainArea tnode = (TerrainArea) node; CommonAreaLoc areaLoc = tnode.getAreaLoc(); if (areasUnloaded.contains(areaLoc)) { areasUnloaded.remove(areaLoc); } if (!lastLoaded.contains(areaLoc)) { areasLoaded.add(areaLoc); } nextLoaded.add(areaLoc); } } for (CommonAreaLoc cal : areasLoaded) { CommonArea ca = cw.getArea(cal); if (ca == null) { continue; } for (CommonObject co : ca.getAllObjects()) { System.out.println("Adding Object from CommonWorld " + co); createObject(co); } } for (CommonAreaLoc cal : areasUnloaded) { CommonArea ca = cw.getArea(cal); if (ca == null) { continue; } for (CommonObject co : ca.getAllObjects()) { // TODO - remove by CommonObject reference. Not as easy as I might have hoped. removeObject(co.getUUID()); } } lastLoaded = nextLoaded; } public void setLoadedAreas(ArrayList<CommonAreaLoc> loc) { ArrayList<CommonAreaLoc> areasUnloaded = new ArrayList<CommonAreaLoc>(); areasUnloaded.addAll(lastLoaded); for (CommonAreaLoc location : loc) { if (areasUnloaded.contains(location)) { areasUnloaded.remove(location); } } for (CommonAreaLoc location : areasUnloaded) { removeArea(location); } } public void removeArea(CommonAreaLoc location) { for (BaseObject obj : getObjects(location)) { removeObjectFromArea(location, obj); } } public void removeObject(UUID id) { synchronized (objects) { for (CommonAreaLoc loc : objects.keySet()) { ArrayList<BaseObject> list = objects.get(loc); ArrayList<BaseObject> copy = new ArrayList<BaseObject>(); synchronized (list) { copy.addAll(list); } for (BaseObject obj : copy) { if (obj.getUUID().compareTo(id) == 0) { removeObjectFromArea(loc, obj); } } } } } private void removeObjectOnly(BaseObject obj) { synchronized (objects) { for (CommonAreaLoc loc : objects.keySet()) { Node n = getAreaNode(loc); n.removeChild(obj); } } } /** * Takes a world location and instantly moves object. Corrects the area it's attatched to in the process * * @param l */ public void setObjectLocation(Location l, UUID id) { // removeObject(id); CommonAreaLoc loc = CommonWorld.getAreaLocFor(l); Node n = getAreaNode(loc); CommonLocation cloc = CommonWorld.negateAreaFromLocation(loc, l); BaseObject obj = getObject(id); removeObjectOnly(obj); obj.setLocation(cloc); n.addChild(obj); } public void addObject(BaseObject obj) { synchronized (objects) { CommonAreaLoc loc = CommonWorld.getAreaLocFor(obj.getLocation()); Node n = getAreaNode(loc); CommonLocation cloc = CommonWorld.negateAreaFromLocation(loc, obj.getLocation()); obj.setLocation(cloc); if (!objects.containsKey(loc)) { objects.put(loc, new ArrayList<BaseObject>()); } synchronized (objects.get(loc)) { objects.get(loc).add(obj); } n.addChild(obj); } } public void removeObjectFromArea(CommonAreaLoc location, BaseObject obj) { synchronized (objects) { synchronized (objects.get(location)) { this.objects.get(location).remove(obj); } Node n = getAreaNode(location); n.removeChild(obj); } } public BaseObject getObject(UUID id) { synchronized (objects) { for (CommonAreaLoc loc : objects.keySet()) { System.out.println("Checking for objects in " + loc.getX() + " " + loc.getY()); synchronized (objects.get(loc)) { for (BaseObject obj : objects.get(loc)) { if (obj.getUUID().compareTo(id) == 0) { return obj; } } } } } return null; } public ArrayList<BaseObject> getObjects(CommonAreaLoc location) { ArrayList<BaseObject> objectList = new ArrayList<BaseObject>(); synchronized (objects) { if (!this.objects.containsKey(location)) { return objectList; } if (this.objects.get(location) == null) { return objectList; } synchronized (objects.get(location)) { for (BaseObject obj : this.objects.get(location)) { objectList.add(obj); } } } return objectList; } private Node getAreaNode(CommonAreaLoc loc) { if (areas.containsKey(loc)) { return areas.get(loc); } EmptyNode n = new EmptyNode(loc); areas.put(loc, n); addChild(n); return n; } }