package gui;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.maps.MapLayer;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.IsometricTiledMapRenderer;
import com.badlogic.gdx.math.Vector2;
import game.GamePlay;
import game.Hakd;
import game.gameplay.Character;
import game.gameplay.City;
import game.gameplay.Player;
import gui.windows.device.DeviceScene;
import networks.InternetProviderNetwork;
import networks.Network;
import networks.NetworkFactory;
import networks.devices.Device;
import networks.devices.DeviceFactory;
import other.Util;
import java.util.*;
public class Room {
public static int TILE_SIZE;
public static int ROOM_HEIGHT;
private final Character player;
private final Network network;
private final Map<String, Device> devices;
private final Map<Vector2, DeviceTile> deviceTileMap;
private final TiledMap map;
private final TiledMapTileLayer floorLayer;
private final TiledMapTileLayer wallLayer;
private final MapLayer deviceLayer; // if it matters, maybe rename this to wall/boundary layer
private final TiledMapTileLayer objectLayer; // Interactable tiles?
private final GamePlay gamePlay;
public Room(Character player, GamePlay gamePlay, RoomMap roomMap) {
this.player = player;
this.gamePlay = gamePlay;
((Player) player).setRoom(this);
deviceTileMap = new HashMap<Vector2, DeviceTile>();
map = new TmxMapLoader().load(Util.ASSETS + "maps/" + roomMap.toString() + ".tmx");
floorLayer = (TiledMapTileLayer) map.getLayers().get("floor");
wallLayer = (TiledMapTileLayer) map.getLayers().get("wall");
deviceLayer = map.getLayers().get("devices");
objectLayer = (TiledMapTileLayer) map.getLayers().get("objects");
ROOM_HEIGHT = floorLayer.getHeight();
TILE_SIZE = (int) floorLayer.getTileWidth();
buildRoom();
gamePlay.getGameScreen().setRenderer(new IsometricTiledMapRenderer(map, 1f / TILE_SIZE)); // don't let this round, that is why 1 is a floatmap
if (player.getNetwork() == null) {
City playerCity = player.getCity();
List<InternetProviderNetwork> isps = new ArrayList<InternetProviderNetwork>(5);
for (Network n : playerCity.getNetworks().values()) {
if (n instanceof InternetProviderNetwork) {
isps.add((InternetProviderNetwork) n);
}
}
network = NetworkFactory.createPlayerNetwork((Player) player, playerCity, gamePlay.getInternet());
InternetProviderNetwork isp = isps.get((int) (Math.random() * isps.size()));
gamePlay.getInternet().addNetworkToInternet(network, isp);
playerCity.addNetwork(network);
network.setDeviceLimit(1);
Device device = DeviceFactory.createDevice(0, Device.DeviceType.SERVER);
HakdSprite tile = new HakdSprite(Hakd.assets.get("nTextures.txt", TextureAtlas.class).findRegion("d0"));
tile.setSize(tile.getWidth() / TILE_SIZE, tile.getHeight() / TILE_SIZE);
tile.setObject(device);
device.setTile(tile);
network.addDevice(device);
} else {
network = player.getNetwork();
}
int deviceLimit = deviceLayer.getObjects().getCount();
network.setDeviceLimit(deviceLimit);
devices = network.getDevices();
}
private void buildRoom() {
for (MapObject o : deviceLayer.getObjects()) {
if (!(o instanceof RectangleMapObject)) {
continue;
}
RectangleMapObject r = (RectangleMapObject) o; // all objects on the device layer will be rectangles
int x = Integer.parseInt((String) r.getProperties().get("x"));
int y = Integer.parseInt((String) r.getProperties().get("y"));
DeviceTile tile = new DeviceTile(x, y);
deviceTileMap.put(tile.isoPos, tile);
}
}
/**
* Finds the device at the specified isometric coordinates.
*
* @return The device found.
* The string "other", if no device was found there.
* Null if the tile in the map does not have an object.
*/
public DeviceTile getDeviceAtTile(int x, int y) {
return deviceTileMap.get(new Vector2(x, y));
}
public void addDevice(Device device) {
if (deviceTileMap.containsKey(device.getIsoPos())) {
deviceTileMap.get(device.getIsoPos()).device = device;
} else { // if the device is not in the room, assign it to a random tile
for (DeviceTile tile : deviceTileMap.values()) { // due to the nature of a set, this should be considered random
if (tile.device == null) {
Vector2 v = tile.getIsoPos();
device.setIsoPos(v);
tile.setDevice(device);
break;
}
}
}
device.setDeviceScene(new DeviceScene(gamePlay.getGameScreen(), device));
}
public void removeDevice(Device device) {
deviceTileMap.get(device.getIsoPos()).device = null;
}
public enum RoomMap {
room1(), room2(), room3(), room4(), room5(), room6();
private RoomMap() {
}
}
public void dispose() {
map.dispose();
}
public static class DeviceTile {
final Vector2 isoPos;
Device device;
private static final Sprite TABLE;
private final HakdSprite table; // the default sprite if there is no device, or the empty device tile
static {
TABLE = new Sprite(Hakd.assets.get("nTextures.txt", TextureAtlas.class).findRegion("d-1"));
TABLE.setSize(TABLE.getWidth() / TILE_SIZE, TABLE.getHeight() / TILE_SIZE);
}
public DeviceTile(int x, int y) {
isoPos = new Vector2(x, y);
table = new HakdSprite(TABLE);
Vector2 pos = Util.isoToOrtho(isoPos.x, isoPos.y);
table.setPosition(pos.x, pos.y);
}
public Vector2 getIsoPos() {
return isoPos;
}
public HakdSprite getTile() {
if (device == null || device.getTile() == null) {
return table;
}
return device.getTile();
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
if (device.getTile() != null) {
device.getTile().setPosition(table.getX(), table.getY());
}
}
}
public Character getPlayer() {
return player;
}
public Network getNetwork() {
return network;
}
public TiledMap getMap() {
return map;
}
public TiledMapTileLayer getFloorLayer() {
return floorLayer;
}
public GamePlay getGamePlay() {
return gamePlay;
}
public TiledMapTileLayer getWallLayer() {
return wallLayer;
}
public MapLayer getDeviceLayer() {
return deviceLayer;
}
public TiledMapTileLayer getObjectLayer() {
return objectLayer;
}
public Map<String, Device> getDevices() {
return devices;
}
public Map<Vector2, DeviceTile> getDeviceTileMap() {
return Collections.unmodifiableMap(deviceTileMap);
}
}
/*
* Just some place to put my ideas: This may be getting away from the old school
* look that I first wanted, I will try to keep the menu the same though.
*
* I have decided to add more to the idea I have in my head. Instead of looking
* at a computer screen, you will see an isometric projection of a server room.
* You will be able to interact with stuff, like open a terminal, check system
* temps, etc. The server room will start out with a desktop in the middle, and
* could potentially scale up to data center sizes. This will allow for better
* visuals and a more in control feeling than just being an admin on a terminal.
* I have a feeling that this is a terrible mistake. // (months later trying to figure this out) probably due to the amount of work it will(has in hindsight) coasted
*
* That means I will need a placement system for servers, like slots in the
* room. I will also need graphics and 3d models on top of the 3d projection
* models for the internet map.
*
* (done)to-do have different virtual screens that return orthocameras or something, matrices maybe?
* (They have render methods.)
*
* To get a new room, you first buy the room. Next you remove the old room, then
* update the network limits. Finally you generate a new room.
*
* Use seeds to generate the internet, that way you can reload a save easier,
* maybe, but all mission networks would have to be pre-generated and nothing
* can ever despawn.
*
* Is this even relevant anymore?
* (talking to my past self again) Not really, but I will keep it as a reminder of what I saw in this game at that time.
*/