/* ChunkClaim Plugin for Minecraft Bukkit Servers Copyright (C) 2012 Felix Schmidt This file is part of ChunkClaim. ChunkClaim 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. ChunkClaim 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 ChunkClaim. If not, see <http://www.gnu.org/licenses/>. */ package com.github.schmidtbochum.chunkclaim; import java.io.*; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Random; import java.util.Vector; import org.bukkit.Location; public abstract class DataStore { public int nextChunkId = 0; int minModifiedBlocks = 10; ArrayList<Chunk> chunks = new ArrayList<Chunk> (); ArrayList<Chunk> unusedChunks = new ArrayList<Chunk> (); HashMap<String,ChunkWorld> worlds = new HashMap<String,ChunkWorld> (); protected HashMap<String, PlayerData> playerNameToPlayerDataMap = new HashMap<String, PlayerData>(); protected final static String dataLayerFolderPath = "plugins" + File.separator + "ChunkClaim"; void initialize() throws Exception { ChunkClaim.addLogEntry(this.chunks.size() + " total claimed chunks loaded."); Random rand = new Random(); nextChunkId = (this.chunks.size()>0?rand.nextInt(this.chunks.size()):0); Vector<String> playerNames = new Vector<String>(); for(int i = 0; i < this.chunks.size(); i++) { Chunk chunk = this.chunks.get(i); if(!playerNames.contains(chunk.ownerName)) { playerNames.add(chunk.ownerName); } } ChunkClaim.addLogEntry(playerNames.size() + " players have claimed chunks in loaded worlds."); System.gc(); } abstract void loadWorldData(String worldName) throws Exception; public void cleanUp(int n) { if(this.chunks.size()<1) return; Date now = new Date(); double deletionTime = (1000 * 60 * 60 * 24)*ChunkClaim.plugin.config_autoDeleteDays; int r = 0; for(int i = 0; i < n; i++) { nextChunkId++; if(nextChunkId >= this.chunks.size()) nextChunkId = 0; Chunk chunk = chunks.get(nextChunkId); if(chunk.modifiedBlocks >=0) { long diff = now.getTime()-chunk.claimDate.getTime(); double chunkDeletionTime = deletionTime; if(diff> chunkDeletionTime) { PlayerData playerData = this.getPlayerData(chunk.ownerName); playerData.credits++; this.savePlayerData(chunk.ownerName, playerData); this.playerNameToPlayerDataMap.remove(chunk.ownerName); ChunkClaim.addLogEntry("Auto-deleted chunk by "+chunk.ownerName+" at " + (chunk.x*16) + " | " + (chunk.z*16)); this.deleteChunk(chunk); r++; }; } if(r > 50) break; } } synchronized void unloadWorldData(String worldName) { this.worlds.remove(worldName); for(int i = 0; i<this.chunks.size(); i++) { while(this.chunks.get(i).worldName.equals(worldName)) { this.chunks.remove(i); } } } synchronized void clearCachedPlayerData(String playerName) { this.playerNameToPlayerDataMap.remove(playerName); } synchronized public void changeChunkOwner(Chunk chunk, String newOwnerName) throws Exception { PlayerData ownerData = this.getPlayerData(chunk.ownerName); PlayerData newOwnerData = this.getPlayerData(newOwnerName); //modify chunk chunk.ownerName = newOwnerName; this.saveChunk(chunk); //modify previous owner data ownerData.credits--; this.savePlayerData(chunk.ownerName, ownerData); //modify new owner data newOwnerData.credits++; this.savePlayerData(newOwnerName, newOwnerData); } synchronized void addChunk(Chunk newChunk) { this.chunks.add(newChunk); if(this.worlds.containsKey(newChunk.worldName)) { this.worlds.get(newChunk.worldName).addChunk(newChunk); newChunk.inDataStore = true; this.saveChunk(newChunk); } } private void saveChunk(Chunk chunk) { this.writeChunkToStorage(chunk); } abstract void writeChunkToStorage(Chunk chunk); synchronized public PlayerData getPlayerData(String playerName) { PlayerData playerData = this.playerNameToPlayerDataMap.get(playerName); if(playerData == null) { playerData = this.getPlayerDataFromStorage(playerName); this.playerNameToPlayerDataMap.put(playerName, playerData); } return this.playerNameToPlayerDataMap.get(playerName); } abstract PlayerData getPlayerDataFromStorage(String playerName); synchronized public void deleteChunk(Chunk chunk) { for(int i = 0; i < this.chunks.size(); i++) { if(this.chunks.get(i).x == chunk.x && this.chunks.get(i).z == chunk.z && this.chunks.get(i).worldName.equals(chunk.worldName)) { this.chunks.remove(i); this.worlds.get(chunk.worldName).removeChunk(chunk); chunk.inDataStore = false; break; } } this.deleteChunkFromSecondaryStorage(chunk); ChunkClaim.plugin.regenerateChunk(chunk); } abstract void deleteChunkFromSecondaryStorage(Chunk chunk); synchronized public Chunk getChunkAt(Location location, Chunk cachedChunk) { if(cachedChunk != null && cachedChunk.inDataStore && cachedChunk.contains(location)) return cachedChunk; if(!worlds.containsKey(location.getWorld().getName())) return null; int x = location.getChunk().getX(); int z = location.getChunk().getZ(); return worlds.get(location.getWorld().getName()).getChunk(x,z); } synchronized public Chunk getChunkAtPos(int x, int z, String worldName) { if(!worlds.containsKey(worldName)) return null; return worlds.get(worldName).getChunk(x,z); } public abstract void savePlayerData(String playerName, PlayerData playerData); synchronized public ArrayList<Chunk> getAllChunksForPlayer(String playerName) { ArrayList <Chunk> playerChunks = new ArrayList <Chunk>(); for(int i = 0; i < chunks.size(); i++) { Chunk chunk = chunks.get(i); if(chunk.ownerName.equals(playerName)) { playerChunks.add(chunk); } } return playerChunks; } synchronized public int deleteChunksForPlayer(String playerName) { ArrayList <Chunk> playerChunks = getAllChunksForPlayer(playerName); PlayerData playerData = this.getPlayerData(playerName); for(int i = 0; i < playerChunks.size(); i++) { Chunk chunk = playerChunks.get(i); this.deleteChunk(chunk); playerData.credits++; } return playerChunks.size(); } abstract void close(); /** * @param location * @return */ public boolean ownsNear(Location location, String playerName) { int x = location.getChunk().getX(); int z = location.getChunk().getZ(); String worldName = location.getWorld().getName(); Chunk a = getChunkAtPos(x-1, z, worldName); Chunk c = getChunkAtPos(x+1, z, worldName); Chunk b = getChunkAtPos(x, z-1, worldName); Chunk d = getChunkAtPos(x, z+1, worldName); //ChunkClaim.addLogEntry((a==null) + ";" + (b==null) + ";" + (c==null) + ";" + (d==null)); if(a==null&&b==null&&c==null&&d==null) {return false;} else if(a!=null&&a.isTrusted(playerName)) {return true;} else if(b!=null&&b.isTrusted(playerName)) {return true;} else if(c!=null&&c.isTrusted(playerName)) {return true;} else if(d!=null&&d.isTrusted(playerName)) {return true;} else {return false;} } }