@Override
  public void repairStructure() throws CivException {
    double cost = getRepairCost();

    if (!this.isValidWall()) {
      throw new CivException(
          "This wall is no longer valid and cannot be repaired. Walls can no longer overlap with protected structure blocks, demolish this wall instead.");
    }

    if (!getTown().getTreasury().hasEnough(cost)) {
      throw new CivException(
          "Your town cannot not afford the " + cost + " coins to build a " + getDisplayName());
    }

    setHitpoints(this.getMaxHitPoints());
    bindStructureBlocks();

    for (WallBlock wb : this.wallBlocks.values()) {
      BlockCoord bcoord = wb.getCoord();
      ItemManager.setTypeId(bcoord.getBlock(), wb.getTypeId());
      ItemManager.setData(bcoord.getBlock(), wb.getData());
    }

    save();
    getTown().getTreasury().withdraw(cost);
    CivMessage.sendTown(
        getTown(),
        CivColor.Yellow + "The town has repaired a " + getDisplayName() + " at " + getCorner());
  }
  @Override
  public void processUndo() throws CivException {

    double refund = 0.0;
    for (WallBlock wb : wallBlocks.values()) {

      Material material = ItemManager.getMaterial(wb.getOldId());
      if (CivSettings.restrictedUndoBlocks.contains(material)) {
        continue;
      }

      ItemManager.setTypeId(wb.getCoord().getBlock(), wb.getOldId());
      ItemManager.setData(wb.getCoord().getBlock(), wb.getOldData());
      refund += COST_PER_SEGMENT;
      try {
        wb.delete();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }

    refund /= HEIGHT;
    refund = Math.round(refund);
    this.getTown().getTreasury().deposit(refund);
    CivMessage.sendTown(
        this.getTown(), CivColor.Yellow + "Refunded " + refund + " coins from wall construction.");
    try {
      this.delete();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
  @Override
  public void onMarkerPlacement(Player player, Location next, ArrayList<Location> locs)
      throws CivException {
    BlockCoord first = new BlockCoord(next);
    BlockCoord second = null;

    CultureChunk cc = CivGlobal.getCultureChunk(next);
    if (cc == null || cc.getTown().getCiv() != this.getTown().getCiv()) {
      throw new CivException("Cannot build here, you need to build inside your culture.");
    }

    if (locs.size() <= 1) {
      CivMessage.send(
          player,
          CivColor.LightGray + "First location placed, place another to start building a wall.");
      return;
    }

    // Validate our locations
    if (locs.get(0).distance(locs.get(1)) > Wall.MAX_SEGMENT) {
      throw new CivException(
          "Can only build a wall in "
              + Wall.MAX_SEGMENT
              + " block segments, pick a closer location");
    }

    second = new BlockCoord(locs.get(0));
    locs.clear();
    MarkerPlacementManager.removeFromPlacementMode(player, false);

    Location secondLoc = second.getLocation();
    // Setting to a new block coord so we can increment in buildWallSegment without changing the
    // corner.
    this.setCorner(new BlockCoord(secondLoc));
    this.setComplete(true);
    this.save();

    // We should now be able to draw a line between these two block points.
    HashMap<String, SimpleBlock> simpleBlocks = new HashMap<String, SimpleBlock>();
    int verticalSegments = this.buildWallSegment(player, first, second, 0, simpleBlocks, 0);

    // Pay the piper
    double cost = verticalSegments * COST_PER_SEGMENT;
    if (!this.getTown().getTreasury().hasEnough(cost)) {

      for (WallBlock wb : this.wallBlocks.values()) {
        try {
          wb.delete();
        } catch (SQLException e) {
          e.printStackTrace();
        }
      }
      this.wallBlocks.clear();

      throw new CivException(
          "Cannot build, not enough coins to pay "
              + cost
              + " coins for wall of length "
              + verticalSegments
              + " blocks.");
    }

    this.getTown().getTreasury().withdraw(cost);

    CivMessage.sendTown(
        this.getTown(),
        CivColor.Yellow + "Paid " + cost + " coins for " + verticalSegments + " wall segments.");

    // build the blocks
    for (SimpleBlock sb : simpleBlocks.values()) {
      BlockCoord bcoord = new BlockCoord(sb);
      ItemManager.setTypeId(bcoord.getBlock(), sb.getType());
      ItemManager.setData(bcoord.getBlock(), sb.getData());
    }

    // Add wall to town and global tables
    this.getTown().addStructure(this);
    CivGlobal.addStructure(this);
    this.getTown().lastBuildableBuilt = this;
  }