Unique IDs for claim subdivisions.
Also performance updates and switch to YAML file format for flat file data stores.
This commit is contained in:
parent
4b3802d189
commit
9c00a47a29
|
|
@ -173,14 +173,14 @@ commands:
|
||||||
permission: griefprevention.ignore
|
permission: griefprevention.ignore
|
||||||
separate:
|
separate:
|
||||||
description: Forces two players to ignore each other in chat.
|
description: Forces two players to ignore each other in chat.
|
||||||
usage: /Separate
|
usage: /Separate <player1> <player2>
|
||||||
permission: griefprevention.separate
|
permission: griefprevention.separate
|
||||||
unseparate:
|
unseparate:
|
||||||
description: Reverses /separate.
|
description: Reverses /separate.
|
||||||
usage: /UnSeparate
|
usage: /UnSeparate <player1> <player2>
|
||||||
permission: griefprevention.separate
|
permission: griefprevention.separate
|
||||||
claimbook:
|
claimbook:
|
||||||
description: Gives a player a replacement land claiming book.
|
description: Gives a player a manual about claiming land.
|
||||||
usage: /ClaimBook <player>
|
usage: /ClaimBook <player>
|
||||||
permission: griefprevention.claimbook
|
permission: griefprevention.claimbook
|
||||||
permissions:
|
permissions:
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ public class Claim
|
||||||
}
|
}
|
||||||
|
|
||||||
//main constructor. note that only creating a claim instance does nothing - a claim must be added to the data store to be effective
|
//main constructor. note that only creating a claim instance does nothing - a claim must be added to the data store to be effective
|
||||||
Claim(Location lesserBoundaryCorner, Location greaterBoundaryCorner, UUID ownerID, String [] builderIDs, String [] containerIds, String [] accessorIDs, String [] managerIDs, Long id)
|
Claim(Location lesserBoundaryCorner, Location greaterBoundaryCorner, UUID ownerID, List<String> builderIDs, List<String> containerIDs, List<String> accessorIDs, List<String> managerIDs, Long id)
|
||||||
{
|
{
|
||||||
//modification date
|
//modification date
|
||||||
this.modifiedDate = Calendar.getInstance().getTime();
|
this.modifiedDate = Calendar.getInstance().getTime();
|
||||||
|
|
@ -202,36 +202,32 @@ public class Claim
|
||||||
this.ownerID = ownerID;
|
this.ownerID = ownerID;
|
||||||
|
|
||||||
//other permissions
|
//other permissions
|
||||||
for(int i = 0; i < builderIDs.length; i++)
|
for(String builderID : builderIDs)
|
||||||
{
|
{
|
||||||
String builderID = builderIDs[i];
|
|
||||||
if(builderID != null && !builderID.isEmpty())
|
if(builderID != null && !builderID.isEmpty())
|
||||||
{
|
{
|
||||||
this.playerIDToClaimPermissionMap.put(builderID, ClaimPermission.Build);
|
this.playerIDToClaimPermissionMap.put(builderID, ClaimPermission.Build);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < containerIds.length; i++)
|
for(String containerID : containerIDs)
|
||||||
{
|
{
|
||||||
String containerID = containerIds[i];
|
|
||||||
if(containerID != null && !containerID.isEmpty())
|
if(containerID != null && !containerID.isEmpty())
|
||||||
{
|
{
|
||||||
this.playerIDToClaimPermissionMap.put(containerID, ClaimPermission.Inventory);
|
this.playerIDToClaimPermissionMap.put(containerID, ClaimPermission.Inventory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < accessorIDs.length; i++)
|
for(String accessorID : accessorIDs)
|
||||||
{
|
{
|
||||||
String accessorID = accessorIDs[i];
|
|
||||||
if(accessorID != null && !accessorID.isEmpty())
|
if(accessorID != null && !accessorID.isEmpty())
|
||||||
{
|
{
|
||||||
this.playerIDToClaimPermissionMap.put(accessorID, ClaimPermission.Access);
|
this.playerIDToClaimPermissionMap.put(accessorID, ClaimPermission.Access);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < managerIDs.length; i++)
|
for(String managerID : managerIDs)
|
||||||
{
|
{
|
||||||
String managerID = managerIDs[i];
|
|
||||||
if(managerID != null && !managerID.isEmpty())
|
if(managerID != null && !managerID.isEmpty())
|
||||||
{
|
{
|
||||||
this.managers.add(managerID);
|
this.managers.add(managerID);
|
||||||
|
|
@ -264,7 +260,7 @@ public class Claim
|
||||||
Claim claim = new Claim
|
Claim claim = new Claim
|
||||||
(new Location(this.lesserBoundaryCorner.getWorld(), this.lesserBoundaryCorner.getBlockX() - howNear, this.lesserBoundaryCorner.getBlockY(), this.lesserBoundaryCorner.getBlockZ() - howNear),
|
(new Location(this.lesserBoundaryCorner.getWorld(), this.lesserBoundaryCorner.getBlockX() - howNear, this.lesserBoundaryCorner.getBlockY(), this.lesserBoundaryCorner.getBlockZ() - howNear),
|
||||||
new Location(this.greaterBoundaryCorner.getWorld(), this.greaterBoundaryCorner.getBlockX() + howNear, this.greaterBoundaryCorner.getBlockY(), this.greaterBoundaryCorner.getBlockZ() + howNear),
|
new Location(this.greaterBoundaryCorner.getWorld(), this.greaterBoundaryCorner.getBlockX() + howNear, this.greaterBoundaryCorner.getBlockY(), this.greaterBoundaryCorner.getBlockZ() + howNear),
|
||||||
null, new String[] {}, new String[] {}, new String[] {}, new String[] {}, null);
|
null, new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), null);
|
||||||
|
|
||||||
return claim.contains(location, false, true);
|
return claim.contains(location, false, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,6 @@
|
||||||
package me.ryanhamshire.GriefPrevention;
|
package me.ryanhamshire.GriefPrevention;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
@ -66,7 +63,7 @@ public abstract class DataStore
|
||||||
final static String softMuteFilePath = dataLayerFolderPath + File.separator + "softMute.txt";
|
final static String softMuteFilePath = dataLayerFolderPath + File.separator + "softMute.txt";
|
||||||
|
|
||||||
//the latest version of the data schema implemented here
|
//the latest version of the data schema implemented here
|
||||||
protected static final int latestSchemaVersion = 1;
|
protected static final int latestSchemaVersion = 2;
|
||||||
|
|
||||||
//reading and writing the schema version to the data store
|
//reading and writing the schema version to the data store
|
||||||
abstract int getSchemaVersionFromStorage();
|
abstract int getSchemaVersionFromStorage();
|
||||||
|
|
@ -129,6 +126,11 @@ public abstract class DataStore
|
||||||
for(Claim claim : this.claims)
|
for(Claim claim : this.claims)
|
||||||
{
|
{
|
||||||
this.saveClaim(claim);
|
this.saveClaim(claim);
|
||||||
|
|
||||||
|
for(Claim subClaim : claim.children)
|
||||||
|
{
|
||||||
|
this.saveClaim(subClaim);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//clean up any UUID conversion work
|
//clean up any UUID conversion work
|
||||||
|
|
@ -363,7 +365,7 @@ public abstract class DataStore
|
||||||
//adds a claim to the datastore, making it an effective claim
|
//adds a claim to the datastore, making it an effective claim
|
||||||
synchronized void addClaim(Claim newClaim, boolean writeToStorage)
|
synchronized void addClaim(Claim newClaim, boolean writeToStorage)
|
||||||
{
|
{
|
||||||
//subdivisions are easy
|
//subdivisions are added under their parent, not directly to the hash map for direct search
|
||||||
if(newClaim.parent != null)
|
if(newClaim.parent != null)
|
||||||
{
|
{
|
||||||
if(!newClaim.parent.children.contains(newClaim))
|
if(!newClaim.parent.children.contains(newClaim))
|
||||||
|
|
@ -425,7 +427,7 @@ public abstract class DataStore
|
||||||
}
|
}
|
||||||
|
|
||||||
//turns a location string back into a location
|
//turns a location string back into a location
|
||||||
Location locationFromString(String string) throws Exception
|
Location locationFromString(String string, List<World> validWorlds) throws Exception
|
||||||
{
|
{
|
||||||
//split the input string on the space
|
//split the input string on the space
|
||||||
String [] elements = string.split(locationStringDelimiter);
|
String [] elements = string.split(locationStringDelimiter);
|
||||||
|
|
@ -442,7 +444,16 @@ public abstract class DataStore
|
||||||
String zString = elements[3];
|
String zString = elements[3];
|
||||||
|
|
||||||
//identify world the claim is in
|
//identify world the claim is in
|
||||||
World world = GriefPrevention.instance.getServer().getWorld(worldName);
|
World world = null;
|
||||||
|
for(World w : validWorlds)
|
||||||
|
{
|
||||||
|
if(w.getName().equalsIgnoreCase(worldName))
|
||||||
|
{
|
||||||
|
world = w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(world == null)
|
if(world == null)
|
||||||
{
|
{
|
||||||
throw new Exception("World not found: \"" + worldName + "\"");
|
throw new Exception("World not found: \"" + worldName + "\"");
|
||||||
|
|
@ -459,15 +470,7 @@ public abstract class DataStore
|
||||||
//saves any changes to a claim to secondary storage
|
//saves any changes to a claim to secondary storage
|
||||||
synchronized public void saveClaim(Claim claim)
|
synchronized public void saveClaim(Claim claim)
|
||||||
{
|
{
|
||||||
//subdivisions don't save to their own files, but instead live in their parent claim's file
|
//ensure a unique identifier for the claim which will be used to name the file on disk
|
||||||
//so any attempt to save a subdivision will save its parent (and thus the subdivision)
|
|
||||||
if(claim.parent != null)
|
|
||||||
{
|
|
||||||
this.saveClaim(claim.parent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//otherwise get a unique identifier for the claim which will be used to name the file on disk
|
|
||||||
if(claim.id == null)
|
if(claim.id == null)
|
||||||
{
|
{
|
||||||
claim.id = this.nextClaimID;
|
claim.id = this.nextClaimID;
|
||||||
|
|
@ -512,23 +515,20 @@ public abstract class DataStore
|
||||||
|
|
||||||
synchronized void deleteClaim(Claim claim, boolean fireEvent)
|
synchronized void deleteClaim(Claim claim, boolean fireEvent)
|
||||||
{
|
{
|
||||||
//subdivisions are simple - just remove them from their parent claim and save that claim
|
//delete any children
|
||||||
|
for(int j = 0; j < claim.children.size(); j++)
|
||||||
|
{
|
||||||
|
this.deleteClaim(claim.children.get(j--), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//subdivisions must also be removed from the parent claim child list
|
||||||
if(claim.parent != null)
|
if(claim.parent != null)
|
||||||
{
|
{
|
||||||
Claim parentClaim = claim.parent;
|
Claim parentClaim = claim.parent;
|
||||||
parentClaim.children.remove(claim);
|
parentClaim.children.remove(claim);
|
||||||
claim.inDataStore = false;
|
|
||||||
this.saveClaim(parentClaim);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//delete any children
|
//mark as deleted so any references elsewhere can be ignored
|
||||||
for(int j = 0; j < claim.children.size(); j++)
|
|
||||||
{
|
|
||||||
this.deleteClaim(claim.children.get(j), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//mark as deleted so any references elsewhere can be ignored
|
|
||||||
claim.inDataStore = false;
|
claim.inDataStore = false;
|
||||||
|
|
||||||
//remove from memory
|
//remove from memory
|
||||||
|
|
@ -558,8 +558,8 @@ public abstract class DataStore
|
||||||
//remove from secondary storage
|
//remove from secondary storage
|
||||||
this.deleteClaimFromSecondaryStorage(claim);
|
this.deleteClaimFromSecondaryStorage(claim);
|
||||||
|
|
||||||
//update player data, except for administrative claims, which have no owner
|
//update player data
|
||||||
if(!claim.isAdminClaim())
|
if(claim.ownerID != null)
|
||||||
{
|
{
|
||||||
PlayerData ownerData = this.getPlayerData(claim.ownerID);
|
PlayerData ownerData = this.getPlayerData(claim.ownerID);
|
||||||
for(int i = 0; i < ownerData.getClaims().size(); i++)
|
for(int i = 0; i < ownerData.getClaims().size(); i++)
|
||||||
|
|
@ -597,14 +597,14 @@ public abstract class DataStore
|
||||||
|
|
||||||
for(Claim claim : claimsInChunk)
|
for(Claim claim : claimsInChunk)
|
||||||
{
|
{
|
||||||
if(claim.contains(location, ignoreHeight, false))
|
if(claim.inDataStore && claim.contains(location, ignoreHeight, false))
|
||||||
{
|
{
|
||||||
//when we find a top level claim, if the location is in one of its subdivisions,
|
//when we find a top level claim, if the location is in one of its subdivisions,
|
||||||
//return the SUBDIVISION, not the top level claim
|
//return the SUBDIVISION, not the top level claim
|
||||||
for(int j = 0; j < claim.children.size(); j++)
|
for(int j = 0; j < claim.children.size(); j++)
|
||||||
{
|
{
|
||||||
Claim subdivision = claim.children.get(j);
|
Claim subdivision = claim.children.get(j);
|
||||||
if(subdivision.contains(location, ignoreHeight, false)) return subdivision;
|
if(subdivision.inDataStore && subdivision.contains(location, ignoreHeight, false)) return subdivision;
|
||||||
}
|
}
|
||||||
|
|
||||||
return claim;
|
return claim;
|
||||||
|
|
@ -620,7 +620,7 @@ public abstract class DataStore
|
||||||
{
|
{
|
||||||
for(Claim claim : this.claims)
|
for(Claim claim : this.claims)
|
||||||
{
|
{
|
||||||
if(claim.getID() == id) return claim;
|
if(claim.inDataStore && claim.getID() == id) return claim;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -702,10 +702,10 @@ public abstract class DataStore
|
||||||
new Location(world, smallx, smally, smallz),
|
new Location(world, smallx, smally, smallz),
|
||||||
new Location(world, bigx, bigy, bigz),
|
new Location(world, bigx, bigy, bigz),
|
||||||
ownerID,
|
ownerID,
|
||||||
new String [] {},
|
new ArrayList<String>(),
|
||||||
new String [] {},
|
new ArrayList<String>(),
|
||||||
new String [] {},
|
new ArrayList<String>(),
|
||||||
new String [] {},
|
new ArrayList<String>(),
|
||||||
id);
|
id);
|
||||||
|
|
||||||
newClaim.parent = parent;
|
newClaim.parent = parent;
|
||||||
|
|
@ -714,7 +714,7 @@ public abstract class DataStore
|
||||||
ArrayList<Claim> claimsToCheck;
|
ArrayList<Claim> claimsToCheck;
|
||||||
if(newClaim.parent != null)
|
if(newClaim.parent != null)
|
||||||
{
|
{
|
||||||
claimsToCheck = newClaim.parent.children;
|
claimsToCheck = newClaim.parent.children;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -726,7 +726,7 @@ public abstract class DataStore
|
||||||
Claim otherClaim = claimsToCheck.get(i);
|
Claim otherClaim = claimsToCheck.get(i);
|
||||||
|
|
||||||
//if we find an existing claim which will be overlapped
|
//if we find an existing claim which will be overlapped
|
||||||
if(otherClaim.overlaps(newClaim))
|
if(otherClaim.id != newClaim.id && otherClaim.inDataStore && otherClaim.overlaps(newClaim))
|
||||||
{
|
{
|
||||||
//result = fail, return conflicting claim
|
//result = fail, return conflicting claim
|
||||||
result.succeeded = false;
|
result.succeeded = false;
|
||||||
|
|
@ -821,27 +821,18 @@ public abstract class DataStore
|
||||||
|
|
||||||
if(claim.parent != null) claim = claim.parent;
|
if(claim.parent != null) claim = claim.parent;
|
||||||
|
|
||||||
//note any subdivisions
|
//adjust to new depth
|
||||||
ArrayList<Claim> subdivisions = new ArrayList<Claim>(claim.children);
|
|
||||||
|
|
||||||
//delete the claim
|
|
||||||
this.deleteClaim(claim, false);
|
|
||||||
|
|
||||||
//re-create it at the new depth
|
|
||||||
claim.lesserBoundaryCorner.setY(newDepth);
|
claim.lesserBoundaryCorner.setY(newDepth);
|
||||||
claim.greaterBoundaryCorner.setY(newDepth);
|
claim.greaterBoundaryCorner.setY(newDepth);
|
||||||
|
for(Claim subdivision : claim.children)
|
||||||
//re-add the subdivisions (deleteClaim() removed them) with the new depth
|
|
||||||
for(Claim subdivision : subdivisions)
|
|
||||||
{
|
{
|
||||||
subdivision.lesserBoundaryCorner.setY(newDepth);
|
subdivision.lesserBoundaryCorner.setY(newDepth);
|
||||||
subdivision.greaterBoundaryCorner.setY(newDepth);
|
subdivision.greaterBoundaryCorner.setY(newDepth);
|
||||||
subdivision.parent = claim;
|
this.saveClaim(subdivision);
|
||||||
this.addClaim(subdivision, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//save changes
|
//save changes
|
||||||
this.addClaim(claim, true);
|
this.saveClaim(claim);
|
||||||
}
|
}
|
||||||
|
|
||||||
//starts a siege on a claim
|
//starts a siege on a claim
|
||||||
|
|
@ -1084,12 +1075,6 @@ public abstract class DataStore
|
||||||
//see CreateClaim() for details on return value
|
//see CreateClaim() for details on return value
|
||||||
synchronized public CreateClaimResult resizeClaim(Claim claim, int newx1, int newx2, int newy1, int newy2, int newz1, int newz2, Player resizingPlayer)
|
synchronized public CreateClaimResult resizeClaim(Claim claim, int newx1, int newx2, int newy1, int newy2, int newz1, int newz2, Player resizingPlayer)
|
||||||
{
|
{
|
||||||
//note any subdivisions before deleting the claim
|
|
||||||
ArrayList<Claim> subdivisions = new ArrayList<Claim>(claim.children);
|
|
||||||
|
|
||||||
//remove old claim
|
|
||||||
this.deleteClaim(claim, false);
|
|
||||||
|
|
||||||
//try to create this new claim, ignoring the original when checking for overlap
|
//try to create this new claim, ignoring the original when checking for overlap
|
||||||
CreateClaimResult result = this.createClaim(claim.getLesserBoundaryCorner().getWorld(), newx1, newx2, newy1, newy2, newz1, newz2, claim.ownerID, claim.parent, claim.id, resizingPlayer);
|
CreateClaimResult result = this.createClaim(claim.getLesserBoundaryCorner().getWorld(), newx1, newx2, newy1, newy2, newz1, newz2, claim.ownerID, claim.parent, claim.id, resizingPlayer);
|
||||||
|
|
||||||
|
|
@ -1118,20 +1103,17 @@ public abstract class DataStore
|
||||||
}
|
}
|
||||||
|
|
||||||
//restore subdivisions
|
//restore subdivisions
|
||||||
for(Claim subdivision : subdivisions)
|
for(Claim subdivision : claim.children)
|
||||||
{
|
{
|
||||||
subdivision.parent = result.claim;
|
subdivision.parent = result.claim;
|
||||||
this.addClaim(subdivision, false);
|
result.claim.children.add(subdivision);
|
||||||
}
|
}
|
||||||
|
|
||||||
//save those changes
|
//save those changes
|
||||||
this.saveClaim(result.claim);
|
this.saveClaim(result.claim);
|
||||||
}
|
|
||||||
|
//make original claim ineffective (it's still in the hash map, so let's make it ignored)
|
||||||
else
|
claim.inDataStore = false;
|
||||||
{
|
|
||||||
//put original claim back
|
|
||||||
this.addClaim(claim, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1421,7 +1403,7 @@ public abstract class DataStore
|
||||||
|
|
||||||
//used in updating the data schema from 0 to 1.
|
//used in updating the data schema from 0 to 1.
|
||||||
//converts player names in a list to uuids
|
//converts player names in a list to uuids
|
||||||
protected String[] convertNameListToUUIDList(String[] names)
|
protected List<String> convertNameListToUUIDList(List<String> names)
|
||||||
{
|
{
|
||||||
//doesn't apply after schema has been updated to version 1
|
//doesn't apply after schema has been updated to version 1
|
||||||
if(this.getSchemaVersion() >= 1) return names;
|
if(this.getSchemaVersion() >= 1) return names;
|
||||||
|
|
@ -1453,14 +1435,7 @@ public abstract class DataStore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//return final result of conversion
|
return resultNames;
|
||||||
String [] resultArray = new String [resultNames.size()];
|
|
||||||
for(int i = 0; i < resultNames.size(); i++)
|
|
||||||
{
|
|
||||||
resultArray[i] = resultNames.get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void close();
|
abstract void close();
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,7 @@ public class DatabaseDataStore extends DataStore
|
||||||
|
|
||||||
ArrayList<Claim> claimsToRemove = new ArrayList<Claim>();
|
ArrayList<Claim> claimsToRemove = new ArrayList<Claim>();
|
||||||
ArrayList<Claim> subdivisionsToLoad = new ArrayList<Claim>();
|
ArrayList<Claim> subdivisionsToLoad = new ArrayList<Claim>();
|
||||||
|
List<World> validWorlds = Bukkit.getServer().getWorlds();
|
||||||
|
|
||||||
while(results.next())
|
while(results.next())
|
||||||
{
|
{
|
||||||
|
|
@ -242,10 +243,10 @@ public class DatabaseDataStore extends DataStore
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lesserCornerString = results.getString("lessercorner");
|
lesserCornerString = results.getString("lessercorner");
|
||||||
lesserBoundaryCorner = this.locationFromString(lesserCornerString);
|
lesserBoundaryCorner = this.locationFromString(lesserCornerString, validWorlds);
|
||||||
|
|
||||||
String greaterCornerString = results.getString("greatercorner");
|
String greaterCornerString = results.getString("greatercorner");
|
||||||
greaterBoundaryCorner = this.locationFromString(greaterCornerString);
|
greaterBoundaryCorner = this.locationFromString(greaterCornerString, validWorlds);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
|
@ -293,19 +294,19 @@ public class DatabaseDataStore extends DataStore
|
||||||
}
|
}
|
||||||
|
|
||||||
String buildersString = results.getString("builders");
|
String buildersString = results.getString("builders");
|
||||||
String [] builderNames = buildersString.split(";");
|
List<String> builderNames = Arrays.asList(buildersString.split(";"));
|
||||||
builderNames = this.convertNameListToUUIDList(builderNames);
|
builderNames = this.convertNameListToUUIDList(builderNames);
|
||||||
|
|
||||||
String containersString = results.getString("containers");
|
String containersString = results.getString("containers");
|
||||||
String [] containerNames = containersString.split(";");
|
List<String> containerNames = Arrays.asList(containersString.split(";"));
|
||||||
containerNames = this.convertNameListToUUIDList(containerNames);
|
containerNames = this.convertNameListToUUIDList(containerNames);
|
||||||
|
|
||||||
String accessorsString = results.getString("accessors");
|
String accessorsString = results.getString("accessors");
|
||||||
String [] accessorNames = accessorsString.split(";");
|
List<String> accessorNames = Arrays.asList(accessorsString.split(";"));
|
||||||
accessorNames = this.convertNameListToUUIDList(accessorNames);
|
accessorNames = this.convertNameListToUUIDList(accessorNames);
|
||||||
|
|
||||||
String managersString = results.getString("managers");
|
String managersString = results.getString("managers");
|
||||||
String [] managerNames = managersString.split(";");
|
List<String> managerNames = Arrays.asList(managersString.split(";"));
|
||||||
managerNames = this.convertNameListToUUIDList(managerNames);
|
managerNames = this.convertNameListToUUIDList(managerNames);
|
||||||
|
|
||||||
Claim claim = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, ownerID, builderNames, containerNames, accessorNames, managerNames, claimID);
|
Claim claim = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, ownerID, builderNames, containerNames, accessorNames, managerNames, claimID);
|
||||||
|
|
@ -356,6 +357,13 @@ public class DatabaseDataStore extends DataStore
|
||||||
this.deleteClaimFromSecondaryStorage(claimsToRemove.get(i));
|
this.deleteClaimFromSecondaryStorage(claimsToRemove.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this.getSchemaVersion() <= 2)
|
||||||
|
{
|
||||||
|
this.refreshDataConnection();
|
||||||
|
statement = this.databaseConnection.createStatement();
|
||||||
|
statement.execute("DELETE FROM griefprevention_claimdata WHERE id='-1';");
|
||||||
|
}
|
||||||
|
|
||||||
super.initialize();
|
super.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,15 +377,8 @@ public class DatabaseDataStore extends DataStore
|
||||||
//wipe out any existing data about this claim
|
//wipe out any existing data about this claim
|
||||||
this.deleteClaimFromSecondaryStorage(claim);
|
this.deleteClaimFromSecondaryStorage(claim);
|
||||||
|
|
||||||
//write top level claim data to the database
|
//write claim data to the database
|
||||||
this.writeClaimData(claim);
|
this.writeClaimData(claim);
|
||||||
|
|
||||||
//for each subdivision
|
|
||||||
for(int i = 0; i < claim.children.size(); i++)
|
|
||||||
{
|
|
||||||
//write the subdivision's data to the database
|
|
||||||
this.writeClaimData(claim.children.get(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(SQLException e)
|
catch(SQLException e)
|
||||||
{
|
{
|
||||||
|
|
@ -435,23 +436,13 @@ public class DatabaseDataStore extends DataStore
|
||||||
parentId = claim.parent.id;
|
parentId = claim.parent.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
long id;
|
|
||||||
if(claim.id == null)
|
|
||||||
{
|
|
||||||
id = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
id = claim.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.refreshDataConnection();
|
this.refreshDataConnection();
|
||||||
|
|
||||||
Statement statement = databaseConnection.createStatement();
|
Statement statement = databaseConnection.createStatement();
|
||||||
statement.execute("INSERT INTO griefprevention_claimdata (id, owner, lessercorner, greatercorner, builders, containers, accessors, managers, parentid) VALUES(" +
|
statement.execute("INSERT INTO griefprevention_claimdata (id, owner, lessercorner, greatercorner, builders, containers, accessors, managers, parentid) VALUES(" +
|
||||||
id + ", '" +
|
claim.id + ", '" +
|
||||||
owner + "', '" +
|
owner + "', '" +
|
||||||
lesserCornerString + "', '" +
|
lesserCornerString + "', '" +
|
||||||
greaterCornerString + "', '" +
|
greaterCornerString + "', '" +
|
||||||
|
|
@ -479,11 +470,7 @@ public class DatabaseDataStore extends DataStore
|
||||||
|
|
||||||
|
|
||||||
Statement statement = this.databaseConnection.createStatement();
|
Statement statement = this.databaseConnection.createStatement();
|
||||||
statement.execute("DELETE FROM griefprevention_claimdata WHERE lessercorner='" + this.locationToString(claim.lesserBoundaryCorner) + "' AND greatercorner = '" + this.locationToString(claim.greaterBoundaryCorner) + "';");
|
statement.execute("DELETE FROM griefprevention_claimdata WHERE id='" + claim.id + "';");
|
||||||
if(claim.id != -1)
|
|
||||||
{
|
|
||||||
statement.execute("DELETE FROM griefprevention_claimdata WHERE parentid=" + claim.id + ";");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(SQLException e)
|
catch(SQLException e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,13 @@ import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
|
|
||||||
|
|
@ -189,200 +194,374 @@ public class FlatFileDataStore extends DataStore
|
||||||
//get a list of all the files in the claims data folder
|
//get a list of all the files in the claims data folder
|
||||||
files = claimDataFolder.listFiles();
|
files = claimDataFolder.listFiles();
|
||||||
|
|
||||||
for(int i = 0; i < files.length; i++)
|
if(this.getSchemaVersion() <= 1)
|
||||||
{
|
{
|
||||||
if(files[i].isFile()) //avoids folders
|
this.loadClaimData_Legacy(files);
|
||||||
{
|
}
|
||||||
//skip any file starting with an underscore, to avoid special files not representing land claims
|
else
|
||||||
if(files[i].getName().startsWith("_")) continue;
|
{
|
||||||
|
this.loadClaimData(files);
|
||||||
//the filename is the claim ID. try to parse it
|
|
||||||
long claimID;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
claimID = Long.parseLong(files[i].getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
//because some older versions used a different file name pattern before claim IDs were introduced,
|
|
||||||
//those files need to be "converted" by renaming them to a unique ID
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
claimID = this.nextClaimID;
|
|
||||||
this.incrementNextClaimID();
|
|
||||||
File newFile = new File(claimDataFolderPath + File.separator + String.valueOf(this.nextClaimID));
|
|
||||||
files[i].renameTo(newFile);
|
|
||||||
files[i] = newFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedReader inStream = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Claim topLevelClaim = null;
|
|
||||||
|
|
||||||
inStream = new BufferedReader(new FileReader(files[i].getAbsolutePath()));
|
|
||||||
String line = inStream.readLine();
|
|
||||||
|
|
||||||
while(line != null)
|
|
||||||
{
|
|
||||||
//skip any SUB:### lines from previous versions
|
|
||||||
if(line.toLowerCase().startsWith("sub:"))
|
|
||||||
{
|
|
||||||
line = inStream.readLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
//skip any UUID lines from previous versions
|
|
||||||
Matcher match = uuidpattern.matcher(line.trim());
|
|
||||||
if(match.find())
|
|
||||||
{
|
|
||||||
line = inStream.readLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
//first line is lesser boundary corner location
|
|
||||||
Location lesserBoundaryCorner = this.locationFromString(line);
|
|
||||||
|
|
||||||
//second line is greater boundary corner location
|
|
||||||
line = inStream.readLine();
|
|
||||||
Location greaterBoundaryCorner = this.locationFromString(line);
|
|
||||||
|
|
||||||
//third line is owner name
|
|
||||||
line = inStream.readLine();
|
|
||||||
String ownerName = line;
|
|
||||||
UUID ownerID = null;
|
|
||||||
if(ownerName.isEmpty() || ownerName.startsWith("--"))
|
|
||||||
{
|
|
||||||
ownerID = null; //administrative land claim or subdivision
|
|
||||||
}
|
|
||||||
else if(this.getSchemaVersion() == 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ownerID = UUIDFetcher.getUUIDOf(ownerName);
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
GriefPrevention.AddLogEntry("Couldn't resolve this name to a UUID: " + ownerName + ".");
|
|
||||||
GriefPrevention.AddLogEntry(" Converted land claim to administrative @ " + lesserBoundaryCorner.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ownerID = UUID.fromString(ownerName);
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
GriefPrevention.AddLogEntry("Error - this is not a valid UUID: " + ownerName + ".");
|
|
||||||
GriefPrevention.AddLogEntry(" Converted land claim to administrative @ " + lesserBoundaryCorner.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//fourth line is list of builders
|
|
||||||
line = inStream.readLine();
|
|
||||||
String [] builderNames = line.split(";");
|
|
||||||
builderNames = this.convertNameListToUUIDList(builderNames);
|
|
||||||
|
|
||||||
//fifth line is list of players who can access containers
|
|
||||||
line = inStream.readLine();
|
|
||||||
String [] containerNames = line.split(";");
|
|
||||||
containerNames = this.convertNameListToUUIDList(containerNames);
|
|
||||||
|
|
||||||
//sixth line is list of players who can use buttons and switches
|
|
||||||
line = inStream.readLine();
|
|
||||||
String [] accessorNames = line.split(";");
|
|
||||||
accessorNames = this.convertNameListToUUIDList(accessorNames);
|
|
||||||
|
|
||||||
//seventh line is list of players who can grant permissions
|
|
||||||
line = inStream.readLine();
|
|
||||||
if(line == null) line = "";
|
|
||||||
String [] managerNames = line.split(";");
|
|
||||||
managerNames = this.convertNameListToUUIDList(managerNames);
|
|
||||||
|
|
||||||
//skip any remaining extra lines, until the "===" string, indicating the end of this claim or subdivision
|
|
||||||
line = inStream.readLine();
|
|
||||||
while(line != null && !line.contains("==="))
|
|
||||||
line = inStream.readLine();
|
|
||||||
|
|
||||||
//build a claim instance from those data
|
|
||||||
//if this is the first claim loaded from this file, it's the top level claim
|
|
||||||
if(topLevelClaim == null)
|
|
||||||
{
|
|
||||||
//instantiate
|
|
||||||
topLevelClaim = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, ownerID, builderNames, containerNames, accessorNames, managerNames, claimID);
|
|
||||||
|
|
||||||
topLevelClaim.modifiedDate = new Date(files[i].lastModified());
|
|
||||||
this.addClaim(topLevelClaim, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//otherwise there's already a top level claim, so this must be a subdivision of that top level claim
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Claim subdivision = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, null, builderNames, containerNames, accessorNames, managerNames, null);
|
|
||||||
|
|
||||||
subdivision.modifiedDate = new Date(files[i].lastModified());
|
|
||||||
subdivision.parent = topLevelClaim;
|
|
||||||
topLevelClaim.children.add(subdivision);
|
|
||||||
subdivision.inDataStore = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//move up to the first line in the next subdivision
|
|
||||||
line = inStream.readLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
inStream.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
//if there's any problem with the file's content, log an error message and skip it
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
if(e.getMessage().contains("World not found"))
|
|
||||||
{
|
|
||||||
inStream.close();
|
|
||||||
files[i].delete();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StringWriter errors = new StringWriter();
|
|
||||||
e.printStackTrace(new PrintWriter(errors));
|
|
||||||
GriefPrevention.AddLogEntry(files[i].getName() + " " + errors.toString(), CustomLogEntryTypes.Exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(inStream != null) inStream.close();
|
|
||||||
}
|
|
||||||
catch(IOException exception) {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.initialize();
|
super.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadClaimData_Legacy(File [] files) throws Exception
|
||||||
|
{
|
||||||
|
List<World> validWorlds = Bukkit.getServer().getWorlds();
|
||||||
|
|
||||||
|
for(int i = 0; i < files.length; i++)
|
||||||
|
{
|
||||||
|
if(files[i].isFile()) //avoids folders
|
||||||
|
{
|
||||||
|
//skip any file starting with an underscore, to avoid special files not representing land claims
|
||||||
|
if(files[i].getName().startsWith("_")) continue;
|
||||||
|
|
||||||
|
//the filename is the claim ID. try to parse it
|
||||||
|
long claimID;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
claimID = Long.parseLong(files[i].getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
//because some older versions used a different file name pattern before claim IDs were introduced,
|
||||||
|
//those files need to be "converted" by renaming them to a unique ID
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
claimID = this.nextClaimID;
|
||||||
|
this.incrementNextClaimID();
|
||||||
|
File newFile = new File(claimDataFolderPath + File.separator + String.valueOf(this.nextClaimID));
|
||||||
|
files[i].renameTo(newFile);
|
||||||
|
files[i] = newFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedReader inStream = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Claim topLevelClaim = null;
|
||||||
|
|
||||||
|
inStream = new BufferedReader(new FileReader(files[i].getAbsolutePath()));
|
||||||
|
String line = inStream.readLine();
|
||||||
|
|
||||||
|
while(line != null)
|
||||||
|
{
|
||||||
|
//skip any SUB:### lines from previous versions
|
||||||
|
if(line.toLowerCase().startsWith("sub:"))
|
||||||
|
{
|
||||||
|
line = inStream.readLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
//skip any UUID lines from previous versions
|
||||||
|
Matcher match = uuidpattern.matcher(line.trim());
|
||||||
|
if(match.find())
|
||||||
|
{
|
||||||
|
line = inStream.readLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
//first line is lesser boundary corner location
|
||||||
|
Location lesserBoundaryCorner = this.locationFromString(line, validWorlds);
|
||||||
|
|
||||||
|
//second line is greater boundary corner location
|
||||||
|
line = inStream.readLine();
|
||||||
|
Location greaterBoundaryCorner = this.locationFromString(line, validWorlds);
|
||||||
|
|
||||||
|
//third line is owner name
|
||||||
|
line = inStream.readLine();
|
||||||
|
String ownerName = line;
|
||||||
|
UUID ownerID = null;
|
||||||
|
if(ownerName.isEmpty() || ownerName.startsWith("--"))
|
||||||
|
{
|
||||||
|
ownerID = null; //administrative land claim or subdivision
|
||||||
|
}
|
||||||
|
else if(this.getSchemaVersion() == 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ownerID = UUIDFetcher.getUUIDOf(ownerName);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
GriefPrevention.AddLogEntry("Couldn't resolve this name to a UUID: " + ownerName + ".");
|
||||||
|
GriefPrevention.AddLogEntry(" Converted land claim to administrative @ " + lesserBoundaryCorner.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ownerID = UUID.fromString(ownerName);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
GriefPrevention.AddLogEntry("Error - this is not a valid UUID: " + ownerName + ".");
|
||||||
|
GriefPrevention.AddLogEntry(" Converted land claim to administrative @ " + lesserBoundaryCorner.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//fourth line is list of builders
|
||||||
|
line = inStream.readLine();
|
||||||
|
List<String> builderNames = Arrays.asList(line.split(";"));
|
||||||
|
builderNames = this.convertNameListToUUIDList(builderNames);
|
||||||
|
|
||||||
|
//fifth line is list of players who can access containers
|
||||||
|
line = inStream.readLine();
|
||||||
|
List<String> containerNames = Arrays.asList(line.split(";"));
|
||||||
|
containerNames = this.convertNameListToUUIDList(containerNames);
|
||||||
|
|
||||||
|
//sixth line is list of players who can use buttons and switches
|
||||||
|
line = inStream.readLine();
|
||||||
|
List<String> accessorNames = Arrays.asList(line.split(";"));
|
||||||
|
accessorNames = this.convertNameListToUUIDList(accessorNames);
|
||||||
|
|
||||||
|
//seventh line is list of players who can grant permissions
|
||||||
|
line = inStream.readLine();
|
||||||
|
if(line == null) line = "";
|
||||||
|
List<String> managerNames = Arrays.asList(line.split(";"));
|
||||||
|
managerNames = this.convertNameListToUUIDList(managerNames);
|
||||||
|
|
||||||
|
//skip any remaining extra lines, until the "===" string, indicating the end of this claim or subdivision
|
||||||
|
line = inStream.readLine();
|
||||||
|
while(line != null && !line.contains("==="))
|
||||||
|
line = inStream.readLine();
|
||||||
|
|
||||||
|
//build a claim instance from those data
|
||||||
|
//if this is the first claim loaded from this file, it's the top level claim
|
||||||
|
if(topLevelClaim == null)
|
||||||
|
{
|
||||||
|
//instantiate
|
||||||
|
topLevelClaim = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, ownerID, builderNames, containerNames, accessorNames, managerNames, claimID);
|
||||||
|
|
||||||
|
topLevelClaim.modifiedDate = new Date(files[i].lastModified());
|
||||||
|
this.addClaim(topLevelClaim, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//otherwise there's already a top level claim, so this must be a subdivision of that top level claim
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Claim subdivision = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, null, builderNames, containerNames, accessorNames, managerNames, null);
|
||||||
|
|
||||||
|
subdivision.modifiedDate = new Date(files[i].lastModified());
|
||||||
|
subdivision.parent = topLevelClaim;
|
||||||
|
topLevelClaim.children.add(subdivision);
|
||||||
|
subdivision.inDataStore = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//move up to the first line in the next subdivision
|
||||||
|
line = inStream.readLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
inStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//if there's any problem with the file's content, log an error message and skip it
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
if(e.getMessage().contains("World not found"))
|
||||||
|
{
|
||||||
|
inStream.close();
|
||||||
|
files[i].delete();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringWriter errors = new StringWriter();
|
||||||
|
e.printStackTrace(new PrintWriter(errors));
|
||||||
|
GriefPrevention.AddLogEntry(files[i].getName() + " " + errors.toString(), CustomLogEntryTypes.Exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(inStream != null) inStream.close();
|
||||||
|
}
|
||||||
|
catch(IOException exception) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadClaimData(File [] files) throws Exception
|
||||||
|
{
|
||||||
|
ConcurrentHashMap<Claim, Long> orphans = new ConcurrentHashMap<Claim, Long>();
|
||||||
|
for(int i = 0; i < files.length; i++)
|
||||||
|
{
|
||||||
|
if(files[i].isFile()) //avoids folders
|
||||||
|
{
|
||||||
|
//skip any file starting with an underscore, to avoid special files not representing land claims
|
||||||
|
if(files[i].getName().startsWith("_")) continue;
|
||||||
|
|
||||||
|
//delete any which don't end in .yml
|
||||||
|
if(!files[i].getName().endsWith(".yml"))
|
||||||
|
{
|
||||||
|
files[i].delete();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//the filename is the claim ID. try to parse it
|
||||||
|
long claimID;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
claimID = Long.parseLong(files[i].getName().split("\\.")[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//because some older versions used a different file name pattern before claim IDs were introduced,
|
||||||
|
//those files need to be "converted" by renaming them to a unique ID
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
claimID = this.nextClaimID;
|
||||||
|
this.incrementNextClaimID();
|
||||||
|
File newFile = new File(claimDataFolderPath + File.separator + String.valueOf(this.nextClaimID) + ".yml");
|
||||||
|
files[i].renameTo(newFile);
|
||||||
|
files[i] = newFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ArrayList<Long> out_parentID = new ArrayList<Long>(); //hacky output parameter
|
||||||
|
Claim claim = this.loadClaim(files[i], out_parentID, claimID);
|
||||||
|
if(out_parentID.size() == 0 || out_parentID.get(0) == -1)
|
||||||
|
{
|
||||||
|
this.addClaim(claim, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
orphans.put(claim, out_parentID.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if there's any problem with the file's content, log an error message and skip it
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
if(e.getMessage() != null && e.getMessage().contains("World not found"))
|
||||||
|
{
|
||||||
|
files[i].delete();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringWriter errors = new StringWriter();
|
||||||
|
e.printStackTrace(new PrintWriter(errors));
|
||||||
|
GriefPrevention.AddLogEntry(files[i].getName() + " " + errors.toString(), CustomLogEntryTypes.Exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//link children to parents
|
||||||
|
for(Claim child : orphans.keySet())
|
||||||
|
{
|
||||||
|
Claim parent = this.getClaim(orphans.get(child));
|
||||||
|
if(parent != null)
|
||||||
|
{
|
||||||
|
child.parent = parent;
|
||||||
|
this.addClaim(child, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Claim loadClaim(File file, ArrayList<Long> out_parentID, long claimID) throws IOException, InvalidConfigurationException, Exception
|
||||||
|
{
|
||||||
|
List<String> lines = Files.readLines(file, Charset.forName("UTF-8"));
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for(String line : lines)
|
||||||
|
{
|
||||||
|
builder.append(line).append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.loadClaim(builder.toString(), out_parentID, file.lastModified(), claimID, Bukkit.getServer().getWorlds());
|
||||||
|
}
|
||||||
|
|
||||||
|
Claim loadClaim(String input, ArrayList<Long> out_parentID, long lastModifiedDate, long claimID, List<World> validWorlds) throws InvalidConfigurationException, Exception
|
||||||
|
{
|
||||||
|
Claim claim = null;
|
||||||
|
YamlConfiguration yaml = new YamlConfiguration();
|
||||||
|
yaml.loadFromString(input);
|
||||||
|
|
||||||
|
//boundaries
|
||||||
|
Location lesserBoundaryCorner = this.locationFromString(yaml.getString("Lesser Boundary Corner"), validWorlds);
|
||||||
|
Location greaterBoundaryCorner = this.locationFromString(yaml.getString("Greater Boundary Corner"), validWorlds);
|
||||||
|
|
||||||
|
//owner
|
||||||
|
String ownerIdentifier = yaml.getString("Owner");
|
||||||
|
UUID ownerID = null;
|
||||||
|
if(!ownerIdentifier.isEmpty())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ownerID = UUID.fromString(ownerIdentifier);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
GriefPrevention.AddLogEntry("Error - this is not a valid UUID: " + ownerIdentifier + ".");
|
||||||
|
GriefPrevention.AddLogEntry(" Converted land claim to administrative @ " + lesserBoundaryCorner.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> builders = yaml.getStringList("Builders");
|
||||||
|
|
||||||
|
List<String> containers = yaml.getStringList("Containers");
|
||||||
|
|
||||||
|
List<String> accessors = yaml.getStringList("Accessors");
|
||||||
|
|
||||||
|
List<String> managers = yaml.getStringList("Managers");
|
||||||
|
|
||||||
|
out_parentID.add(yaml.getLong("Parent Claim ID", -1L));
|
||||||
|
|
||||||
|
//instantiate
|
||||||
|
claim = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, ownerID, builders, containers, accessors, managers, claimID);
|
||||||
|
claim.modifiedDate = new Date(lastModifiedDate);
|
||||||
|
claim.id = claimID;
|
||||||
|
|
||||||
|
return claim;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getYamlForClaim(Claim claim)
|
||||||
|
{
|
||||||
|
YamlConfiguration yaml = new YamlConfiguration();
|
||||||
|
|
||||||
|
//boundaries
|
||||||
|
yaml.set("Lesser Boundary Corner", this.locationToString(claim.lesserBoundaryCorner));
|
||||||
|
yaml.set("Greater Boundary Corner", this.locationToString(claim.greaterBoundaryCorner));
|
||||||
|
|
||||||
|
//owner
|
||||||
|
String ownerID = "";
|
||||||
|
if(claim.ownerID != null) ownerID = claim.ownerID.toString();
|
||||||
|
yaml.set("Owner", ownerID);
|
||||||
|
|
||||||
|
ArrayList<String> builders = new ArrayList<String>();
|
||||||
|
ArrayList<String> containers = new ArrayList<String>();
|
||||||
|
ArrayList<String> accessors = new ArrayList<String>();
|
||||||
|
ArrayList<String> managers = new ArrayList<String>();
|
||||||
|
claim.getPermissions(builders, containers, accessors, managers);
|
||||||
|
|
||||||
|
yaml.set("Builders", builders);
|
||||||
|
yaml.set("Containers", containers);
|
||||||
|
yaml.set("Accessors", accessors);
|
||||||
|
yaml.set("Managers", managers);
|
||||||
|
|
||||||
|
Long parentID = -1L;
|
||||||
|
if(claim.parent != null)
|
||||||
|
{
|
||||||
|
parentID = claim.parent.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
yaml.set("Parent Claim ID", parentID);
|
||||||
|
|
||||||
|
return yaml.saveToString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized void writeClaimToStorage(Claim claim)
|
synchronized void writeClaimToStorage(Claim claim)
|
||||||
{
|
{
|
||||||
String claimID = String.valueOf(claim.id);
|
String claimID = String.valueOf(claim.id);
|
||||||
|
|
||||||
BufferedWriter outStream = null;
|
String yaml = this.getYamlForClaim(claim);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//open the claim's file
|
//open the claim's file
|
||||||
File claimFile = new File(claimDataFolderPath + File.separator + claimID);
|
File claimFile = new File(claimDataFolderPath + File.separator + claimID + ".yml");
|
||||||
claimFile.createNewFile();
|
claimFile.createNewFile();
|
||||||
outStream = new BufferedWriter(new FileWriter(claimFile));
|
Files.write(yaml.getBytes("UTF-8"), claimFile);
|
||||||
|
|
||||||
//write top level claim data to the file
|
|
||||||
this.writeClaimData(claim, outStream);
|
|
||||||
|
|
||||||
//for each subdivision
|
|
||||||
for(int i = 0; i < claim.children.size(); i++)
|
|
||||||
{
|
|
||||||
//write the subdivision's data to the file
|
|
||||||
this.writeClaimData(claim.children.get(i), outStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if any problem, log it
|
//if any problem, log it
|
||||||
|
|
@ -392,80 +571,16 @@ public class FlatFileDataStore extends DataStore
|
||||||
e.printStackTrace(new PrintWriter(errors));
|
e.printStackTrace(new PrintWriter(errors));
|
||||||
GriefPrevention.AddLogEntry(claimID + " " + errors.toString(), CustomLogEntryTypes.Exception);
|
GriefPrevention.AddLogEntry(claimID + " " + errors.toString(), CustomLogEntryTypes.Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
//close the file
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(outStream != null) outStream.close();
|
|
||||||
}
|
|
||||||
catch(IOException exception) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//actually writes claim data to an output stream
|
//deletes a claim from the file system
|
||||||
synchronized private void writeClaimData(Claim claim, BufferedWriter outStream) throws IOException
|
|
||||||
{
|
|
||||||
//first line is lesser boundary corner location
|
|
||||||
outStream.write(this.locationToString(claim.getLesserBoundaryCorner()));
|
|
||||||
outStream.newLine();
|
|
||||||
|
|
||||||
//second line is greater boundary corner location
|
|
||||||
outStream.write(this.locationToString(claim.getGreaterBoundaryCorner()));
|
|
||||||
outStream.newLine();
|
|
||||||
|
|
||||||
//third line is owner name
|
|
||||||
String lineToWrite = "";
|
|
||||||
if(claim.ownerID != null) lineToWrite = claim.ownerID.toString();
|
|
||||||
outStream.write(lineToWrite);
|
|
||||||
outStream.newLine();
|
|
||||||
|
|
||||||
ArrayList<String> builders = new ArrayList<String>();
|
|
||||||
ArrayList<String> containers = new ArrayList<String>();
|
|
||||||
ArrayList<String> accessors = new ArrayList<String>();
|
|
||||||
ArrayList<String> managers = new ArrayList<String>();
|
|
||||||
|
|
||||||
claim.getPermissions(builders, containers, accessors, managers);
|
|
||||||
|
|
||||||
//fourth line is list of players with build permission
|
|
||||||
for(int i = 0; i < builders.size(); i++)
|
|
||||||
{
|
|
||||||
outStream.write(builders.get(i) + ";");
|
|
||||||
}
|
|
||||||
outStream.newLine();
|
|
||||||
|
|
||||||
//fifth line is list of players with container permission
|
|
||||||
for(int i = 0; i < containers.size(); i++)
|
|
||||||
{
|
|
||||||
outStream.write(containers.get(i) + ";");
|
|
||||||
}
|
|
||||||
outStream.newLine();
|
|
||||||
|
|
||||||
//sixth line is list of players with access permission
|
|
||||||
for(int i = 0; i < accessors.size(); i++)
|
|
||||||
{
|
|
||||||
outStream.write(accessors.get(i) + ";");
|
|
||||||
}
|
|
||||||
outStream.newLine();
|
|
||||||
|
|
||||||
//seventh line is list of players who may grant permissions for others
|
|
||||||
for(int i = 0; i < managers.size(); i++)
|
|
||||||
{
|
|
||||||
outStream.write(managers.get(i) + ";");
|
|
||||||
}
|
|
||||||
outStream.newLine();
|
|
||||||
|
|
||||||
//cap each claim with "=========="
|
|
||||||
outStream.write("==========");
|
|
||||||
outStream.newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
//deletes a top level claim from the file system
|
|
||||||
@Override
|
@Override
|
||||||
synchronized void deleteClaimFromSecondaryStorage(Claim claim)
|
synchronized void deleteClaimFromSecondaryStorage(Claim claim)
|
||||||
{
|
{
|
||||||
String claimID = String.valueOf(claim.id);
|
String claimID = String.valueOf(claim.id);
|
||||||
|
|
||||||
//remove from disk
|
//remove from disk
|
||||||
File claimFile = new File(claimDataFolderPath + File.separator + claimID);
|
File claimFile = new File(claimDataFolderPath + File.separator + claimID + ".yml");
|
||||||
if(claimFile.exists() && !claimFile.delete())
|
if(claimFile.exists() && !claimFile.delete())
|
||||||
{
|
{
|
||||||
GriefPrevention.AddLogEntry("Error: Unable to delete claim file \"" + claimFile.getAbsolutePath() + "\".");
|
GriefPrevention.AddLogEntry("Error: Unable to delete claim file \"" + claimFile.getAbsolutePath() + "\".");
|
||||||
|
|
@ -671,6 +786,10 @@ public class FlatFileDataStore extends DataStore
|
||||||
{
|
{
|
||||||
Claim claim = this.claims.get(i);
|
Claim claim = this.claims.get(i);
|
||||||
databaseStore.addClaim(claim, true);
|
databaseStore.addClaim(claim, true);
|
||||||
|
for(Claim child : claim.children)
|
||||||
|
{
|
||||||
|
databaseStore.addClaim(child, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//migrate groups
|
//migrate groups
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,11 @@ public class PlayerData
|
||||||
for(int i = 0; i < dataStore.claims.size(); i++)
|
for(int i = 0; i < dataStore.claims.size(); i++)
|
||||||
{
|
{
|
||||||
Claim claim = dataStore.claims.get(i);
|
Claim claim = dataStore.claims.get(i);
|
||||||
|
if(!claim.inDataStore)
|
||||||
|
{
|
||||||
|
dataStore.claims.remove(i--);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if(playerID.equals(claim.ownerID))
|
if(playerID.equals(claim.ownerID))
|
||||||
{
|
{
|
||||||
this.claims.add(claim);
|
this.claims.add(claim);
|
||||||
|
|
@ -317,6 +322,7 @@ public class PlayerData
|
||||||
GriefPrevention.AddLogEntry("Total blocks: " + totalBlocks + " Total claimed area: " + totalClaimsArea, CustomLogEntryTypes.Debug, true);
|
GriefPrevention.AddLogEntry("Total blocks: " + totalBlocks + " Total claimed area: " + totalClaimsArea, CustomLogEntryTypes.Debug, true);
|
||||||
for(Claim claim : this.claims)
|
for(Claim claim : this.claims)
|
||||||
{
|
{
|
||||||
|
if(!claim.inDataStore) continue;
|
||||||
GriefPrevention.AddLogEntry(
|
GriefPrevention.AddLogEntry(
|
||||||
GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()) + " // "
|
GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()) + " // "
|
||||||
+ GriefPrevention.getfriendlyLocationString(claim.getGreaterBoundaryCorner()) + " = "
|
+ GriefPrevention.getfriendlyLocationString(claim.getGreaterBoundaryCorner()) + " = "
|
||||||
|
|
@ -341,6 +347,14 @@ public class PlayerData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < this.claims.size(); i++)
|
||||||
|
{
|
||||||
|
if(!claims.get(i).inDataStore)
|
||||||
|
{
|
||||||
|
claims.remove(i--);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return claims;
|
return claims;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2130,7 +2130,7 @@ class PlayerEventHandler implements Listener
|
||||||
Claim newClaim = new Claim(
|
Claim newClaim = new Claim(
|
||||||
new Location(oldClaim.getLesserBoundaryCorner().getWorld(), newx1, newy1, newz1),
|
new Location(oldClaim.getLesserBoundaryCorner().getWorld(), newx1, newy1, newz1),
|
||||||
new Location(oldClaim.getLesserBoundaryCorner().getWorld(), newx2, newy2, newz2),
|
new Location(oldClaim.getLesserBoundaryCorner().getWorld(), newx2, newy2, newz2),
|
||||||
null, new String[]{}, new String[]{}, new String[]{}, new String[]{}, null);
|
null, new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), null);
|
||||||
|
|
||||||
//if the new claim is smaller
|
//if the new claim is smaller
|
||||||
if(!newClaim.contains(oldClaim.getLesserBoundaryCorner(), true, false) || !newClaim.contains(oldClaim.getGreaterBoundaryCorner(), true, false))
|
if(!newClaim.contains(oldClaim.getLesserBoundaryCorner(), true, false) || !newClaim.contains(oldClaim.getGreaterBoundaryCorner(), true, false))
|
||||||
|
|
@ -2353,7 +2353,7 @@ class PlayerEventHandler implements Listener
|
||||||
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.ClaimStart);
|
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.ClaimStart);
|
||||||
|
|
||||||
//show him where he's working
|
//show him where he's working
|
||||||
Visualization visualization = Visualization.FromClaim(new Claim(clickedBlock.getLocation(), clickedBlock.getLocation(), null, new String[]{}, new String[]{}, new String[]{}, new String[]{}, null), clickedBlock.getY(), VisualizationType.RestoreNature, player.getLocation());
|
Visualization visualization = Visualization.FromClaim(new Claim(clickedBlock.getLocation(), clickedBlock.getLocation(), null, new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), null), clickedBlock.getY(), VisualizationType.RestoreNature, player.getLocation());
|
||||||
Visualization.Apply(player, visualization);
|
Visualization.Apply(player, visualization);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
package me.ryanhamshire.GriefPrevention;
|
package me.ryanhamshire.GriefPrevention;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
|
@ -112,7 +114,7 @@ class RestoreNatureExecutionTask implements Runnable
|
||||||
//show visualization to player who started the restoration
|
//show visualization to player who started the restoration
|
||||||
if(player != null)
|
if(player != null)
|
||||||
{
|
{
|
||||||
Claim claim = new Claim(lesserCorner, greaterCorner, null, new String[] {}, new String[] {}, new String[] {}, new String[] {}, null);
|
Claim claim = new Claim(lesserCorner, greaterCorner, null, new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), null);
|
||||||
Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature, player.getLocation());
|
Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature, player.getLocation());
|
||||||
Visualization.Apply(player, visualization);
|
Visualization.Apply(player, visualization);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ public class Visualization
|
||||||
player.sendBlockChange(element.location, element.realMaterial, element.realData);
|
player.sendBlockChange(element.location, element.realMaterial, element.realData);
|
||||||
}
|
}
|
||||||
|
|
||||||
playerData.currentVisualization = null;
|
playerData.currentVisualization = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +105,9 @@ public class Visualization
|
||||||
//add subdivisions first
|
//add subdivisions first
|
||||||
for(int i = 0; i < claim.children.size(); i++)
|
for(int i = 0; i < claim.children.size(); i++)
|
||||||
{
|
{
|
||||||
visualization.addClaimElements(claim.children.get(i), height, VisualizationType.Subdivision, locality);
|
Claim child = claim.children.get(i);
|
||||||
|
if(!child.inDataStore) continue;
|
||||||
|
visualization.addClaimElements(child, height, VisualizationType.Subdivision, locality);
|
||||||
}
|
}
|
||||||
|
|
||||||
//special visualization for administrative land claims
|
//special visualization for administrative land claims
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user