mirror of
https://github.com/taoneill/war.git
synced 2025-01-03 06:17:33 +01:00
Zone database structure update
Breaks backwards compatibility, but the material changes already did that so whatever. Replaces deprecated durability and tile entity serialisation with BlockData serialisation. Optimises space by caching all used type/data strings.
This commit is contained in:
parent
b24e495df7
commit
2af9379287
@ -12,7 +12,6 @@ import com.tommytony.war.job.LogKillsDeathsJob;
|
||||
import com.tommytony.war.job.LogKillsDeathsJob.KillsDeathsRecord;
|
||||
import com.tommytony.war.job.ZoneTimeJob;
|
||||
import com.tommytony.war.mapper.LoadoutYmlMapper;
|
||||
import com.tommytony.war.mapper.VolumeMapper;
|
||||
import com.tommytony.war.mapper.ZoneVolumeMapper;
|
||||
import com.tommytony.war.structure.*;
|
||||
import com.tommytony.war.utility.*;
|
||||
@ -2087,7 +2086,7 @@ public class Warzone {
|
||||
}
|
||||
|
||||
public Volume loadStructure(String volName, World world) throws SQLException {
|
||||
return loadStructure(volName, world, ZoneVolumeMapper.getZoneConnection(volume, name, world));
|
||||
return loadStructure(volName, world, ZoneVolumeMapper.getZoneConnection(volume, name));
|
||||
}
|
||||
|
||||
public Volume loadStructure(String volName, Connection zoneConnection) throws SQLException {
|
||||
@ -2096,12 +2095,6 @@ public class Warzone {
|
||||
|
||||
public Volume loadStructure(String volName, World world, Connection zoneConnection) throws SQLException {
|
||||
Volume volume = new Volume(volName, world);
|
||||
if (!containsTable(String.format("structure_%d_corners", volName.hashCode() & Integer.MAX_VALUE), zoneConnection)) {
|
||||
volume = VolumeMapper.loadVolume(volName, name, world);
|
||||
ZoneVolumeMapper.saveStructure(volume, zoneConnection);
|
||||
War.war.getLogger().log(Level.INFO, "Stuffed structure {0} into database for warzone {1}", new Object[] {volName, name});
|
||||
return volume;
|
||||
}
|
||||
ZoneVolumeMapper.loadStructure(volume, zoneConnection);
|
||||
return volume;
|
||||
}
|
||||
|
@ -1,15 +1,13 @@
|
||||
package com.tommytony.war.command;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
import com.tommytony.war.mapper.VolumeMapper;
|
||||
import com.tommytony.war.mapper.WarYmlMapper;
|
||||
import com.tommytony.war.structure.WarHub;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Deletes the warhub.
|
||||
@ -30,7 +28,7 @@ public class DeleteWarhubCommand extends AbstractWarAdminCommand {
|
||||
if (War.war.getWarHub() != null) {
|
||||
// reset existing hub
|
||||
War.war.getWarHub().getVolume().resetBlocks();
|
||||
VolumeMapper.delete(War.war.getWarHub().getVolume());
|
||||
VolumeMapper.deleteSimpleVolume(War.war.getWarHub().getVolume());
|
||||
War.war.setWarHub((WarHub) null);
|
||||
for (Warzone zone : War.war.getWarzones()) {
|
||||
if (zone.getLobby() != null) {
|
||||
|
@ -1,24 +1,25 @@
|
||||
package com.tommytony.war.job;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
import com.tommytony.war.mapper.ZoneVolumeMapper;
|
||||
import com.tommytony.war.structure.ZoneLobby;
|
||||
import com.tommytony.war.volume.ZoneVolume;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
import com.tommytony.war.structure.ZoneLobby;
|
||||
import com.tommytony.war.volume.ZoneVolume;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class PartialZoneResetJob extends BukkitRunnable implements Cloneable {
|
||||
|
||||
@ -61,7 +62,7 @@ public class PartialZoneResetJob extends BukkitRunnable implements Cloneable {
|
||||
public void run() {
|
||||
try {
|
||||
if (conn == null || conn.isClosed()) {
|
||||
conn = ZoneVolumeMapper.getZoneConnection(volume, zone.getName(), volume.getWorld());
|
||||
conn = ZoneVolumeMapper.getZoneConnection(volume, zone.getName());
|
||||
}
|
||||
if (completed >= total) {
|
||||
int airChanges = 0;
|
||||
|
@ -1,69 +0,0 @@
|
||||
package com.tommytony.war.job;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
import com.tommytony.war.mapper.VolumeMapper;
|
||||
import com.tommytony.war.structure.WarHub;
|
||||
import com.tommytony.war.volume.Volume;
|
||||
|
||||
public class RestoreWarhubJob implements Runnable {
|
||||
|
||||
private final String hubStr;
|
||||
|
||||
public RestoreWarhubJob(String hubStr) {
|
||||
this.hubStr = hubStr;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
String[] hubStrSplit = this.hubStr.split(",");
|
||||
|
||||
int hubX = Integer.parseInt(hubStrSplit[0]);
|
||||
int hubY = Integer.parseInt(hubStrSplit[1]);
|
||||
int hubZ = Integer.parseInt(hubStrSplit[2]);
|
||||
World world = null;
|
||||
String worldName;
|
||||
String hubOrientation = "west";
|
||||
if (hubStrSplit.length > 3) {
|
||||
worldName = hubStrSplit[3];
|
||||
world = War.war.getServer().getWorld(worldName);
|
||||
if (hubStrSplit.length > 4) {
|
||||
hubOrientation = hubStrSplit[4];
|
||||
}
|
||||
} else {
|
||||
worldName = "DEFAULT";
|
||||
world = War.war.getServer().getWorlds().get(0); // default to first world
|
||||
}
|
||||
if (world != null) {
|
||||
Location hubLocation = new Location(world, hubX, hubY, hubZ);
|
||||
WarHub hub = new WarHub(hubLocation, hubOrientation);
|
||||
War.war.setWarHub(hub);
|
||||
Volume vol;
|
||||
try {
|
||||
vol = VolumeMapper.loadVolume("warhub", "", world);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
hub.setVolume(vol);
|
||||
hub.getVolume().resetBlocks();
|
||||
hub.initialize();
|
||||
|
||||
// In the previous job started by the mapper, warzones were created, but their lobbies are missing the war hub gate (because it didn't exist yet)
|
||||
for (Warzone zone : War.war.getWarzones()) {
|
||||
if (zone.getLobby() != null) {
|
||||
zone.getLobby().getVolume().resetBlocks();
|
||||
zone.getLobby().initialize();
|
||||
}
|
||||
}
|
||||
War.war.log("Warhub ready.", Level.INFO);
|
||||
} else {
|
||||
War.war.log("Failed to restore warhub. The specified world (name: " + worldName + ") does not exist!", Level.WARNING);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +1,16 @@
|
||||
package com.tommytony.war.job;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
import com.tommytony.war.mapper.VolumeMapper;
|
||||
import com.tommytony.war.structure.WarHub;
|
||||
import com.tommytony.war.volume.Volume;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class RestoreYmlWarhubJob implements Runnable {
|
||||
|
||||
@ -54,7 +52,7 @@ public class RestoreYmlWarhubJob implements Runnable {
|
||||
War.war.setWarHub(hub);
|
||||
Volume vol;
|
||||
try {
|
||||
vol = VolumeMapper.loadVolume("warhub", "", world);
|
||||
vol = VolumeMapper.loadSimpleVolume("warhub", world);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
package com.tommytony.war.job;
|
||||
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.mapper.ZoneVolumeMapper;
|
||||
import com.tommytony.war.volume.Volume;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class ZoneVolumeSaveJob extends BukkitRunnable {
|
||||
private final Volume volume;
|
||||
private final String zoneName;
|
||||
|
||||
public ZoneVolumeSaveJob(Volume volume, String zoneName) {
|
||||
this.volume = volume;
|
||||
this.zoneName = zoneName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ZoneVolumeMapper.save(this.volume, this.zoneName);
|
||||
} catch (SQLException ex) {
|
||||
War.war.log(ex.getMessage(), Level.SEVERE);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,407 +0,0 @@
|
||||
package com.tommytony.war.mapper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Used for accessing and creating .[properties] files, reads them as utf-8, saves as utf-8. Internationalization is key importance especially for character codes.
|
||||
*
|
||||
* @author Nijikokun
|
||||
* @version 1.0.4, %G%
|
||||
*/
|
||||
public final class PropertiesFile {
|
||||
|
||||
private static final Logger log = Logger.getLogger("Minecraft");
|
||||
private String fileName;
|
||||
private Properties props = new Properties();
|
||||
private FileInputStream inputStream;
|
||||
private FileOutputStream outputStream;
|
||||
|
||||
// private List<String> lines = new ArrayList<String>();
|
||||
// private Map<String, String> props = new HashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Creates or opens a properties file using specified filename
|
||||
*
|
||||
* @param fileName
|
||||
*/
|
||||
public PropertiesFile(String fileName) {
|
||||
this.fileName = fileName;
|
||||
|
||||
File file = new File(fileName);
|
||||
|
||||
try {
|
||||
if (file.exists()) {
|
||||
this.load();
|
||||
} else {
|
||||
this.save();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
PropertiesFile.log.severe("[PropertiesFile] Unable to load " + fileName + "!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The loader for property files, it reads the file as UTF8 or converts the string into UTF8. Used for simple runthrough's, loading, or reloading of the file.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void load() throws IOException {
|
||||
this.inputStream = new FileInputStream(this.fileName);
|
||||
this.props.load(this.inputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out the <code>key=value</code> properties that were changed into a .[properties] file in UTF8.
|
||||
*/
|
||||
public void save() {
|
||||
try {
|
||||
this.outputStream = new FileOutputStream(this.fileName);
|
||||
this.props.store(this.outputStream, null);
|
||||
} catch (IOException ex) {
|
||||
PropertiesFile.log.severe("[PropertiesFile] Unable to save " + this.fileName + "!");
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (this.outputStream != null) {
|
||||
try {
|
||||
this.outputStream.close();
|
||||
} catch (IOException e) {
|
||||
PropertiesFile.log.severe("[PropertiesFile] Failed to close " + this.fileName + " writer!");
|
||||
}
|
||||
} else if (this.inputStream != null) {
|
||||
try {
|
||||
this.inputStream.close();
|
||||
} catch (IOException e) {
|
||||
PropertiesFile.log.severe("[PropertiesFile] Failed to close " + this.fileName + " reader!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Map of all <code>key=value</code> properties in the file as <code><key (java.lang.String), value (java.lang.String)></code> <br />
|
||||
* <br />
|
||||
* Example: <blockquote>
|
||||
*
|
||||
* <pre>
|
||||
* PropertiesFile settings = new PropertiesFile("settings.properties");
|
||||
* Map<String, String> mappedSettings;
|
||||
*
|
||||
* try {
|
||||
* mappedSettings = settings.returnMap();
|
||||
* } catch (Exception ex) {
|
||||
* log.info("Failed mapping settings.properties");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* @return <code>map</code> - Simple Map HashMap of the entire <code>key=value</code> as <code><key (java.lang.String), value (java.lang.String)></code>
|
||||
* @throws Exception
|
||||
* If the properties file doesn't exist.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String> returnMap() throws Exception {
|
||||
return (Map<String, String>) this.props.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the .[properties] file contains the given <code>key</code>.
|
||||
*
|
||||
* @param var
|
||||
* The key we are going to be checking the existance of.
|
||||
* @return <code>Boolean</code> - True if the <code>key</code> exists, false if it cannot be found.
|
||||
*/
|
||||
public boolean containsKey(String var) {
|
||||
return this.props.containsKey(var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if this <code>key</code> exists in the .[properties] file.
|
||||
*
|
||||
* @param var
|
||||
* The key we are grabbing the value of.
|
||||
* @return <code>java.lang.String</code> - True if the <code>key</code> exists, false if it cannot be found.
|
||||
*/
|
||||
public String getProperty(String var) {
|
||||
return this.props.getProperty(var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a key from the file if it exists. This will save() which will invoke a load() on the file.
|
||||
*
|
||||
* @see #save()
|
||||
* @param var
|
||||
* The <code>key</code> that will be removed from the file
|
||||
*/
|
||||
public void removeKey(String var) {
|
||||
if (this.props.containsKey(var)) {
|
||||
this.props.remove(var);
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the existance of a <code>key</code>.
|
||||
*
|
||||
* @see #containsKey(java.lang.String)
|
||||
* @param key
|
||||
* The <code>key</code> in question of existance.
|
||||
* @return <code>Boolean</code> - True for existance, false for <code>key</code> found.
|
||||
*/
|
||||
public boolean keyExists(String key) {
|
||||
return this.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <code>key</code> given as a <code>String</code>, however we do not set a string if no <code>key</code> is found.
|
||||
*
|
||||
* @see #getProperty(java.lang.String)
|
||||
* @param key
|
||||
* The <code>key</code> we will retrieve the property from, if no <code>key</code> is found default to "" or empty.
|
||||
*/
|
||||
public String getString(String key) {
|
||||
if (this.containsKey(key)) {
|
||||
return this.getProperty(key);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <code>key</code> given as a <code>String</code>. If it is not found, it will invoke saving the default <code>value</code> to the properties file.
|
||||
*
|
||||
* @see #setString(java.lang.String, java.lang.String)
|
||||
* @see #getProperty(java.lang.String)
|
||||
* @param key
|
||||
* The key that we will be grabbing the value from, if no value is found set and return <code>value</code>
|
||||
* @param value
|
||||
* The default value that we will be setting if no prior <code>key</code> is found.
|
||||
* @return java.lang.String Either we will return the default value or a prior existing value depending on existance.
|
||||
*/
|
||||
public String getString(String key, String value) {
|
||||
if (this.containsKey(key)) {
|
||||
return this.getProperty(key);
|
||||
}
|
||||
|
||||
this.setString(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the value given as a <code>String</code> on the specified key.
|
||||
*
|
||||
* @see #save()
|
||||
* @param key
|
||||
* The <code>key</code> that we will be addressing the <code>value</code> to.
|
||||
* @param value
|
||||
* The <code>value</code> we will be setting inside the <code>.[properties]</code> file.
|
||||
*/
|
||||
public void setString(String key, String value) {
|
||||
this.props.put(key, value);
|
||||
this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <code>key</code> given in a Integer, however we do not set a string if no <code>key</code> is found.
|
||||
*
|
||||
* @see #getProperty(String var)
|
||||
* @param key
|
||||
* The <code>key</code> we will retrieve the property from, if no <code>key</code> is found default to 0
|
||||
*/
|
||||
public int getInt(String key) {
|
||||
if (this.containsKey(key)) {
|
||||
return Integer.parseInt(this.getProperty(key));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the int value of a key
|
||||
*
|
||||
* @see #setInt(String key, int value)
|
||||
* @param key
|
||||
* The key that we will be grabbing the value from, if no value is found set and return <code>value</code>
|
||||
* @param value
|
||||
* The default value that we will be setting if no prior <code>key</code> is found.
|
||||
* @return <code>Integer</code> - Either we will return the default value or a prior existing value depending on existance.
|
||||
*/
|
||||
public int getInt(String key, int value) {
|
||||
if (this.containsKey(key)) {
|
||||
return Integer.parseInt(this.getProperty(key));
|
||||
}
|
||||
|
||||
this.setInt(key, value);
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the value given as a <code>int</code> on the specified key.
|
||||
*
|
||||
* @see #save()
|
||||
* @param key
|
||||
* The <code>key</code> that we will be addressing the <code>value</code> to.
|
||||
* @param value
|
||||
* The <code>value</code> we will be setting inside the <code>.[properties]</code> file.
|
||||
*/
|
||||
public void setInt(String key, int value) {
|
||||
this.props.put(key, String.valueOf(value));
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <code>key</code> given in a Double, however we do not set a string if no <code>key</code> is found.
|
||||
*
|
||||
* @see #getProperty(String var)
|
||||
* @param key
|
||||
* The <code>key</code> we will retrieve the property from, if no <code>key</code> is found default to 0.0
|
||||
*/
|
||||
public double getDouble(String key) {
|
||||
if (this.containsKey(key)) {
|
||||
return Double.parseDouble(this.getProperty(key));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the double value of a key
|
||||
*
|
||||
* @see #setDouble(String key, double value)
|
||||
* @param key
|
||||
* The key that we will be grabbing the value from, if no value is found set and return <code>value</code>
|
||||
* @param value
|
||||
* The default value that we will be setting if no prior <code>key</code> is found.
|
||||
* @return <code>Double</code> - Either we will return the default value or a prior existing value depending on existance.
|
||||
*/
|
||||
public double getDouble(String key, double value) {
|
||||
if (this.containsKey(key)) {
|
||||
return Double.parseDouble(this.getProperty(key));
|
||||
}
|
||||
|
||||
this.setDouble(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the value given as a <code>double</code> on the specified key.
|
||||
*
|
||||
* @see #save()
|
||||
* @param key
|
||||
* The <code>key</code> that we will be addressing the <code>value</code> to.
|
||||
* @param value
|
||||
* The <code>value</code> we will be setting inside the <code>.[properties]</code> file.
|
||||
*/
|
||||
public void setDouble(String key, double value) {
|
||||
this.props.put(key, String.valueOf(value));
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <code>key</code> given in a Long, however we do not set a string if no <code>key</code> is found.
|
||||
*
|
||||
* @see #getProperty(String var)
|
||||
* @param key
|
||||
* The <code>key</code> we will retrieve the property from, if no <code>key</code> is found default to 0L
|
||||
*/
|
||||
public long getLong(String key) {
|
||||
if (this.containsKey(key)) {
|
||||
return Long.parseLong(this.getProperty(key));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long value of a key
|
||||
*
|
||||
* @see #setLong(String key, long value)
|
||||
* @param key
|
||||
* The key that we will be grabbing the value from, if no value is found set and return <code>value</code>
|
||||
* @param value
|
||||
* The default value that we will be setting if no prior <code>key</code> is found.
|
||||
* @return <code>Long</code> - Either we will return the default value or a prior existing value depending on existance.
|
||||
*/
|
||||
public long getLong(String key, long value) {
|
||||
if (this.containsKey(key)) {
|
||||
return Long.parseLong(this.getProperty(key));
|
||||
}
|
||||
|
||||
this.setLong(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the value given as a <code>long</code> on the specified key.
|
||||
*
|
||||
* @see #save()
|
||||
* @param key
|
||||
* The <code>key</code> that we will be addressing the <code>value</code> to.
|
||||
* @param value
|
||||
* The <code>value</code> we will be setting inside the <code>.[properties]</code> file.
|
||||
*/
|
||||
public void setLong(String key, long value) {
|
||||
this.props.put(key, String.valueOf(value));
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <code>key</code> given in a Boolean, however we do not set a string if no <code>key</code> is found.
|
||||
*
|
||||
* @see #getProperty(String var)
|
||||
* @param key
|
||||
* The <code>key</code> we will retrieve the property from, if no <code>key</code> is found default to false
|
||||
*/
|
||||
public boolean getBoolean(String key) {
|
||||
if (this.containsKey(key)) {
|
||||
return Boolean.parseBoolean(this.getProperty(key));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the boolean value of a key
|
||||
*
|
||||
* @see #setBoolean(String key, boolean value)
|
||||
* @param key
|
||||
* The key that we will be grabbing the value from, if no value is found set and return <code>value</code>
|
||||
* @param value
|
||||
* The default value that we will be setting if no prior <code>key</code> is found.
|
||||
* @return <code>Boolean</code> - Either we will return the default value or a prior existing value depending on existance.
|
||||
*/
|
||||
public boolean getBoolean(String key, boolean value) {
|
||||
if (this.containsKey(key)) {
|
||||
return Boolean.parseBoolean(this.getProperty(key));
|
||||
}
|
||||
|
||||
this.setBoolean(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the value given as a <code>boolean</code> on the specified key.
|
||||
*
|
||||
* @see #save()
|
||||
* @param key
|
||||
* The <code>key</code> that we will be addressing the <code>value</code> to.
|
||||
* @param value
|
||||
* The <code>value</code> we will be setting inside the <code>.[properties]</code> file.
|
||||
*/
|
||||
public void setBoolean(String key, boolean value) {
|
||||
this.props.put(key, String.valueOf(value));
|
||||
|
||||
this.save();
|
||||
}
|
||||
}
|
@ -2,15 +2,20 @@ package com.tommytony.war.mapper;
|
||||
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.volume.Volume;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
@ -20,43 +25,13 @@ import java.util.logging.Level;
|
||||
*/
|
||||
public class VolumeMapper {
|
||||
|
||||
public static Volume loadVolume(String volumeName, String zoneName, World world) throws SQLException {
|
||||
Volume volume = new Volume(volumeName, world);
|
||||
VolumeMapper.load(volume, zoneName, world);
|
||||
return volume;
|
||||
}
|
||||
protected static final String delim = "-------mcwar iSdgraIyMvOanTEJjZgocczfuG------";
|
||||
protected static final int DATABASE_VERSION = 3;
|
||||
|
||||
public static void load(Volume volume, String zoneName, World world) throws SQLException {
|
||||
File databaseFile = new File(War.war.getDataFolder(), String.format(
|
||||
"/dat/volume-%s.sl3", volume.getName()));
|
||||
if (!zoneName.isEmpty()) {
|
||||
databaseFile = new File(War.war.getDataFolder(),
|
||||
String.format("/dat/warzone-%s/volume-%s.sl3", zoneName,
|
||||
volume.getName()));
|
||||
}
|
||||
if (!databaseFile.exists()) {
|
||||
// dropped nimitz compatibility with the MC 1.13 update
|
||||
War.war.log("Volume " + volume.getName() + " for zone " + zoneName + " not found. Will not attempt converting legacy War version formats.", Level.WARNING);
|
||||
return;
|
||||
}
|
||||
Connection databaseConnection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getPath());
|
||||
public static void loadCorners(Connection databaseConnection, Volume volume, World world, String prefix) throws SQLException {
|
||||
Validate.isTrue(!databaseConnection.isClosed());
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
ResultSet versionQuery = stmt.executeQuery("PRAGMA user_version");
|
||||
int version = versionQuery.getInt("user_version");
|
||||
versionQuery.close();
|
||||
if (version > DATABASE_VERSION) {
|
||||
try {
|
||||
throw new IllegalStateException("Unsupported zone format " + version);
|
||||
} finally {
|
||||
stmt.close();
|
||||
databaseConnection.close();
|
||||
}
|
||||
} else if (version < DATABASE_VERSION) {
|
||||
switch (version) {
|
||||
// Run some update SQL for each old version
|
||||
}
|
||||
}
|
||||
ResultSet cornerQuery = stmt.executeQuery("SELECT * FROM corners");
|
||||
ResultSet cornerQuery = stmt.executeQuery("SELECT * FROM " + prefix + "corners");
|
||||
cornerQuery.next();
|
||||
final Block corner1 = world.getBlockAt(cornerQuery.getInt("x"), cornerQuery.getInt("y"), cornerQuery.getInt("z"));
|
||||
cornerQuery.next();
|
||||
@ -64,40 +39,153 @@ public class VolumeMapper {
|
||||
cornerQuery.close();
|
||||
volume.setCornerOne(corner1);
|
||||
volume.setCornerTwo(corner2);
|
||||
ResultSet query = stmt.executeQuery("SELECT * FROM blocks");
|
||||
stmt.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given volume
|
||||
*
|
||||
* @param databaseConnection Open connection to zone database
|
||||
* @param volume Volume to load
|
||||
* @param start Starting position to load blocks at
|
||||
* @param total Amount of blocks to read
|
||||
* @return Changed blocks
|
||||
* @throws SQLException Error communicating with SQLite3 database
|
||||
*/
|
||||
public static int loadBlocks(Connection databaseConnection, Volume volume, int start, int total, boolean[][][] changes, boolean inMemory, String prefix) throws SQLException {
|
||||
Validate.isTrue(!databaseConnection.isClosed());
|
||||
if (inMemory) {
|
||||
volume.getBlocks().clear();
|
||||
}
|
||||
final Block corner1 = volume.getCornerOne().getBlock();
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
Map<Integer, String> stringCache = new HashMap<>();
|
||||
stringCache.put(0, null);
|
||||
ResultSet cacheQuery = stmt.executeQuery("SELECT * FROM "+ prefix +"strings");
|
||||
while (cacheQuery.next()) {
|
||||
stringCache.put(cacheQuery.getInt("id"), cacheQuery.getString("type"));
|
||||
}
|
||||
cacheQuery.close();
|
||||
int minX = volume.getMinX(), minY = volume.getMinY(), minZ = volume.getMinZ();
|
||||
int changed = 0;
|
||||
ResultSet query = stmt.executeQuery("SELECT * FROM "+ prefix + "blocks ORDER BY rowid LIMIT " + start + ", " + total);
|
||||
while (query.next()) {
|
||||
int x = query.getInt("x"), y = query.getInt("y"), z = query.getInt("z");
|
||||
BlockState modify = corner1.getRelative(x, y, z).getState();
|
||||
ItemStack data = new ItemStack(Material.valueOf(query.getString("type")), 0, query.getShort("data"));
|
||||
modify.setType(data.getType());
|
||||
modify.setData(data.getData());
|
||||
volume.getBlocks().add(modify);
|
||||
changed++;
|
||||
Block relative = corner1.getRelative(x, y, z);
|
||||
int xi = relative.getX() - minX, yi = relative.getY() - minY, zi = relative.getZ() - minZ;
|
||||
if (changes != null) {
|
||||
changes[xi][yi][zi] = true;
|
||||
}
|
||||
BlockState modify = relative.getState();
|
||||
String type = stringCache.get(query.getInt("type"));
|
||||
String data = stringCache.get(query.getInt("data"));
|
||||
|
||||
Material mat = Material.getMaterial(type);
|
||||
if (mat == null) {
|
||||
War.war.getLogger().log(Level.WARNING, "Failed to parse block type. x:" + x + " y:" + y + " z:" + z + " type:" + type + " data:" + data);
|
||||
continue;
|
||||
}
|
||||
BlockData bdata = null;
|
||||
try {
|
||||
if (data != null) {
|
||||
bdata = mat.createBlockData(data);
|
||||
}
|
||||
} catch (IllegalArgumentException iae) {
|
||||
War.war.getLogger().log(Level.WARNING, "Exception loading some tile data. x:" + x + " y:" + y + " z:" + z + " type:" + type + " data:" + data, iae);
|
||||
}
|
||||
|
||||
if (inMemory) {
|
||||
modify.setType(mat);
|
||||
if (bdata != null) {
|
||||
modify.setBlockData(bdata);
|
||||
}
|
||||
volume.getBlocks().add(modify);
|
||||
} else {
|
||||
if (modify.getType() != mat || (bdata != null && !modify.getBlockData().equals(bdata))) {
|
||||
// Update the type & data if it has changed
|
||||
modify.setType(mat);
|
||||
if (bdata != null) {
|
||||
modify.setBlockData(bdata);
|
||||
}
|
||||
modify.update(true, false); // No-physics update, preventing the need for deferring blocks
|
||||
}
|
||||
}
|
||||
}
|
||||
query.close();
|
||||
stmt.close();
|
||||
databaseConnection.close();
|
||||
return changed;
|
||||
}
|
||||
|
||||
public static final int DATABASE_VERSION = 1;
|
||||
public static void save(Volume volume, String zoneName) throws SQLException {
|
||||
File databaseFile = new File(War.war.getDataFolder(), String.format(
|
||||
"/dat/volume-%s.sl3", volume.getName()));
|
||||
if (!zoneName.isEmpty()) {
|
||||
databaseFile = new File(War.war.getDataFolder(),
|
||||
String.format("/dat/warzone-%s/volume-%s.sl3", zoneName,
|
||||
volume.getName()));
|
||||
/**
|
||||
* Load saved entities.
|
||||
*
|
||||
* @param databaseConnection Open databaseConnection to warzone DB file.
|
||||
* @param volume Volume for warzone.
|
||||
* @return number affected
|
||||
* @throws SQLException SQLite error
|
||||
*/
|
||||
public static int loadEntities(Connection databaseConnection, Volume volume) throws SQLException {
|
||||
Validate.isTrue(!databaseConnection.isClosed());
|
||||
// first, clear entities from the area
|
||||
for (Entity e : volume.getWorld().getEntitiesByClass(Hanging.class)) {
|
||||
if (volume.contains(e.getLocation())) {
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
Connection databaseConnection = DriverManager
|
||||
.getConnection("jdbc:sqlite:" + databaseFile.getPath());
|
||||
int changed = 0;
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
final Block corner1 = volume.getCornerOne().getBlock();
|
||||
Location test = new Location(volume.getWorld(), 0, 253, 0); // admins pls don't build stuff here kthx
|
||||
ResultSet query = stmt.executeQuery("SELECT * FROM entities ORDER BY rowid");
|
||||
while (query.next()) {
|
||||
double x = query.getDouble("x"), y = query.getDouble("y"), z = query.getDouble("z");
|
||||
changed++;
|
||||
// translate from relative DB location to absolute
|
||||
Location absolute = corner1.getLocation().clone().add(x, y, z);
|
||||
int type = query.getInt("type");
|
||||
String facing = query.getString("facing");
|
||||
String metadata = query.getString("metadata");
|
||||
BlockFace face = BlockFace.valueOf(facing);
|
||||
|
||||
// Spawn the paintings in the sky somewhere, works because I can only get them to spawn north/south
|
||||
test.getBlock().setType(Material.AIR);
|
||||
test.add(2, 0, 0).getBlock().setType(Material.STONE);
|
||||
|
||||
try {
|
||||
if (type == 1) {
|
||||
Painting p = (Painting) volume.getWorld().spawnEntity(test.clone().add(0, 0, 1), EntityType.PAINTING);
|
||||
Art art = Art.valueOf(metadata);
|
||||
p.teleport(calculatePainting(art, face, absolute));
|
||||
p.setFacingDirection(face, true);
|
||||
p.setArt(art, true);
|
||||
} else if (type == 2) {
|
||||
ItemFrame itemFrame = (ItemFrame) volume.getWorld().spawnEntity(test.clone().add(0, 0, 1), EntityType.ITEM_FRAME);
|
||||
itemFrame.teleport(absolute);
|
||||
itemFrame.setFacingDirection(face, true);
|
||||
String[] args = metadata.split(delim);
|
||||
itemFrame.setRotation(Rotation.valueOf(args[0]));
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
config.loadFromString(args[1]);
|
||||
itemFrame.setItem(config.getItemStack("item"));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
War.war.getLogger().log(Level.WARNING, "Exception loading entity. x:" + x + " y:" + y + " z:" + z + " type:" + type, ex);
|
||||
}
|
||||
}
|
||||
test.getBlock().setType(Material.AIR);
|
||||
query.close();
|
||||
stmt.close();
|
||||
return changed;
|
||||
}
|
||||
|
||||
public static void saveCorners(Connection databaseConnection, Volume volume, String prefix) throws SQLException {
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
stmt.executeUpdate("PRAGMA user_version = " + DATABASE_VERSION);
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS blocks (x BIGINT, y BIGINT, z BIGINT, type TEXT, data SMALLINT)");
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS corners (pos INTEGER PRIMARY KEY NOT NULL UNIQUE, x INTEGER NOT NULL, y INTEGER NOT NULL, z INTEGER NOT NULL)");
|
||||
stmt.executeUpdate("DELETE FROM blocks");
|
||||
stmt.executeUpdate("DELETE FROM corners");
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS "+prefix+"corners (pos INTEGER PRIMARY KEY NOT NULL UNIQUE, x INTEGER NOT NULL, y INTEGER NOT NULL, z INTEGER NOT NULL)");
|
||||
stmt.executeUpdate("DELETE FROM "+prefix+"corners");
|
||||
stmt.close();
|
||||
PreparedStatement cornerStmt = databaseConnection
|
||||
.prepareStatement("INSERT INTO corners SELECT 1 AS pos, ? AS x, ? AS y, ? AS z UNION SELECT 2, ?, ?, ?");
|
||||
PreparedStatement cornerStmt = databaseConnection.prepareStatement("INSERT INTO corners SELECT 1 AS pos, ? AS x, ? AS y, ? AS z UNION SELECT 2, ?, ?, ?");
|
||||
cornerStmt.setInt(1, volume.getCornerOne().getBlockX());
|
||||
cornerStmt.setInt(2, volume.getCornerOne().getBlockY());
|
||||
cornerStmt.setInt(3, volume.getCornerOne().getBlockZ());
|
||||
@ -106,37 +194,262 @@ public class VolumeMapper {
|
||||
cornerStmt.setInt(6, volume.getCornerTwo().getBlockZ());
|
||||
cornerStmt.executeUpdate();
|
||||
cornerStmt.close();
|
||||
PreparedStatement dataStmt = databaseConnection
|
||||
.prepareStatement("INSERT INTO blocks VALUES (?, ?, ?, ?, ?)");
|
||||
databaseConnection.setAutoCommit(false);
|
||||
final int batchSize = 1000;
|
||||
}
|
||||
|
||||
public static int saveEntities(Connection databaseConnection, Volume volume) throws SQLException {
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS entities (x NUMERIC, y NUMERIC, z NUMERIC, type SMALLINT, facing TEXT, metadata TEXT)");
|
||||
stmt.executeUpdate("DELETE FROM entities");
|
||||
stmt.close();
|
||||
PreparedStatement entityStmt = databaseConnection.prepareStatement("INSERT INTO entities (x, y, z, type, facing, metadata) VALUES (?, ?, ?, ?, ?, ?)");
|
||||
int i = 0;
|
||||
for (Entity e : volume.getWorld().getEntities()) {
|
||||
if (volume.contains(e.getLocation()) && e instanceof Hanging) {
|
||||
entityStmt.setDouble(1, e.getLocation().getX() - volume.getCornerOne().getBlockX());
|
||||
entityStmt.setDouble(2, e.getLocation().getY() - volume.getCornerOne().getBlockY());
|
||||
entityStmt.setDouble(3, e.getLocation().getZ() - volume.getCornerOne().getBlockZ());
|
||||
entityStmt.setString(5, ((Hanging) e).getFacing().name());
|
||||
if (e instanceof Painting) {
|
||||
Painting p = (Painting) e;
|
||||
entityStmt.setInt(4, 1);
|
||||
entityStmt.setString(6, p.getArt().name());
|
||||
} else if (e instanceof ItemFrame) {
|
||||
ItemFrame itemFrame = (ItemFrame) e;
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
config.set("item", itemFrame.getItem());
|
||||
entityStmt.setInt(4, 2);
|
||||
entityStmt.setString(6, itemFrame.getRotation().name() + delim + config.saveToString());
|
||||
} else {
|
||||
entityStmt.setInt(4, 0);
|
||||
entityStmt.setString(6, "");
|
||||
}
|
||||
entityStmt.addBatch();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
entityStmt.executeBatch();
|
||||
entityStmt.close();
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int saveBlocks(Connection databaseConnection, Volume volume, String prefix) throws SQLException {
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS "+prefix+"blocks (x BIGINT, y BIGINT, z BIGINT, type BIGINT, data BIGINT)");
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS "+prefix+"strings (id INTEGER PRIMARY KEY NOT NULL UNIQUE, type TEXT)");
|
||||
stmt.executeUpdate("DELETE FROM "+prefix+"blocks");
|
||||
stmt.executeUpdate("DELETE FROM "+prefix+"strings");
|
||||
stmt.close();
|
||||
Map<String, Integer> stringCache = new HashMap<>();
|
||||
int cachei = 1;
|
||||
int changed = 0;
|
||||
for (BlockState block : volume.getBlocks()) {
|
||||
final Location relLoc = ZoneVolumeMapper.rebase(
|
||||
volume.getCornerOne(), block.getLocation());
|
||||
dataStmt.setInt(1, relLoc.getBlockX());
|
||||
dataStmt.setInt(2, relLoc.getBlockY());
|
||||
dataStmt.setInt(3, relLoc.getBlockZ());
|
||||
dataStmt.setString(4, block.getType().toString());
|
||||
dataStmt.setShort(5, block.getData().toItemStack(1).getDurability());
|
||||
dataStmt.addBatch();
|
||||
if (++changed % batchSize == 0) {
|
||||
dataStmt.executeBatch();
|
||||
long startTime = System.currentTimeMillis();
|
||||
PreparedStatement dataStmt = databaseConnection.prepareStatement("INSERT INTO "+prefix+"blocks (x, y, z, type, data) VALUES (?, ?, ?, ?, ?)");
|
||||
databaseConnection.setAutoCommit(false);
|
||||
final int batchSize = 10000;
|
||||
for (int i = 0, x = volume.getMinX(); i < volume.getSizeX(); i++, x++) {
|
||||
for (int j = 0, y = volume.getMinY(); j < volume.getSizeY(); j++, y++) {
|
||||
for (int k = 0, z = volume.getMinZ(); k < volume.getSizeZ(); k++, z++) {
|
||||
// Make sure we are using zone volume-relative coords
|
||||
final Block block = volume.getWorld().getBlockAt(x, y, z);
|
||||
if (block.getType() == Material.AIR) {
|
||||
continue; // Do not save air blocks to the file anymore.
|
||||
}
|
||||
int typeid, dataid;
|
||||
// Save even more space by writing each string only once
|
||||
if (stringCache.containsKey(block.getType().name())) {
|
||||
typeid = stringCache.get(block.getType().name());
|
||||
} else {
|
||||
typeid = cachei;
|
||||
stringCache.put(block.getType().name(), cachei++);
|
||||
}
|
||||
// Save new-style data
|
||||
if (BlockData.class.isAssignableFrom(block.getType().data)) {
|
||||
String data = block.getBlockData().getAsString();
|
||||
if (stringCache.containsKey(data)) {
|
||||
dataid = stringCache.get(data);
|
||||
} else {
|
||||
dataid = cachei;
|
||||
stringCache.put(data, cachei++);
|
||||
}
|
||||
} else {
|
||||
dataid = 0;
|
||||
}
|
||||
|
||||
dataStmt.setInt(1, block.getX() - volume.getCornerOne().getBlockX());
|
||||
dataStmt.setInt(2, block.getY() - volume.getCornerOne().getBlockY());
|
||||
dataStmt.setInt(3, block.getZ() - volume.getCornerOne().getBlockZ());
|
||||
dataStmt.setInt(4, typeid);
|
||||
dataStmt.setInt(5, dataid);
|
||||
|
||||
dataStmt.addBatch();
|
||||
|
||||
if (++changed % batchSize == 0) {
|
||||
dataStmt.executeBatch();
|
||||
if ((System.currentTimeMillis() - startTime) >= 5000L) {
|
||||
String seconds = new DecimalFormat("#0.00").format((double) (System.currentTimeMillis() - startTime) / 1000.0D);
|
||||
War.war.getLogger().log(Level.FINE, "Still saving volume {0} , {1} seconds elapsed.", new Object[] {volume.getName(), seconds});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dataStmt.executeBatch(); // insert remaining records
|
||||
databaseConnection.commit();
|
||||
dataStmt.close();
|
||||
databaseConnection.close();
|
||||
PreparedStatement stringStmt = databaseConnection.prepareStatement("INSERT INTO "+prefix+"strings (id, type) VALUES (?, ?)");
|
||||
for (Map.Entry<String, Integer> mapping : stringCache.entrySet()) {
|
||||
stringStmt.setInt(1, mapping.getValue());
|
||||
stringStmt.setString(2, mapping.getKey());
|
||||
stringStmt.addBatch();
|
||||
}
|
||||
stringStmt.executeBatch();
|
||||
databaseConnection.commit();
|
||||
databaseConnection.setAutoCommit(true);
|
||||
return changed;
|
||||
|
||||
}
|
||||
|
||||
public static void delete(Volume volume) {
|
||||
File volFile = new File(War.war.getDataFolder(), String.format(
|
||||
"/dat/volume-%s.sl3", volume.getName()));
|
||||
/**
|
||||
* Save a simple volume, like the WarHub.
|
||||
*
|
||||
* @param volume Volume to save (takes corner data and loads from world).
|
||||
* @return amount of changed blocks
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static int saveSimpleVolume(Volume volume) throws SQLException {
|
||||
File volFile = new File(War.war.getDataFolder(), String.format("/dat/volume-%s.sl3", volume.getName()));
|
||||
Connection databaseConnection = getConnection(volFile);
|
||||
int changed = 0;
|
||||
saveCorners(databaseConnection, volume, "");
|
||||
saveBlocks(databaseConnection, volume, "");
|
||||
databaseConnection.close();
|
||||
return changed;
|
||||
}
|
||||
|
||||
public static boolean deleteSimpleVolume(Volume volume) {
|
||||
File volFile = new File(War.war.getDataFolder(), String.format("/dat/volume-%s.sl3", volume.getName()));
|
||||
boolean deletedData = volFile.delete();
|
||||
if (!deletedData) {
|
||||
War.war.log("Failed to delete file " + volFile.getName(), Level.WARNING);
|
||||
}
|
||||
return deletedData;
|
||||
}
|
||||
|
||||
public static Volume loadSimpleVolume(String volumeName, World world) throws SQLException {
|
||||
File volFile = new File(War.war.getDataFolder(), String.format("/dat/volume-%s.sl3", volumeName));
|
||||
Connection databaseConnection = getConnection(volFile);
|
||||
int version = checkConvert(databaseConnection);
|
||||
Volume v = new Volume(volumeName, world);
|
||||
switch (version) {
|
||||
case 1:
|
||||
case 2:
|
||||
War.war.log(volumeName + " cannot be migrated from War 1.9 due to breaking MC1.13 changes - please resave.", Level.WARNING);
|
||||
loadCorners(databaseConnection, v, world, "");
|
||||
convertSchema2_3(databaseConnection, "", true);
|
||||
return v;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException(String.format("Unsupported volume format (was already converted to version: %d, current format: %d)", version, DATABASE_VERSION));
|
||||
}
|
||||
loadCorners(databaseConnection, v, world, "");
|
||||
loadBlocks(databaseConnection, v, 0, 0, null, true, "");
|
||||
return v;
|
||||
}
|
||||
|
||||
protected static Connection getConnection(File filename) throws SQLException {
|
||||
return DriverManager.getConnection("jdbc:sqlite:" + filename.getPath());
|
||||
}
|
||||
|
||||
protected static int checkConvert(Connection databaseConnection) throws SQLException {
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
ResultSet versionQuery = stmt.executeQuery("PRAGMA user_version");
|
||||
int version = versionQuery.getInt("user_version");
|
||||
versionQuery.close();
|
||||
stmt.close();
|
||||
return version;
|
||||
}
|
||||
|
||||
protected static void convertSchema2_3(Connection databaseConnection, String prefix, boolean isSimple) throws SQLException {
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
stmt.executeUpdate("DROP TABLE " + prefix + "blocks");
|
||||
stmt.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Finds the correct location to place a painting based on its characteristics.
|
||||
* Credit goes to whatever forum I got this from.
|
||||
*
|
||||
* @param art Painting type
|
||||
* @param facing Block face
|
||||
* @param loc Desired location
|
||||
* @return Corrected location
|
||||
*/
|
||||
private static Location calculatePainting(Art art, BlockFace facing, Location loc) {
|
||||
switch(art) {
|
||||
|
||||
// 1x1
|
||||
case ALBAN:
|
||||
case AZTEC:
|
||||
case AZTEC2:
|
||||
case BOMB:
|
||||
case KEBAB:
|
||||
case PLANT:
|
||||
case WASTELAND:
|
||||
return loc; // No calculation needed.
|
||||
|
||||
// 1x2
|
||||
case GRAHAM:
|
||||
case WANDERER:
|
||||
return loc.getBlock().getLocation().add(0, -1, 0);
|
||||
|
||||
// 2x1
|
||||
case CREEBET:
|
||||
case COURBET:
|
||||
case POOL:
|
||||
case SEA:
|
||||
case SUNSET: // Use same as 4x3
|
||||
|
||||
// 4x3
|
||||
case DONKEY_KONG:
|
||||
case SKELETON:
|
||||
if(facing == BlockFace.WEST)
|
||||
return loc.getBlock().getLocation().add(0, 0, -1);
|
||||
else if(facing == BlockFace.SOUTH)
|
||||
return loc.getBlock().getLocation().add(-1, 0, 0);
|
||||
else
|
||||
return loc;
|
||||
|
||||
// 2x2
|
||||
case BUST:
|
||||
case MATCH:
|
||||
case SKULL_AND_ROSES:
|
||||
case STAGE:
|
||||
case VOID:
|
||||
case WITHER: // Use same as 4x2
|
||||
|
||||
// 4x2
|
||||
case FIGHTERS: // Use same as 4x4
|
||||
|
||||
// 4x4
|
||||
case BURNING_SKULL:
|
||||
case PIGSCENE:
|
||||
case POINTER:
|
||||
if(facing == BlockFace.WEST)
|
||||
return loc.getBlock().getLocation().add(0, -1, -1);
|
||||
else if(facing == BlockFace.SOUTH)
|
||||
return loc.getBlock().getLocation().add(-1, -1, 0);
|
||||
else
|
||||
return loc.add(0, -1, 0);
|
||||
|
||||
// Unsupported artwork
|
||||
default:
|
||||
return loc;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,18 +1,5 @@
|
||||
package com.tommytony.war.mapper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
import com.tommytony.war.config.KillstreakReward;
|
||||
@ -21,6 +8,17 @@ import com.tommytony.war.job.RestoreYmlWarhubJob;
|
||||
import com.tommytony.war.job.RestoreYmlWarzonesJob;
|
||||
import com.tommytony.war.structure.WarHub;
|
||||
import com.tommytony.war.utility.Direction;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class WarYmlMapper {
|
||||
|
||||
@ -190,7 +188,7 @@ public class WarYmlMapper {
|
||||
hubConfigSection.set("materials.light", War.war.getWarhubMaterials().getLightBlock());
|
||||
|
||||
try {
|
||||
VolumeMapper.save(hub.getVolume(), "");
|
||||
VolumeMapper.saveSimpleVolume(hub.getVolume());
|
||||
} catch (SQLException e) {
|
||||
// who really even cares
|
||||
War.war.getLogger().log(Level.WARNING, "Failed to save warhub volume blocks", e);
|
||||
|
@ -1,5 +1,21 @@
|
||||
package com.tommytony.war.mapper;
|
||||
|
||||
import com.tommytony.war.Team;
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
import com.tommytony.war.config.TeamConfig;
|
||||
import com.tommytony.war.config.TeamKind;
|
||||
import com.tommytony.war.config.WarzoneConfig;
|
||||
import com.tommytony.war.structure.*;
|
||||
import com.tommytony.war.utility.Direction;
|
||||
import com.tommytony.war.volume.Volume;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
@ -10,24 +26,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.tommytony.war.config.WarzoneConfig;
|
||||
import com.tommytony.war.structure.*;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.tommytony.war.Team;
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
import com.tommytony.war.config.TeamConfig;
|
||||
import com.tommytony.war.config.TeamKind;
|
||||
import com.tommytony.war.utility.Direction;
|
||||
import com.tommytony.war.volume.Volume;
|
||||
import com.tommytony.war.volume.ZoneVolume;
|
||||
|
||||
public class WarzoneYmlMapper {
|
||||
|
||||
public static Warzone load(String name) { // removed createNewVolume, as it did nothing
|
||||
@ -304,7 +302,7 @@ public class WarzoneYmlMapper {
|
||||
}
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = ZoneVolumeMapper.getZoneConnection(warzone.getVolume(), warzone.getName(), warzone.getWorld());
|
||||
connection = ZoneVolumeMapper.getZoneConnection(warzone.getVolume(), warzone.getName());
|
||||
} catch (SQLException e) {
|
||||
War.war.getLogger().log(Level.WARNING, "Failed to load warzone structures volume", e);
|
||||
}
|
||||
@ -658,7 +656,7 @@ public class WarzoneYmlMapper {
|
||||
}
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = ZoneVolumeMapper.getZoneConnection(warzone.getVolume(), warzone.getName(), warzone.getWorld());
|
||||
connection = ZoneVolumeMapper.getZoneConnection(warzone.getVolume(), warzone.getName());
|
||||
} catch (SQLException e) {
|
||||
War.war.getLogger().log(Level.WARNING, "Failed to load warzone structures volume", e);
|
||||
}
|
||||
|
@ -1,38 +1,17 @@
|
||||
package com.tommytony.war.mapper;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Note.Tone;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.CommandBlock;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.block.Jukebox;
|
||||
import org.bukkit.block.NoteBlock;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.Skull;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.volume.Volume;
|
||||
import com.tommytony.war.volume.ZoneVolume;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Loads and saves zone blocks to SQLite3 database.
|
||||
@ -40,52 +19,33 @@ import com.tommytony.war.volume.ZoneVolume;
|
||||
* @author cmastudios
|
||||
* @since 1.8
|
||||
*/
|
||||
public class ZoneVolumeMapper {
|
||||
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
private static final String delim = "-------mcwar iSdgraIyMvOanTEJjZgocczfuG------";
|
||||
public class ZoneVolumeMapper extends VolumeMapper {
|
||||
|
||||
/**
|
||||
* Get a connection to the warzone database, converting blocks if not found.
|
||||
* @param volume zone volume to load
|
||||
* @param zoneName warzone to load
|
||||
* @param world world containing this warzone
|
||||
* @return an open connection to the sqlite file
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static Connection getZoneConnection(ZoneVolume volume, String zoneName, World world) throws SQLException {
|
||||
public static Connection getZoneConnection(ZoneVolume volume, String zoneName) throws SQLException {
|
||||
File databaseFile = new File(War.war.getDataFolder(), String.format("/dat/warzone-%s/volume-%s.sl3", zoneName, volume.getName()));
|
||||
if (!databaseFile.exists()) {
|
||||
// dropped nimitz compatibility with the MC 1.13 update
|
||||
War.war.log("Warzone " + zoneName + " not found - creating new file. Will not attempt converting legacy War version formats.", Level.WARNING);
|
||||
}
|
||||
Connection databaseConnection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getPath());
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
ResultSet versionQuery = stmt.executeQuery("PRAGMA user_version");
|
||||
int version = versionQuery.getInt("user_version");
|
||||
versionQuery.close();
|
||||
if (version > DATABASE_VERSION) {
|
||||
stmt.close();
|
||||
databaseConnection.close();
|
||||
|
||||
// Can't load this too-recent format
|
||||
throw new IllegalStateException(String.format("Unsupported zone format (was already converted to version: %d, current format: %d)", version, DATABASE_VERSION));
|
||||
} else if (version < DATABASE_VERSION) {
|
||||
stmt.close();
|
||||
|
||||
// We need to migrate to newest schema
|
||||
switch (version) {
|
||||
// Run some update SQL for each old version
|
||||
case 1:
|
||||
// Run update from 1 to 2
|
||||
updateFromVersionOneToTwo(zoneName, databaseConnection);
|
||||
|
||||
// How to continue this pattern: (@tommytony multiple in one shouldn't be needed, just don't put a break in the switch)
|
||||
// case 2:
|
||||
// // Run update from 2 to 3
|
||||
// updateFromVersionTwoToTree(zoneName, databaseConnection);
|
||||
}
|
||||
|
||||
Connection databaseConnection = getConnection(databaseFile);
|
||||
int version = checkConvert(databaseConnection);
|
||||
switch (version) {
|
||||
case 1:
|
||||
case 2:
|
||||
War.war.log(zoneName + " cannot be migrated from War 1.9 due to breaking MC1.13 changes - please resave.", Level.WARNING);
|
||||
convertSchema2_3(databaseConnection, "", false);
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException(String.format("Unsupported volume format (was already converted to version: %d, current format: %d)", version, DATABASE_VERSION));
|
||||
}
|
||||
return databaseConnection;
|
||||
}
|
||||
@ -95,332 +55,28 @@ public class ZoneVolumeMapper {
|
||||
*
|
||||
* @param databaseConnection Open connection to zone database
|
||||
* @param volume Volume to load
|
||||
* @param world The world the zone is located
|
||||
* @param onlyLoadCorners Should only the corners be loaded
|
||||
* @param start Starting position to load blocks at
|
||||
* @param total Amount of blocks to read
|
||||
* @return Changed blocks
|
||||
* @throws SQLException Error communicating with SQLite3 database
|
||||
*/
|
||||
public static int load(Connection databaseConnection, ZoneVolume volume, World world, boolean onlyLoadCorners, int start, int total, boolean[][][] changes) throws SQLException {
|
||||
Validate.isTrue(!databaseConnection.isClosed());
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
ResultSet cornerQuery = stmt.executeQuery("SELECT * FROM corners");
|
||||
cornerQuery.next();
|
||||
final Block corner1 = world.getBlockAt(cornerQuery.getInt("x"), cornerQuery.getInt("y"), cornerQuery.getInt("z"));
|
||||
cornerQuery.next();
|
||||
final Block corner2 = world.getBlockAt(cornerQuery.getInt("x"), cornerQuery.getInt("y"), cornerQuery.getInt("z"));
|
||||
cornerQuery.close();
|
||||
volume.setCornerOne(corner1);
|
||||
volume.setCornerTwo(corner2);
|
||||
if (onlyLoadCorners) {
|
||||
stmt.close();
|
||||
return 0;
|
||||
}
|
||||
int minX = volume.getMinX(), minY = volume.getMinY(), minZ = volume.getMinZ();
|
||||
int changed = 0;
|
||||
ResultSet query = stmt.executeQuery("SELECT * FROM blocks ORDER BY rowid LIMIT " + start + ", " + total);
|
||||
while (query.next()) {
|
||||
int x = query.getInt("x"), y = query.getInt("y"), z = query.getInt("z");
|
||||
changed++;
|
||||
Block relative = corner1.getRelative(x, y, z);
|
||||
int xi = relative.getX() - minX, yi = relative.getY() - minY, zi = relative.getZ() - minZ;
|
||||
if (changes != null) {
|
||||
changes[xi][yi][zi] = true;
|
||||
}
|
||||
BlockState modify = relative.getState();
|
||||
ItemStack data = new ItemStack(Material.valueOf(query.getString("type")), 0, query.getShort("data"));
|
||||
if (modify.getType() != data.getType() || !modify.getData().equals(data.getData())) {
|
||||
// Update the type & data if it has changed
|
||||
modify.setType(data.getType());
|
||||
modify.setData(data.getData());
|
||||
modify.update(true, false); // No-physics update, preventing the need for deferring blocks
|
||||
modify = corner1.getRelative(x, y, z).getState(); // Grab a new instance
|
||||
}
|
||||
if (query.getString("metadata") == null || query.getString("metadata").isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (modify instanceof Sign) {
|
||||
final String[] lines = query.getString("metadata").split("\n");
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
((Sign) modify).setLine(i, lines[i]);
|
||||
}
|
||||
modify.update(true, false);
|
||||
}
|
||||
|
||||
// Containers
|
||||
if (modify instanceof InventoryHolder) {
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
config.loadFromString(query.getString("metadata"));
|
||||
((InventoryHolder) modify).getInventory().clear();
|
||||
for (Object obj : config.getList("items")) {
|
||||
if (obj instanceof ItemStack) {
|
||||
((InventoryHolder) modify).getInventory().addItem((ItemStack) obj);
|
||||
}
|
||||
}
|
||||
modify.update(true, false);
|
||||
}
|
||||
|
||||
// Notes
|
||||
if (modify instanceof NoteBlock) {
|
||||
String[] split = query.getString("metadata").split("\n");
|
||||
Note note = new Note(Integer.parseInt(split[1]), Tone.valueOf(split[0]), Boolean.parseBoolean(split[2]));
|
||||
((NoteBlock) modify).setNote(note);
|
||||
modify.update(true, false);
|
||||
}
|
||||
|
||||
// Records
|
||||
if (modify instanceof Jukebox) {
|
||||
((Jukebox) modify).setPlaying(Material.valueOf(query.getString("metadata")));
|
||||
modify.update(true, false);
|
||||
}
|
||||
|
||||
// Skulls
|
||||
if (modify instanceof Skull) {
|
||||
String[] opts = query.getString("metadata").split("\n");
|
||||
if (!opts[0].isEmpty()) {
|
||||
// TODO upgrade to store owning players by UUID
|
||||
((Skull) modify).setOwningPlayer(Bukkit.getOfflinePlayer(opts[0]));
|
||||
}
|
||||
((Skull) modify).setSkullType(SkullType.valueOf(opts[1]));
|
||||
((Skull) modify).setRotation(BlockFace.valueOf(opts[2]));
|
||||
modify.update(true, false);
|
||||
}
|
||||
|
||||
// Command blocks
|
||||
if (modify instanceof CommandBlock) {
|
||||
final String[] commandArray = query.getString("metadata").split("\n");
|
||||
((CommandBlock) modify).setName(commandArray[0]);
|
||||
((CommandBlock) modify).setCommand(commandArray[1]);
|
||||
modify.update(true, false);
|
||||
}
|
||||
|
||||
// Creature spawner
|
||||
if (modify instanceof CreatureSpawner) {
|
||||
((CreatureSpawner) modify).setSpawnedType(EntityType.valueOf(query.getString("metadata")));
|
||||
modify.update(true, false);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
War.war.getLogger().log(Level.WARNING, "Exception loading some tile data. x:" + x + " y:" + y + " z:" + z + " type:" + modify.getType().toString() + " data:" + modify.getData().toString(), ex);
|
||||
}
|
||||
}
|
||||
query.close();
|
||||
stmt.close();
|
||||
return changed;
|
||||
public static int reloadZoneBlocks(Connection databaseConnection, ZoneVolume volume, int start, int total, boolean[][][] changes) throws SQLException {
|
||||
return loadBlocks(databaseConnection, volume, start, total, changes, false, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Load saved entities.
|
||||
*
|
||||
* @param connection Open connection to warzone DB file.
|
||||
* @param volume Volume for warzone.
|
||||
* @return number affected
|
||||
* @throws SQLException SQLite error
|
||||
*/
|
||||
public static int loadEntities(Connection connection, ZoneVolume volume) throws SQLException {
|
||||
Validate.isTrue(!connection.isClosed());
|
||||
// first, clear entities from the area
|
||||
for (Entity e : volume.getWorld().getEntitiesByClass(Hanging.class)) {
|
||||
if (volume.contains(e.getLocation())) {
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
int changed = 0;
|
||||
Statement stmt = connection.createStatement();
|
||||
ResultSet cornerQuery = stmt.executeQuery("SELECT * FROM corners");
|
||||
cornerQuery.next();
|
||||
final Block corner1 = volume.getWorld().getBlockAt(cornerQuery.getInt("x"), cornerQuery.getInt("y"), cornerQuery.getInt("z"));
|
||||
cornerQuery.close();
|
||||
Location test = new Location(volume.getWorld(), 0, 253, 0); // admins pls don't build stuff here kthx
|
||||
// TODO move this to a migration step
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS entities (x NUMERIC, y NUMERIC, z NUMERIC, type SMALLINT, facing TEXT, metadata TEXT)");
|
||||
ResultSet query = stmt.executeQuery("SELECT * FROM entities ORDER BY rowid");
|
||||
while (query.next()) {
|
||||
double x = query.getDouble("x"), y = query.getDouble("y"), z = query.getDouble("z");
|
||||
changed++;
|
||||
// translate from relative DB location to absolute
|
||||
Location absolute = corner1.getLocation().clone().add(x, y, z);
|
||||
int type = query.getInt("type");
|
||||
String facing = query.getString("facing");
|
||||
String metadata = query.getString("metadata");
|
||||
BlockFace face = BlockFace.valueOf(facing);
|
||||
|
||||
// Spawn the paintings in the sky somewhere, works because I can only get them to spawn north/south
|
||||
test.getBlock().setType(Material.AIR);
|
||||
test.add(2, 0, 0).getBlock().setType(Material.STONE);
|
||||
|
||||
try {
|
||||
if (type == 1) {
|
||||
Painting p = (Painting) volume.getWorld().spawnEntity(test.clone().add(0, 0, 1), EntityType.PAINTING);
|
||||
Art art = Art.valueOf(metadata);
|
||||
p.teleport(calculatePainting(art, face, absolute));
|
||||
p.setFacingDirection(face, true);
|
||||
p.setArt(art, true);
|
||||
} else if (type == 2) {
|
||||
ItemFrame itemFrame = (ItemFrame) volume.getWorld().spawnEntity(test.clone().add(0, 0, 1), EntityType.ITEM_FRAME);
|
||||
itemFrame.teleport(absolute);
|
||||
itemFrame.setFacingDirection(face, true);
|
||||
String[] args = metadata.split(delim);
|
||||
itemFrame.setRotation(Rotation.valueOf(args[0]));
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
config.loadFromString(args[1]);
|
||||
itemFrame.setItem(config.getItemStack("item"));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
War.war.getLogger().log(Level.WARNING, "Exception loading entity. x:" + x + " y:" + y + " z:" + z + " type:" + type, ex);
|
||||
}
|
||||
}
|
||||
test.getBlock().setType(Material.AIR);
|
||||
query.close();
|
||||
stmt.close();
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the correct location to place a painting based on its characteristics.
|
||||
* Credit goes to whatever forum I got this from.
|
||||
*
|
||||
* @param art Painting type
|
||||
* @param facing Block face
|
||||
* @param loc Desired location
|
||||
* @return Corrected location
|
||||
*/
|
||||
private static Location calculatePainting(Art art, BlockFace facing, Location loc) {
|
||||
switch(art) {
|
||||
|
||||
// 1x1
|
||||
case ALBAN:
|
||||
case AZTEC:
|
||||
case AZTEC2:
|
||||
case BOMB:
|
||||
case KEBAB:
|
||||
case PLANT:
|
||||
case WASTELAND:
|
||||
return loc; // No calculation needed.
|
||||
|
||||
// 1x2
|
||||
case GRAHAM:
|
||||
case WANDERER:
|
||||
return loc.getBlock().getLocation().add(0, -1, 0);
|
||||
|
||||
// 2x1
|
||||
case CREEBET:
|
||||
case COURBET:
|
||||
case POOL:
|
||||
case SEA:
|
||||
case SUNSET: // Use same as 4x3
|
||||
|
||||
// 4x3
|
||||
case DONKEY_KONG:
|
||||
case SKELETON:
|
||||
if(facing == BlockFace.WEST)
|
||||
return loc.getBlock().getLocation().add(0, 0, -1);
|
||||
else if(facing == BlockFace.SOUTH)
|
||||
return loc.getBlock().getLocation().add(-1, 0, 0);
|
||||
else
|
||||
return loc;
|
||||
|
||||
// 2x2
|
||||
case BUST:
|
||||
case MATCH:
|
||||
case SKULL_AND_ROSES:
|
||||
case STAGE:
|
||||
case VOID:
|
||||
case WITHER: // Use same as 4x2
|
||||
|
||||
// 4x2
|
||||
case FIGHTERS: // Use same as 4x4
|
||||
|
||||
// 4x4
|
||||
case BURNING_SKULL:
|
||||
case PIGSCENE:
|
||||
case POINTER:
|
||||
if(facing == BlockFace.WEST)
|
||||
return loc.getBlock().getLocation().add(0, -1, -1);
|
||||
else if(facing == BlockFace.SOUTH)
|
||||
return loc.getBlock().getLocation().add(-1, -1, 0);
|
||||
else
|
||||
return loc.add(0, -1, 0);
|
||||
|
||||
// Unsupported artwork
|
||||
default:
|
||||
return loc;
|
||||
}
|
||||
}
|
||||
|
||||
public static int saveStructure(Volume volume, Connection databaseConnection) throws SQLException {
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
stmt.executeUpdate("PRAGMA user_version = " + DATABASE_VERSION);
|
||||
// Storing zonemaker-inputted name could result in injection or undesirable behavior.
|
||||
String prefix = String.format("structure_%d", volume.getName().hashCode() & Integer.MAX_VALUE);
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix +
|
||||
"_blocks (x BIGINT, y BIGINT, z BIGINT, type TEXT, data SMALLINT)");
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix +
|
||||
"_corners (pos INTEGER PRIMARY KEY NOT NULL UNIQUE, x INTEGER NOT NULL, y INTEGER NOT NULL, z INTEGER NOT NULL)");
|
||||
stmt.executeUpdate("DELETE FROM " + prefix + "_blocks");
|
||||
stmt.executeUpdate("DELETE FROM " + prefix + "_corners");
|
||||
stmt.close();
|
||||
PreparedStatement cornerStmt = databaseConnection
|
||||
.prepareStatement("INSERT INTO " + prefix + "_corners SELECT 1 AS pos, ? AS x, ? AS y, ? AS z UNION SELECT 2, ?, ?, ?");
|
||||
cornerStmt.setInt(1, volume.getCornerOne().getBlockX());
|
||||
cornerStmt.setInt(2, volume.getCornerOne().getBlockY());
|
||||
cornerStmt.setInt(3, volume.getCornerOne().getBlockZ());
|
||||
cornerStmt.setInt(4, volume.getCornerTwo().getBlockX());
|
||||
cornerStmt.setInt(5, volume.getCornerTwo().getBlockY());
|
||||
cornerStmt.setInt(6, volume.getCornerTwo().getBlockZ());
|
||||
cornerStmt.executeUpdate();
|
||||
cornerStmt.close();
|
||||
PreparedStatement dataStmt = databaseConnection
|
||||
.prepareStatement("INSERT INTO " + prefix + "_blocks VALUES (?, ?, ?, ?, ?)");
|
||||
databaseConnection.setAutoCommit(false);
|
||||
final int batchSize = 1000;
|
||||
int changed = 0;
|
||||
for (BlockState block : volume.getBlocks()) {
|
||||
final Location relLoc = ZoneVolumeMapper.rebase(
|
||||
volume.getCornerOne(), block.getLocation());
|
||||
dataStmt.setInt(1, relLoc.getBlockX());
|
||||
dataStmt.setInt(2, relLoc.getBlockY());
|
||||
dataStmt.setInt(3, relLoc.getBlockZ());
|
||||
dataStmt.setString(4, block.getType().toString());
|
||||
dataStmt.setShort(5, block.getData().toItemStack(1).getDurability());
|
||||
dataStmt.addBatch();
|
||||
if (++changed % batchSize == 0) {
|
||||
dataStmt.executeBatch();
|
||||
}
|
||||
}
|
||||
dataStmt.executeBatch(); // insert remaining records
|
||||
databaseConnection.commit();
|
||||
databaseConnection.setAutoCommit(true);
|
||||
dataStmt.close();
|
||||
return changed;
|
||||
String prefix = String.format("structure_%d_", volume.getName().hashCode() & Integer.MAX_VALUE);
|
||||
saveCorners(databaseConnection, volume, prefix);
|
||||
return saveBlocks(databaseConnection, volume, prefix);
|
||||
}
|
||||
|
||||
public static void loadStructure(Volume volume, Connection databaseConnection) throws SQLException {
|
||||
String prefix = String.format("structure_%d", volume.getName().hashCode() & Integer.MAX_VALUE);
|
||||
String prefix = String.format("structure_%d_", volume.getName().hashCode() & Integer.MAX_VALUE);
|
||||
World world = volume.getWorld();
|
||||
Validate.notNull(world, String.format("Cannot find the warzone for %s", prefix));
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
ResultSet cornerQuery = stmt.executeQuery("SELECT * FROM " + prefix + "_corners");
|
||||
cornerQuery.next();
|
||||
final Block corner1 = world.getBlockAt(cornerQuery.getInt("x"), cornerQuery.getInt("y"), cornerQuery.getInt("z"));
|
||||
cornerQuery.next();
|
||||
final Block corner2 = world.getBlockAt(cornerQuery.getInt("x"), cornerQuery.getInt("y"), cornerQuery.getInt("z"));
|
||||
cornerQuery.close();
|
||||
volume.setCornerOne(corner1);
|
||||
volume.setCornerTwo(corner2);
|
||||
volume.getBlocks().clear();
|
||||
ResultSet query = stmt.executeQuery("SELECT * FROM " + prefix + "_blocks");
|
||||
while (query.next()) {
|
||||
int x = query.getInt("x"), y = query.getInt("y"), z = query.getInt("z");
|
||||
BlockState modify = corner1.getRelative(x, y, z).getState();
|
||||
ItemStack data = new ItemStack(Material.valueOf(query.getString("type")), 0, query.getShort("data"));
|
||||
modify.setType(data.getType());
|
||||
modify.setData(data.getData());
|
||||
volume.getBlocks().add(modify);
|
||||
}
|
||||
query.close();
|
||||
stmt.close();
|
||||
loadCorners(databaseConnection, volume, world, prefix);
|
||||
loadBlocks(databaseConnection, volume, 0, 0, null, true, prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -431,8 +87,7 @@ public class ZoneVolumeMapper {
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static int getTotalSavedBlocks(ZoneVolume volume, String zoneName) throws SQLException {
|
||||
File databaseFile = new File(War.war.getDataFolder(), String.format("/dat/warzone-%s/volume-%s.sl3", zoneName, volume.getName()));
|
||||
Connection databaseConnection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getPath());
|
||||
Connection databaseConnection = getZoneConnection(volume, zoneName);
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
ResultSet sizeQuery = stmt.executeQuery("SELECT COUNT(*) AS total FROM blocks");
|
||||
int size = sizeQuery.getInt("total");
|
||||
@ -450,166 +105,18 @@ public class ZoneVolumeMapper {
|
||||
* @return amount of changed blocks
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static int save(Volume volume, String zoneName) throws SQLException {
|
||||
long startTime = System.currentTimeMillis();
|
||||
int changed = 0;
|
||||
public static int saveZoneBlocksAndEntities(ZoneVolume volume, String zoneName) throws SQLException {
|
||||
File warzoneDir = new File(War.war.getDataFolder().getPath() + "/dat/warzone-" + zoneName);
|
||||
if (!warzoneDir.exists() && !warzoneDir.mkdirs()) {
|
||||
throw new RuntimeException("Failed to create warzone data directory");
|
||||
}
|
||||
File databaseFile = new File(War.war.getDataFolder(), String.format("/dat/warzone-%s/volume-%s.sl3", zoneName, volume.getName()));
|
||||
Connection databaseConnection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getPath());
|
||||
Statement stmt = databaseConnection.createStatement();
|
||||
stmt.executeUpdate("PRAGMA user_version = " + DATABASE_VERSION);
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS blocks (x BIGINT, y BIGINT, z BIGINT, type TEXT, data SMALLINT, metadata BLOB)");
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS entities (x NUMERIC, y NUMERIC, z NUMERIC, type SMALLINT, facing TEXT, metadata TEXT)");
|
||||
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS corners (pos INTEGER PRIMARY KEY NOT NULL UNIQUE, x INTEGER NOT NULL, y INTEGER NOT NULL, z INTEGER NOT NULL)");
|
||||
stmt.executeUpdate("DELETE FROM blocks");
|
||||
stmt.executeUpdate("DELETE FROM corners");
|
||||
stmt.executeUpdate("DELETE FROM entities");
|
||||
stmt.close();
|
||||
PreparedStatement cornerStmt = databaseConnection.prepareStatement("INSERT INTO corners SELECT 1 AS pos, ? AS x, ? AS y, ? AS z UNION SELECT 2, ?, ?, ?");
|
||||
cornerStmt.setInt(1, volume.getCornerOne().getBlockX());
|
||||
cornerStmt.setInt(2, volume.getCornerOne().getBlockY());
|
||||
cornerStmt.setInt(3, volume.getCornerOne().getBlockZ());
|
||||
cornerStmt.setInt(4, volume.getCornerTwo().getBlockX());
|
||||
cornerStmt.setInt(5, volume.getCornerTwo().getBlockY());
|
||||
cornerStmt.setInt(6, volume.getCornerTwo().getBlockZ());
|
||||
cornerStmt.executeUpdate();
|
||||
cornerStmt.close();
|
||||
PreparedStatement entityStmt = databaseConnection.prepareStatement("INSERT INTO entities (x, y, z, type, facing, metadata) VALUES (?, ?, ?, ?, ?, ?)");
|
||||
for (Entity e : volume.getWorld().getEntities()) {
|
||||
if (volume.contains(e.getLocation()) && e instanceof Hanging) {
|
||||
entityStmt.setDouble(1, e.getLocation().getX() - volume.getCornerOne().getBlockX());
|
||||
entityStmt.setDouble(2, e.getLocation().getY() - volume.getCornerOne().getBlockY());
|
||||
entityStmt.setDouble(3, e.getLocation().getZ() - volume.getCornerOne().getBlockZ());
|
||||
entityStmt.setString(5, ((Hanging) e).getFacing().name());
|
||||
if (e instanceof Painting) {
|
||||
Painting p = (Painting) e;
|
||||
entityStmt.setInt(4, 1);
|
||||
entityStmt.setString(6, p.getArt().name());
|
||||
} else if (e instanceof ItemFrame) {
|
||||
ItemFrame itemFrame = (ItemFrame) e;
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
config.set("item", itemFrame.getItem());
|
||||
entityStmt.setInt(4, 2);
|
||||
entityStmt.setString(6, itemFrame.getRotation().name() + delim + config.saveToString());
|
||||
} else {
|
||||
entityStmt.setInt(4, 0);
|
||||
entityStmt.setString(6, "");
|
||||
}
|
||||
entityStmt.addBatch();
|
||||
}
|
||||
}
|
||||
entityStmt.executeBatch();
|
||||
entityStmt.close();
|
||||
PreparedStatement dataStmt = databaseConnection.prepareStatement("INSERT INTO blocks (x, y, z, type, data, metadata) VALUES (?, ?, ?, ?, ?, ?)");
|
||||
databaseConnection.setAutoCommit(false);
|
||||
final int batchSize = 10000;
|
||||
for (int i = 0, x = volume.getMinX(); i < volume.getSizeX(); i++, x++) {
|
||||
for (int j = 0, y = volume.getMinY(); j < volume.getSizeY(); j++, y++) {
|
||||
for (int k = 0, z = volume.getMinZ(); k < volume.getSizeZ(); k++, z++) {
|
||||
// Make sure we are using zone volume-relative coords
|
||||
final Block block = volume.getWorld().getBlockAt(x, y, z);
|
||||
if (block.getType() == Material.AIR) {
|
||||
continue; // Do not save air blocks to the file anymore.
|
||||
}
|
||||
final BlockState state = block.getState();
|
||||
dataStmt.setInt(1, block.getX() - volume.getCornerOne().getBlockX());
|
||||
dataStmt.setInt(2, block.getY() - volume.getCornerOne().getBlockY());
|
||||
dataStmt.setInt(3, block.getZ() - volume.getCornerOne().getBlockZ());
|
||||
dataStmt.setString(4, block.getType().name());
|
||||
dataStmt.setShort(5, state.getData().toItemStack(1).getDurability());
|
||||
if (state instanceof Sign) {
|
||||
final String signText = StringUtils.join(((Sign) block.getState()).getLines(), "\n");
|
||||
dataStmt.setString(6, signText);
|
||||
} else if (state instanceof InventoryHolder) {
|
||||
List<ItemStack> items = Arrays.asList(((InventoryHolder) block.getState()).getInventory().getContents());
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
// Serialize to config, then store config in database
|
||||
config.set("items", items);
|
||||
dataStmt.setString(6, config.saveToString());
|
||||
} else if (state instanceof NoteBlock) {
|
||||
Note note = ((NoteBlock) block.getState()).getNote();
|
||||
dataStmt.setString(6, note.getTone().toString() + '\n' + note.getOctave() + '\n' + note.isSharped());
|
||||
} else if (state instanceof Jukebox) {
|
||||
dataStmt.setString(6, ((Jukebox) block.getState()).getPlaying().toString());
|
||||
} else if (state instanceof Skull) {
|
||||
// TODO upgrade to store owning player by UUID
|
||||
dataStmt.setString(6, String.format("%s\n%s\n%s",
|
||||
((Skull) block.getState()).hasOwner() ? ((Skull) block.getState()).getOwningPlayer().getName() : "",
|
||||
// TODO remove deprecation when Spigot updates their docs about the replacement
|
||||
((Skull) block.getState()).getSkullType().toString(),
|
||||
((Skull) block.getState()).getRotation().toString()));
|
||||
} else if (state instanceof CommandBlock) {
|
||||
dataStmt.setString(6, ((CommandBlock) block.getState()).getName()
|
||||
+ "\n" + ((CommandBlock) block.getState()).getCommand());
|
||||
} else if (state instanceof CreatureSpawner) {
|
||||
dataStmt.setString(6, ((CreatureSpawner) block.getState()).getSpawnedType().toString());
|
||||
} else {
|
||||
dataStmt.setString(6, "");
|
||||
}
|
||||
|
||||
dataStmt.addBatch();
|
||||
|
||||
if (++changed % batchSize == 0) {
|
||||
dataStmt.executeBatch();
|
||||
if ((System.currentTimeMillis() - startTime) >= 5000L) {
|
||||
String seconds = new DecimalFormat("#0.00").format((double) (System.currentTimeMillis() - startTime) / 1000.0D);
|
||||
War.war.getLogger().log(Level.FINE, "Still saving warzone {0} , {1} seconds elapsed.", new Object[] {zoneName, seconds});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dataStmt.executeBatch(); // insert remaining records
|
||||
databaseConnection.commit();
|
||||
dataStmt.close();
|
||||
databaseConnection.setAutoCommit(true);
|
||||
Connection databaseConnection = getZoneConnection(volume, zoneName);
|
||||
int changed = 0;
|
||||
saveCorners(databaseConnection, volume, "");
|
||||
saveBlocks(databaseConnection, volume, "");
|
||||
saveEntities(databaseConnection, volume);
|
||||
databaseConnection.close();
|
||||
String seconds = new DecimalFormat("#0.00").format((double) (System.currentTimeMillis() - startTime) / 1000.0D);
|
||||
War.war.getLogger().log(Level.INFO, "Saved warzone {0} in {1} seconds.", new Object[] {zoneName, seconds});
|
||||
return changed;
|
||||
}
|
||||
|
||||
static Location rebase(final Location base, final Location exact) {
|
||||
return new Location(base.getWorld(),
|
||||
exact.getBlockX() - base.getBlockX(),
|
||||
exact.getBlockY() - base.getBlockY(),
|
||||
exact.getBlockZ() - base.getBlockZ());
|
||||
}
|
||||
|
||||
private static void updateFromVersionOneToTwo(String zoneName, Connection connection) throws SQLException {
|
||||
War.war.log("Migrating warzone " + zoneName + " from v1 to v2 of schema...", Level.INFO);
|
||||
|
||||
// We want to do this in a transaction
|
||||
connection.setAutoCommit(false);
|
||||
|
||||
Statement stmt = connection.createStatement();
|
||||
|
||||
// We want to combine all extra columns into a single metadata BLOB one. To delete some columns we need to drop the table so we use a temp one.
|
||||
stmt.executeUpdate("CREATE TEMPORARY TABLE blocks_backup(x BIGINT, y BIGINT, z BIGINT, type TEXT, data SMALLINT, sign TEXT, container BLOB, note INT, record TEXT, skull TEXT, command TEXT, mobid TEXT)");
|
||||
stmt.executeUpdate("INSERT INTO blocks_backup SELECT x, y, z, type, data, sign, container, note, record, skull, command, mobid FROM blocks");
|
||||
stmt.executeUpdate("DROP TABLE blocks");
|
||||
stmt.executeUpdate("CREATE TABLE blocks(x BIGINT, y BIGINT, z BIGINT, type TEXT, data SMALLINT, metadata BLOB)");
|
||||
stmt.executeUpdate("INSERT INTO blocks SELECT x, y, z, type, data, coalesce(container, sign, note, record, skull, command, mobid) FROM blocks_backup");
|
||||
stmt.executeUpdate("DROP TABLE blocks_backup");
|
||||
stmt.executeUpdate("PRAGMA user_version = 2");
|
||||
stmt.close();
|
||||
|
||||
// Commit transaction
|
||||
connection.commit();
|
||||
|
||||
connection.setAutoCommit(true);
|
||||
|
||||
War.war.log("Warzone " + zoneName + " converted! Compacting database...", Level.INFO);
|
||||
|
||||
// Pack the database otherwise we won't get any space savings.
|
||||
// This rebuilds the database completely and takes some time.
|
||||
stmt = connection.createStatement();
|
||||
stmt.execute("VACUUM");
|
||||
stmt.close();
|
||||
|
||||
War.war.log("Migration of warzone " + zoneName + " to v2 of schema finished.", Level.INFO);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,5 @@
|
||||
package com.tommytony.war.structure;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.material.Sign;
|
||||
|
||||
import com.tommytony.war.Team;
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
@ -19,6 +7,17 @@ import com.tommytony.war.config.TeamConfig;
|
||||
import com.tommytony.war.config.WarzoneConfig;
|
||||
import com.tommytony.war.utility.Direction;
|
||||
import com.tommytony.war.volume.Volume;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.material.Sign;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -236,8 +235,7 @@ public class WarHub {
|
||||
/**
|
||||
* Resets the sign of the given warzone
|
||||
*
|
||||
* @param Warzone
|
||||
* zone
|
||||
* @param zone
|
||||
*/
|
||||
public void resetZoneSign(Warzone zone) {
|
||||
BlockFace left;
|
||||
|
@ -1,13 +1,5 @@
|
||||
package com.tommytony.war.volume;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import com.tommytony.war.Team;
|
||||
import com.tommytony.war.War;
|
||||
import com.tommytony.war.Warzone;
|
||||
@ -15,6 +7,13 @@ import com.tommytony.war.config.WarConfig;
|
||||
import com.tommytony.war.job.PartialZoneResetJob;
|
||||
import com.tommytony.war.mapper.ZoneVolumeMapper;
|
||||
import com.tommytony.war.structure.Monument;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -36,7 +35,7 @@ public class ZoneVolume extends Volume {
|
||||
// Save blocks directly to disk (i.e. don't put everything in memory)
|
||||
int saved = 0;
|
||||
try {
|
||||
saved = ZoneVolumeMapper.save(this, this.zone.getName());
|
||||
saved = ZoneVolumeMapper.saveZoneBlocksAndEntities(this, this.zone.getName());
|
||||
} catch (SQLException ex) {
|
||||
War.war.log("Failed to save warzone " + zone.getName() + ": " + ex.getMessage(), Level.WARNING);
|
||||
ex.printStackTrace();
|
||||
@ -51,8 +50,8 @@ public class ZoneVolume extends Volume {
|
||||
}
|
||||
|
||||
public void loadCorners() throws SQLException {
|
||||
Connection conn = ZoneVolumeMapper.getZoneConnection(this, this.zone.getName(), this.getWorld());
|
||||
ZoneVolumeMapper.load(conn, this, this.getWorld(), true, 0, 0, null);
|
||||
Connection conn = ZoneVolumeMapper.getZoneConnection(this, this.zone.getName());
|
||||
ZoneVolumeMapper.loadCorners(conn, this, this.getWorld(), "");
|
||||
this.isSaved = true;
|
||||
}
|
||||
|
||||
@ -60,8 +59,8 @@ public class ZoneVolume extends Volume {
|
||||
public void resetBlocks() {
|
||||
// Load blocks directly from disk and onto the map (i.e. no more in-memory warzone blocks)
|
||||
try {
|
||||
Connection conn = ZoneVolumeMapper.getZoneConnection(this, this.zone.getName(), this.getWorld());
|
||||
ZoneVolumeMapper.load(conn, this, this.getWorld(), false, 0, Integer.MAX_VALUE, null);
|
||||
Connection conn = ZoneVolumeMapper.getZoneConnection(this, this.zone.getName());
|
||||
ZoneVolumeMapper.reloadZoneBlocks(conn, this, 0, Integer.MAX_VALUE, null);
|
||||
} catch (SQLException ex) {
|
||||
War.war.log("Failed to load warzone " + zone.getName() + ": " + ex.getMessage(), Level.WARNING);
|
||||
ex.printStackTrace();
|
||||
@ -82,7 +81,7 @@ public class ZoneVolume extends Volume {
|
||||
* @throws SQLException
|
||||
*/
|
||||
public int resetSection(Connection conn, int start, int total, boolean[][][] changes) throws SQLException {
|
||||
return ZoneVolumeMapper.load(conn, this, this.getWorld(), false, start, total, changes);
|
||||
return ZoneVolumeMapper.reloadZoneBlocks(conn, this, start, total, changes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user