Package me.daddychurchill.CityWorld.Plugins

Source Code of me.daddychurchill.CityWorld.Plugins.HouseProvider$Room

package me.daddychurchill.CityWorld.Plugins;

import org.bukkit.DyeColor;
import org.bukkit.Material;

import me.daddychurchill.CityWorld.WorldGenerator;
import me.daddychurchill.CityWorld.Context.DataContext;
import me.daddychurchill.CityWorld.Plugins.LootProvider.LootLocation;
import me.daddychurchill.CityWorld.Support.BlackMagic;
import me.daddychurchill.CityWorld.Support.Direction;
import me.daddychurchill.CityWorld.Support.Odds;
import me.daddychurchill.CityWorld.Support.RealChunk;
import me.daddychurchill.CityWorld.Support.Direction.Door;
import me.daddychurchill.CityWorld.Support.Direction.Facing;
import me.daddychurchill.CityWorld.Support.Direction.Stair;

public class HouseProvider extends Provider {

//  private static RoomProvider contentsKitchen = new HouseKitchens();
//  private static RoomProvider contentsBedroom = new HouseBedrooms();
//  private static RoomProvider contentsDiningRoom = new HouseDiningRooms();
//  private static RoomProvider contentsLivingRoom = new HouseLivingRooms();
 
  public HouseProvider() {
    super();

  }
 
  public final static HouseProvider loadProvider(WorldGenerator generator) {
    // for now
    return new HouseProvider();
  }
 
  private final static double oddsOfFurnace = Odds.oddsSomewhatUnlikely;
  private final static double oddsOfCraftingTable = Odds.oddsSomewhatUnlikely;
 
  public void generateShed(WorldGenerator generator, RealChunk chunk, DataContext context, Odds odds, int x, int y, int z, int radius) {
    int x1 = x - radius;
    int x2 = x + radius + 1;
    int z1 = z - radius;
    int z2 = z + radius + 1;
    int y1 = y;
    int y2 = y + DataContext.FloorHeight - 1;
    int xR = x2 - x1 - 2;
    int zR = z2 - z1 - 2;
   
    byte roofData = (byte) odds.getRandomInt(6);
    Material wallMat = pickShedWall(roofData);
   
    chunk.setWalls(x1, x2, y1, y2, z1, z2, wallMat);
    BlackMagic.setBlocks(chunk, x1 + 1, x2 - 1, y2, z1 + 1, z2 - 1, Material.STEP, roofData);
   
    switch (odds.getRandomInt(4)) {
    case 0: // north
      chunk.setWoodenDoor(x1 + odds.getRandomInt(xR) + 1, y1, z1, Direction.Door.NORTHBYNORTHEAST);
      chunk.setBlock(x1 + odds.getRandomInt(xR) + 1, y1 + 1, z2 - 1, materialGlass);
      placeShedTable(generator, chunk, odds, x1 + odds.getRandomInt(xR) + 1, y1, z2 - 2, Direction.General.SOUTH);
      placeShedChest(generator, chunk, odds, x1 - 1, y1, z1 + odds.getRandomInt(zR) + 1, Direction.General.WEST);
      placeShedChest(generator, chunk, odds, x2, y1, z1 + odds.getRandomInt(zR) + 1, Direction.General.EAST);
      break;
    case 1: // south
      chunk.setWoodenDoor(x1 + odds.getRandomInt(xR) + 1, y1, z2 - 1, Direction.Door.SOUTHBYSOUTHWEST);
      chunk.setBlock(x1 + odds.getRandomInt(xR) + 1, y1 + 1, z1, materialGlass);
      placeShedTable(generator, chunk, odds, x1 + odds.getRandomInt(xR) + 1, y1, z1 + 1, Direction.General.NORTH);
      placeShedChest(generator, chunk, odds, x1 - 1, y1, z1 + odds.getRandomInt(zR) + 1, Direction.General.WEST);
      placeShedChest(generator, chunk, odds, x2, y1, z1 + odds.getRandomInt(zR) + 1, Direction.General.EAST);
      break;
    case 2: // west
      chunk.setWoodenDoor(x1, y1, z1 + odds.getRandomInt(zR) + 1, Direction.Door.WESTBYNORTHWEST);
      chunk.setBlock(x2 - 1, y1 + 1, z1 + odds.getRandomInt(zR) + 1, materialGlass);
      placeShedTable(generator, chunk, odds, x2 - 2, y1, z1 + odds.getRandomInt(zR) + 1, Direction.General.EAST);
      placeShedChest(generator, chunk, odds, x1 + odds.getRandomInt(xR) + 1, y1, z1 - 1, Direction.General.NORTH);
      placeShedChest(generator, chunk, odds, x1 + odds.getRandomInt(xR) + 1, y1, z2, Direction.General.SOUTH);
      break;
    default: // east
      chunk.setWoodenDoor(x1, y1, z1 + odds.getRandomInt(zR) + 1, Direction.Door.EASTBYSOUTHEAST);
      chunk.setBlock(x2 - 1, y1 + 1, z1 + odds.getRandomInt(zR) + 1, materialGlass);
      placeShedTable(generator, chunk, odds, x1 + 1, y1, z1 + odds.getRandomInt(zR) + 1, Direction.General.WEST);
      placeShedChest(generator, chunk, odds, x1 + odds.getRandomInt(xR) + 1, y1, z1 - 1, Direction.General.NORTH);
      placeShedChest(generator, chunk, odds, x1 + odds.getRandomInt(xR) + 1, y1, z2, Direction.General.SOUTH);
      break;
    }
  }
 
  private void placeShedTable(WorldGenerator generator, RealChunk chunk, Odds odds, int x, int y, int z, Direction.General direction) {
    if (odds.playOdds(oddsOfFurnace))
      chunk.setFurnace(x, y, z, direction);
    else if (odds.playOdds(oddsOfCraftingTable))
      chunk.setBlock(x, y, z, Material.WORKBENCH);
    else {
      chunk.setBlock(x, y, z, Material.FENCE);
      chunk.setBlock(x, y + 1, z, Material.WOOD_PLATE);
    }
  }
 
  private void placeShedChest(WorldGenerator generator, RealChunk chunk, Odds odds, int x, int y, int z, Direction.General direction) {
    switch (direction) {
    case NORTH:
      chunk.setChest(x + 1, y, z, direction, odds, generator.lootProvider, LootLocation.STORAGESHED);
      break;
    case SOUTH:
      chunk.setChest(x - 1, y, z, direction, odds, generator.lootProvider, LootLocation.STORAGESHED);
      break;
    case WEST:
      chunk.setChest(x, y, z + 1, direction, odds, generator.lootProvider, LootLocation.STORAGESHED);
      break;
    case EAST:
      chunk.setChest(x, y, z - 1, direction, odds, generator.lootProvider, LootLocation.STORAGESHED);
      break;
    }
  }

  private final static Material matWindow = Material.THIN_GLASS;
  private final static Material matPole = Material.FENCE;
  private final static Material matFire = Material.FIRE;
  private final static Material matFireBase = Material.NETHERRACK;
  private final static Material matFireRing = Material.COBBLESTONE_STAIRS;
  private final static Material matLog = Material.LOG;
 
  public void generateCampground(WorldGenerator generator, RealChunk chunk, DataContext context, Odds odds, int baseY) {
   
    // what are we made of?
    DyeColor matColor = odds.getRandomColor();
    boolean matCamo = odds.playOdds(Odds.oddsSomewhatUnlikely);
   
    // direction?
    if (odds.flipCoin()) {
     
      // north/south tent first
      for (int z = 3; z < 9; z++) {
        chunk.setWool(3, baseY, z, getTentColor(odds, matColor, matCamo));
        chunk.setWool(4, baseY + 1, z, getTentColor(odds, matColor, matCamo));
        chunk.setWool(5, baseY + 2, z, getTentColor(odds, matColor, matCamo));
        chunk.setWool(6, baseY + 3, z, getTentColor(odds, matColor, matCamo));
        chunk.setWool(7, baseY + 2, z, getTentColor(odds, matColor, matCamo));
        chunk.setWool(8, baseY + 1, z, getTentColor(odds, matColor, matCamo));
        chunk.setWool(9, baseY, z, getTentColor(odds, matColor, matCamo));
      }
     
      // back wall
      chunk.setWool(4, baseY, 3, getTentColor(odds, matColor, matCamo));
      chunk.setWool(5, baseY, 3, getTentColor(odds, matColor, matCamo));
      chunk.setWool(5, baseY + 1, 3, getTentColor(odds, matColor, matCamo));
      chunk.setWool(6, baseY, 3, getTentColor(odds, matColor, matCamo));
      chunk.setBlock(6, baseY + 1, 3, matWindow);
      chunk.setWool(6, baseY + 2, 3, getTentColor(odds, matColor, matCamo));
      chunk.setWool(7, baseY + 1, 3, getTentColor(odds, matColor, matCamo));
      chunk.setWool(7, baseY, 3, getTentColor(odds, matColor, matCamo));
      chunk.setWool(8, baseY, 3, getTentColor(odds, matColor, matCamo));
         
      // post
      chunk.setBlocks(6, baseY, baseY + 3, 8, matPole);
     
      // beds
      chunk.setBed(5, baseY, 4, Facing.SOUTH);
      chunk.setBed(7, baseY, 4, Facing.SOUTH);
    } else {
      // north/south tent first
      for (int x = 3; x < 9; x++) {
        chunk.setWool(x, baseY, 3, getTentColor(odds, matColor, matCamo));
        chunk.setWool(x, baseY + 1, 4, getTentColor(odds, matColor, matCamo));
        chunk.setWool(x, baseY + 2, 5, getTentColor(odds, matColor, matCamo));
        chunk.setWool(x, baseY + 3, 6, getTentColor(odds, matColor, matCamo));
        chunk.setWool(x, baseY + 2, 7, getTentColor(odds, matColor, matCamo));
        chunk.setWool(x, baseY + 1, 8, getTentColor(odds, matColor, matCamo));
        chunk.setWool(x, baseY, 9, getTentColor(odds, matColor, matCamo));
      }
     
      // back wall
      chunk.setWool(3, baseY, 4, getTentColor(odds, matColor, matCamo));
      chunk.setWool(3, baseY, 5, getTentColor(odds, matColor, matCamo));
      chunk.setWool(3, baseY + 1, 5, getTentColor(odds, matColor, matCamo));
      chunk.setWool(3, baseY, 6, getTentColor(odds, matColor, matCamo));
      chunk.setBlock(3, baseY + 1, 6, matWindow);
      chunk.setWool(3, baseY + 2, 6, getTentColor(odds, matColor, matCamo));
      chunk.setWool(3, baseY + 1, 7, getTentColor(odds, matColor, matCamo));
      chunk.setWool(3, baseY, 7, getTentColor(odds, matColor, matCamo));
      chunk.setWool(3, baseY, 8, getTentColor(odds, matColor, matCamo));
         
      // post
      chunk.setBlocks(8, baseY, baseY + 3, 6, matPole);
     
      // beds
      chunk.setBed(4, baseY, 5, Facing.EAST);
      chunk.setBed(4, baseY, 7, Facing.EAST);
    }
   
    // now the fire pit
    chunk.setStair(11, baseY - 1, 10, matFireRing, Stair.SOUTH);
    chunk.setStair(12, baseY - 1, 11, matFireRing, Stair.WEST);
    chunk.setStair(11, baseY - 1, 12, matFireRing, Stair.NORTH);
    chunk.setStair(10, baseY - 1, 11, matFireRing, Stair.EAST);
    chunk.setStair(10, baseY - 1, 10, matFireRing, Stair.SOUTH);
    chunk.setStair(12, baseY - 1, 10, matFireRing, Stair.WEST);
    chunk.setStair(12, baseY - 1, 12, matFireRing, Stair.NORTH);
    chunk.setStair(10, baseY - 1, 12, matFireRing, Stair.EAST);

    // and the fire itself
    chunk.setBlock(11, baseY - 1, 11, matFireBase);
    chunk.setBlock(11, baseY, 11, matFire);
   
    // and the logs
    int logType = odds.getRandomWoodType();
    BlackMagic.setBlock(chunk, 11, baseY, 8, matLog, logType + logWestEast);
    BlackMagic.setBlock(chunk, 12, baseY, 8, matLog, logType + logWestEast);
    BlackMagic.setBlock(chunk, 8, baseY, 11, matLog, logType + logNorthSouth);
    BlackMagic.setBlock(chunk, 8, baseY, 12, matLog, logType + logNorthSouth);
  }
 
  private int logWestEast = 0x4;
  private int logNorthSouth = 0x8;
 
  private DyeColor getTentColor(Odds odds, DyeColor baseColor, boolean camoMode) {
    if (camoMode) {
      if (baseColor == DyeColor.PINK) {
        switch (odds.getRandomInt(3)) {
        case 1:
          return DyeColor.PINK;
        case 2:
          return DyeColor.SILVER;
        default:
          return DyeColor.RED;
        }
      } else {
        switch (odds.getRandomInt(3)) {
        case 1:
          return DyeColor.BROWN;
        case 2:
          return DyeColor.GRAY;
        default:
          return DyeColor.GREEN;
        }
      }
    } else
      return baseColor;
  }
 
  private enum HouseRoofStyle {FLAT, NORTHSOUTH, WESTEAST, ANGLED};
 
  public int generateShack(WorldGenerator generator, RealChunk chunk, DataContext context, Odds odds, int baseY, int roomWidth) {
   
    // what are we made of?
    Material matWall = Material.WOOD;
    Material matFloor = Material.WOOD;
    Material matCeiling = Material.WOOD;
    Material matRoof = Material.WOOD;
    HouseRoofStyle styleRoof = HouseRoofStyle.FLAT;
    int floors = 1;
   
    //chunk.setWalls(2, 13, baseY, baseY + ContextData.FloorHeight, 2, 13, Material.WOOD);
    generateColonial(generator, chunk, context, odds, baseY, matFloor, matWall, matCeiling, matRoof, floors, roomWidth, roomWidth, styleRoof, false);
    return floors;
  }
 
  private Material matTrapDoor = Material.TRAP_DOOR;
 
  public int generateHouse(WorldGenerator generator, RealChunk chunk, DataContext context, Odds odds, int baseY, int maxFloors, int maxRoomWidth) {
   
    // what are we made of?
    Material matWall = pickWallMaterial(odds);
    Material matFloor = pickFloorMaterial(odds);
    Material matCeiling = pickCeilingMaterial(odds);
    Material matRoof = pickRoofMaterial(odds);
    HouseRoofStyle styleRoof = pickRoofStyle(odds);
    int floors = odds.getRandomInt(maxFloors) + 1;
   
    //TODO add bed
    //TODO add kitchen
    //TODO add living room
    //TODO add split level house style
   
    // draw the house
    generateColonial(generator, chunk, context, odds, baseY, matFloor, matWall, matCeiling, matRoof, floors, MinSize, maxRoomWidth, styleRoof, true);
    return floors;
  }

  public int generateHouse(WorldGenerator generator, RealChunk chunk, DataContext context, Odds odds, int baseY, int maxFloors) {
    return generateHouse(generator, chunk, context, odds, baseY, maxFloors, MaxSize);
  }

  private void generateColonial(WorldGenerator generator, RealChunk chunk, DataContext context,
      Odds odds, int baseY,
      Material matFloor, Material matWall, Material matCeiling, Material matRoof,
      int floors, int minRoomWidth, int maxRoomWidth, HouseRoofStyle styleRoof, boolean allowMissingRooms) {
   
    // what are the rooms like?
    Room[][][] rooms = new Room[floors][2][2];
    for (int f = 0; f < floors; f++) {
      boolean missingRoom = false;
      for (int x = 0; x < 2; x++) {
        for (int z = 0; z < 2; z++) {
         
          // missing rooms?
          boolean thisRoomMissing = false;
          if (allowMissingRooms && floors > 1) {
            thisRoomMissing = odds.getRandomInt(MissingRoomOdds) == 0;
          }
         
          // what does the room "look" like?
          int thisRoomWidthZ = getRoomWidth(odds, minRoomWidth, maxRoomWidth);
          int thisRoomWidthX = getRoomWidth(odds, minRoomWidth, maxRoomWidth);
          boolean thisRoomHasWalls = true;
          Room.Style thisRoomStyle = Room.Style.BED;
         
          // create the room
          rooms[f][x][z] = new Room(thisRoomMissing,
                        thisRoomWidthZ, thisRoomWidthX,
                        thisRoomHasWalls, thisRoomStyle);
         
          // single floor is a little different
          if (floors == 1) {
            if (rooms[f][x][z].missing) {
              if (!missingRoom)
                missingRoom = true;
              else
                rooms[f][x][z].missing = false;
            }
          } else {
           
            // first floor must be complete
            if (f == 0)
              rooms[f][x][z].missing = false;
           
            // each additional floors must include any missing rooms from below
            else if (rooms[f - 1][x][z].missing)
              rooms[f][x][z].missing = true;
           
            // only one new missing room per floor
            else if (rooms[f][x][z].missing) {
              if (!missingRoom)
                missingRoom = true;
              else
                rooms[f][x][z].missing = false;
            }
           
            // all rooms must be the same size (or smaller) than the one below it
            if (f > 0) {
              rooms[f][x][z].widthX = Math.min(rooms[f][x][z].widthX, rooms[f - 1][x][z].widthX);
              rooms[f][x][z].widthZ = Math.min(rooms[f][x][z].widthZ, rooms[f - 1][x][z].widthZ);
            }
          }
        }
      }
    }
   
    // find a non-missing room on the first floor
    int roomX = odds.getRandomInt(2);
    int roomZ = odds.getRandomInt(2);
    while (rooms[0][roomX][roomZ].missing) {
      roomX = odds.getRandomInt(2);
      roomZ = odds.getRandomInt(2);
    }
   
    // pick the entry room
    for (int f = 0; f < floors; f++) {
       
      // set the style and make sure there is room for stairs
      rooms[f][roomX][roomZ].missing = false;
      rooms[f][roomX][roomZ].style = Room.Style.ENTRY;
      rooms[f][roomX][roomZ].widthX = maxRoomWidth;
      rooms[f][roomX][roomZ].widthZ = maxRoomWidth;
     
      // and on the second floor
      if (f == 1) {
       
        // if one of the side rooms is missing, make it not missing and make the opposite one is
        if (rooms[f][roomX][flip(roomZ)].missing) {
          rooms[f][roomX][flip(roomZ)].missing = false;
          rooms[f][flip(roomX)][flip(roomZ)].missing = true;
        } else if (rooms[f][flip(roomX)][roomZ].missing) {
          rooms[f][flip(roomX)][roomZ].missing = false;
          rooms[f][flip(roomX)][flip(roomZ)].missing = true;
        }
      }
    }
   
    // now the kitchen
    roomZ = flip(roomZ);
    if (rooms[0][roomX][roomZ].missing) {
      roomX = flip(roomX);
      roomZ = flip(roomZ);
    }
    rooms[0][roomX][roomZ].style = Room.Style.KITCHEN;

    // is this a single story house?
    if (floors == 1) {

      // next find the dining room
      roomX = flip(roomX);
      if (!rooms[0][roomX][roomZ].missing) {
        rooms[0][roomX][roomZ].style = Room.Style.DINING;
      }
     
      // put the bed in the last spot
      roomZ = flip(roomZ);
      rooms[0][roomX][roomZ].missing = false;
      rooms[0][roomX][roomZ].style = Room.Style.BED;
   
    // got more floors!
    } else {
     
      // next find the dining room
      roomX = flip(roomX);
      if (!rooms[0][roomX][roomZ].missing) {
        rooms[0][roomX][roomZ].style = Room.Style.DINING;
       
        // put the living room in the last spot if available
        roomZ = flip(roomZ);
        if (!rooms[0][roomX][roomZ].missing) {
          rooms[0][roomX][roomZ].style = Room.Style.LIVING;
        }
     
      // only one room left, dining room please!
      } else {
        roomZ = flip(roomZ);
        if (!rooms[0][roomX][roomZ].missing) {
          rooms[0][roomX][roomZ].style = Room.Style.DINING;
        }
      }
    }
   
    // where is the center of the house?
    int roomOffsetX = chunk.width / 2 + odds.getRandomInt(2) - 1;
    int roomOffsetZ = chunk.width / 2 + odds.getRandomInt(2) - 1;
   
    // draw the individual rooms
    for (int f = 0; f < floors; f++) {
     
      // just in case we come across an entry way
      int entryX = -1;
      int entryZ = -1;
     
      // do the rooms
      for (int x = 0; x < 2; x++) {
        for (int z = 0; z < 2; z++) {
         
          // do entry ways later
          if (rooms[f][x][z].style == Room.Style.ENTRY) {
            entryX = x;
            entryZ = z;
          } else
            drawRoom(generator, chunk, context, odds, rooms, f, floors, x, z, roomOffsetX, roomOffsetZ, baseY, matFloor, matWall, matCeiling, matRoof);
        }
      }
     
      // found an entry
      if (entryX != -1) {
        drawRoom(generator, chunk, context, odds, rooms, f, floors, entryX, entryZ, roomOffsetX, roomOffsetZ, baseY, matFloor, matWall, matCeiling, matRoof);
      }
    }
   
    // figure out roofs
    int roofBottom = baseY + floors * DataContext.FloorHeight - 1;
    int roofHeight = DataContext.FloorHeight + 1;
    boolean makeAttic = true;
   
    switch (styleRoof) {
    case ANGLED:
    default:
     
      // place the roof!
      for (int y = 0; y < roofHeight; y++) {
        for (int x = 1; x < chunk.width - 1; x++) {
          for (int z = 1; z < chunk.width - 1; z++) {
            int yAt = y + roofBottom;
            if (y == 0) {
              if (chunk.isOfTypes(x, yAt, z, matRoof, matTrapDoor) &&
                chunk.isOfTypes(x - 1, yAt, z, matRoof, matTrapDoor) &&
                chunk.isOfTypes(x + 1, yAt, z, matRoof, matTrapDoor) &&
                chunk.isOfTypes(x, yAt, z - 1, matRoof, matTrapDoor) &&
                chunk.isOfTypes(x, yAt, z + 1, matRoof, matTrapDoor))
                chunk.setBlock(x, yAt + 1, z, matRoof);
            } else {
              if (chunk.isType(x, yAt, z, matRoof) &&
                chunk.isType(x - 1, yAt, z, matRoof) &&
                chunk.isType(x + 1, yAt, z, matRoof) &&
                chunk.isType(x, yAt, z - 1, matRoof) &&
                chunk.isType(x, yAt, z + 1, matRoof))
                chunk.setBlock(x, yAt + 1, z, matRoof);
            }
//            if (chunk.isOfTypes(x, yAt, z, matRoof, matTrapDoor) &&
//              !chunk.isEmpty(x - 1, yAt, z) && !chunk.isEmpty(x + 1, yAt, z) &&
//              !chunk.isEmpty(x, yAt, z - 1) && !chunk.isEmpty(x, yAt, z + 1))
//              chunk.setBlock(x, yAt + 1, z, matRoof);
          }
        }
      }
      break;
    case NORTHSOUTH:
     
      // place the roof!
      for (int y = 0; y < roofHeight; y++) {
        for (int x = 1; x < chunk.width - 1; x++) {
          for (int z = 1; z < chunk.width - 1; z++) {
            int yAt = y + roofBottom;
            if (y == 0) {
              if (chunk.isOfTypes(x, yAt, z, matRoof, matTrapDoor) &&
                chunk.isOfTypes(x - 1, yAt, z, matRoof, matTrapDoor) &&
                chunk.isOfTypes(x + 1, yAt, z, matRoof, matTrapDoor))
                chunk.setBlock(x, yAt + 1, z, matRoof);
            } else {
              if (chunk.isType(x, yAt, z, matRoof) &&
                chunk.isType(x - 1, yAt, z, matRoof) &&
                chunk.isType(x + 1, yAt, z, matRoof))
                chunk.setBlock(x, yAt + 1, z, matRoof);
            }
//            if (chunk.isOfTypes(x, yAt, z, matRoof, matTrapDoor) &&
//              !chunk.isEmpty(x - 1, yAt, z) && !chunk.isEmpty(x + 1, yAt, z))
//              chunk.setBlock(x, yAt + 1, z, matRoof);
          }
        }
      }
      break;
    case WESTEAST:

      // place the roof!
      for (int y = 0; y < roofHeight; y++) {
        for (int x = 1; x < chunk.width - 1; x++) {
          for (int z = 1; z < chunk.width - 1; z++) {
            int yAt = y + roofBottom;
            if (y == 0) {
              if (chunk.isOfTypes(x, yAt, z, matRoof, matTrapDoor) &&
                chunk.isOfTypes(x, yAt, z - 1, matRoof, matTrapDoor) &&
                chunk.isOfTypes(x, yAt, z + 1, matRoof, matTrapDoor))
                chunk.setBlock(x, yAt + 1, z, matRoof);
            } else {
              if (chunk.isType(x, yAt, z, matRoof) &&
                chunk.isType(x, yAt, z - 1, matRoof) &&
                chunk.isType(x, yAt, z + 1, matRoof))
                chunk.setBlock(x, yAt + 1, z, matRoof);
            }
//            if (chunk.isOfTypes(x, yAt, z, matRoof, matTrapDoor) &&
//              !chunk.isEmpty(x, yAt, z - 1) && !chunk.isEmpty(x, yAt, z + 1))
//              chunk.setBlock(x, yAt + 1, z, matRoof);
          }
        }
      }
      break;
    case FLAT:

      // place the roof!
      for (int y = 0; y < 1; y++) {
        for (int x = 1; x < chunk.width - 1; x++) {
          for (int z = 1; z < chunk.width - 1; z++) {
            int yAt = y + roofBottom;
            if (chunk.isOfTypes(x, yAt, z, matRoof, matTrapDoor) &&
              (chunk.isEmpty(x - 1, yAt, z) ||
               chunk.isEmpty(x + 1, yAt, z) ||
               chunk.isEmpty(x, yAt, z - 1) ||
               chunk.isEmpty(x, yAt, z + 1)))
              chunk.setBlock(x, yAt + 1, z, matRoof);
          }
        }
      }
      makeAttic = false;
      break;
    }
   
   
    if (makeAttic) {
     
      // fill the potential attic space with something silly
      for (int y = 1; y < roofHeight - 1; y++) {
        for (int x = 1; x < chunk.width - 1; x++) {
          for (int z = 1; z < chunk.width - 1; z++) {
            int yAt = y + roofBottom;
            if (/*!chunk.isEmpty(x, yAt + 1, z)) */
              chunk.isType(x, yAt, z, matRoof))
              chunk.setBlock(x, yAt, z, Material.BEDROCK); // mark potential attic space
          }
        }
      }
     
      // but don't over do it and go too far
      for (int y = 1; y < roofHeight - 1; y++) {
        for (int x = 1; x < chunk.width - 1; x++) {
          for (int z = 1; z < chunk.width - 1; z++) {
            int yAt = y + roofBottom;
            if (chunk.isType(x, yAt, z, Material.BEDROCK)) { // where we think the attic might be
              if (chunk.isEmpty(x - 1, yAt, z) || chunk.isEmpty(x + 1, yAt, z) ||
                chunk.isEmpty(x, yAt, z - 1) || chunk.isEmpty(x, yAt, z + 1))
                chunk.setBlock(x, yAt, z, matRoof);
            }
          }
        }
      }
     
      // finally remove the silliness from the attic
      for (int y = 1; y < roofHeight - 1; y++) {
        for (int x = 1; x < chunk.width - 1; x++) {
          for (int z = 1; z < chunk.width - 1; z++) {
            int yAt = y + roofBottom;
            if (chunk.isType(x, yAt, z, Material.BEDROCK))
              chunk.clearBlock(x, yAt, z);
          }
        }
      }
    }
  }
 
  private int flip(int i) {
    return i == 0 ? 1 : 0;
  }
 
  private void drawRoom(WorldGenerator generator, RealChunk chunk, DataContext context,
      Odds odds, Room[][][] rooms, int floor, int floors, int x, int z,
      int roomOffsetX, int roomOffsetZ, int baseY,
      Material matFloor, Material matWall, Material matCeiling, Material matRoof) {

    // which room?
    Room room = rooms[floor][x][z];
   
    // missing?
    if (room.missing) {
     
      // is there a floor below?
      if (floor > 0 && !rooms[floor - 1][x][z].missing)
        rooms[floor - 1][x][z].DrawRailing(chunk);
    } else {

      // draw bottom bits
      if (floor == 0) {
        room.DrawFloor(chunk, context, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY, matFloor);
      }
 
      // draw outside bits
      room.DrawWalls(chunk, context, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY, matWall);
 
      // top floor's top
      if (floor == floors - 1) {
        room.DrawRoof(chunk, context, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY, matRoof);
     
      } else {
        room.DrawCeiling(chunk, context, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY, matCeiling);
      }
     
      // now the inner bits
      room.DrawStyle(generator, chunk, context, odds, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY);
    }
  }
 
  private int getRoomWidth(Odds odds, int minRoomWidth, int maxRoomWidth) {
    return odds.getRandomInt(maxRoomWidth - minRoomWidth + 1) + minRoomWidth;
  }
 
  private Material pickWallMaterial(Odds odds) {
    switch (odds.getRandomInt(9)) {
    case 1:
      return Material.COBBLESTONE;
    case 2:
      return Material.MOSSY_COBBLESTONE;
    case 3:
      return Material.STONE;
    case 4:
      return Material.SMOOTH_BRICK;
    case 5:
      return Material.SANDSTONE;
    case 6:
      return Material.NETHER_BRICK;
    case 7:
      return Material.BRICK;
    case 8:
      return Material.CLAY;
    default:
      return Material.WOOD;
    }
  }

  private Material pickCeilingMaterial(Odds odds) {
    switch (odds.getRandomInt(5)) {
    case 1:
      return Material.COBBLESTONE;
    case 2:
      return Material.STONE;
    case 3:
      return Material.SMOOTH_BRICK;
    case 4:
      return Material.SANDSTONE;
    default:
      return Material.WOOD;
    }
  }

  private Material pickFloorMaterial(Odds odds) {
    switch (odds.getRandomInt(4)) {
    case 1:
      return Material.COBBLESTONE;
    case 2:
      return Material.STONE;
    case 3:
      return Material.WOOL;
    default:
      return Material.WOOD;
    }
  }

  private Material pickRoofMaterial(Odds odds) {
    switch (odds.getRandomInt(6)) {
    case 1:
      return Material.COBBLESTONE;
    case 2:
      return Material.MOSSY_COBBLESTONE;
    case 3:
      return Material.STONE;
    case 4:
      return Material.SMOOTH_BRICK;
    case 5:
      return Material.SANDSTONE;
    default:
      return Material.WOOD;
    }
  }
 
  private HouseRoofStyle pickRoofStyle(Odds odds) {
    switch (odds.getRandomInt(4)) {
    default:
    case 0:
      return HouseRoofStyle.ANGLED;
    case 1:
      return HouseRoofStyle.NORTHSOUTH;
    case 2:
      return HouseRoofStyle.WESTEAST;
    case 3:
      return HouseRoofStyle.FLAT;
    }
  }
 
  private Material pickShedWall(int i) {
    switch (i) {
    case 0:
      return Material.STONE;
    case 1:
      return Material.SANDSTONE;
    case 2:
      return Material.WOOD;
    case 3:
      return Material.COBBLESTONE;
    case 4:
      return Material.BRICK;
    default:
      return Material.SMOOTH_BRICK;
    }
  }
  private final static Material materialAir = Material.AIR;
  private final static Material materialGlass = Material.GLASS;
  private final static Material materialFence = Material.FENCE;
  private final static Material materialStair = Material.WOOD_STAIRS;
  private final static Material materialUnderStairs = Material.WOOD;
 
  private final static int MinSize = 4;
  private final static int MaxSize = 6;
  private final static int MissingRoomOdds = 5; // 1/n of the time a room is missing
 
  // the description of a single room
  private final static class Room {
    public enum Style {BED, KITCHEN, DINING, ENTRY, LIVING};
   
    public int widthX;
    public int widthZ;
    public boolean missing;
    public boolean walls;
    public Style style;
   
    public Room(boolean aMissing, int aWidthX, int aWidthZ, boolean aWalls, Style aStyle) {
      super();
     
      missing = aMissing;
      widthX = aWidthX;
      widthZ = aWidthZ;
      walls = aWalls;
      style = aStyle;
    }
   
    // where are we?
    boolean located;
    boolean roomEast;
    boolean roomSouth;
    int x1;
    int x2;
    int z1;
    int z2;
    int y1;
    int y2;
   
    protected void Locate(DataContext context, int floor, int floors,
        int x, int z, int roomOffsetX, int roomOffsetZ, int baseY) {
      if (!located) {
        located = true;
        roomEast = x != 0;
        roomSouth = z != 0;
        x1 = roomOffsetX - (roomEast ? 0 : widthX);
        x2 = roomOffsetX + (roomEast ? widthX : 0);
        z1 = roomOffsetZ - (roomSouth ? 0 : widthZ);
        z2 = roomOffsetZ + (roomSouth ? widthZ : 0);
        y1 = baseY + floor * DataContext.FloorHeight;
        y2 = y1 + DataContext.FloorHeight - 1;
      }
    }
   
    protected void DrawWalls(RealChunk chunk, DataContext context, int floor, int floors,
        int x, int z, int roomOffsetX, int roomOffsetZ, int baseY,
        Material matWall) {
     
      // find ourselves
      Locate(context, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY);
     
      // draw the walls
      if (roomEast) {
        chunk.setBlocks(x2, x2 + 1, y1,   y2,   z1,   z2 + 1, matWall); // east wall
        chunk.setBlocks(x2, x2 + 1, y1 + 1, y2 - 1, z1 + 1, z2    , materialGlass); // eastern window
       
        if (roomSouth) {
          chunk.setBlocks(x1,   x2 + 1, y1,   y2,   z2, z2 + 1, matWall); // south wall
          chunk.setBlocks(x1 + 1, x2    , y1 + 1, y2 - 1, z2, z2 + 1, materialGlass); // southern window

          chunk.setBlocks(x1, x2 + 1, y1, y2,  z1, z1 + 1, matWall); // north wall
          chunk.setBlocks(x1, x1 + 1, y1, y2, z1, z2 + 1, matWall); // west wall
         
        } else {
          chunk.setBlocks(x1,   x2 + 1, y1,   y2,   z1, z1 + 1, matWall); // north wall
          chunk.setBlocks(x1 + 1, x2    , y1 + 1, y2 - 1, z1,  z1 + 1, materialGlass); // northern window
         
          chunk.setBlocks(x1, x2 + 1, y1, y2, z2, z2 + 1, matWall); // south wall
          chunk.setBlocks(x1, x1 + 1, y1, y2, z1, z2 + 1, matWall); // west wall
         
        }
      } else {
        chunk.setBlocks(x1, x1 + 1, y1,   y2,   z1,   z2 + 1, matWall); // west wall
        chunk.setBlocks(x1, x1 + 1, y1 + 1, y2 - 1, z1 + 1, z2    , materialGlass); // western window
       
        if (roomSouth) {
          chunk.setBlocks(x1,   x2 + 1, y1,   y2,   z2, z2 + 1, matWall); // south wall
          chunk.setBlocks(x1 + 1, x2    , y1 + 1, y2 - 1, z2, z2 + 1, materialGlass); // southern window

          chunk.setBlocks(x1, x2 + 1, y1, y2, z1, z1 + 1, matWall); // north wall
          chunk.setBlocks(x2, x2 + 1, y1, y2, z1, z2 + 1, matWall); // east wall
         
        } else {
          chunk.setBlocks(x1,   x2 + 1, y1,   y2,   z1, z1 + 1, matWall); // north wall
          chunk.setBlocks(x1 + 1, x2    , y1 + 1, y2 - 1, z1, z1 + 1, materialGlass); // northern window
         
          chunk.setBlocks(x1, x2 + 1, y1, y2, z2, z2 + 1, matWall); // south wall
          chunk.setBlocks(x2, x2 + 1, y1, y2, z1, z2 + 1, matWall); // east wall
        }
      }
    }
   
    protected void DrawFloor(RealChunk chunk, DataContext context, int floor, int floors,
        int x, int z, int roomOffsetX, int roomOffsetZ, int baseY,
        Material matFloor) {
     
      // find ourselves
      Locate(context, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY);
     
      // put the rug down
      chunk.setBlocks(x1, x2 + 1, y1 - 1, y1, z1, z2 + 1, matFloor);
    }
   
    protected void DrawCeiling(RealChunk chunk, DataContext context, int floor, int floors,
        int x, int z, int roomOffsetX, int roomOffsetZ, int baseY,
        Material matCeiling) {
     
      // find ourselves
      Locate(context, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY);
     
      // put the rug down
      chunk.setBlocks(x1, x2 + 1, y2, y2 + 1, z1, z2 + 1, matCeiling);
    }
   
    protected void DrawRoof(RealChunk chunk, DataContext context, int floor, int floors,
        int x, int z, int roomOffsetX, int roomOffsetZ, int baseY,
        Material matRoof) {
     
      // find ourselves
      Locate(context, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY);
     
      // put roof on top
      //TODO need fancier roofs
      chunk.setBlocks(x1, x2 + 1, y2, y2 + 1, z1, z2 + 1, matRoof);
    }

    protected void DrawRailing(RealChunk chunk) {
     
      // only if we have found ourselves
      if (located) {
       
        // north and south ones
        for (int x = x1; x <= x2; x++) {
          chunk.setEmptyBlock(x, y2 + 1, z1, materialFence);
          chunk.setEmptyBlock(x, y2 + 1, z2, materialFence);
        }
       
        // west and east ones
        for (int z = z1; z <= z2; z++) {
          chunk.setEmptyBlock(x1, y2 + 1, z, materialFence);
          chunk.setEmptyBlock(x2, y2 + 1, z, materialFence);
        }
      }
    }

    protected void DrawStyle(WorldGenerator generator, RealChunk chunk, DataContext context,
        Odds odds, int floor, int floors,
        int x, int z, int roomOffsetX, int roomOffsetZ, int baseY) {
     
      // which door or halls do we do?
      boolean doorNorth = false;
      boolean doorSouth = false;
      boolean doorWest = false;
      boolean doorEast = false;
      boolean hallNorth = walls;
      boolean hallSouth = walls;
      boolean hallWest = walls;
      boolean hallEast = walls;
     
      // find ourselves
      Locate(context, floor, floors, x, z, roomOffsetX, roomOffsetZ, baseY);
     
      // our bits!
      switch (style) {
      case KITCHEN:
       
        // where is the door?
        if (odds.flipCoin()) {
          doorNorth = !roomSouth;
          doorSouth = roomSouth;
        } else {
          doorWest = !roomEast;
          doorEast = roomEast;
        }
       
//        chunk.setBlock((x2 - x1) / 2 + x1, y1, (z2 - z1) / 2 + z1, Material.CHEST);
        break;
      case DINING:
       
//        chunk.setBlock((x2 - x1) / 2 + x1, y1, (z2 - z1) / 2 + z1, Material.FENCE);
//        chunk.setBlock((x2 - x1) / 2 + x1, y1 + 1, (z2 - z1) / 2 + z1, Material.WOOD_PLATE);
        break;
      case ENTRY:
       
        // where is the door?
        if (floor == 0) {
          if (odds.flipCoin()) {
            doorNorth = !roomSouth;
            doorSouth = roomSouth;
          } else {
            doorWest = !roomEast;
            doorEast = roomEast;
          }
        }
       
        // below the top floor
        if (floor < floors - 1) {
          if (roomEast) {
            if (roomSouth) {
              chunk.setBlocks(x1 + 1, x2, y2, z1 + 1, z1 + 2, materialAir);

              chunk.setBlock(x1 + 1, y1 + 3, z1 + 1, materialUnderStairs);

              chunk.setStair(x1 + 2, y1 + 3, z1 + 1, materialStair, Stair.WEST);
              chunk.setStair(x1 + 2, y1 + 2, z1 + 1, materialStair, Stair.EASTFLIP);

              chunk.setStair(x1 + 3, y1 + 2, z1 + 1, materialStair, Stair.WEST);
              chunk.setStair(x1 + 3, y1 + 1, z1 + 1, materialStair, Stair.EASTFLIP);
             
              chunk.setStair(x1 + 4, y1 + 1, z1 + 1, materialStair, Stair.WEST);
              chunk.setStair(x1 + 4, y1    , z1 + 1, materialStair, Stair.EASTFLIP);

              chunk.setBlock(x1 + 5, y1    , z1 + 1, materialUnderStairs);
              chunk.setStair(x1 + 5, y1    , z1 + 2, materialStair, Stair.NORTH);
             
//              chunk.setBlocks(x1 + 3, y1, y2 + 50, z1 + 3, Material.FENCE);
//              chunk.setBlock(x1 + 3, y2 + 50, z1 + 3, Material.GOLD_BLOCK);
            } else {
              chunk.setBlocks(x1 + 1, x1 + 2, y2, z1 + 1, z2, materialAir);

              chunk.setBlock(x1 + 1, y1 + 3, z2 - 1, materialUnderStairs);

              chunk.setStair(x1 + 1, y1 + 3, z2 - 2, materialStair, Stair.SOUTH);
              chunk.setStair(x1 + 1, y1 + 2, z2 - 2, materialStair, Stair.NORTHFLIP);

              chunk.setStair(x1 + 1, y1 + 2, z2 - 3, materialStair, Stair.SOUTH);
              chunk.setStair(x1 + 1, y1 + 1, z2 - 3, materialStair, Stair.NORTHFLIP);
             
              chunk.setStair(x1 + 1, y1 + 1, z2 - 4, materialStair, Stair.SOUTH);
              chunk.setStair(x1 + 1, y1    , z2 - 4, materialStair, Stair.NORTHFLIP);

              chunk.setBlock(x1 + 1, y1    , z2 - 5, materialUnderStairs);
              chunk.setStair(x1 + 2, y1    , z2 - 5, materialStair, Stair.WEST);
             
//              chunk.setBlocks(x1 + 3, y1, y2 + 50, z1 + 3, Material.FENCE);
//              chunk.setBlock(x1 + 3, y2 + 50, z1 + 3, Material.LAPIS_BLOCK);
            }
          } else {
            if (roomSouth) {
              chunk.setBlocks(x2 - 1, x2, y2, z1 + 1, z2, materialAir);

              chunk.setBlock(x2 - 1, y1 + 3, z1 + 1, materialUnderStairs);

              chunk.setStair(x2 - 1, y1 + 3, z1 + 2, materialStair, Stair.NORTH);
              chunk.setStair(x2 - 1, y1 + 2, z1 + 2, materialStair, Stair.SOUTHFLIP);

              chunk.setStair(x2 - 1, y1 + 2, z1 + 3, materialStair, Stair.NORTH);
              chunk.setStair(x2 - 1, y1 + 1, z1 + 3, materialStair, Stair.SOUTHFLIP);
             
              chunk.setStair(x2 - 1, y1 + 1, z1 + 4, materialStair, Stair.NORTH);
              chunk.setStair(x2 - 1, y1    , z1 + 4, materialStair, Stair.SOUTHFLIP);

              chunk.setBlock(x2 - 1, y1    , z1 + 5, materialUnderStairs);
              chunk.setStair(x2 - 2, y1    , z1 + 5, materialStair, Stair.EAST);
             
//              chunk.setBlocks(x1 + 3, y1, y2 + 50, z1 + 3, Material.FENCE);
//              chunk.setBlock(x1 + 3, y2 + 50, z1 + 3, Material.DIAMOND_BLOCK);
            } else {
              chunk.setBlocks(x1 + 1, x2, y2, z2 - 1, z2, materialAir);

              chunk.setBlock(x2 - 1, y1 + 3, z2 - 1, materialUnderStairs);

              chunk.setStair(x2 - 2, y1 + 3, z2 - 1, materialStair, Stair.EAST);
              chunk.setStair(x2 - 2, y1 + 2, z2 - 1, materialStair, Stair.WESTFLIP);

              chunk.setStair(x2 - 3, y1 + 2, z2 - 1, materialStair, Stair.EAST);
              chunk.setStair(x2 - 3, y1 + 1, z2 - 1, materialStair, Stair.WESTFLIP);
             
              chunk.setStair(x2 - 4, y1 + 1, z2 - 1, materialStair, Stair.EAST);
              chunk.setStair(x2 - 4, y1    , z2 - 1, materialStair, Stair.WESTFLIP);

              chunk.setBlock(x2 - 5, y1    , z2 - 1, materialUnderStairs);
              chunk.setStair(x2 - 5, y1    , z2 - 2, materialStair, Stair.SOUTH);
             
//              chunk.setBlocks(x1 + 3, y1, y2 + 50, z1 + 3, Material.FENCE);
//              chunk.setBlock(x1 + 3, y2 + 50, z1 + 3, Material.GLOWSTONE);
            }
          }
        }
       
        // above the bottom floor
        if (floor > 0) {
          if (roomEast) {
            if (roomSouth) {
              hallNorth = false;
             
            } else {
              hallWest = false;

            }
          } else {
            if (roomSouth) {
              hallEast = false;
 
            } else {
              hallSouth = false;
           
            }
          }
        }
       
        // the top floor
        if (floor == floors - 1) {
          if (roomEast) {
            if (roomSouth) {
              chunk.setLadder(x1 + 1, y1, y1 + 3, z1 + 1, Direction.General.SOUTH);
              chunk.setTrapDoor(x1 + 1, y2, z1 + 1, Direction.TrapDoor.SOUTH);
             
            } else {
              chunk.setLadder(x1 + 1, y1, y1 + 3, z2 - 1, Direction.General.EAST);
              chunk.setTrapDoor(x1 + 1, y2, z2 - 1, Direction.TrapDoor.EAST);

            }
          } else {
            if (roomSouth) {
              chunk.setLadder(x2 - 1, y1, y1 + 3, z1 + 1, Direction.General.WEST);
              chunk.setTrapDoor(x2 - 1, y2, z1 + 1, Direction.TrapDoor.WEST);
 
            } else {
              chunk.setLadder(x2 - 1, y1, y1 + 3, z2 - 1, Direction.General.NORTH);
              chunk.setTrapDoor(x2 - 1, y2, z2 - 1, Direction.TrapDoor.NORTH);
           
            }
          }
        }
       
        break;
      case LIVING:
       
//        chunk.setBlock((x2 - x1) / 2 + x1, y1, (z2 - z1) / 2 + z1, Material.DIAMOND_BLOCK);
        break;
      case BED:
//        chunk.setBlock((x2 - x1) / 2 + x1, y1, (z2 - z1) / 2 + z1, Material.WOOL);
        break;
      }
     
      // draw the walls
      if (roomEast) {
        if (roomSouth) {
          if (doorSouth)
            chunk.setWoodenDoor(x1 + 3,  y1, z2, Door.SOUTHBYSOUTHEAST);
          if (doorEast)
            chunk.setWoodenDoor(x2, y1, z1 + 3, Door.EASTBYSOUTHEAST);

          if (hallNorth)
            chunk.setWoodenDoor(x1 + 2,  y1, z1,  Door.NORTHBYNORTHWEST);
          if (hallWest)
            chunk.setWoodenDoor(x1, y1, z1 + 2, Door.WESTBYNORTHWEST);
         
        } else {
          if (doorNorth)
            chunk.setWoodenDoor(x1 + 3, y1, z1, Door.NORTHBYNORTHEAST);
          if (doorEast)
            chunk.setWoodenDoor(x2, y1, z2 - 3, Door.EASTBYNORTHEAST);

          if (hallSouth)
            chunk.setWoodenDoor(x1 + 2, y1, z2, Door.SOUTHBYSOUTHWEST);
          if (hallWest)
            chunk.setWoodenDoor(x1, y1, z2 - 2, Door.WESTBYSOUTHWEST);
         
        }
      } else {
        if (roomSouth) {
          if (doorSouth)
            chunk.setWoodenDoor(x2 - 3, y1, z2, Door.SOUTHBYSOUTHWEST);
          if (doorWest)
            chunk.setWoodenDoor(x1, y1, z1 + 3, Door.WESTBYSOUTHWEST);

          if (hallNorth)
            chunk.setWoodenDoor(x2 - 2, y1, z1, Door.NORTHBYNORTHEAST);
          if (hallEast)
            chunk.setWoodenDoor(x2, y1, z1 + 2, Door.EASTBYNORTHEAST);
         
        } else {
          if (doorNorth)
            chunk.setWoodenDoor(x2 - 3, y1, z1, Door.NORTHBYNORTHWEST);
          if (doorWest)
            chunk.setWoodenDoor(x1, y1, z2 - 3, Door.WESTBYNORTHWEST);

          if (hallSouth)
            chunk.setWoodenDoor(x2 - 2, y1, z2, Door.SOUTHBYSOUTHEAST);
          if (hallEast)
            chunk.setWoodenDoor(x2, y1, z2 - 2, Door.EASTBYSOUTHEAST);
        }
      }
    }
  }
}
TOP

Related Classes of me.daddychurchill.CityWorld.Plugins.HouseProvider$Room

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.