diff --git a/.gitignore b/.gitignore index 117335e1..32c274ae 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ *.project *.classpath /target/ +/.gradle +/.idea \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..9d7f8f4f --- /dev/null +++ b/build.gradle @@ -0,0 +1,46 @@ +buildscript { + repositories { + mavenCentral() + maven { url = "https://oss.sonatype.org/content/repositories/snapshots/" } + jcenter() + } + dependencies { + classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' + } +} + +group = 'com.boydti.fawe' +version = '3.3.4' +description = """FastAsyncWorldEdit""" + +subprojects { + apply plugin: 'java' + apply plugin: 'maven' + apply plugin: 'eclipse' + apply plugin: 'idea' + + dependencies { + compile(group: 'com.sk89q', name: 'worldedit', version:'6.0.0-SNAPSHOT') { + exclude(module: 'bukkit-classloader-check') + } + compile 'com.sk89q:worldguard:6.0.0-SNAPSHOT' + compile 'com.intellectualcrafters.plot:plotsquared:3.3.1' + } + + repositories { + mavenCentral() + maven {url "http://empcraft.com/maven2"} + maven {url "http://repo.mcstats.org/content/repositories/public"} + maven {url "https://hub.spigotmc.org/nexus/content/groups/public/"} + maven {url "http://maven.sk89q.com/repo/"} + maven {url "http://nexus.theyeticave.net/content/repositories/pub_releases"} + maven {url "http://repo.maven.apache.org/maven2"} + maven {url "http://repo.techcable.net/content/groups/public/"} + maven {url "http://hub.spigotmc.org/nexus/content/groups/public/"} + maven {url "http://ci.frostcast.net/plugin/repository/everything"} + maven {url "http://maven.sk89q.com/artifactory/repo/"} + maven {url "http://nexus.theyeticave.net/content/repositories/pub_releases"} + maven {url "http://repo.spongepowered.org/maven"} + + } +} \ No newline at end of file diff --git a/bukkit/build.gradle b/bukkit/build.gradle new file mode 100644 index 00000000..c06771d0 --- /dev/null +++ b/bukkit/build.gradle @@ -0,0 +1,53 @@ +dependencies { + compile project(':core') + compile 'org.bukkit:bukkit:1.9-R0.1-SNAPSHOT' + compile 'org.mcstats.bukkit:metrics:R7' + compile 'net.milkbowl.vault:VaultAPI:1.5' + compile 'javax.websocket:javax.websocket-api:1.1' + compile 'org.spongepowered:spongeapi:2.1-SNAPSHOT' + compile 'org.bukkit:bukkit:1.9-R0.1-SNAPSHOT' + compile 'org.PrimeSoft:blockshub:1.2' + compile 'com.massivecraft:factions:2.8.0' + compile 'com.drtshock:factions:1.6.9.5' + compile 'me.ryanhamshire:GriefPrevention:11.5.2' + compile 'com.massivecraft:mcore:7.0.1' + compile 'net.sacredlabyrinth.Phaed:PreciousStones:9.6.6' + compile 'net.jzx7:regios:5.9.9' + compile 'com.bekvon.bukkit:residence:2.6.6.6' + compile 'com.palmergames.bukkit:towny:0.84.0.9' + compile 'com.worldcretornica:plotme_core:0.16.3' + compile 'junit:junit:4.11' + +} + +sourceCompatibility = 1.7 +targetCompatibility = 1.7 + +processResources { + from('src/main/resources') { + include 'plugin.yml' + expand( + name: project.parent.name, + version: project.parent.version + ) + } +} + +apply plugin: 'com.github.johnrengelman.shadow' +// We only want the shadow jar produced +jar.enabled = false +shadowJar { + dependencies { + include(dependency(':core')) + include(dependency('org.mcstats.bukkit:metrics:R7')) + } + relocate 'org.mcstats', 'com.plotsquared.stats' + archiveName = "${parent.name}-${project.name}-${parent.version}.jar" + destinationDir = file '../target' +} +shadowJar.doLast { + task -> + ant.checksum file: task.archivePath +} + +build.dependsOn(shadowJar); \ No newline at end of file diff --git a/src/main/resources/config.yml b/bukkit/build/resources/main/config.yml similarity index 100% rename from src/main/resources/config.yml rename to bukkit/build/resources/main/config.yml diff --git a/src/main/resources/plugin.yml b/bukkit/build/resources/main/plugin.yml similarity index 100% rename from src/main/resources/plugin.yml rename to bukkit/build/resources/main/plugin.yml diff --git a/src/main/java/com/boydti/fawe/bukkit/BukkitCommand.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitCommand.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/BukkitCommand.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitCommand.java diff --git a/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java diff --git a/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java diff --git a/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java diff --git a/src/main/java/com/boydti/fawe/bukkit/VaultUtil.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/VaultUtil.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/VaultUtil.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/VaultUtil.java diff --git a/src/main/java/com/boydti/fawe/bukkit/WEListener.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/WEListener.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/WEListener.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/WEListener.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMaskManager.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMaskManager.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/BukkitMaskManager.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMaskManager.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/FactionsFeature.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsFeature.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/FactionsFeature.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsFeature.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/FactionsUUIDFeature.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsUUIDFeature.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/FactionsUUIDFeature.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsUUIDFeature.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/FaweMask.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FaweMask.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/FaweMask.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FaweMask.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/GriefPreventionFeature.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/GriefPreventionFeature.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/GriefPreventionFeature.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/GriefPreventionFeature.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/PlotMeFeature.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PlotMeFeature.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/PlotMeFeature.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PlotMeFeature.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/PlotSquaredFeature.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PlotSquaredFeature.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/PlotSquaredFeature.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PlotSquaredFeature.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/PreciousStonesFeature.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PreciousStonesFeature.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/PreciousStonesFeature.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PreciousStonesFeature.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/ResidenceFeature.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/ResidenceFeature.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/ResidenceFeature.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/ResidenceFeature.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/TownyFeature.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/TownyFeature.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/TownyFeature.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/TownyFeature.java diff --git a/src/main/java/com/boydti/fawe/bukkit/regions/Worldguard.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/Worldguard.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/regions/Worldguard.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/regions/Worldguard.java diff --git a/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java diff --git a/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java diff --git a/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java diff --git a/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitEditSessionWrapper_1_8.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitEditSessionWrapper_1_8.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitEditSessionWrapper_1_8.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitEditSessionWrapper_1_8.java diff --git a/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue_1_8.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue_1_8.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue_1_8.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue_1_8.java diff --git a/src/main/java/com/boydti/fawe/bukkit/v1_8/FaweGenerator_1_8.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/FaweGenerator_1_8.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/v1_8/FaweGenerator_1_8.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/FaweGenerator_1_8.java diff --git a/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java diff --git a/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9.java similarity index 100% rename from src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9.java rename to bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9.java diff --git a/bukkit/src/main/resources/config.yml b/bukkit/src/main/resources/config.yml new file mode 100644 index 00000000..e69de29b diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml new file mode 100644 index 00000000..c38f7c85 --- /dev/null +++ b/bukkit/src/main/resources/plugin.yml @@ -0,0 +1,32 @@ +name: FastAsyncWorldEdit +main: com.boydti.fawe.bukkit.FaweBukkit +version: 3.3.4 +description: Fast Async WorldEdit plugin +authors: [Empire92] +loadbefore: [WorldEdit] +load: STARTUP +database: false +#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] +commands: + wea: + description: (FAWE) Bypass WorldEdit processing and area restrictions + aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere] + usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass" + fixlighting: + description: (FAWE) Fix the lighting in your current chunk + aliases: [/fixlighting] + stream: + description: (FAWE) Stream a schematic into the world + aliases: [/stream] + wrg: + description: (FAWE) Select your current WorldEdit Region. + aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region] +permissions: + fawe.bypass: + default: false + fawe.admin: + default: false + fawe.stream: + default: false + fawe.fixlighting: + default: false diff --git a/core/build.gradle b/core/build.gradle new file mode 100644 index 00000000..0bc5f44c --- /dev/null +++ b/core/build.gradle @@ -0,0 +1,11 @@ +dependencies { + testCompile 'junit:junit:4.12' + compile 'org.yaml:snakeyaml:1.16' + compile 'com.google.code.gson:gson:2.2.4' +} + +sourceCompatibility = 1.7 +targetCompatibility = 1.7 + +jar.archiveName="FastAsyncWorldEdit-API-${parent.version}.jar" +jar.destinationDir = file '../target' \ No newline at end of file diff --git a/src/main/java/com/boydti/fawe/Fawe.java b/core/src/main/java/com/boydti/fawe/Fawe.java similarity index 97% rename from src/main/java/com/boydti/fawe/Fawe.java rename to core/src/main/java/com/boydti/fawe/Fawe.java index e818a3a6..a4afc7c7 100644 --- a/src/main/java/com/boydti/fawe/Fawe.java +++ b/core/src/main/java/com/boydti/fawe/Fawe.java @@ -217,10 +217,15 @@ public class Fawe { NonRisingVisitor.inject(); RecursiveVisitor.inject(); RegionVisitor.inject(); - CommandManager.inject(); EntityCreate.inject(); EntityRemove.inject(); LocalSession.inject(); + try { + CommandManager.inject(); + } catch (Throwable e) { + e.printStackTrace(); + IMP.debug("Incompatible version of WorldEdit, please update the plugin or contact the Author!"); + } } private void setupMemoryListener() { diff --git a/src/main/java/com/boydti/fawe/FaweAPI.java b/core/src/main/java/com/boydti/fawe/FaweAPI.java similarity index 100% rename from src/main/java/com/boydti/fawe/FaweAPI.java rename to core/src/main/java/com/boydti/fawe/FaweAPI.java diff --git a/src/main/java/com/boydti/fawe/FaweCache.java b/core/src/main/java/com/boydti/fawe/FaweCache.java similarity index 100% rename from src/main/java/com/boydti/fawe/FaweCache.java rename to core/src/main/java/com/boydti/fawe/FaweCache.java diff --git a/src/main/java/com/boydti/fawe/IFawe.java b/core/src/main/java/com/boydti/fawe/IFawe.java similarity index 100% rename from src/main/java/com/boydti/fawe/IFawe.java rename to core/src/main/java/com/boydti/fawe/IFawe.java diff --git a/src/main/java/com/boydti/fawe/command/FixLighting.java b/core/src/main/java/com/boydti/fawe/command/FixLighting.java similarity index 100% rename from src/main/java/com/boydti/fawe/command/FixLighting.java rename to core/src/main/java/com/boydti/fawe/command/FixLighting.java diff --git a/src/main/java/com/boydti/fawe/command/Stream.java b/core/src/main/java/com/boydti/fawe/command/Stream.java similarity index 100% rename from src/main/java/com/boydti/fawe/command/Stream.java rename to core/src/main/java/com/boydti/fawe/command/Stream.java diff --git a/src/main/java/com/boydti/fawe/command/Wea.java b/core/src/main/java/com/boydti/fawe/command/Wea.java similarity index 100% rename from src/main/java/com/boydti/fawe/command/Wea.java rename to core/src/main/java/com/boydti/fawe/command/Wea.java diff --git a/src/main/java/com/boydti/fawe/command/WorldEditRegion.java b/core/src/main/java/com/boydti/fawe/command/WorldEditRegion.java similarity index 100% rename from src/main/java/com/boydti/fawe/command/WorldEditRegion.java rename to core/src/main/java/com/boydti/fawe/command/WorldEditRegion.java diff --git a/src/main/java/com/boydti/fawe/config/BBC.java b/core/src/main/java/com/boydti/fawe/config/BBC.java similarity index 100% rename from src/main/java/com/boydti/fawe/config/BBC.java rename to core/src/main/java/com/boydti/fawe/config/BBC.java diff --git a/src/main/java/com/boydti/fawe/config/Settings.java b/core/src/main/java/com/boydti/fawe/config/Settings.java similarity index 100% rename from src/main/java/com/boydti/fawe/config/Settings.java rename to core/src/main/java/com/boydti/fawe/config/Settings.java diff --git a/src/main/java/com/boydti/fawe/logging/BlocksHubHook.java b/core/src/main/java/com/boydti/fawe/logging/BlocksHubHook.java similarity index 100% rename from src/main/java/com/boydti/fawe/logging/BlocksHubHook.java rename to core/src/main/java/com/boydti/fawe/logging/BlocksHubHook.java diff --git a/src/main/java/com/boydti/fawe/logging/LoggingExtent.java b/core/src/main/java/com/boydti/fawe/logging/LoggingExtent.java similarity index 100% rename from src/main/java/com/boydti/fawe/logging/LoggingExtent.java rename to core/src/main/java/com/boydti/fawe/logging/LoggingExtent.java diff --git a/src/main/java/com/boydti/fawe/object/ChunkLoc.java b/core/src/main/java/com/boydti/fawe/object/ChunkLoc.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/ChunkLoc.java rename to core/src/main/java/com/boydti/fawe/object/ChunkLoc.java diff --git a/src/main/java/com/boydti/fawe/object/EditSessionWrapper.java b/core/src/main/java/com/boydti/fawe/object/EditSessionWrapper.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/EditSessionWrapper.java rename to core/src/main/java/com/boydti/fawe/object/EditSessionWrapper.java diff --git a/src/main/java/com/boydti/fawe/object/FaweChangeSet.java b/core/src/main/java/com/boydti/fawe/object/FaweChangeSet.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/FaweChangeSet.java rename to core/src/main/java/com/boydti/fawe/object/FaweChangeSet.java diff --git a/src/main/java/com/boydti/fawe/object/FaweChunk.java b/core/src/main/java/com/boydti/fawe/object/FaweChunk.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/FaweChunk.java rename to core/src/main/java/com/boydti/fawe/object/FaweChunk.java diff --git a/src/main/java/com/boydti/fawe/object/FaweCommand.java b/core/src/main/java/com/boydti/fawe/object/FaweCommand.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/FaweCommand.java rename to core/src/main/java/com/boydti/fawe/object/FaweCommand.java diff --git a/src/main/java/com/boydti/fawe/object/FaweLocation.java b/core/src/main/java/com/boydti/fawe/object/FaweLocation.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/FaweLocation.java rename to core/src/main/java/com/boydti/fawe/object/FaweLocation.java diff --git a/src/main/java/com/boydti/fawe/object/FawePlayer.java b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java similarity index 94% rename from src/main/java/com/boydti/fawe/object/FawePlayer.java rename to core/src/main/java/com/boydti/fawe/object/FawePlayer.java index 1c0f8bb7..0a5c076d 100644 --- a/src/main/java/com/boydti/fawe/object/FawePlayer.java +++ b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java @@ -50,7 +50,7 @@ public abstract class FawePlayer { } public LocalSession getSession() { - return this.session != null ? this.session : Fawe.get().getWorldEdit().getSession(this.getPlayer()); + return (this.session != null || this.getPlayer() == null) ? this.session : Fawe.get().getWorldEdit().getSession(this.getPlayer()); } public HashSet getCurrentRegions() { diff --git a/src/main/java/com/boydti/fawe/object/HistoryExtent.java b/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/HistoryExtent.java rename to core/src/main/java/com/boydti/fawe/object/HistoryExtent.java diff --git a/src/main/java/com/boydti/fawe/object/IntegerPair.java b/core/src/main/java/com/boydti/fawe/object/IntegerPair.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/IntegerPair.java rename to core/src/main/java/com/boydti/fawe/object/IntegerPair.java diff --git a/src/main/java/com/boydti/fawe/object/NullChangeSet.java b/core/src/main/java/com/boydti/fawe/object/NullChangeSet.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/NullChangeSet.java rename to core/src/main/java/com/boydti/fawe/object/NullChangeSet.java diff --git a/src/main/java/com/boydti/fawe/object/PseudoRandom.java b/core/src/main/java/com/boydti/fawe/object/PseudoRandom.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/PseudoRandom.java rename to core/src/main/java/com/boydti/fawe/object/PseudoRandom.java diff --git a/src/main/java/com/boydti/fawe/object/RegionWrapper.java b/core/src/main/java/com/boydti/fawe/object/RegionWrapper.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/RegionWrapper.java rename to core/src/main/java/com/boydti/fawe/object/RegionWrapper.java diff --git a/src/main/java/com/boydti/fawe/object/SendChunk.java b/core/src/main/java/com/boydti/fawe/object/SendChunk.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/SendChunk.java rename to core/src/main/java/com/boydti/fawe/object/SendChunk.java diff --git a/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedHistory.java b/core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedHistory.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedHistory.java rename to core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedHistory.java diff --git a/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java b/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java rename to core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java diff --git a/src/main/java/com/boydti/fawe/object/changeset/FlushableChangeSet.java b/core/src/main/java/com/boydti/fawe/object/changeset/FlushableChangeSet.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/changeset/FlushableChangeSet.java rename to core/src/main/java/com/boydti/fawe/object/changeset/FlushableChangeSet.java diff --git a/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java b/core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java rename to core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java diff --git a/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java rename to core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java diff --git a/src/main/java/com/boydti/fawe/object/extent/NullExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/NullExtent.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/extent/NullExtent.java rename to core/src/main/java/com/boydti/fawe/object/extent/NullExtent.java diff --git a/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java rename to core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java diff --git a/src/main/java/com/boydti/fawe/object/extent/SafeExtentWrapper.java b/core/src/main/java/com/boydti/fawe/object/extent/SafeExtentWrapper.java similarity index 100% rename from src/main/java/com/boydti/fawe/object/extent/SafeExtentWrapper.java rename to core/src/main/java/com/boydti/fawe/object/extent/SafeExtentWrapper.java diff --git a/src/main/java/com/boydti/fawe/regions/FaweMaskManager.java b/core/src/main/java/com/boydti/fawe/regions/FaweMaskManager.java similarity index 100% rename from src/main/java/com/boydti/fawe/regions/FaweMaskManager.java rename to core/src/main/java/com/boydti/fawe/regions/FaweMaskManager.java diff --git a/src/main/java/com/boydti/fawe/util/ExtentWrapper.java b/core/src/main/java/com/boydti/fawe/util/ExtentWrapper.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/ExtentWrapper.java rename to core/src/main/java/com/boydti/fawe/util/ExtentWrapper.java diff --git a/src/main/java/com/boydti/fawe/util/FaweQueue.java b/core/src/main/java/com/boydti/fawe/util/FaweQueue.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/FaweQueue.java rename to core/src/main/java/com/boydti/fawe/util/FaweQueue.java diff --git a/src/main/java/com/boydti/fawe/util/Lag.java b/core/src/main/java/com/boydti/fawe/util/Lag.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/Lag.java rename to core/src/main/java/com/boydti/fawe/util/Lag.java diff --git a/src/main/java/com/boydti/fawe/util/MainUtil.java b/core/src/main/java/com/boydti/fawe/util/MainUtil.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/MainUtil.java rename to core/src/main/java/com/boydti/fawe/util/MainUtil.java diff --git a/src/main/java/com/boydti/fawe/util/MemUtil.java b/core/src/main/java/com/boydti/fawe/util/MemUtil.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/MemUtil.java rename to core/src/main/java/com/boydti/fawe/util/MemUtil.java diff --git a/src/main/java/com/boydti/fawe/util/Perm.java b/core/src/main/java/com/boydti/fawe/util/Perm.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/Perm.java rename to core/src/main/java/com/boydti/fawe/util/Perm.java diff --git a/src/main/java/com/boydti/fawe/util/ReflectionUtils.java b/core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/ReflectionUtils.java rename to core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java diff --git a/src/main/java/com/boydti/fawe/util/SetQueue.java b/core/src/main/java/com/boydti/fawe/util/SetQueue.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/SetQueue.java rename to core/src/main/java/com/boydti/fawe/util/SetQueue.java diff --git a/src/main/java/com/boydti/fawe/util/StringMan.java b/core/src/main/java/com/boydti/fawe/util/StringMan.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/StringMan.java rename to core/src/main/java/com/boydti/fawe/util/StringMan.java diff --git a/src/main/java/com/boydti/fawe/util/TaskManager.java b/core/src/main/java/com/boydti/fawe/util/TaskManager.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/TaskManager.java rename to core/src/main/java/com/boydti/fawe/util/TaskManager.java diff --git a/src/main/java/com/boydti/fawe/util/WEManager.java b/core/src/main/java/com/boydti/fawe/util/WEManager.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/WEManager.java rename to core/src/main/java/com/boydti/fawe/util/WEManager.java diff --git a/src/main/java/com/boydti/fawe/util/WESubscriber.java b/core/src/main/java/com/boydti/fawe/util/WESubscriber.java similarity index 100% rename from src/main/java/com/boydti/fawe/util/WESubscriber.java rename to core/src/main/java/com/boydti/fawe/util/WESubscriber.java diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java similarity index 99% rename from src/main/java/com/sk89q/worldedit/EditSession.java rename to core/src/main/java/com/sk89q/worldedit/EditSession.java index 927563e7..a1308b77 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -248,7 +248,7 @@ public class EditSession implements Extent { final String name = actor.getName(); final FawePlayer fp = FawePlayer.wrap(name); final LocalSession session = fp.getSession(); - if (this.fastmode = session.hasFastMode()) { + if (this.fastmode = (session == null ? false : session.hasFastMode())) { session.clearHistory(); } if (fp.hasWorldEditBypass()) { diff --git a/src/main/java/com/sk89q/worldedit/LocalSession.java b/core/src/main/java/com/sk89q/worldedit/LocalSession.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/LocalSession.java rename to core/src/main/java/com/sk89q/worldedit/LocalSession.java diff --git a/src/main/java/com/sk89q/worldedit/command/FlattenedClipboardTransform.java b/core/src/main/java/com/sk89q/worldedit/command/FlattenedClipboardTransform.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/command/FlattenedClipboardTransform.java rename to core/src/main/java/com/sk89q/worldedit/command/FlattenedClipboardTransform.java diff --git a/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/command/SchematicCommands.java rename to core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java diff --git a/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java rename to core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java similarity index 96% rename from src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java rename to core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java index 87d8d538..6775741b 100644 --- a/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java @@ -29,6 +29,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; +import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; import com.google.common.base.Joiner; import com.sk89q.minecraft.util.commands.CommandException; @@ -218,7 +219,7 @@ public final class CommandManager { TaskManager.IMP.async(new Runnable() { @Override public void run() { - Actor actor = platformManager.createProxyActor(event.getActor()); + final Actor actor = platformManager.createProxyActor(event.getActor()); String[] split = commandDetection(event.getArguments().split(" ")); // No command found! @@ -270,9 +271,16 @@ public final class CommandManager { if (editSession != null) { session.remember(editSession); editSession.flushQueue(); - + long time = System.currentTimeMillis() - start; + if (time > 5 && editSession.size() != 0) { + SetQueue.IMP.addTask(new Runnable() { + @Override + public void run() { + actor.print("[FAWE] Action complete"); + } + }); + } if (config.profile) { - long time = System.currentTimeMillis() - start; int changed = editSession.getBlockChangeCount(); if (time > 0) { double throughput = changed / (time / 1000.0); diff --git a/src/main/java/com/sk89q/worldedit/function/operation/Operations.java b/core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/function/operation/Operations.java rename to core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java diff --git a/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java rename to core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java diff --git a/src/main/java/com/sk89q/worldedit/function/visitor/DownwardVisitor.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/DownwardVisitor.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/function/visitor/DownwardVisitor.java rename to core/src/main/java/com/sk89q/worldedit/function/visitor/DownwardVisitor.java diff --git a/src/main/java/com/sk89q/worldedit/function/visitor/EntityVisitor.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/EntityVisitor.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/function/visitor/EntityVisitor.java rename to core/src/main/java/com/sk89q/worldedit/function/visitor/EntityVisitor.java diff --git a/src/main/java/com/sk89q/worldedit/function/visitor/FlatRegionVisitor.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/FlatRegionVisitor.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/function/visitor/FlatRegionVisitor.java rename to core/src/main/java/com/sk89q/worldedit/function/visitor/FlatRegionVisitor.java diff --git a/src/main/java/com/sk89q/worldedit/function/visitor/LayerVisitor.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/LayerVisitor.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/function/visitor/LayerVisitor.java rename to core/src/main/java/com/sk89q/worldedit/function/visitor/LayerVisitor.java diff --git a/src/main/java/com/sk89q/worldedit/function/visitor/NonRisingVisitor.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/NonRisingVisitor.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/function/visitor/NonRisingVisitor.java rename to core/src/main/java/com/sk89q/worldedit/function/visitor/NonRisingVisitor.java diff --git a/src/main/java/com/sk89q/worldedit/function/visitor/RecursiveVisitor.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/RecursiveVisitor.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/function/visitor/RecursiveVisitor.java rename to core/src/main/java/com/sk89q/worldedit/function/visitor/RecursiveVisitor.java diff --git a/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java rename to core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java diff --git a/src/main/java/com/sk89q/worldedit/history/change/EntityCreate.java b/core/src/main/java/com/sk89q/worldedit/history/change/EntityCreate.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/history/change/EntityCreate.java rename to core/src/main/java/com/sk89q/worldedit/history/change/EntityCreate.java diff --git a/src/main/java/com/sk89q/worldedit/history/change/EntityRemove.java b/core/src/main/java/com/sk89q/worldedit/history/change/EntityRemove.java similarity index 100% rename from src/main/java/com/sk89q/worldedit/history/change/EntityRemove.java rename to core/src/main/java/com/sk89q/worldedit/history/change/EntityRemove.java diff --git a/src/main/resources/LICENSE b/core/src/main/resources/LICENSE similarity index 100% rename from src/main/resources/LICENSE rename to core/src/main/resources/LICENSE diff --git a/forge/.gradle/gradle.log b/forge/.gradle/gradle.log new file mode 100644 index 00000000..e69de29b diff --git a/forge/build.gradle b/forge/build.gradle new file mode 100644 index 00000000..ec7e5d8f --- /dev/null +++ b/forge/build.gradle @@ -0,0 +1,81 @@ +buildscript { + repositories { + jcenter() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + maven {url = "http://repo.minecrell.net/snapshots"} + } + dependencies { + classpath 'net.minecrell:VanillaGradle:2.0.3-SNAPSHOT' + classpath 'net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT' + } +} + +apply plugin: 'net.minecrell.vanilla.server.library' +apply plugin: 'com.github.johnrengelman.shadow' + +dependencies { + compile project(':core') + compile 'org.spongepowered:spongeapi:4.+' + compile 'org.mcstats.sponge:metrics:R8-SNAPSHOT' +} + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +repositories { + maven { + name = 'forge' + url = 'http://files.minecraftforge.net/maven' + } + maven { + name = "Sponge" + url = "https://repo.spongepowered.org/maven" + } + maven { + name = "Sponge Metrics" + url = "http://repo.mcstats.org/content/repositories/releases/" + } +} +minecraft { + version = "1.8.9" + mappings = "stable_22" + runDir = 'run' +} + +project.archivesBaseName = "${project.archivesBaseName}-mc${minecraft.version}" + +processResources { + from(sourceSets.main.resources.srcDirs) { + expand 'version': project.version, + 'mcVersion': project.minecraft.version + } +} +shadowJar { + dependencies { + include(dependency(':core')) + include(dependency('org.mcstats.sponge:metrics:R8-SNAPSHOT')) + } + relocate 'org.mcstats', 'com.boydti.fawe.stats' + archiveName = "${parent.name}-${project.name}-${parent.version}.jar" + destinationDir = file '../target' +} +shadowJar.doLast { + task -> + ant.checksum file: task.archivePath +} + +reobf { + shadowJar { + mappingType = 'SEARGE' + } +} + +task deobfJar(type: Jar) { + from sourceSets.main.output + classifier = 'dev' +} + +build.dependsOn(shadowJar) diff --git a/forge/src/main/java/com/boydti/fawe/forge/BukkitCommand.java b/forge/src/main/java/com/boydti/fawe/forge/BukkitCommand.java new file mode 100644 index 00000000..27ebfd96 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/BukkitCommand.java @@ -0,0 +1,31 @@ +package com.boydti.fawe.bukkit; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.config.BBC; +import com.boydti.fawe.object.FaweCommand; +import com.boydti.fawe.object.FawePlayer; + +public class BukkitCommand implements CommandExecutor { + + private final FaweCommand cmd; + + public BukkitCommand(final FaweCommand cmd) { + this.cmd = cmd; + } + + @Override + public boolean onCommand(final CommandSender sender, final Command cmd, final String label, final String[] args) { + final FawePlayer plr = Fawe.imp().wrap(sender); + if (!sender.hasPermission(this.cmd.getPerm())) { + BBC.NO_PERM.send(plr, this.cmd.getPerm()); + return true; + } + this.cmd.execute(plr, args); + return true; + } + +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/BukkitPlayer.java b/forge/src/main/java/com/boydti/fawe/forge/BukkitPlayer.java new file mode 100644 index 00000000..55296e6e --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/BukkitPlayer.java @@ -0,0 +1,71 @@ +package com.boydti.fawe.bukkit; + +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.object.FaweLocation; +import com.boydti.fawe.object.FawePlayer; + +public class BukkitPlayer extends FawePlayer { + + public BukkitPlayer(final Player parent) { + super(parent); + } + + @Override + public String getName() { + return this.parent.getName(); + } + + @Override + public UUID getUUID() { + return this.parent.getUniqueId(); + } + + @Override + public boolean hasPermission(final String perm) { + return this.parent.hasPermission(perm); + } + + @Override + public void setPermission(final String perm, final boolean flag) { + /* + * Permissions are used to managing WorldEdit region restrictions + * - The `/wea` command will give/remove the required bypass permission + */ + if (Fawe. imp().getVault() == null) { + this.parent.addAttachment(Fawe. imp()).setPermission("fawe.bypass", flag); + } else if (flag) { + Fawe. imp().getVault().permission.playerAdd(this.parent, perm); + } else { + Fawe. imp().getVault().permission.playerRemove(this.parent, perm); + } + } + + @Override + public void sendMessage(final String message) { + this.parent.sendMessage(ChatColor.translateAlternateColorCodes('&', message)); + } + + @Override + public void executeCommand(final String cmd) { + Bukkit.getServer().dispatchCommand(this.parent, cmd); + } + + @Override + public FaweLocation getLocation() { + final Location loc = this.parent.getLocation(); + return new FaweLocation(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + } + + @Override + public com.sk89q.worldedit.entity.Player getPlayer() { + return Fawe. imp().getWorldEditPlugin().wrapPlayer(this.parent); + } + +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/BukkitTaskMan.java b/forge/src/main/java/com/boydti/fawe/forge/BukkitTaskMan.java new file mode 100644 index 00000000..56c634bb --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/BukkitTaskMan.java @@ -0,0 +1,67 @@ +package com.boydti.fawe.bukkit; + +import java.util.HashMap; + +import org.apache.commons.lang.mutable.MutableInt; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.util.TaskManager; + +public class BukkitTaskMan extends TaskManager { + + private final Plugin plugin; + + public BukkitTaskMan(final Plugin plugin) { + this.plugin = plugin; + } + + @Override + public int repeat(final Runnable r, final int interval) { + return this.plugin.getServer().getScheduler().scheduleSyncRepeatingTask(this.plugin, r, interval, interval); + } + + @Override + public int repeatAsync(final Runnable r, final int interval) { + return this.plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(this.plugin, r, interval, interval); + } + + public MutableInt index = new MutableInt(0); + public HashMap tasks = new HashMap<>(); + + @Override + public void async(final Runnable r) { + if (r == null) { + return; + } + this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, r).getTaskId(); + } + + @Override + public void task(final Runnable r) { + if (r == null) { + return; + } + this.plugin.getServer().getScheduler().runTask(this.plugin, r).getTaskId(); + } + + @Override + public void later(final Runnable r, final int delay) { + if (r == null) { + return; + } + this.plugin.getServer().getScheduler().runTaskLater(this.plugin, r, delay).getTaskId(); + } + + @Override + public void laterAsync(final Runnable r, final int delay) { + this.plugin.getServer().getScheduler().runTaskLaterAsynchronously(this.plugin, r, delay); + } + + @Override + public void cancel(final int task) { + if (task != -1) { + Bukkit.getScheduler().cancelTask(task); + } + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/FaweBukkit.java b/forge/src/main/java/com/boydti/fawe/forge/FaweBukkit.java new file mode 100644 index 00000000..8afdacad --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/FaweBukkit.java @@ -0,0 +1,298 @@ +package com.boydti.fawe.bukkit; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweAPI; +import com.boydti.fawe.IFawe; +import com.boydti.fawe.bukkit.regions.FactionsFeature; +import com.boydti.fawe.bukkit.regions.FactionsUUIDFeature; +import com.boydti.fawe.bukkit.regions.GriefPreventionFeature; +import com.boydti.fawe.bukkit.regions.PlotMeFeature; +import com.boydti.fawe.bukkit.regions.PlotSquaredFeature; +import com.boydti.fawe.bukkit.regions.PreciousStonesFeature; +import com.boydti.fawe.bukkit.regions.ResidenceFeature; +import com.boydti.fawe.bukkit.regions.TownyFeature; +import com.boydti.fawe.bukkit.regions.Worldguard; +import com.boydti.fawe.bukkit.v1_8.BukkitEditSessionWrapper_1_8; +import com.boydti.fawe.bukkit.v1_8.BukkitQueue_1_8; +import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9; +import com.boydti.fawe.object.EditSessionWrapper; +import com.boydti.fawe.object.FaweCommand; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.regions.FaweMaskManager; +import com.boydti.fawe.util.FaweQueue; +import com.boydti.fawe.util.StringMan; +import com.boydti.fawe.util.TaskManager; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; + +public class FaweBukkit extends JavaPlugin implements IFawe { + + private VaultUtil vault; + private WorldEditPlugin worldedit; + + public VaultUtil getVault() { + return this.vault; + } + + public WorldEditPlugin getWorldEditPlugin() { + if (this.worldedit == null) { + this.worldedit = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"); + } + return this.worldedit; + } + + @Override + public void onEnable() { + try { + Fawe.set(this); + try { + final Class clazz = Class.forName("org.spigotmc.AsyncCatcher"); + final Field field = clazz.getDeclaredField("enabled"); + field.set(null, false); + } catch (final Throwable e) { + e.printStackTrace(); + } + } catch (final Exception e) { + e.printStackTrace(); + this.getServer().shutdown(); + } + } + + @Override + public void debug(final String s) { + this.getLogger().info(ChatColor.translateAlternateColorCodes('&', s)); + } + + @Override + public File getDirectory() { + return this.getDataFolder(); + } + + @Override + public void setupCommand(final String label, final FaweCommand cmd) { + this.getCommand(label).setExecutor(new BukkitCommand(cmd)); + } + + @Override + public FawePlayer wrap(final Object obj) { + if (obj.getClass() == String.class) { + return new BukkitPlayer(Bukkit.getPlayer((String) obj)); + } else if (obj instanceof Player) { + return new BukkitPlayer((Player) obj); + } else { + return null; + } + } + + /** + * Kinda a really messy class I just copied over from an old project
+ * - Still works, so cbf cleaning it up
+ * - Completely optional to have this class enabled since things get cancelled further down anyway
+ * - Useful since it informs the player why an edit changed no blocks etc.
+ * - Predicts the number of blocks changed and cancels the edit if it's too large
+ * - Predicts where the edit will effect and cancels it if it's outside a region
+ * - Restricts the brush iteration limit
+ */ + @Override + public void setupWEListener() { + this.getServer().getPluginManager().registerEvents(new WEListener(), this); + } + + /** + * Vault isn't required, but used for setting player permissions (WorldEdit bypass) + * @return + */ + @Override + public void setupVault() { + try { + this.vault = new VaultUtil(); + } catch (final Throwable e) { + this.debug("&cPlease install vault!"); + } + } + + /** + * The task manager handles sync/async tasks + */ + @Override + public TaskManager getTaskManager() { + return new BukkitTaskMan(this); + } + + @Override + public int[] getVersion() { + try { + final int[] version = new int[3]; + final String[] split = Bukkit.getBukkitVersion().split("-")[0].split("\\."); + version[0] = Integer.parseInt(split[0]); + version[1] = Integer.parseInt(split[1]); + if (split.length == 3) { + version[2] = Integer.parseInt(split[2]); + } + return version; + } catch (final Exception e) { + e.printStackTrace(); + this.debug(StringMan.getString(Bukkit.getBukkitVersion())); + this.debug(StringMan.getString(Bukkit.getBukkitVersion().split("-")[0].split("\\."))); + return new int[] { Integer.MAX_VALUE, 0, 0 }; + } + } + + /** + * The FaweQueue is a core part of block placement
+ * - The queue returned here is used in the SetQueue class (SetQueue handles the implementation specific queue)
+ * - Block changes are grouped by chunk (as it's more efficient for lighting/packet sending)
+ * - The FaweQueue returned here will provide the wrapper around the chunk object (FaweChunk)
+ * - When a block change is requested, the SetQueue will first check if the chunk exists in the queue, or it will create and add it
+ */ + @Override + public FaweQueue getQueue() { + if (FaweAPI.checkVersion(this.getServerVersion(), 1, 9, 0)) { + try { + return new BukkitQueue_1_9(); + } catch (final Throwable e) { + e.printStackTrace(); + } + } + return new BukkitQueue_1_8(); + } + + private int[] version; + + public int[] getServerVersion() { + if (this.version == null) { + try { + this.version = new int[3]; + final String[] split = Bukkit.getBukkitVersion().split("-")[0].split("\\."); + this.version[0] = Integer.parseInt(split[0]); + this.version[1] = Integer.parseInt(split[1]); + if (split.length == 3) { + this.version[2] = Integer.parseInt(split[2]); + } + } catch (final NumberFormatException e) { + e.printStackTrace(); + Fawe.debug(StringMan.getString(Bukkit.getBukkitVersion())); + Fawe.debug(StringMan.getString(Bukkit.getBukkitVersion().split("-")[0].split("\\."))); + return new int[] { Integer.MAX_VALUE, 0, 0 }; + } + } + return this.version; + } + + /** + * The EditSessionWrapper should have the same functionality as the normal EditSessionWrapper but with some optimizations + */ + @Override + public EditSessionWrapper getEditSessionWrapper(final EditSession session) { + return new BukkitEditSessionWrapper_1_8(session); + } + + /** + * A mask manager handles region restrictions e.g. PlotSquared plots / WorldGuard regions + */ + @Override + public Collection getMaskManagers() { + final Plugin worldguardPlugin = Bukkit.getServer().getPluginManager().getPlugin("WorldGuard"); + final ArrayList managers = new ArrayList<>(); + if ((worldguardPlugin != null) && worldguardPlugin.isEnabled()) { + try { + managers.add(new Worldguard(worldguardPlugin, this)); + Fawe.debug("Plugin 'WorldGuard' found. Using it now."); + } catch (final Throwable e) { + e.printStackTrace(); + } + } else { + Fawe.debug("Plugin 'WorldGuard' not found. Worldguard features disabled."); + } + final Plugin plotmePlugin = Bukkit.getServer().getPluginManager().getPlugin("PlotMe"); + if ((plotmePlugin != null) && plotmePlugin.isEnabled()) { + try { + managers.add(new PlotMeFeature(plotmePlugin, this)); + Fawe.debug("Plugin 'PlotMe' found. Using it now."); + } catch (final Throwable e) { + e.printStackTrace(); + } + } else { + Fawe.debug("Plugin 'PlotMe' not found. PlotMe features disabled."); + } + final Plugin townyPlugin = Bukkit.getServer().getPluginManager().getPlugin("Towny"); + if ((townyPlugin != null) && townyPlugin.isEnabled()) { + try { + managers.add(new TownyFeature(townyPlugin, this)); + Fawe.debug("Plugin 'Towny' found. Using it now."); + } catch (final Throwable e) { + e.printStackTrace(); + } + } else { + Fawe.debug("Plugin 'Towny' not found. Towny features disabled."); + } + final Plugin factionsPlugin = Bukkit.getServer().getPluginManager().getPlugin("Factions"); + if ((factionsPlugin != null) && factionsPlugin.isEnabled()) { + try { + managers.add(new FactionsFeature(factionsPlugin, this)); + Fawe.debug("Plugin 'Factions' found. Using it now."); + } catch (final Throwable e) { + managers.add(new FactionsUUIDFeature(factionsPlugin, this)); + Fawe.debug("Plugin 'FactionsUUID' found. Using it now."); + } + } else { + Fawe.debug("Plugin 'Factions' not found. Factions features disabled."); + } + final Plugin residencePlugin = Bukkit.getServer().getPluginManager().getPlugin("Residence"); + if ((residencePlugin != null) && residencePlugin.isEnabled()) { + try { + managers.add(new ResidenceFeature(residencePlugin, this)); + Fawe.debug("Plugin 'Residence' found. Using it now."); + } catch (final Throwable e) { + e.printStackTrace(); + } + } else { + Fawe.debug("Plugin 'Residence' not found. Factions features disabled."); + } + final Plugin griefpreventionPlugin = Bukkit.getServer().getPluginManager().getPlugin("GriefPrevention"); + if ((griefpreventionPlugin != null) && griefpreventionPlugin.isEnabled()) { + try { + managers.add(new GriefPreventionFeature(griefpreventionPlugin, this)); + Fawe.debug("Plugin 'GriefPrevention' found. Using it now."); + } catch (final Throwable e) { + e.printStackTrace(); + } + } else { + Fawe.debug("Plugin 'GriefPrevention' not found. GriefPrevention features disabled."); + } + final Plugin plotsquaredPlugin = Bukkit.getServer().getPluginManager().getPlugin("PlotSquared"); + if ((plotsquaredPlugin != null) && plotsquaredPlugin.isEnabled()) { + try { + managers.add(new PlotSquaredFeature(plotsquaredPlugin, this)); + Fawe.debug("Plugin 'PlotSquared' found. Using it now."); + } catch (final Throwable e) { + e.printStackTrace(); + } + } else { + Fawe.debug("Plugin 'PlotSquared' not found. PlotSquared features disabled."); + } + final Plugin preciousstonesPlugin = Bukkit.getServer().getPluginManager().getPlugin("PreciousStones"); + if ((preciousstonesPlugin != null) && preciousstonesPlugin.isEnabled()) { + try { + managers.add(new PreciousStonesFeature(preciousstonesPlugin, this)); + Fawe.debug("Plugin 'PreciousStones' found. Using it now."); + } catch (final Throwable e) { + e.printStackTrace(); + } + } else { + Fawe.debug("Plugin 'PreciousStones' not found. PreciousStones features disabled."); + } + return managers; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/VaultUtil.java b/forge/src/main/java/com/boydti/fawe/forge/VaultUtil.java new file mode 100644 index 00000000..5deda5f8 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/VaultUtil.java @@ -0,0 +1,19 @@ +package com.boydti.fawe.bukkit; + +import net.milkbowl.vault.permission.Permission; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.RegisteredServiceProvider; + +public class VaultUtil { + public final Permission permission; + + public VaultUtil() { + final RegisteredServiceProvider permissionProvider = Bukkit.getServer().getServicesManager().getRegistration(net.milkbowl.vault.permission.Permission.class); + if (permissionProvider != null) { + this.permission = permissionProvider.getProvider(); + } else { + this.permission = null; + } + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/WEListener.java b/forge/src/main/java/com/boydti/fawe/forge/WEListener.java new file mode 100644 index 00000000..ece78735 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/WEListener.java @@ -0,0 +1,321 @@ +package com.boydti.fawe.bukkit; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.config.BBC; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.RegionWrapper; +import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.Perm; +import com.boydti.fawe.util.WEManager; +import com.sk89q.worldedit.BlockVector; +import com.sk89q.worldedit.IncompleteRegionException; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.bukkit.BukkitUtil; +import com.sk89q.worldedit.regions.Region; + +/** + * Kinda a really messy class I just copied over from an old project
+ * - Still works, so cbf cleaning it up
+ * - Completely optional to have this class enabled since things get cancelled further down anyway
+ * - Useful since it informs the player why an edit changed no blocks etc.
+ * - Predicts the number of blocks changed and cancels the edit if it's too large
+ * - Predicts where the edit will effect and cancels it if it's outside a region
+ * - Restricts the brush iteration limit
+ * @deprecated as I plan on replacing it at some point + */ +@Deprecated +public class WEListener implements Listener { + + public final HashSet rad1 = new HashSet<>(Arrays.asList("forestgen", "pumpkins", "drain", "fixwater", "fixlava", "replacenear", "snow", "thaw", "ex", "butcher", "size")); + public final HashSet rad2 = new HashSet<>(Arrays.asList("fill", "fillr", "removenear", "remove")); + public final HashSet rad2_1 = new HashSet<>(Arrays.asList("hcyl", "cyl")); + public final HashSet rad2_2 = new HashSet<>(Arrays.asList("sphere", "pyramid")); + public final HashSet rad2_3 = new HashSet<>(Arrays.asList("brush smooth")); + public final HashSet rad3_1 = new HashSet<>(Arrays.asList("brush gravity")); + public final HashSet rad3_2 = new HashSet<>(Arrays.asList("brush sphere", "brush cylinder")); + + public final HashSet region = new HashSet<>(Arrays.asList("move", "set", "replace", "overlay", "walls", "outline", "deform", "hollow", "smooth", "naturalize", "paste", "count", "distr", + "copy", "cut", "green", "setbiome")); + public final HashSet regionExtend = new HashSet<>(Arrays.asList("stack")); + public final HashSet unregioned = new HashSet<>(Arrays.asList("paste", "redo", "undo", "rotate", "flip", "generate", "schematic", "schem")); + public final HashSet unsafe1 = new HashSet<>(Arrays.asList("cs", ".s", "restore", "snapshot", "delchunks", "listchunks")); + public final HashSet restricted = new HashSet<>(Arrays.asList("up")); + public final HashSet other = new HashSet<>(Arrays.asList("undo", "redo", "schematic", "schem", "count")); + + public boolean checkCommand(final List list, final String cmd) { + for (final String identifier : list) { + if (("/" + identifier).equals(cmd) || ("//" + identifier).equals(cmd) || ("/worldedit:/" + identifier).equals(cmd) || ("/worldedit:" + identifier).equals(cmd)) { + return true; + } + } + return false; + } + + public String reduceCmd(final String cmd, final boolean single) { + if (cmd.startsWith("/worldedit:/")) { + return cmd.substring(12); + } + if (cmd.startsWith("/worldedit:")) { + return cmd.substring(11); + } + if (cmd.startsWith("//")) { + return cmd.substring(2); + } + if (single && cmd.startsWith("/")) { + return cmd.substring(1); + } + return cmd; + } + + public int getInt(final String s) { + try { + int max = 0; + final String[] split = s.split(","); + for (final String rad : split) { + final int val = Integer.parseInt(rad); + if (val > max) { + max = val; + } + } + return max; + } catch (final NumberFormatException e) { + return 0; + } + } + + public boolean checkVolume(final FawePlayer player, final long volume, final long max, final Cancellable e) { + if (volume > max) { + MainUtil.sendMessage(FawePlayer.wrap(player.getName()), BBC.WORLDEDIT_VOLUME.s().replaceAll("%current%", volume + "").replaceAll("%max%", max + "")); + e.setCancelled(true); + } + if (Perm.hasPermission(player, "fawe.admin") && !Perm.hasPermission(player, "fawe.bypass")) { + BBC.WORLDEDIT_BYPASS.send(player); + } + return true; + } + + public boolean checkSelection(final FawePlayer player, final int modifier, final long max, final Cancellable e) { + final LocalSession session = Fawe.get().getWorldEdit().getSession(player.getName()); + final LocalWorld w = BukkitUtil.getLocalWorld(player.parent.getWorld()); + Region selection = null; + try { + selection = session.getSelection(w); + } catch (final IncompleteRegionException e2) {} + if (selection == null) { + return true; + } + final BlockVector pos1 = selection.getMinimumPoint().toBlockVector(); + final BlockVector pos2 = selection.getMaximumPoint().toBlockVector(); + final HashSet mask = WEManager.IMP.getMask(player); + final RegionWrapper region = new RegionWrapper(pos1.getBlockX(), pos2.getBlockX(), pos1.getBlockZ(), pos2.getBlockZ()); + if (Settings.REQUIRE_SELECTION) { + String arg = null; + if (!WEManager.IMP.regionContains(region, mask)) { + arg = "pos1 + pos2"; + } else if (!WEManager.IMP.maskContains(mask, pos1.getBlockX(), pos1.getBlockZ())) { + arg = "pos1"; + } else if (!WEManager.IMP.maskContains(mask, pos2.getBlockX(), pos2.getBlockZ())) { + arg = "pos2"; + } + if (arg != null) { + BBC.REQUIRE_SELECTION_IN_MASK.send(player, arg); + e.setCancelled(true); + if (Perm.hasPermission(player, "fawe.admin") && !Perm.hasPermission(player, "fawe.bypass")) { + BBC.WORLDEDIT_BYPASS.send(player); + } + return true; + } + if (!WEManager.IMP.regionContains(region, mask)) { + BBC.REQUIRE_SELECTION_IN_MASK.send(player, "pos1 + pos2"); + e.setCancelled(true); + if (Perm.hasPermission(player, "fawe.admin") && !Perm.hasPermission(player, "fawe.bypass")) { + BBC.WORLDEDIT_BYPASS.send(player); + } + return true; + } + } + final long volume = Math.abs((pos1.getBlockX() - pos2.getBlockX()) * (pos1.getBlockY() - pos2.getBlockY()) * (pos1.getBlockZ() - pos2.getBlockZ())) * modifier; + return this.checkVolume(player, volume, max, e); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public boolean onPlayerCommand(final PlayerCommandPreprocessEvent e) { + final FawePlayer player = FawePlayer.wrap(e.getPlayer()); + final String message = e.getMessage(); + final String cmd = message.toLowerCase(); + final boolean single = true; + final String[] split = cmd.split(" "); + + final long maxVolume = Settings.WE_MAX_VOLUME; + final long maxIterations = Settings.WE_MAX_ITERATIONS; + // if (player.hasPermission("fawe.bypass")) { + // return true; + // } + if (split.length >= 2) { + final String reduced = this.reduceCmd(split[0], single); + final String reduced2 = this.reduceCmd(split[0] + " " + split[1], single); + if (this.rad1.contains(reduced)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + final long volume = this.getInt(split[1]) * 256; + return this.checkVolume(player, volume, maxVolume, e); + } + if (this.rad2.contains(reduced)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + if (split.length >= 3) { + final long volume = this.getInt(split[2]) * 256; + return this.checkVolume(player, volume, maxVolume, e); + } + return true; + } + if (this.rad2_1.contains(reduced)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + if (split.length >= 4) { + final long volume = this.getInt(split[2]) * this.getInt(split[3]); + return this.checkVolume(player, volume, maxVolume, e); + } + return true; + } + if (this.rad2_2.contains(reduced)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + if (split.length >= 3) { + final long radius = this.getInt(split[2]); + final long volume = radius * radius; + return this.checkVolume(player, volume, maxVolume, e); + } + return true; + } + if (this.rad2_3.contains(reduced2)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + if (split.length >= 3) { + if (split.length == 4) { + final int iterations = this.getInt(split[3]); + if (iterations > maxIterations) { + MainUtil.sendMessage(player, BBC.WORLDEDIT_ITERATIONS.s().replaceAll("%current%", iterations + "").replaceAll("%max%", maxIterations + "")); + e.setCancelled(true); + if (Perm.hasPermission(player, "fawe.admin") && !Perm.hasPermission(player, "fawe.bypass")) { + BBC.WORLDEDIT_BYPASS.send(player); + } + return true; + } + } + final long radius = this.getInt(split[2]); + final long volume = radius * radius; + return this.checkVolume(player, volume, maxVolume, e); + } + return true; + } + if (this.rad3_1.contains(reduced2)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + if (split.length >= 3) { + int i = 2; + if (split[i].equalsIgnoreCase("-h")) { + i = 3; + } + final long radius = this.getInt(split[i]); + final long volume = radius * radius; + return this.checkVolume(player, volume, maxVolume, e); + } + return true; + } + if (this.rad3_2.contains(reduced2)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + if (split.length >= 4) { + int i = 3; + if (split[i].equalsIgnoreCase("-h")) { + i = 4; + } + final long radius = this.getInt(split[i]); + final long volume = radius * radius; + return this.checkVolume(player, volume, maxVolume, e); + } + return true; + } + if (this.regionExtend.contains(reduced)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + return this.checkSelection(player, this.getInt(split[1]), maxVolume, e); + } + } + final String reduced = this.reduceCmd(split[0], single); + if (Settings.WE_BLACKLIST.contains(reduced)) { + BBC.WORLDEDIT_UNSAFE.send(player); + e.setCancelled(true); + if (Perm.hasPermission(player, "fawe.admin") && !Perm.hasPermission(player, "fawe.bypass")) { + BBC.WORLDEDIT_BYPASS.send(player); + } + } + if (this.restricted.contains(reduced)) { + final HashSet mask = WEManager.IMP.getMask(player); + final Location loc = player.parent.getLocation(); + for (final RegionWrapper region : mask) { + if (region.isIn(loc.getBlockX(), loc.getBlockZ())) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + return true; + } + } + e.setCancelled(true); + BBC.REQUIRE_SELECTION_IN_MASK.send(player); + return true; + } + if (this.region.contains(reduced)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + return this.checkSelection(player, 1, maxVolume, e); + } + if (this.unregioned.contains(reduced)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + } + if (this.other.contains(reduced)) { + if (WEManager.IMP.delay(player, message)) { + e.setCancelled(true); + return true; + } + } + return true; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/BukkitMaskManager.java b/forge/src/main/java/com/boydti/fawe/forge/regions/BukkitMaskManager.java new file mode 100644 index 00000000..4a78360d --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/BukkitMaskManager.java @@ -0,0 +1,12 @@ +package com.boydti.fawe.bukkit.regions; + +import org.bukkit.entity.Player; + +import com.boydti.fawe.regions.FaweMaskManager; + +public abstract class BukkitMaskManager extends FaweMaskManager { + + public BukkitMaskManager(final String plugin) { + super(plugin); + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/FactionsFeature.java b/forge/src/main/java/com/boydti/fawe/forge/regions/FactionsFeature.java new file mode 100644 index 00000000..6ff9cf1c --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/FactionsFeature.java @@ -0,0 +1,49 @@ +package com.boydti.fawe.bukkit.regions; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.object.FawePlayer; +import com.massivecraft.factions.entity.BoardColl; +import com.massivecraft.factions.entity.Faction; +import com.massivecraft.massivecore.ps.PS; + +public class FactionsFeature extends BukkitMaskManager implements Listener { + FaweBukkit plugin; + Plugin factions; + + public FactionsFeature(final Plugin factionsPlugin, final FaweBukkit p3) { + super(factionsPlugin.getName()); + this.factions = factionsPlugin; + this.plugin = p3; + BoardColl.get(); + } + + @Override + public FaweMask getMask(final FawePlayer fp) { + final Player player = fp.parent; + final Location loc = player.getLocation(); + final PS ps = PS.valueOf(loc); + final Faction fac = BoardColl.get().getFactionAt(ps); + if (fac != null) { + if (fac.getOnlinePlayers().contains(player)) { + if (fac.getComparisonName().equals("wilderness") == false) { + final Chunk chunk = loc.getChunk(); + final Location pos1 = new Location(loc.getWorld(), chunk.getX() * 16, 0, chunk.getZ() * 16); + final Location pos2 = new Location(loc.getWorld(), (chunk.getX() * 16) + 15, 156, (chunk.getZ() * 16) + 15); + return new FaweMask(pos1, pos2) { + @Override + public String getName() { + return "CHUNK:" + loc.getChunk().getX() + "," + loc.getChunk().getZ(); + } + }; + } + } + } + return null; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/FactionsUUIDFeature.java b/forge/src/main/java/com/boydti/fawe/forge/regions/FactionsUUIDFeature.java new file mode 100644 index 00000000..7ab6eb2e --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/FactionsUUIDFeature.java @@ -0,0 +1,103 @@ +package com.boydti.fawe.bukkit.regions; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.RegionWrapper; +import com.boydti.fawe.util.Perm; +import com.massivecraft.factions.Board; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.Faction; + +public class FactionsUUIDFeature extends BukkitMaskManager implements Listener { + private final Board instance; + + public FactionsUUIDFeature(final Plugin factionsPlugin, final FaweBukkit p3) { + super(factionsPlugin.getName()); + this.instance = Board.getInstance(); + } + + @Override + public FaweMask getMask(final FawePlayer fp) { + final Player player = fp.parent; + final Chunk chunk = player.getLocation().getChunk(); + final boolean perm = Perm.hasPermission(FawePlayer.wrap(player), "fawe.factions.wilderness"); + final RegionWrapper locs = new RegionWrapper(chunk.getX(), chunk.getX(), chunk.getZ(), chunk.getZ()); + final World world = player.getWorld(); + + int count = 32; + + if (this.isAdded(locs, world, player, perm)) { + boolean hasPerm = true; + + RegionWrapper chunkSelection; + while (hasPerm && (count > 0)) { + count--; + + hasPerm = false; + + chunkSelection = new RegionWrapper(locs.maxX + 1, locs.maxX + 1, locs.minZ, locs.maxZ); + + if (this.isAdded(chunkSelection, world, player, perm)) { + locs.maxX += 1; + hasPerm = true; + } + + chunkSelection = new RegionWrapper(locs.minX - 1, locs.minX - 1, locs.minZ, locs.maxZ); + + if (this.isAdded(chunkSelection, world, player, perm)) { + locs.minX -= 1; + hasPerm = true; + } + + chunkSelection = new RegionWrapper(locs.minX, locs.maxX, locs.maxZ + 1, locs.maxZ + 1); + + if (this.isAdded(chunkSelection, world, player, perm)) { + locs.maxZ += 1; + hasPerm = true; + } + + chunkSelection = new RegionWrapper(locs.minX, locs.maxX, locs.minZ - 1, locs.minZ - 1); + + if (this.isAdded(chunkSelection, world, player, perm)) { + locs.minZ -= 1; + hasPerm = true; + } + } + + final Location pos1 = new Location(world, locs.minX << 4, 1, locs.minZ << 4); + final Location pos2 = new Location(world, 15 + (locs.maxX << 4), 256, 15 + (locs.maxZ << 4)); + return new FaweMask(pos1, pos2) { + @Override + public String getName() { + return "CHUNK:" + pos1.getChunk().getX() + "," + pos1.getChunk().getZ(); + } + }; + } + return null; + } + + public boolean isAdded(final RegionWrapper locs, final World world, final Player player, final boolean perm) { + for (int x = locs.minX; x <= locs.maxX; x++) { + for (int z = locs.minZ; z <= locs.maxZ; z++) { + final Faction fac = this.instance.getFactionAt(new FLocation(world.getName(), x, z)); + if (fac == null) { + return false; + } + if (!fac.getOnlinePlayers().contains(player)) { + return false; + } + if (fac.isWilderness() && !perm) { + return false; + } + } + } + return true; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/FaweMask.java b/forge/src/main/java/com/boydti/fawe/forge/regions/FaweMask.java new file mode 100644 index 00000000..02014725 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/FaweMask.java @@ -0,0 +1,97 @@ +package com.boydti.fawe.bukkit.regions; + +import java.util.Arrays; +import java.util.HashSet; + +import org.bukkit.Location; + +import com.boydti.fawe.object.RegionWrapper; + +public class FaweMask { + private String description = null; + private Location position1; + private Location position2; + + public FaweMask(final Location pos1, final Location pos2, final String id) { + if ((pos1 == null) || (pos2 == null)) { + throw new IllegalArgumentException("Locations cannot be null!"); + } + if (pos1.getWorld().equals(pos2.getWorld()) == false) { + throw new IllegalArgumentException("Locations must be in the same world!"); + } + this.description = id; + this.position1 = new Location(pos1.getWorld(), Math.min(pos1.getBlockX(), pos2.getBlockX()), 0, Math.min(pos1.getBlockZ(), pos2.getBlockZ())); + this.position2 = new Location(pos1.getWorld(), Math.max(pos1.getBlockX(), pos2.getBlockX()), 256, Math.max(pos1.getBlockZ(), pos2.getBlockZ())); + } + + public FaweMask(final Location pos1, final Location pos2) { + if ((pos1 == null) || (pos2 == null)) { + throw new IllegalArgumentException("Locations cannot be null!"); + } + if (pos1.getWorld().equals(pos2.getWorld()) == false) { + throw new IllegalArgumentException("Locations must be in the same world!"); + } + this.position1 = new Location(pos1.getWorld(), Math.min(pos1.getBlockX(), pos2.getBlockX()), 0, Math.min(pos1.getBlockZ(), pos2.getBlockZ())); + this.position2 = new Location(pos1.getWorld(), Math.max(pos1.getBlockX(), pos2.getBlockX()), 256, Math.max(pos1.getBlockZ(), pos2.getBlockZ())); + } + + public HashSet getRegions() { + final Location lower = this.getLowerBound(); + final Location upper = this.getUpperBound(); + return new HashSet<>(Arrays.asList(new RegionWrapper(lower.getBlockX(), upper.getBlockX(), lower.getBlockZ(), upper.getBlockZ()))); + } + + public String getName() { + return this.description; + } + + public Location getLowerBound() { + return this.position1; + } + + public Location getUpperBound() { + return this.position2; + } + + public void setBounds(final Location pos1, final Location pos2) { + if ((pos1 == null) || (pos2 == null)) { + throw new IllegalArgumentException("Locations cannot be null!"); + } + if (pos1.getWorld().equals(pos2.getWorld()) == false) { + throw new IllegalArgumentException("Locations must be in the same world!"); + } + this.position1 = new Location(pos1.getWorld(), Math.min(pos1.getBlockX(), pos2.getBlockX()), 0, Math.min(pos1.getBlockZ(), pos2.getBlockZ())); + this.position2 = new Location(pos1.getWorld(), Math.max(pos1.getBlockX(), pos2.getBlockX()), 256, Math.max(pos1.getBlockZ(), pos2.getBlockZ())); + } + + public Location[] getBounds() { + final Location[] locations = { this.position1, this.position2 }; + return locations; + } + + public boolean contains(final Location loc) { + if (this.position1.getWorld().equals(loc.getWorld())) { + if (loc.getBlockX() < this.position1.getBlockX()) { + return false; + } + if (loc.getBlockX() > this.position2.getBlockX()) { + return false; + } + if (loc.getBlockZ() < this.position1.getBlockZ()) { + return false; + } + if (loc.getBlockZ() > this.position2.getBlockZ()) { + return false; + } + if (loc.getBlockY() < this.position1.getBlockY()) { + return false; + } + if (loc.getBlockY() > this.position2.getBlockY()) { + return false; + } + } else { + return false; + } + return true; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/GriefPreventionFeature.java b/forge/src/main/java/com/boydti/fawe/forge/regions/GriefPreventionFeature.java new file mode 100644 index 00000000..022e0de4 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/GriefPreventionFeature.java @@ -0,0 +1,46 @@ +package com.boydti.fawe.bukkit.regions; + +import me.ryanhamshire.GriefPrevention.Claim; +import me.ryanhamshire.GriefPrevention.GriefPrevention; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.object.FawePlayer; + +public class GriefPreventionFeature extends BukkitMaskManager implements Listener { + FaweBukkit plugin; + Plugin griefprevention; + + public GriefPreventionFeature(final Plugin griefpreventionPlugin, final FaweBukkit p3) { + super(griefpreventionPlugin.getName()); + this.griefprevention = griefpreventionPlugin; + this.plugin = p3; + } + + @Override + public FaweMask getMask(final FawePlayer fp) { + final Player player = fp.parent; + final Location location = player.getLocation(); + final Claim claim = GriefPrevention.instance.dataStore.getClaimAt(location, true, null); + if (claim != null) { + final String uuid = player.getUniqueId().toString(); + if (claim.getOwnerName().equalsIgnoreCase(player.getName()) || claim.getOwnerName().equals(uuid)) { + claim.getGreaterBoundaryCorner().getBlockX(); + final Location pos1 = new Location(location.getWorld(), claim.getLesserBoundaryCorner().getBlockX(), 0, claim.getLesserBoundaryCorner().getBlockZ()); + final Location pos2 = new Location(location.getWorld(), claim.getGreaterBoundaryCorner().getBlockX(), 256, claim.getGreaterBoundaryCorner().getBlockZ()); + return new FaweMask(pos1, pos2) { + @Override + public String getName() { + return "CLAIM:" + claim.toString(); + } + }; + } + } + return null; + + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/PlotMeFeature.java b/forge/src/main/java/com/boydti/fawe/forge/regions/PlotMeFeature.java new file mode 100644 index 00000000..9949e37f --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/PlotMeFeature.java @@ -0,0 +1,50 @@ +package com.boydti.fawe.bukkit.regions; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.object.FawePlayer; +import com.worldcretornica.plotme_core.Plot; +import com.worldcretornica.plotme_core.PlotMe_Core; +import com.worldcretornica.plotme_core.bukkit.PlotMe_CorePlugin; +import com.worldcretornica.plotme_core.bukkit.api.BukkitPlayer; +import com.worldcretornica.plotme_core.bukkit.api.BukkitWorld; + +public class PlotMeFeature extends BukkitMaskManager implements Listener { + FaweBukkit plugin; + PlotMe_Core plotme; + + public PlotMeFeature(final Plugin plotmePlugin, final FaweBukkit p3) { + super(plotmePlugin.getName()); + this.plotme = ((PlotMe_CorePlugin) plotmePlugin).getAPI(); + this.plugin = p3; + + } + + @Override + public FaweMask getMask(final FawePlayer fp) { + final Player player = fp.parent; + final Location location = player.getLocation(); + final Plot plot = this.plotme.getPlotMeCoreManager().getPlotById(new BukkitPlayer(player)); + if (plot == null) { + return null; + } + final boolean isallowed = plot.isAllowed(player.getUniqueId()); + if (isallowed) { + final Location pos1 = new Location(location.getWorld(), this.plotme.getGenManager(player.getWorld().getName()).bottomX(plot.getId(), new BukkitWorld(player.getWorld())), 0, this.plotme + .getGenManager(player.getWorld().getName()).bottomZ(plot.getId(), new BukkitWorld(player.getWorld()))); + final Location pos2 = new Location(location.getWorld(), this.plotme.getGenManager(player.getWorld().getName()).topX(plot.getId(), new BukkitWorld(player.getWorld())), 256, this.plotme + .getGenManager(player.getWorld().getName()).topZ(plot.getId(), new BukkitWorld(player.getWorld()))); + return new FaweMask(pos1, pos2) { + @Override + public String getName() { + return plot.getId(); + } + }; + } + return null; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/PlotSquaredFeature.java b/forge/src/main/java/com/boydti/fawe/forge/regions/PlotSquaredFeature.java new file mode 100644 index 00000000..6d070267 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/PlotSquaredFeature.java @@ -0,0 +1,85 @@ +package com.boydti.fawe.bukkit.regions; + +import java.util.HashSet; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.RegionWrapper; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotId; +import com.intellectualcrafters.plot.object.PlotPlayer; +import com.plotsquared.bukkit.BukkitMain; + +public class PlotSquaredFeature extends BukkitMaskManager implements Listener { + FaweBukkit plugin; + + public PlotSquaredFeature(final Plugin plotPlugin, final FaweBukkit p3) { + super(plotPlugin.getName()); + this.plugin = p3; + BukkitMain.worldEdit = null; + PS.get().worldedit = null; + } + + @Override + public FaweMask getMask(final FawePlayer fp) { + final PlotPlayer pp = PlotPlayer.wrap(fp.parent); + Plot plot = pp.getCurrentPlot(); + if (plot == null) { + final com.intellectualcrafters.plot.object.Location loc = pp.getLocation(); + final String world = loc.getWorld(); + int min = Integer.MAX_VALUE; + for (final Plot p : pp.getPlots()) { + if (p.getArea().worldname.equals(world)) { + final double d = p.getHome().getEuclideanDistanceSquared(loc); + if (d < min) { + min = (int) d; + plot = p; + } + } + } + } + if (plot != null) { + final PlotId id = plot.getId(); + boolean hasPerm = false; + if (plot.owner != null) { + if (plot.owner.equals(pp.getUUID())) { + hasPerm = true; + } else if (plot.isAdded(pp.getUUID()) && pp.hasPermission("fawe.plotsquared.member")) { + hasPerm = true; + } + if (hasPerm) { + final World world = fp.parent.getWorld(); + final com.intellectualcrafters.plot.object.RegionWrapper region = plot.getLargestRegion(); + final HashSet regions = plot.getRegions(); + + final Location pos1 = new Location(world, region.minX, 0, region.minZ); + final Location pos2 = new Location(world, region.maxX, 256, region.maxZ); + + final HashSet faweRegions = new HashSet(); + for (final com.intellectualcrafters.plot.object.RegionWrapper current : regions) { + faweRegions.add(new RegionWrapper(current.minX, current.maxX, current.minZ, current.maxZ)); + } + return new FaweMask(pos1, pos2) { + @Override + public String getName() { + return "PLOT^2:" + id; + } + + @Override + public HashSet getRegions() { + return faweRegions; + } + }; + } + } + } + return null; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/PreciousStonesFeature.java b/forge/src/main/java/com/boydti/fawe/forge/regions/PreciousStonesFeature.java new file mode 100644 index 00000000..f1dc0068 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/PreciousStonesFeature.java @@ -0,0 +1,47 @@ +package com.boydti.fawe.bukkit.regions; + +import java.util.List; + +import net.sacredlabyrinth.Phaed.PreciousStones.FieldFlag; +import net.sacredlabyrinth.Phaed.PreciousStones.PreciousStones; +import net.sacredlabyrinth.Phaed.PreciousStones.vectors.Field; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.object.FawePlayer; + +public class PreciousStonesFeature extends BukkitMaskManager implements Listener { + FaweBukkit plugin; + Plugin preciousstones; + + public PreciousStonesFeature(final Plugin preciousstonesPlugin, final FaweBukkit p3) { + super(preciousstonesPlugin.getName()); + this.preciousstones = preciousstonesPlugin; + this.plugin = p3; + + } + + @Override + public FaweMask getMask(final FawePlayer fp) { + final Player player = fp.parent; + final Location location = player.getLocation(); + final List fields = PreciousStones.API().getFieldsProtectingArea(FieldFlag.PLOT, location); + for (final Field myfield : fields) { + if (myfield.getOwner().equalsIgnoreCase(player.getName()) || (myfield.getAllowed().contains(player.getName()))) { + final Location pos1 = new Location(location.getWorld(), myfield.getCorners().get(0).getBlockX(), myfield.getCorners().get(0).getBlockY(), myfield.getCorners().get(0).getBlockZ()); + final Location pos2 = new Location(location.getWorld(), myfield.getCorners().get(1).getBlockX(), myfield.getCorners().get(1).getBlockY(), myfield.getCorners().get(1).getBlockZ()); + return new FaweMask(pos1, pos2) { + @Override + public String getName() { + return "FIELD:" + myfield.toString(); + } + }; + } + } + return null; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/ResidenceFeature.java b/forge/src/main/java/com/boydti/fawe/forge/regions/ResidenceFeature.java new file mode 100644 index 00000000..e1c78ef8 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/ResidenceFeature.java @@ -0,0 +1,45 @@ +package com.boydti.fawe.bukkit.regions; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +import com.bekvon.bukkit.residence.Residence; +import com.bekvon.bukkit.residence.protection.ClaimedResidence; +import com.bekvon.bukkit.residence.protection.CuboidArea; +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.object.FawePlayer; + +public class ResidenceFeature extends BukkitMaskManager implements Listener { + FaweBukkit plugin; + Plugin residence; + + public ResidenceFeature(final Plugin residencePlugin, final FaweBukkit p3) { + super(residencePlugin.getName()); + this.residence = residencePlugin; + this.plugin = p3; + + } + + @Override + public FaweMask getMask(final FawePlayer fp) { + final Player player = fp.parent; + final Location location = player.getLocation(); + final ClaimedResidence residence = Residence.getResidenceManager().getByLoc(location); + if (residence != null) { + if (residence.getPlayersInResidence().contains(player)) { + final CuboidArea area = residence.getAreaArray()[0]; + final Location pos1 = area.getHighLoc(); + final Location pos2 = area.getLowLoc(); + return new FaweMask(pos1, pos2) { + @Override + public String getName() { + return "RESIDENCE: " + residence.getName(); + } + }; + } + } + return null; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/TownyFeature.java b/forge/src/main/java/com/boydti/fawe/forge/regions/TownyFeature.java new file mode 100644 index 00000000..367db8ab --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/TownyFeature.java @@ -0,0 +1,72 @@ +package com.boydti.fawe.bukkit.regions; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.object.FawePlayer; +import com.palmergames.bukkit.towny.Towny; +import com.palmergames.bukkit.towny.object.PlayerCache; +import com.palmergames.bukkit.towny.object.TownBlock; +import com.palmergames.bukkit.towny.object.TownyUniverse; +import com.palmergames.bukkit.towny.object.WorldCoord; + +public class TownyFeature extends BukkitMaskManager implements Listener { + FaweBukkit plugin; + Plugin towny; + + public TownyFeature(final Plugin townyPlugin, final FaweBukkit p3) { + super(townyPlugin.getName()); + this.towny = townyPlugin; + this.plugin = p3; + } + + @Override + public FaweMask getMask(final FawePlayer fp) { + final Player player = fp.parent; + final Location location = player.getLocation(); + try { + final PlayerCache cache = ((Towny) this.towny).getCache(player); + final WorldCoord mycoord = cache.getLastTownBlock(); + if (mycoord == null) { + return null; + } else { + final TownBlock myplot = mycoord.getTownBlock(); + if (myplot == null) { + return null; + } else { + boolean isMember = false; + try { + if (myplot.getResident().getName().equals(player.getName())) { + isMember = true; + } + } catch (final Exception e) { + + } + if (!isMember) { + if (player.hasPermission("fawe.towny.*")) { + isMember = true; + } else if (myplot.getTown().isMayor(TownyUniverse.getDataSource().getResident(player.getName()))) { + isMember = true; + } + } + if (isMember) { + final Chunk chunk = location.getChunk(); + final Location pos1 = new Location(location.getWorld(), chunk.getX() * 16, 0, chunk.getZ() * 16); + final Location pos2 = new Location(location.getWorld(), (chunk.getX() * 16) + 15, 156, (chunk.getZ() * 16) + 15); + return new FaweMask(pos1, pos2) { + @Override + public String getName() { + return "PLOT:" + location.getChunk().getX() + "," + location.getChunk().getZ(); + } + }; + } + } + } + } catch (final Exception e) {} + return null; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/regions/Worldguard.java b/forge/src/main/java/com/boydti/fawe/forge/regions/Worldguard.java new file mode 100644 index 00000000..eacd04f3 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/regions/Worldguard.java @@ -0,0 +1,93 @@ +package com.boydti.fawe.bukkit.regions; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.object.FawePlayer; +import com.sk89q.worldedit.BlockVector; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.managers.RegionManager; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; + +public class Worldguard extends BukkitMaskManager implements Listener { + WorldGuardPlugin worldguard; + FaweBukkit plugin; + + private WorldGuardPlugin getWorldGuard() { + final Plugin plugin = Bukkit.getPluginManager().getPlugin("WorldGuard"); + + // WorldGuard may not be loaded + if ((plugin == null) || !(plugin instanceof WorldGuardPlugin)) { + return null; // Maybe you want throw an exception instead + } + + return (WorldGuardPlugin) plugin; + } + + public Worldguard(final Plugin p2, final FaweBukkit p3) { + super(p2.getName()); + this.worldguard = this.getWorldGuard(); + this.plugin = p3; + + } + + public ProtectedRegion isowner(final Player player, final Location location) { + final com.sk89q.worldguard.LocalPlayer localplayer = this.worldguard.wrapPlayer(player); + final RegionManager manager = this.worldguard.getRegionManager(player.getWorld()); + final ApplicableRegionSet regions = manager.getApplicableRegions(player.getLocation()); + for (final ProtectedRegion region : regions) { + if (region.isOwner(localplayer)) { + return region; + } else if (region.getId().toLowerCase().equals(player.getName().toLowerCase())) { + return region; + } else if (region.getId().toLowerCase().contains(player.getName().toLowerCase() + "//")) { + return region; + } else if (region.isOwner("*")) { + return region; + } + } + return null; + } + + public ProtectedRegion getregion(final Player player, final BlockVector location) { + final com.sk89q.worldguard.LocalPlayer localplayer = this.worldguard.wrapPlayer(player); + final ApplicableRegionSet regions = this.worldguard.getRegionManager(player.getWorld()).getApplicableRegions(location); + for (final ProtectedRegion region : regions) { + if (region.isOwner(localplayer)) { + return region; + } else if (region.getId().toLowerCase().equals(player.getName().toLowerCase())) { + return region; + } else if (region.getId().toLowerCase().contains(player.getName().toLowerCase() + "//")) { + return region; + } else if (region.isOwner("*")) { + return region; + } + } + return null; + } + + @Override + public FaweMask getMask(final FawePlayer fp) { + final Player player = fp.parent; + final Location location = player.getLocation(); + final ProtectedRegion myregion = this.isowner(player, location); + if (myregion != null) { + final Location pos1 = new Location(location.getWorld(), myregion.getMinimumPoint().getBlockX(), myregion.getMinimumPoint().getBlockY(), myregion.getMinimumPoint().getBlockZ()); + final Location pos2 = new Location(location.getWorld(), myregion.getMaximumPoint().getBlockX(), myregion.getMaximumPoint().getBlockY(), myregion.getMaximumPoint().getBlockZ()); + return new FaweMask(pos1, pos2) { + @Override + public String getName() { + return myregion.getId(); + } + }; + } else { + return null; + } + + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/v0/BukkitEditSessionWrapper_0.java b/forge/src/main/java/com/boydti/fawe/forge/v0/BukkitEditSessionWrapper_0.java new file mode 100644 index 00000000..eb5ffae3 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/v0/BukkitEditSessionWrapper_0.java @@ -0,0 +1,32 @@ +package com.boydti.fawe.bukkit.v0; + +import com.boydti.fawe.logging.BlocksHubHook; +import com.boydti.fawe.object.EditSessionWrapper; +import com.boydti.fawe.object.FawePlayer; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.history.changeset.ChangeSet; + +public class BukkitEditSessionWrapper_0 extends EditSessionWrapper { + + private BlocksHubHook hook; + + public BukkitEditSessionWrapper_0(final EditSession session) { + super(session); + try { + // Try to hook into BlocksHub + this.hook = new BlocksHubHook(); + } catch (final Throwable e) {} + } + + @Override + public Extent getHistoryExtent(final Extent parent, final ChangeSet set, final FawePlayer player) { + if (this.hook != null) { + // If we are doing logging, return a custom logging extent + return this.hook.getLoggingExtent(parent, set, player); + } + // Otherwise return the normal history extent + return super.getHistoryExtent(parent, set, player); + } + +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/v0/BukkitQueue_0.java b/forge/src/main/java/com/boydti/fawe/forge/v0/BukkitQueue_0.java new file mode 100644 index 00000000..1466f35e --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/v0/BukkitQueue_0.java @@ -0,0 +1,232 @@ +package com.boydti.fawe.bukkit.v0; + +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.event.world.WorldUnloadEvent; +import org.bukkit.plugin.Plugin; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.ChunkLoc; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.util.FaweQueue; +import com.boydti.fawe.util.SetQueue; +import com.boydti.fawe.util.TaskManager; +import com.sk89q.worldedit.world.biome.BaseBiome; + +/** + * The base object for + */ +public abstract class BukkitQueue_0 extends FaweQueue implements Listener { + + /** + * Map of loaded chunks for quicker checking + */ + private final HashMap> loaded = new HashMap<>(); + + /** + * Map of chunks in the queue + */ + private final ConcurrentHashMap> blocks = new ConcurrentHashMap<>(); + + public BukkitQueue_0() { + TaskManager.IMP.task(new Runnable() { + @Override + public void run() { + Bukkit.getPluginManager().registerEvents(BukkitQueue_0.this, (Plugin) Fawe.imp()); + } + }); + for (final World world : Bukkit.getWorlds()) { + for (final Chunk chunk : world.getLoadedChunks()) { + this.addLoaded(chunk); + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onWorldLoad(final WorldLoadEvent event) { + final World world = event.getWorld(); + for (final Chunk chunk : world.getLoadedChunks()) { + this.addLoaded(chunk); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onWorldUnload(final WorldUnloadEvent event) { + this.loaded.remove(event.getWorld().getName()); + } + + public void addLoaded(final Chunk chunk) { + final String world = chunk.getWorld().getName(); + final long x = chunk.getX(); + final long z = chunk.getZ(); + final long id = (x << 32) | (z & 0xFFFFFFFFL); + HashSet map = this.loaded.get(world); + if (map != null) { + map.add(id); + } else { + map = new HashSet<>(Arrays.asList(id)); + this.loaded.put(world, map); + } + } + + public void removeLoaded(final Chunk chunk) { + final String world = chunk.getWorld().getName(); + final long x = chunk.getX(); + final long z = chunk.getZ(); + final long id = (x << 32) | (z & 0xFFFFFFFFL); + final HashSet map = this.loaded.get(world); + if (map != null) { + map.remove(id); + } + } + + @Override + public boolean isChunkLoaded(final String world, final int x, final int z) { + final long id = ((long) x << 32) | (z & 0xFFFFFFFFL); + final HashSet map = this.loaded.get(world); + if (map != null) { + return map.contains(id); + } + return false; + }; + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onChunkLoad(final ChunkLoadEvent event) { + final Chunk chunk = event.getChunk(); + this.addLoaded(chunk); + if (Settings.FIX_ALL_LIGHTING) { + this.fixLighting(this.getChunk(new ChunkLoc(chunk.getWorld().getName(), chunk.getX(), chunk.getZ())), false); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onChunkUnload(final ChunkUnloadEvent event) { + this.removeLoaded(event.getChunk()); + } + + @Override + public void addTask(String world, int x, int y, int z, Runnable runnable) { + // TODO Auto-generated method stub + final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4); + FaweChunk result = this.blocks.get(wrap); + if (result == null) { + throw new IllegalArgumentException("Task must be accompanied by a block change or manually adding to queue!"); + } + result.addTask(runnable); + } + + @Override + public boolean setBlock(final String world, int x, final int y, int z, final short id, final byte data) { + if ((y > 255) || (y < 0)) { + return false; + } + final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4); + x = x & 15; + z = z & 15; + FaweChunk result = this.blocks.get(wrap); + if (result == null) { + result = this.getChunk(wrap); + result.setBlock(x, y, z, id, data); + final FaweChunk previous = this.blocks.put(wrap, result); + if (previous == null) { + return true; + } + this.blocks.put(wrap, previous); + result = previous; + } + result.setBlock(x, y, z, id, data); + return true; + } + + @Override + public boolean setBiome(final String world, int x, int z, final BaseBiome biome) { + final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4); + x = x & 15; + z = z & 15; + FaweChunk result = this.blocks.get(wrap); + if (result == null) { + result = this.getChunk(wrap); + final FaweChunk previous = this.blocks.put(wrap, result); + if (previous != null) { + this.blocks.put(wrap, previous); + result = previous; + } + } + result.setBiome(x, z, biome); + return true; + } + + @Override + public FaweChunk next() { + try { + if (this.blocks.size() == 0) { + return null; + } + final Iterator>> iter = this.blocks.entrySet().iterator(); + final FaweChunk toReturn = iter.next().getValue(); + if (SetQueue.IMP.isWaiting()) { + return null; + } + iter.remove(); + this.execute(toReturn); + return toReturn; + } catch (final Throwable e) { + e.printStackTrace(); + return null; + } + } + + private final ArrayDeque> toUpdate = new ArrayDeque<>(); + + public boolean execute(final FaweChunk fc) { + if (fc == null) { + return false; + } + // Load chunk + final Chunk chunk = fc.getChunk(); + chunk.load(true); + // Set blocks / entities / biome + if (!this.setComponents(fc)) { + return false; + } + fc.executeTasks(); + return true; + } + + @Override + public void clear() { + this.blocks.clear(); + } + + @Override + public void setChunk(final FaweChunk chunk) { + this.blocks.put(chunk.getChunkLoc(), (FaweChunk) chunk); + } + + public abstract Collection> sendChunk(final Collection> fcs); + + public abstract boolean setComponents(final FaweChunk fc); + + @Override + public abstract FaweChunk getChunk(final ChunkLoc wrap); + + @Override + public abstract boolean fixLighting(final FaweChunk fc, final boolean fixAll); +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/v1_8/BukkitChunk_1_8.java b/forge/src/main/java/com/boydti/fawe/forge/v1_8/BukkitChunk_1_8.java new file mode 100644 index 00000000..686bff61 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/v1_8/BukkitChunk_1_8.java @@ -0,0 +1,232 @@ +package com.boydti.fawe.bukkit.v1_8; + +import java.util.Arrays; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; + +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.object.ChunkLoc; +import com.boydti.fawe.object.FaweChunk; +import com.sk89q.worldedit.world.biome.BaseBiome; + +public class BukkitChunk_1_8 extends FaweChunk { + + private char[][] ids; + + private final short[] count; + private final short[] air; + private final short[] relight; + private int[][] biomes; + + public Chunk chunk; + + /** + * A FaweSections object represents a chunk and the blocks that you wish to change in it. + */ + protected BukkitChunk_1_8(final ChunkLoc chunk) { + super(chunk); + this.ids = new char[16][]; + this.count = new short[16]; + this.air = new short[16]; + this.relight = new short[16]; + } + + @Override + public Chunk getChunk() { + if (this.chunk == null) { + final ChunkLoc cl = this.getChunkLoc(); + this.chunk = Bukkit.getWorld(cl.world).getChunkAt(cl.x, cl.z); + } + return this.chunk; + } + + @Override + public void setChunkLoc(final ChunkLoc loc) { + super.setChunkLoc(loc); + this.chunk = null; + } + + /** + * Get the number of block changes in a specified section + * @param i + * @return + */ + public int getCount(final int i) { + return this.count[i]; + } + + public int getAir(final int i) { + return this.air[i]; + } + + public void setCount(final int i, final short value) { + this.count[i] = value; + } + + /** + * Get the number of block changes in a specified section + * @param i + * @return + */ + public int getRelight(final int i) { + return this.relight[i]; + } + + public int getTotalCount() { + int total = 0; + for (int i = 0; i < 16; i++) { + total += this.count[i]; + } + return total; + } + + public int getTotalRelight() { + if ((this.getTotalCount() == 0) && (this.biomes == null)) { + Arrays.fill(this.count, (short) 1); + Arrays.fill(this.relight, Short.MAX_VALUE); + return Short.MAX_VALUE; + } + int total = 0; + for (int i = 0; i < 16; i++) { + total += this.relight[i]; + } + return total; + } + + /** + * Get the raw data for a section + * @param i + * @return + */ + public char[] getIdArray(final int i) { + return this.ids[i]; + } + + public void clear() { + this.ids = null; + this.biomes = null; + } + + public int[][] getBiomeArray() { + return this.biomes; + } + + @Override + public void setBlock(final int x, final int y, final int z, final int id, byte data) { + final int i = FaweCache.CACHE_I[y][x][z]; + final int j = FaweCache.CACHE_J[y][x][z]; + char[] vs = this.ids[i]; + if (vs == null) { + vs = this.ids[i] = new char[4096]; + this.count[i]++; + } else if (vs[j] == 0) { + this.count[i]++; + } + switch (id) { + case 0: + this.air[i]++; + vs[j] = (char) 1; + return; + case 10: + case 11: + case 39: + case 40: + case 51: + case 74: + case 89: + case 122: + case 124: + case 138: + case 169: + this.relight[i]++; + case 2: + case 4: + case 13: + case 14: + case 15: + case 20: + case 21: + case 22: + case 30: + case 32: + case 37: + case 41: + case 42: + case 45: + case 46: + case 47: + case 48: + case 49: + case 56: + case 57: + case 58: + case 60: + case 7: + case 8: + case 9: + case 73: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 85: + case 87: + case 88: + case 101: + case 102: + case 103: + case 110: + case 112: + case 113: + case 121: + case 129: + case 133: + case 165: + case 166: + case 170: + case 172: + case 173: + case 174: + case 181: + case 182: + case 188: + case 189: + case 190: + case 191: + case 192: + vs[j] = (char) (id << 4); + return; + case 130: + case 76: + case 62: + this.relight[i]++; + case 54: + case 146: + case 61: + case 65: + case 68: + case 50: + if (data < 2) { + data = 2; + } + default: + vs[j] = (char) ((id << 4) + data); + return; + } + } + + @Override + public void setBiome(final int x, final int z, final BaseBiome biome) { + if (this.biomes == null) { + this.biomes = new int[16][]; + } + int[] index = this.biomes[x]; + if (index == null) { + index = this.biomes[x] = new int[16]; + } + index[z] = biome.getId(); + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/v1_8/BukkitEditSessionWrapper_1_8.java b/forge/src/main/java/com/boydti/fawe/forge/v1_8/BukkitEditSessionWrapper_1_8.java new file mode 100644 index 00000000..af5df568 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/v1_8/BukkitEditSessionWrapper_1_8.java @@ -0,0 +1,164 @@ +package com.boydti.fawe.bukkit.v1_8; + +import static com.boydti.fawe.util.ReflectionUtils.getRefClass; + +import org.bukkit.Bukkit; + +import com.boydti.fawe.bukkit.v0.BukkitEditSessionWrapper_0; +import com.boydti.fawe.util.ReflectionUtils.RefClass; +import com.boydti.fawe.util.ReflectionUtils.RefField; +import com.boydti.fawe.util.ReflectionUtils.RefMethod; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BlockType; + +public class BukkitEditSessionWrapper_1_8 extends BukkitEditSessionWrapper_0 { + + private final RefClass classCraftWorld = getRefClass("{cb}.CraftWorld"); + private final RefClass classChunk = getRefClass("{nms}.Chunk"); + private final RefClass classWorld = getRefClass("{nms}.World"); + + private RefMethod worldGetHandle; + private RefMethod methodGetChunkAt; + private RefField heightMap; + private Object nmsWorld; + + private int lastXMin; + private int lastZMin; + private Object lastChunk; + + public BukkitEditSessionWrapper_1_8(final EditSession session) { + super(session); + try { + this.worldGetHandle = this.classCraftWorld.getMethod("getHandle"); + this.methodGetChunkAt = this.classWorld.getMethod("getChunkAt", int.class, int.class); + this.heightMap = this.classChunk.getField("heightMap"); + this.nmsWorld = this.worldGetHandle.of(Bukkit.getWorld(session.getWorld().getName())).call(); + } catch (final Exception e) { + e.printStackTrace(); + } + } + + @Override + public int getHighestTerrainBlock(final int x, final int z, final int minY, final int maxY, final boolean naturalOnly) { + final int bx = x >> 4; + final int bz = z >> 4; + int[] heights; + if ((this.lastChunk == null) || (bx != this.lastXMin) || (bz != this.lastZMin)) { + this.lastXMin = bx; + this.lastZMin = bz; + this.lastChunk = this.methodGetChunkAt.of(this.nmsWorld).call(bx, bz); + } + if (this.lastChunk != null) { + heights = (int[]) this.heightMap.of(this.lastChunk).get(); + final int lx = x & 15; + final int lz = z & 15; + final int height = heights[((lz << 4) | lx)]; + if ((height <= maxY) && (height >= minY)) { + final Vector pt = new Vector(x, height, z); + final int id = this.session.getBlockType(pt); + if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, 0) : !BlockType.canPassThrough(id, 0)) { + return height; + } + } + } + for (int y = maxY; y >= minY; --y) { + final Vector pt = new Vector(x, y, z); + final int id = this.session.getBlockType(pt); + int data; + switch (id) { + case 0: { + continue; + } + case 2: + case 4: + case 13: + case 14: + case 15: + case 20: + case 21: + case 22: + case 25: + case 30: + case 32: + case 37: + case 39: + case 40: + case 41: + case 42: + case 45: + case 46: + case 47: + case 48: + case 49: + case 51: + case 52: + case 54: + case 55: + case 56: + case 57: + case 58: + case 60: + case 61: + case 62: + case 7: + case 8: + case 9: + case 10: + case 11: + case 73: + case 74: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + case 85: + case 87: + case 88: + case 101: + case 102: + case 103: + case 110: + case 112: + case 113: + case 117: + case 121: + case 122: + case 123: + case 124: + case 129: + case 133: + case 138: + case 137: + case 140: + case 165: + case 166: + case 169: + case 170: + case 172: + case 173: + case 174: + case 176: + case 177: + case 181: + case 182: + case 188: + case 189: + case 190: + case 191: + case 192: + return y; + default: + data = 0; + } + if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) { + return y; + } + } + return minY; + } + +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/v1_8/BukkitQueue_1_8.java b/forge/src/main/java/com/boydti/fawe/forge/v1_8/BukkitQueue_1_8.java new file mode 100644 index 00000000..3fe69cfe --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/v1_8/BukkitQueue_1_8.java @@ -0,0 +1,690 @@ +package com.boydti.fawe.bukkit.v1_8; + +import static com.boydti.fawe.util.ReflectionUtils.getRefClass; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.ChunkGenerator; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.ChunkLoc; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.IntegerPair; +import com.boydti.fawe.util.MemUtil; +import com.boydti.fawe.util.ReflectionUtils.RefClass; +import com.boydti.fawe.util.ReflectionUtils.RefConstructor; +import com.boydti.fawe.util.ReflectionUtils.RefField; +import com.boydti.fawe.util.ReflectionUtils.RefMethod; +import com.boydti.fawe.util.ReflectionUtils.RefMethod.RefExecutor; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.bukkit.BukkitUtil; +import com.sk89q.worldedit.world.biome.BaseBiome; + +public class BukkitQueue_1_8 extends BukkitQueue_0 { + + private final RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer"); + private final RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk"); + private final RefClass classPacket = getRefClass("{nms}.Packet"); + private final RefClass classConnection = getRefClass("{nms}.PlayerConnection"); + private final RefClass classChunk = getRefClass("{nms}.Chunk"); + private final RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer"); + private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); + private final RefClass classWorld = getRefClass("{nms}.World"); + private final RefField mustSave = this.classChunk.getField("mustSave"); + private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition"); + private final RefClass classChunkSection = getRefClass("{nms}.ChunkSection"); + + private RefMethod methodGetHandlePlayer; + private RefMethod methodGetHandleChunk; + private RefConstructor MapChunk; + private RefField connection; + private RefMethod send; + private RefMethod methodInitLighting; + private RefConstructor classBlockPositionConstructor; + private RefConstructor classChunkSectionConstructor; + private RefMethod methodX; + private RefMethod methodAreNeighborsLoaded; + private RefField fieldSections; + private RefField fieldWorld; + private RefMethod methodGetIdArray; + private RefMethod methodGetWorld; + private RefField tileEntityListTick; + + private final HashMap worldMap = new HashMap<>(); + + public BukkitQueue_1_8() { + try { + this.methodGetHandlePlayer = this.classCraftPlayer.getMethod("getHandle"); + this.methodGetHandleChunk = this.classCraftChunk.getMethod("getHandle"); + this.methodInitLighting = this.classChunk.getMethod("initLighting"); + this.MapChunk = this.classMapChunk.getConstructor(this.classChunk.getRealClass(), boolean.class, int.class); + this.connection = this.classEntityPlayer.getField("playerConnection"); + this.send = this.classConnection.getMethod("sendPacket", this.classPacket.getRealClass()); + this.classBlockPositionConstructor = this.classBlockPosition.getConstructor(int.class, int.class, int.class); + this.methodX = this.classWorld.getMethod("x", this.classBlockPosition.getRealClass()); + this.fieldSections = this.classChunk.getField("sections"); + this.fieldWorld = this.classChunk.getField("world"); + this.methodGetIdArray = this.classChunkSection.getMethod("getIdArray"); + this.methodAreNeighborsLoaded = this.classChunk.getMethod("areNeighborsLoaded", int.class); + this.classChunkSectionConstructor = this.classChunkSection.getConstructor(int.class, boolean.class, char[].class); + this.tileEntityListTick = this.classWorld.getField("tileEntityList"); + this.methodGetWorld = this.classChunk.getMethod("getWorld"); + } catch (final NoSuchMethodException e) { + e.printStackTrace(); + } + } + + public FaweGenerator_1_8 getFaweGenerator(final World world) { + final ChunkGenerator gen = world.getGenerator(); + if ((gen != null) && (gen instanceof FaweGenerator_1_8)) { + return (FaweGenerator_1_8) gen; + } + FaweGenerator_1_8 faweGen = this.worldMap.get(world.getName()); + if (faweGen != null) { + return faweGen; + } + faweGen = new FaweGenerator_1_8(this, world); + this.worldMap.put(world.getName(), faweGen); + return faweGen; + } + + @Override + public Collection> sendChunk(final Collection> fcs) { + final HashMap, Object> packets = new HashMap<>(); + final HashMap>> map = new HashMap<>(); + + for (final FaweChunk fc : fcs) { + final String world = fc.getChunkLoc().world; + ArrayList> list = map.get(world); + if (list == null) { + list = new ArrayList<>(); + map.put(world, list); + } + list.add(fc); + } + final int view = Bukkit.getServer().getViewDistance(); + for (final Player player : Bukkit.getOnlinePlayers()) { + final String world = player.getWorld().getName(); + final ArrayList> list = map.get(world); + if (list == null) { + continue; + } + final Location loc = player.getLocation(); + final int cx = loc.getBlockX() >> 4; + final int cz = loc.getBlockZ() >> 4; + final Object entity = this.methodGetHandlePlayer.of(player).call(); + + for (final FaweChunk fc : list) { + final int dx = Math.abs(cx - fc.getChunkLoc().x); + final int dz = Math.abs(cz - fc.getChunkLoc().z); + if ((dx > view) || (dz > view)) { + continue; + } + final RefExecutor con = this.send.of(this.connection.of(entity).get()); + Object packet = packets.get(fc); + if (packet == null) { + final Object c = this.methodGetHandleChunk.of(fc.getChunk()).call(); + packet = this.MapChunk.create(c, true, 65535); + packets.put(fc, packet); + con.call(packet); + } else { + con.call(packet); + } + } + } + final HashSet> chunks = new HashSet>(); + for (final FaweChunk fc : fcs) { + final Chunk chunk = fc.getChunk(); + chunk.unload(true, false); + chunk.load(); + final ChunkLoc loc = fc.getChunkLoc(); + chunk.getWorld().refreshChunk(loc.x, loc.z); + if (!this.fixLighting(fc, Settings.FIX_ALL_LIGHTING)) { + chunks.add(fc); + } + } + return chunks; + } + + @Override + public boolean fixLighting(final FaweChunk fc, final boolean fixAll) { + try { + final BukkitChunk_1_8 bc = (BukkitChunk_1_8) fc; + final Chunk chunk = bc.getChunk(); + if (!chunk.isLoaded()) { + chunk.load(false); + } + + // Initialize lighting + final Object c = this.methodGetHandleChunk.of(chunk).call(); + + this.methodInitLighting.of(c).call(); + + if (((bc.getTotalRelight() == 0) && !fixAll)) { + return true; + } + + final Object[] sections = (Object[]) this.fieldSections.of(c).get(); + final Object w = this.fieldWorld.of(c).get(); + + final int X = chunk.getX() << 4; + final int Z = chunk.getZ() << 4; + + final RefExecutor relight = this.methodX.of(w); + for (int j = 0; j < sections.length; j++) { + final Object section = sections[j]; + if (section == null) { + continue; + } + if (((bc.getRelight(j) == 0) && !fixAll) || (bc.getCount(j) == 0) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0))) { + continue; + } + final char[] array = this.getIdArray(section); + if (array == null) { + continue; + } + int l = FaweCache.RANDOM.random(2); + for (int k = 0; k < array.length; k++) { + final int i = array[k]; + if (i < 16) { + continue; + } + final short id = FaweCache.CACHE_ID[i]; + switch (id) { // Lighting + default: + if (!fixAll) { + continue; + } + if ((k & 1) == l) { + l = 1 - l; + continue; + } + case 10: + case 11: + case 39: + case 40: + case 50: + case 51: + case 62: + case 74: + case 76: + case 89: + case 122: + case 124: + case 130: + case 138: + case 169: + final int x = FaweCache.CACHE_X[j][k]; + final int y = FaweCache.CACHE_Y[j][k]; + final int z = FaweCache.CACHE_Z[j][k]; + if (this.isSurrounded(sections, x, y, z)) { + continue; + } + final Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z); + relight.call(pos); + } + } + } + return true; + } catch (final Throwable e) { + e.printStackTrace(); + } + return false; + } + + public boolean isSurrounded(final Object[] sections, final int x, final int y, final int z) { + return this.isSolid(this.getId(sections, x, y + 1, z)) + && this.isSolid(this.getId(sections, x + 1, y - 1, z)) + && this.isSolid(this.getId(sections, x - 1, y, z)) + && this.isSolid(this.getId(sections, x, y, z + 1)) + && this.isSolid(this.getId(sections, x, y, z - 1)); + } + + public boolean isSolid(final int i) { + if (i == 0) { + return false; + } + return Material.getMaterial(i).isOccluding(); + } + + public int getId(final Object[] sections, final int x, final int y, final int z) { + if ((x < 0) || (x > 15) || (z < 0) || (z > 15)) { + return 1; + } + if ((y < 0) || (y > 255)) { + return 1; + } + final int i = FaweCache.CACHE_I[y][x][z]; + final Object section = sections[i]; + if (section == null) { + return 0; + } + final char[] array = this.getIdArray(section); + final int j = FaweCache.CACHE_J[y][x][z]; + return array[j] >> 4; + } + + @Override + public boolean setComponents(final FaweChunk fc) { + try { + final BukkitChunk_1_8 fs = ((BukkitChunk_1_8) fc); + final Chunk chunk = fs.getChunk(); + final World world = chunk.getWorld(); + + final boolean flag = world.getEnvironment() == Environment.NORMAL; + + // Sections + final Method getHandele = chunk.getClass().getDeclaredMethod("getHandle"); + final Object c = getHandele.invoke(chunk); + final Object w = this.methodGetWorld.of(c).call(); + final Class clazz = c.getClass(); + final Field sf = clazz.getDeclaredField("sections"); + sf.setAccessible(true); + final Field tf = clazz.getDeclaredField("tileEntities"); + final Field ef = clazz.getDeclaredField("entitySlices"); + + final Object[] sections = (Object[]) sf.get(c); + final HashMap tiles = (HashMap) tf.get(c); + final Collection[] entities = (Collection[]) ef.get(c); + + Method xm = null; + Method ym = null; + Method zm = null; + + // Trim tiles + boolean removed = false; + final Set> entryset = (Set>) (Set) tiles.entrySet(); + final Iterator> iter = entryset.iterator(); + while (iter.hasNext()) { + final Entry tile = iter.next(); + final Object pos = tile.getKey(); + if (xm == null) { + final Class clazz2 = pos.getClass().getSuperclass(); + xm = clazz2.getDeclaredMethod("getX"); + ym = clazz2.getDeclaredMethod("getY"); + zm = clazz2.getDeclaredMethod("getZ"); + } + final int lx = (int) xm.invoke(pos) & 15; + final int ly = (int) ym.invoke(pos); + final int lz = (int) zm.invoke(pos) & 15; + final int j = FaweCache.CACHE_I[ly][lx][lz]; + final int k = FaweCache.CACHE_J[ly][lx][lz]; + final char[] array = fs.getIdArray(j); + if (array == null) { + continue; + } + if (array[k] != 0) { + removed = true; + iter.remove(); + } + } + if (removed) { + ((Collection) this.tileEntityListTick.of(w).get()).clear(); + } + + // Trim entities + for (int i = 0; i < 16; i++) { + if ((entities[i] != null) && (fs.getCount(i) >= 4096)) { + entities[i].clear(); + } + } + + // Efficiently merge sections + for (int j = 0; j < sections.length; j++) { + if (fs.getCount(j) == 0) { + continue; + } + final char[] newArray = fs.getIdArray(j); + if (newArray == null) { + continue; + } + Object section = sections[j]; + if ((section == null) || (fs.getCount(j) >= 4096)) { + section = sections[j] = this.newChunkSection(j << 4, flag, newArray); + continue; + } + final char[] currentArray = this.getIdArray(section); + boolean fill = true; + for (int k = 0; k < newArray.length; k++) { + final char n = newArray[k]; + if (n == 0) { + fill = false; + continue; + } + switch (n) { + case 0: + fill = false; + continue; + case 1: + fill = false; + currentArray[k] = 0; + continue; + default: + currentArray[k] = n; + continue; + } + } + if (fill) { + fs.setCount(j, Short.MAX_VALUE); + } + } + + // Biomes + final int[][] biomes = fs.getBiomeArray(); + if (biomes != null) { + final LocalWorld lw = BukkitUtil.getLocalWorld(world); + final int X = fs.getChunkLoc().x << 4; + final int Z = fs.getChunkLoc().z << 4; + final BaseBiome bb = new BaseBiome(0); + int last = 0; + for (int x = 0; x < 16; x++) { + final int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + final int biome = array[z]; + if (biome == 0) { + continue; + } + if (last != biome) { + last = biome; + bb.setId(biome); + } + lw.setBiome(new Vector2D(X + x, Z + z), bb); + } + } + } + + // Clear + fs.clear(); + return true; + } catch (final Exception e) { + e.printStackTrace(); + } + return false; + } + + /** + * This method is called when the server is < 1% available memory (i.e. likely to crash)
+ * - You can disable this in the conifg
+ * - Will try to free up some memory
+ * - Clears the queue
+ * - Clears worldedit history
+ * - Clears entities
+ * - Unloads chunks in vacant worlds
+ * - Unloads non visible chunks
+ */ + @Override + public void clear() { + // Clear the queue + super.clear(); + ArrayDeque toUnload = new ArrayDeque<>(); + final int distance = Bukkit.getViewDistance() + 2; + HashMap> players = new HashMap<>(); + for (final Player player : Bukkit.getOnlinePlayers()) { + // Clear history + final FawePlayer fp = FawePlayer.wrap(player); + final LocalSession s = fp.getSession(); + if (s != null) { + s.clearHistory(); + s.setClipboard(null); + } + final Location loc = player.getLocation(); + final World worldObj = loc.getWorld(); + final String world = worldObj.getName(); + HashMap map = players.get(world); + if (map == null) { + map = new HashMap<>(); + players.put(world, map); + } + final IntegerPair origin = new IntegerPair(loc.getBlockX() >> 4, loc.getBlockZ() >> 4); + Integer val = map.get(origin); + int check; + if (val != null) { + if (val == distance) { + continue; + } + check = distance - val; + } else { + check = distance; + map.put(origin, distance); + } + for (int x = -distance; x <= distance; x++) { + if ((x >= check) || (-x >= check)) { + continue; + } + for (int z = -distance; z <= distance; z++) { + if ((z >= check) || (-z >= check)) { + continue; + } + final int weight = distance - Math.max(Math.abs(x), Math.abs(z)); + final IntegerPair chunk = new IntegerPair(x + origin.x, z + origin.z); + val = map.get(chunk); + if ((val == null) || (val < weight)) { + map.put(chunk, weight); + } + } + } + } + Fawe.get().getWorldEdit().clearSessions(); + for (final World world : Bukkit.getWorlds()) { + final String name = world.getName(); + final HashMap map = players.get(name); + if ((map == null) || (map.size() == 0)) { + final boolean save = world.isAutoSave(); + world.setAutoSave(false); + for (final Chunk chunk : world.getLoadedChunks()) { + this.unloadChunk(name, chunk); + } + world.setAutoSave(save); + continue; + } + final Chunk[] chunks = world.getLoadedChunks(); + for (final Chunk chunk : chunks) { + final int x = chunk.getX(); + final int z = chunk.getZ(); + if (!map.containsKey(new IntegerPair(x, z))) { + toUnload.add(chunk); + } else if (chunk.getEntities().length > 4096) { + for (final Entity ent : chunk.getEntities()) { + ent.remove(); + } + } + } + } + // GC again + System.gc(); + System.gc(); + // If still critical memory + int free = MemUtil.calculateMemory(); + if (free <= 1) { + for (final Chunk chunk : toUnload) { + this.unloadChunk(chunk.getWorld().getName(), chunk); + } + } else if (free == Integer.MAX_VALUE) { + for (final Chunk chunk : toUnload) { + chunk.unload(true, false); + } + } else { + return; + } + toUnload = null; + players = null; + } + + public Object newChunkSection(final int i, final boolean flag, final char[] ids) { + return this.classChunkSectionConstructor.create(i, flag, ids); + } + + public char[] getIdArray(final Object obj) { + return (char[]) this.methodGetIdArray.of(obj).call(); + } + + @Override + public FaweChunk getChunk(final ChunkLoc wrap) { + return new BukkitChunk_1_8(wrap); + } + + public boolean unloadChunk(final String world, final Chunk chunk) { + final Object c = this.methodGetHandleChunk.of(chunk).call(); + this.mustSave.of(c).set(false); + if (chunk.isLoaded()) { + chunk.unload(false, false); + } + return true; + } + + public ChunkGenerator setGenerator(final World world, final ChunkGenerator newGen) { + try { + final ChunkGenerator gen = world.getGenerator(); + final Class clazz = world.getClass(); + final Field generator = clazz.getDeclaredField("generator"); + generator.setAccessible(true); + generator.set(world, newGen); + + final Field wf = clazz.getDeclaredField("world"); + wf.setAccessible(true); + final Object w = wf.get(world); + final Class clazz2 = w.getClass().getSuperclass(); + final Field generator2 = clazz2.getDeclaredField("generator"); + generator2.set(w, newGen); + + return gen; + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } + + public List setPopulator(final World world, final List newPop) { + try { + final List pop = world.getPopulators(); + final Field populators = world.getClass().getDeclaredField("populators"); + populators.setAccessible(true); + populators.set(world, newPop); + return pop; + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } + + public void setEntitiesAndTiles(final Chunk chunk, final List[] entities, final Map tiles) { + try { + final Class clazz = chunk.getClass(); + final Method handle = clazz.getMethod("getHandle"); + final Object c = handle.invoke(chunk); + final Class clazz2 = c.getClass(); + + if (tiles.size() > 0) { + final Field tef = clazz2.getDeclaredField("tileEntities"); + final Map te = (Map) tef.get(c); + final Method put = te.getClass().getMethod("putAll", Map.class); + put.invoke(te, tiles); + } + + final Field esf = clazz2.getDeclaredField("entitySlices"); + esf.setAccessible(true); + esf.set(c, entities); + } catch (final Exception e) { + e.printStackTrace(); + } + } + + public Object getProvider(final World world) { + try { + // Provider 1 + final Class clazz = world.getClass(); + final Field wf = clazz.getDeclaredField("world"); + wf.setAccessible(true); + final Object w = wf.get(world); + final Field provider = w.getClass().getSuperclass().getDeclaredField("chunkProvider"); + provider.setAccessible(true); + // ChunkProviderServer + final Class clazz2 = w.getClass(); + final Field wpsf = clazz2.getDeclaredField("chunkProviderServer"); + // Store old provider server + final Object worldProviderServer = wpsf.get(w); + // Store the old provider + final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider"); + return cp.get(worldProviderServer); + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } + + public Object setProvider(final World world, Object newProvider) { + try { + // Provider 1 + final Class clazz = world.getClass(); + final Field wf = clazz.getDeclaredField("world"); + wf.setAccessible(true); + final Object w = wf.get(world); + // ChunkProviderServer + final Class clazz2 = w.getClass(); + final Field wpsf = clazz2.getDeclaredField("chunkProviderServer"); + // Store old provider server + final Object worldProviderServer = wpsf.get(w); + // Store the old provider + final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider"); + final Object oldProvider = cp.get(worldProviderServer); + // Provider 2 + final Class clazz3 = worldProviderServer.getClass(); + final Field provider2 = clazz3.getDeclaredField("chunkProvider"); + // If the provider needs to be calculated + if (newProvider == null) { + Method k; + try { + k = clazz2.getDeclaredMethod("k"); + } catch (final Throwable e) { + try { + k = clazz2.getDeclaredMethod("j"); + } catch (final Throwable e2) { + e2.printStackTrace(); + return null; + } + } + k.setAccessible(true); + final Object tempProviderServer = k.invoke(w); + newProvider = cp.get(tempProviderServer); + // Restore old provider + wpsf.set(w, worldProviderServer); + } + // Set provider for provider server + provider2.set(worldProviderServer, newProvider); + // Return the previous provider + return oldProvider; + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/v1_8/FaweGenerator_1_8.java b/forge/src/main/java/com/boydti/fawe/forge/v1_8/FaweGenerator_1_8.java new file mode 100644 index 00000000..f05027e3 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/v1_8/FaweGenerator_1_8.java @@ -0,0 +1,459 @@ +package com.boydti.fawe.bukkit.v1_8; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Biome; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.world.ChunkPopulateEvent; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.ChunkGenerator; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.ChunkLoc; + +/** + * Please ignore + */ +@Deprecated +public class FaweGenerator_1_8 extends ChunkGenerator implements Listener { + private boolean events; + + private final ChunkGenerator parent; + private final List pops; + private final Object provider; + + private short[][] ids; + private byte[][] data; + private Map tiles; + private List[] entities; + private Biome[][] biomes; + + private final World world; + + private final BukkitQueue_1_8 queue; + + private void registerEvents() { + if (this.events) { + return; + } + Bukkit.getPluginManager().registerEvents(this, Fawe. imp()); + } + + @EventHandler + private void onPopulate(final ChunkPopulateEvent event) { + final World world = event.getWorld(); + final ChunkGenerator gen = world.getGenerator(); + if (gen instanceof FaweGenerator_1_8) { + final FaweGenerator_1_8 fawe = (FaweGenerator_1_8) gen; + if (fawe.data == null) { + return; + } + fawe.populate(event.getChunk()); + this.decouple((FaweGenerator_1_8) gen, world); + } + } + + public void setBlock(final short[][] result, final int x, final int y, final int z, final short blkid) { + if (result[FaweCache.CACHE_I[y][x][z]] == null) { + result[FaweCache.CACHE_I[y][x][z]] = new short[4096]; + } + result[FaweCache.CACHE_I[y][x][z]][FaweCache.CACHE_J[y][x][z]] = blkid; + } + + public void setBlock(final short[][] result, final int x, final int y, final int z, final short[] blkid) { + if (blkid.length == 1) { + this.setBlock(result, x, y, z, blkid[0]); + } + final short id = blkid[FaweCache.RANDOM.random(blkid.length)]; + if (result[FaweCache.CACHE_I[y][x][z]] == null) { + result[FaweCache.CACHE_I[y][x][z]] = new short[4096]; + } + result[FaweCache.CACHE_I[y][x][z]][FaweCache.CACHE_J[y][x][z]] = id; + } + + public void setBlocks(final short[][] ids, final byte[][] data, final int x, final int z) { + this.ids = ids; + this.data = data == null ? new byte[16][] : data; + if (this.parent == null) { + this.inject(this, this.world); + } + this.world.regenerateChunk(x, z); + } + + /** + * Regenerate chunk with the provided id / data / block count
+ * - You can provide null for datas / count but it will be marginally slower + * @param ids + * @param datas + * @param count + * @param chunk + */ + @Deprecated + public void regenerateBlocks(final short[][] ids, byte[][] datas, short[] count, final Chunk chunk) { + if (datas == null) { + datas = new byte[16][]; + } + if (count == null) { + count = new short[16]; + } + final int x = chunk.getX(); + final int z = chunk.getZ(); + + boolean skip = true; + for (int i = 0; i < 16; i++) { + if (count[i] < 4096) { + skip = false; + break; + } + } + + if (!skip) { + try { + chunk.load(true); + this.biomes = new Biome[16][16]; + final int X = x << 4; + final int Z = z << 4; + for (int xx = 0; xx < 16; xx++) { + final int xxx = X + x; + for (int zz = 0; zz < 16; zz++) { + final int zzz = Z + zz; + this.biomes[xx][zz] = this.world.getBiome(xxx, zzz); + } + } + final Method getHandele = chunk.getClass().getDeclaredMethod("getHandle"); + final Object c = getHandele.invoke(chunk); + final Class clazz = c.getClass(); + final Field sf = clazz.getDeclaredField("sections"); + sf.setAccessible(true); + final Field tf = clazz.getDeclaredField("tileEntities"); + final Field ef = clazz.getDeclaredField("entitySlices"); + + final Object[] sections = (Object[]) sf.get(c); + final HashMap tiles = (HashMap) tf.get(c); + final List[] entities = (List[]) ef.get(c); + + Method xm = null; + Method ym = null; + Method zm = null; + + // Copy entities / blockstates + final Set> entryset = (Set>) (Set) tiles.entrySet(); + final Iterator> iter = entryset.iterator(); + while (iter.hasNext()) { + final Entry tile = iter.next(); + final Object loc = tile.getKey(); + if (xm == null) { + final Class clazz2 = loc.getClass().getSuperclass(); + xm = clazz2.getDeclaredMethod("getX"); + ym = clazz2.getDeclaredMethod("getY"); + zm = clazz2.getDeclaredMethod("getZ"); + } + final int lx = (int) xm.invoke(loc) & 15; + final int ly = (int) ym.invoke(loc); + final int lz = (int) zm.invoke(loc) & 15; + final int j = FaweCache.CACHE_I[ly][lx][lz]; + final int k = FaweCache.CACHE_J[ly][lx][lz]; + if (ids[j] == null) { + continue; + } + if (ids[j][k] != 0) { + iter.remove(); + } + } + + this.tiles = tiles; + // Trim entities + for (int i = 0; i < 16; i++) { + if ((entities[i] != null) && (count[i] >= 4096)) { + entities[i].clear(); + } + } + this.entities = entities; + + // Efficiently merge sections + Method getIdArray = null; + for (int j = 0; j < sections.length; j++) { + if (count[j] >= 4096) { + continue; + } + final Object section = sections[j]; + if (section == null) { + continue; + } + if (getIdArray == null) { + final Class clazz2 = section.getClass(); + getIdArray = clazz2.getDeclaredMethod("getIdArray"); + } + final char[] array = (char[]) getIdArray.invoke(section); + for (int k = 0; k < array.length; k++) { + final int i = array[k]; + if (i < 16) { + continue; + } + short[] va = ids[j]; + if (va == null) { + va = new short[4096]; + ids[j] = va; + } + final short v = va[k]; + if (v != 0) { + continue; + } + final short id = FaweCache.CACHE_ID[i]; + va[k] = id; + switch (id) { + case 0: + case 2: + case 4: + case 13: + case 14: + case 15: + case 20: + case 21: + case 22: + case 30: + case 32: + case 37: + case 39: + case 40: + case 41: + case 42: + case 45: + case 46: + case 47: + case 48: + case 49: + case 51: + case 56: + case 57: + case 58: + case 60: + case 7: + case 8: + case 9: + case 10: + case 11: + case 73: + case 74: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 85: + case 87: + case 88: + case 101: + case 102: + case 103: + case 110: + case 112: + case 113: + case 121: + case 122: + case 129: + case 133: + case 165: + case 166: + case 169: + case 170: + case 172: + case 173: + case 174: + case 181: + case 182: + case 188: + case 189: + case 190: + case 191: + case 192: + continue; + case 53: + case 67: + case 108: + case 109: + case 114: + case 128: + case 134: + case 135: + case 136: + case 156: + case 163: + case 164: + case 180: + byte db = FaweCache.CACHE_DATA[i]; + if (db == 0) { + db = -1; + } + if (datas[j] == null) { + datas[j] = new byte[4096]; + } + datas[j][k] = db; + continue; + } + final byte db = FaweCache.CACHE_DATA[i]; + if (db == 0) { + continue; + } + if (datas[j] == null) { + datas[j] = new byte[4096]; + } + datas[j][k] = db; + } + } + + } catch (final Throwable e) { + e.printStackTrace(); + return; + } + } + // Execute + this.ids = ids; + this.data = datas; + if (this.parent == null) { + this.inject(this, this.world); + } + this.world.regenerateChunk(x, z); + } + + public void inject(final FaweGenerator_1_8 gen, final World world) { + this.queue.setGenerator(world, gen); + this.queue.setPopulator(world, new ArrayList()); + this.queue.setProvider(world, null); + } + + public void decouple(final FaweGenerator_1_8 gen, final World world) { + gen.data = null; + gen.ids = null; + gen.tiles = null; + gen.entities = null; + gen.biomes = null; + if (gen.parent == null) { + this.queue.setGenerator(world, gen.parent); + this.queue.setPopulator(world, gen.pops); + if (gen.provider != null) { + this.queue.setProvider(world, gen.provider); + } + } + } + + public FaweGenerator_1_8(final BukkitQueue_1_8 queue, final World world) { + this.queue = queue; + this.world = world; + this.parent = world.getGenerator(); + this.pops = world.getPopulators(); + if (this.parent == null) { + this.provider = queue.getProvider(world); + } else { + this.provider = null; + } + this.registerEvents(); + } + + @Override + public short[][] generateExtBlockSections(final World world, final Random random, final int x, final int z, final BiomeGrid biomes) { + short[][] result; + if (this.ids != null) { + result = this.ids; + if ((biomes != null) && (this.biomes != null)) { + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + biomes.setBiome(i, j, this.biomes[i][j]); + } + } + } + } else if (this.parent != null) { + result = this.parent.generateExtBlockSections(world, random, x, z, biomes); + } else { + result = null; + } + return result; + } + + public void populate(final Chunk chunk) { + for (int i = 0; i < this.data.length; i++) { + final byte[] section = this.data[i]; + if (section == null) { + continue; + } + for (int j = 0; j < section.length; j++) { + final byte v = section[j]; + if (v == 0) { + continue; + } + final int x = FaweCache.CACHE_X[i][j]; + final int y = FaweCache.CACHE_Y[i][j]; + final int z = FaweCache.CACHE_Z[i][j]; + chunk.getBlock(x, y, z).setData(v != -1 ? v : 0, false); + } + } + if ((this.tiles != null) || (this.entities != null)) { + this.queue.setEntitiesAndTiles(chunk, this.entities, this.tiles); + } + final BukkitChunk_1_8 fc = new BukkitChunk_1_8(new ChunkLoc(chunk.getWorld().getName(), chunk.getX(), chunk.getZ())); + fc.chunk = chunk; + this.queue.fixLighting(fc, Settings.FIX_ALL_LIGHTING); + } + + @Override + public byte[] generate(final World world, final Random random, final int x, final int z) { + if (this.ids == null) { + try { + this.parent.generate(world, random, x, z); + } catch (final Throwable e) { + return null; + } + } + return null; + } + + @Override + public byte[][] generateBlockSections(final World world, final Random random, final int x, final int z, final BiomeGrid biomes) { + if ((this.ids == null) && (this.parent != null)) { + return this.parent.generateBlockSections(world, random, x, z, biomes); + } + return null; + } + + @Override + public boolean canSpawn(final World world, final int x, final int z) { + if (this.parent != null) { + return this.parent.canSpawn(world, x, z); + } + return true; + } + + @Override + public List getDefaultPopulators(final World world) { + if ((this.ids == null) && (this.parent != null)) { + return this.parent.getDefaultPopulators(world); + } + return null; + } + + @Override + public Location getFixedSpawnLocation(final World world, final Random random) { + if ((this.ids == null) && (this.parent != null)) { + return this.parent.getFixedSpawnLocation(world, random); + } + return null; + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/v1_9/BukkitChunk_1_9.java b/forge/src/main/java/com/boydti/fawe/forge/v1_9/BukkitChunk_1_9.java new file mode 100644 index 00000000..60759e04 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/v1_9/BukkitChunk_1_9.java @@ -0,0 +1,236 @@ +package com.boydti.fawe.bukkit.v1_9; + +import java.util.Arrays; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; + +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.object.ChunkLoc; +import com.boydti.fawe.object.FaweChunk; +import com.sk89q.worldedit.world.biome.BaseBiome; + +public class BukkitChunk_1_9 extends FaweChunk { + + private int[][] ids; + + private final short[] count; + private final short[] air; + private final short[] relight; + public int[][] biomes; + + public Chunk chunk; + + /** + * A FaweSections object represents a chunk and the blocks that you wish to change in it. + */ + protected BukkitChunk_1_9(final ChunkLoc chunk) { + super(chunk); + this.ids = new int[16][]; + this.count = new short[16]; + this.air = new short[16]; + this.relight = new short[16]; + } + + @Override + public Chunk getChunk() { + if (this.chunk == null) { + final ChunkLoc cl = this.getChunkLoc(); + this.chunk = Bukkit.getWorld(cl.world).getChunkAt(cl.x, cl.z); + } + return this.chunk; + } + + @Override + public void setChunkLoc(final ChunkLoc loc) { + super.setChunkLoc(loc); + this.chunk = null; + } + + /** + * Get the number of block changes in a specified section + * @param i + * @return + */ + public int getCount(final int i) { + return this.count[i]; + } + + public int getAir(final int i) { + return this.air[i]; + } + + public void setCount(final int i, final short value) { + this.count[i] = value; + } + + /** + * Get the number of block changes in a specified section + * @param i + * @return + */ + public int getRelight(final int i) { + return this.relight[i]; + } + + public int getTotalCount() { + int total = 0; + for (int i = 0; i < 16; i++) { + total += this.count[i]; + } + return total; + } + + public int getTotalRelight() { + if ((this.getTotalCount() == 0) && (this.biomes == null)) { + Arrays.fill(this.count, (short) 1); + Arrays.fill(this.relight, Short.MAX_VALUE); + return Short.MAX_VALUE; + } + int total = 0; + for (int i = 0; i < 16; i++) { + total += this.relight[i]; + } + return total; + } + + /** + * Get the raw data for a section + * @param i + * @return + */ + public int[] getIdArray(final int i) { + return this.ids[i]; + } + + public int[][] getIdArrays() { + return this.ids; + } + + public void clear() { + this.ids = null; + this.biomes = null; + } + + public int[][] getBiomeArray() { + return this.biomes; + } + + @Override + public void setBlock(final int x, final int y, final int z, final int id, byte data) { + final int i = FaweCache.CACHE_I[y][x][z]; + final int j = FaweCache.CACHE_J[y][x][z]; + int[] vs = this.ids[i]; + if (vs == null) { + vs = this.ids[i] = new int[4096]; + this.count[i]++; + } else if (vs[j] == 0) { + this.count[i]++; + } + switch (id) { + case 0: + this.air[i]++; + vs[j] = -1; + return; + case 10: + case 11: + case 39: + case 40: + case 51: + case 74: + case 89: + case 122: + case 124: + case 138: + case 169: + this.relight[i]++; + case 2: + case 4: + case 13: + case 14: + case 15: + case 20: + case 21: + case 22: + case 30: + case 32: + case 37: + case 41: + case 42: + case 45: + case 46: + case 47: + case 48: + case 49: + case 56: + case 57: + case 58: + case 60: + case 7: + case 8: + case 9: + case 73: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 85: + case 87: + case 88: + case 101: + case 102: + case 103: + case 110: + case 112: + case 113: + case 121: + case 129: + case 133: + case 165: + case 166: + case 170: + case 172: + case 173: + case 174: + case 181: + case 182: + case 188: + case 189: + case 190: + case 191: + case 192: + vs[j] = (id); + return; + case 130: + case 76: + case 62: + this.relight[i]++; + case 54: + case 146: + case 61: + case 65: + case 68: + case 50: + if (data < 2) { + data = 2; + } + default: + vs[j] = id + (data << 12); + return; + } + } + + @Override + public void setBiome(final int x, final int z, final BaseBiome biome) { + if (this.biomes == null) { + this.biomes = new int[16][]; + } + int[] index = this.biomes[x]; + if (index == null) { + index = this.biomes[x] = new int[16]; + } + index[z] = biome.getId(); + } +} diff --git a/forge/src/main/java/com/boydti/fawe/forge/v1_9/BukkitQueue_1_9.java b/forge/src/main/java/com/boydti/fawe/forge/v1_9/BukkitQueue_1_9.java new file mode 100644 index 00000000..d66ff013 --- /dev/null +++ b/forge/src/main/java/com/boydti/fawe/forge/v1_9/BukkitQueue_1_9.java @@ -0,0 +1,624 @@ +package com.boydti.fawe.bukkit.v1_9; + +import static com.boydti.fawe.util.ReflectionUtils.getRefClass; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.block.Biome; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.ChunkGenerator; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.ChunkLoc; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.IntegerPair; +import com.boydti.fawe.object.PseudoRandom; +import com.boydti.fawe.util.MemUtil; +import com.boydti.fawe.util.ReflectionUtils.RefClass; +import com.boydti.fawe.util.ReflectionUtils.RefConstructor; +import com.boydti.fawe.util.ReflectionUtils.RefField; +import com.boydti.fawe.util.ReflectionUtils.RefMethod; +import com.boydti.fawe.util.ReflectionUtils.RefMethod.RefExecutor; +import com.boydti.fawe.util.TaskManager; +import com.sk89q.worldedit.LocalSession; + +public class BukkitQueue_1_9 extends BukkitQueue_0 { + + private final RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk"); + private final RefClass classChunk = getRefClass("{nms}.Chunk"); + private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); + private final RefClass classWorld = getRefClass("{nms}.World"); + private final RefField mustSave = this.classChunk.getField("mustSave"); + private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition"); + private final RefClass classChunkSection = getRefClass("{nms}.ChunkSection"); + private final RefClass classBlock = getRefClass("{nms}.Block"); + private final RefClass classIBlockData = getRefClass("{nms}.IBlockData"); + private final RefMethod methodGetHandleChunk; + private final RefMethod methodInitLighting; + private final RefConstructor classBlockPositionConstructor; + private final RefConstructor classChunkSectionConstructor; + private final RefMethod methodW; + private final RefField fieldSections; + private final RefField fieldWorld; + private final RefMethod methodGetBlocks; + private final RefMethod methodSetType; + private final RefMethod methodGetByCombinedId; + private final Object air; + private final RefMethod methodGetWorld; + private final RefField tileEntityListTick; + + public BukkitQueue_1_9() throws NoSuchMethodException, RuntimeException { + this.methodGetHandleChunk = this.classCraftChunk.getMethod("getHandle"); + this.methodInitLighting = this.classChunk.getMethod("initLighting"); + this.classBlockPositionConstructor = this.classBlockPosition.getConstructor(int.class, int.class, int.class); + this.methodW = this.classWorld.getMethod("w", this.classBlockPosition.getRealClass()); + this.fieldSections = this.classChunk.getField("sections"); + this.fieldWorld = this.classChunk.getField("world"); + this.methodGetByCombinedId = this.classBlock.getMethod("getByCombinedId", int.class); + this.methodGetBlocks = this.classChunkSection.getMethod("getBlocks"); + this.methodSetType = this.classChunkSection.getMethod("setType", int.class, int.class, int.class, this.classIBlockData.getRealClass()); + this.classChunkSectionConstructor = this.classChunkSection.getConstructor(int.class, boolean.class, char[].class); + this.air = this.methodGetByCombinedId.call(0); + this.tileEntityListTick = this.classWorld.getField("tileEntityListTick"); + this.methodGetWorld = this.classChunk.getMethod("getWorld"); + } + + @Override + public Collection> sendChunk(final Collection> fcs) { + for (final FaweChunk fc : fcs) { + sendChunk(fc); + } + return new ArrayList<>(); + } + + public void sendChunk(FaweChunk fc) { + fixLighting(fc, Settings.FIX_ALL_LIGHTING); + final Chunk chunk = fc.getChunk(); + final ChunkLoc loc = fc.getChunkLoc(); + chunk.getWorld().refreshChunk(loc.x, loc.z); + } + + @Override + public boolean fixLighting(final FaweChunk pc, final boolean fixAll) { + try { + final BukkitChunk_1_9 bc = (BukkitChunk_1_9) pc; + final Chunk chunk = bc.getChunk(); + if (!chunk.isLoaded()) { + chunk.load(false); + } + // Initialize lighting + final Object c = this.methodGetHandleChunk.of(chunk).call(); + + this.methodInitLighting.of(c).call(); + + if (((bc.getTotalRelight() == 0) && !fixAll)) { + return true; + } + + final Object[] sections = (Object[]) this.fieldSections.of(c).get(); + final Object w = this.fieldWorld.of(c).get(); + + final int X = chunk.getX() << 4; + final int Z = chunk.getZ() << 4; + + final RefExecutor relight = this.methodW.of(w); + for (int j = 0; j < sections.length; j++) { + final Object section = sections[j]; + if (section == null) { + continue; + } + if (((bc.getRelight(j) == 0) && !fixAll) || (bc.getCount(j) == 0) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0))) { + continue; + } + final int[] array = bc.getIdArray(j); + if (array == null) { + continue; + } + int l = PseudoRandom.random.random(2); + for (int k = 0; k < array.length; k++) { + final int i = array[k]; + if (i < 16) { + continue; + } + final short id = (short) (i >> 4); + switch (id) { // Lighting + default: + if (!fixAll) { + continue; + } + if ((k & 1) == l) { + l = 1 - l; + continue; + } + case 10: + case 11: + case 39: + case 40: + case 50: + case 51: + case 62: + case 74: + case 76: + case 89: + case 122: + case 124: + case 130: + case 138: + case 169: + final int x = FaweCache.CACHE_X[j][k]; + final int y = FaweCache.CACHE_Y[j][k]; + final int z = FaweCache.CACHE_Z[j][k]; + if (this.isSurrounded(bc.getIdArrays(), x, y, z)) { + continue; + } + final Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z); + relight.call(pos); + } + } + } + return true; + } catch (final Throwable e) { + e.printStackTrace(); + } + return false; + } + + public boolean isSurrounded(final int[][] sections, final int x, final int y, final int z) { + return this.isSolid(this.getId(sections, x, y + 1, z)) + && this.isSolid(this.getId(sections, x + 1, y - 1, z)) + && this.isSolid(this.getId(sections, x - 1, y, z)) + && this.isSolid(this.getId(sections, x, y, z + 1)) + && this.isSolid(this.getId(sections, x, y, z - 1)); + } + + public boolean isSolid(final int i) { + if (i != 0) { + final Material material = Material.getMaterial(i); + return (material != null) && Material.getMaterial(i).isOccluding(); + } + return false; + } + + public int getId(final int[][] sections, final int x, final int y, final int z) { + if ((x < 0) || (x > 15) || (z < 0) || (z > 15)) { + return 1; + } + if ((y < 0) || (y > 255)) { + return 1; + } + final int i = FaweCache.CACHE_I[y][x][z]; + final int[] section = sections[i]; + if (section == null) { + return 0; + } + final int j = FaweCache.CACHE_J[y][x][z]; + return section[j]; + } + + public Object getBlocks(final Object obj) { + return this.methodGetBlocks.of(obj).call(); + } + + @Override + public boolean setComponents(final FaweChunk pc) { + final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc; + final Chunk chunk = pc.getChunk(); + final World world = chunk.getWorld(); + chunk.load(true); + try { + final boolean flag = world.getEnvironment() == Environment.NORMAL; + + // Sections + final Method getHandele = chunk.getClass().getDeclaredMethod("getHandle"); + final Object c = getHandele.invoke(chunk); + final Object w = this.methodGetWorld.of(c).call(); + final Class clazz = c.getClass(); + final Field sf = clazz.getDeclaredField("sections"); + sf.setAccessible(true); + final Field tf = clazz.getDeclaredField("tileEntities"); + final Field ef = clazz.getDeclaredField("entitySlices"); + + final Object[] sections = (Object[]) sf.get(c); + final HashMap tiles = (HashMap) tf.get(c); + final Collection[] entities = (Collection[]) ef.get(c); + + Method xm = null; + Method ym = null; + Method zm = null; + + // Trim tiles + boolean removed = false; + final Set> entryset = (Set>) (Set) tiles.entrySet(); + final Iterator> iter = entryset.iterator(); + while (iter.hasNext()) { + final Entry tile = iter.next(); + final Object pos = tile.getKey(); + if (xm == null) { + final Class clazz2 = pos.getClass().getSuperclass(); + xm = clazz2.getDeclaredMethod("getX"); + ym = clazz2.getDeclaredMethod("getY"); + zm = clazz2.getDeclaredMethod("getZ"); + } + final int lx = (int) xm.invoke(pos) & 15; + final int ly = (int) ym.invoke(pos); + final int lz = (int) zm.invoke(pos) & 15; + final int j = FaweCache.CACHE_I[ly][lx][lz]; + final int k = FaweCache.CACHE_J[ly][lx][lz]; + final int[] array = fs.getIdArray(j); + if (array == null) { + continue; + } + if (array[k] != 0) { + removed = true; + iter.remove(); + } + } + if (removed) { + ((Collection) this.tileEntityListTick.of(w).get()).clear(); + } + + // Trim entities + for (int i = 0; i < 16; i++) { + if ((entities[i] != null) && (fs.getCount(i) >= 4096)) { + entities[i].clear(); + } + } + + // Efficiently merge sections + for (int j = 0; j < sections.length; j++) { + if (fs.getCount(j) == 0) { + continue; + } + final int[] newArray = fs.getIdArray(j); + if (newArray == null) { + continue; + } + Object section = sections[j]; + if ((section == null) || (fs.getCount(j) >= 4096)) { + final char[] array = new char[4096]; + for (int i = 0; i < newArray.length; i++) { + final int combined = newArray[i]; + final int id = combined & 4095; + final int data = combined >> 12; + array[i] = (char) ((id << 4) + data); + } + section = sections[j] = this.newChunkSection(j << 4, flag, array); + continue; + } + this.getBlocks(section); + final RefExecutor setType = this.methodSetType.of(section); + boolean fill = true; + for (int k = 0; k < newArray.length; k++) { + final int n = newArray[k]; + switch (n) { + case 0: + fill = false; + continue; + case -1: { + fill = false; + final int x = FaweCache.CACHE_X[j][k]; + final int y = FaweCache.CACHE_Y[j][k]; + final int z = FaweCache.CACHE_Z[j][k]; + setType.call(x, y & 15, z, this.air); + continue; + } + default: { + final int x = FaweCache.CACHE_X[j][k]; + final int y = FaweCache.CACHE_Y[j][k]; + final int z = FaweCache.CACHE_Z[j][k]; + final Object iblock = this.methodGetByCombinedId.call(n); + setType.call(x, y & 15, z, iblock); + continue; + } + } + } + if (fill) { + fs.setCount(j, Short.MAX_VALUE); + } + } + // Clear + } catch (IllegalAccessException | IllegalArgumentException | NoSuchMethodException | SecurityException | InvocationTargetException | NoSuchFieldException e) { + e.printStackTrace(); + } + final int[][] biomes = fs.biomes; + final Biome[] values = Biome.values(); + if (biomes != null) { + for (int x = 0; x < 16; x++) { + final int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + final int biome = array[z]; + if (biome == 0) { + continue; + } + chunk.getBlock(x, 0, z).setBiome(values[biome]); + } + } + } + TaskManager.IMP.later(new Runnable() { + @Override + public void run() { + sendChunk(fs); + } + }, 1); + return true; + } + + /** + * This method is called when the server is < 1% available memory (i.e. likely to crash)
+ * - You can disable this in the conifg
+ * - Will try to free up some memory
+ * - Clears the queue
+ * - Clears worldedit history
+ * - Clears entities
+ * - Unloads chunks in vacant worlds
+ * - Unloads non visible chunks
+ */ + @Override + public void clear() { + // Clear the queue + super.clear(); + ArrayDeque toUnload = new ArrayDeque<>(); + final int distance = Bukkit.getViewDistance() + 2; + HashMap> players = new HashMap<>(); + for (final Player player : Bukkit.getOnlinePlayers()) { + // Clear history + final FawePlayer fp = FawePlayer.wrap(player); + final LocalSession s = fp.getSession(); + if (s != null) { + s.clearHistory(); + s.setClipboard(null); + } + final Location loc = player.getLocation(); + final World worldObj = loc.getWorld(); + final String world = worldObj.getName(); + HashMap map = players.get(world); + if (map == null) { + map = new HashMap<>(); + players.put(world, map); + } + final IntegerPair origin = new IntegerPair(loc.getBlockX() >> 4, loc.getBlockZ() >> 4); + Integer val = map.get(origin); + int check; + if (val != null) { + if (val == distance) { + continue; + } + check = distance - val; + } else { + check = distance; + map.put(origin, distance); + } + for (int x = -distance; x <= distance; x++) { + if ((x >= check) || (-x >= check)) { + continue; + } + for (int z = -distance; z <= distance; z++) { + if ((z >= check) || (-z >= check)) { + continue; + } + final int weight = distance - Math.max(Math.abs(x), Math.abs(z)); + final IntegerPair chunk = new IntegerPair(x + origin.x, z + origin.z); + val = map.get(chunk); + if ((val == null) || (val < weight)) { + map.put(chunk, weight); + } + } + } + } + Fawe.get().getWorldEdit().clearSessions(); + for (final World world : Bukkit.getWorlds()) { + final String name = world.getName(); + final HashMap map = players.get(name); + if ((map == null) || (map.size() == 0)) { + final boolean save = world.isAutoSave(); + world.setAutoSave(false); + for (final Chunk chunk : world.getLoadedChunks()) { + this.unloadChunk(name, chunk); + } + world.setAutoSave(save); + continue; + } + final Chunk[] chunks = world.getLoadedChunks(); + for (final Chunk chunk : chunks) { + final int x = chunk.getX(); + final int z = chunk.getZ(); + if (!map.containsKey(new IntegerPair(x, z))) { + toUnload.add(chunk); + } else if (chunk.getEntities().length > 4096) { + for (final Entity ent : chunk.getEntities()) { + ent.remove(); + } + } + } + } + // GC again + System.gc(); + System.gc(); + // If still critical memory + int free = MemUtil.calculateMemory(); + if (free <= 1) { + for (final Chunk chunk : toUnload) { + this.unloadChunk(chunk.getWorld().getName(), chunk); + } + } else if (free == Integer.MAX_VALUE) { + for (final Chunk chunk : toUnload) { + chunk.unload(true, false); + } + } else { + return; + } + toUnload = null; + players = null; + } + + public Object newChunkSection(final int i, final boolean flag, final char[] ids) { + return this.classChunkSectionConstructor.create(i, flag, ids); + } + + @Override + public FaweChunk getChunk(final ChunkLoc wrap) { + return new BukkitChunk_1_9(wrap); + } + + public boolean unloadChunk(final String world, final Chunk chunk) { + final Object c = this.methodGetHandleChunk.of(chunk).call(); + this.mustSave.of(c).set(false); + if (chunk.isLoaded()) { + chunk.unload(false, false); + } + return true; + } + + public ChunkGenerator setGenerator(final World world, final ChunkGenerator newGen) { + try { + final ChunkGenerator gen = world.getGenerator(); + final Class clazz = world.getClass(); + final Field generator = clazz.getDeclaredField("generator"); + generator.setAccessible(true); + generator.set(world, newGen); + + final Field wf = clazz.getDeclaredField("world"); + wf.setAccessible(true); + final Object w = wf.get(world); + final Class clazz2 = w.getClass().getSuperclass(); + final Field generator2 = clazz2.getDeclaredField("generator"); + generator2.set(w, newGen); + + return gen; + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } + + public List setPopulator(final World world, final List newPop) { + try { + final List pop = world.getPopulators(); + final Field populators = world.getClass().getDeclaredField("populators"); + populators.setAccessible(true); + populators.set(world, newPop); + return pop; + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } + + public void setEntitiesAndTiles(final Chunk chunk, final List[] entities, final Map tiles) { + try { + final Class clazz = chunk.getClass(); + final Method handle = clazz.getMethod("getHandle"); + final Object c = handle.invoke(chunk); + final Class clazz2 = c.getClass(); + + if (tiles.size() > 0) { + final Field tef = clazz2.getDeclaredField("tileEntities"); + final Map te = (Map) tef.get(c); + final Method put = te.getClass().getMethod("putAll", Map.class); + put.invoke(te, tiles); + } + + final Field esf = clazz2.getDeclaredField("entitySlices"); + esf.setAccessible(true); + esf.set(c, entities); + } catch (final Exception e) { + e.printStackTrace(); + } + } + + public Object getProvider(final World world) { + try { + // Provider 1 + final Class clazz = world.getClass(); + final Field wf = clazz.getDeclaredField("world"); + wf.setAccessible(true); + final Object w = wf.get(world); + final Field provider = w.getClass().getSuperclass().getDeclaredField("chunkProvider"); + provider.setAccessible(true); + // ChunkProviderServer + final Class clazz2 = w.getClass(); + final Field wpsf = clazz2.getDeclaredField("chunkProviderServer"); + // Store old provider server + final Object worldProviderServer = wpsf.get(w); + // Store the old provider + final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider"); + return cp.get(worldProviderServer); + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } + + public Object setProvider(final World world, Object newProvider) { + try { + // Provider 1 + final Class clazz = world.getClass(); + final Field wf = clazz.getDeclaredField("world"); + wf.setAccessible(true); + final Object w = wf.get(world); + // ChunkProviderServer + final Class clazz2 = w.getClass(); + final Field wpsf = clazz2.getDeclaredField("chunkProviderServer"); + // Store old provider server + final Object worldProviderServer = wpsf.get(w); + // Store the old provider + final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider"); + final Object oldProvider = cp.get(worldProviderServer); + // Provider 2 + final Class clazz3 = worldProviderServer.getClass(); + final Field provider2 = clazz3.getDeclaredField("chunkProvider"); + // If the provider needs to be calculated + if (newProvider == null) { + Method k; + try { + k = clazz2.getDeclaredMethod("k"); + } catch (final Throwable e) { + try { + k = clazz2.getDeclaredMethod("j"); + } catch (final Throwable e2) { + e2.printStackTrace(); + return null; + } + } + k.setAccessible(true); + final Object tempProviderServer = k.invoke(w); + newProvider = cp.get(tempProviderServer); + // Restore old provider + wpsf.set(w, worldProviderServer); + } + // Set provider for provider server + provider2.set(worldProviderServer, newProvider); + // Return the previous provider + return oldProvider; + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/forge/src/main/resources/config.yml b/forge/src/main/resources/config.yml new file mode 100644 index 00000000..e69de29b diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..0ff1aa36 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.daemon=true +org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +org.gradle.configureondemand=true +org.gradle.parallel=true \ No newline at end of file diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..91a7e269 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/pom.xml b/pom.xml index ec25141e..8b550179 100644 --- a/pom.xml +++ b/pom.xml @@ -12,104 +12,53 @@ FastAsyncWorldEdit jar - FastAsyncWorldEdit-Uber - src/main/java + FastAsyncWorldEdit-Bukkit-${project.version} + Bukkit/src/main/java - - true - - LICENSE - - ${basedir}/src/main/resources/ - - - false - - LICENSE - - ${basedir}/src/main/resources/ - + + true + + **/*.* + + bukkit/src/main/resources/ + + + false + + **/*.* + + core/src/main/resources/ + - - maven-jar-plugin - 2.3.2 - - - bukkit - - jar - - package - - FastAsyncWorldEdit-Bukkit - - **/com/boydti/fawe/forge/** - **/com/boydti/fawe/sponge/** - - - - - forge - - jar - - package - - FastAsyncWorldEdit-Forge - - **/com/boydti/fawe/bukkit/** - **/com/boydti/fawe/sponge/** - - - - - sponge - - jar - - package - - FastAsyncWorldEdit-Sponge - - **/com/boydti/fawe/bukkit/** - **/com/boydti/fawe/forge/** - - - - - api - - jar - - package - - FastAsyncWorldEdit-Null - - **/com/boydti/fawe/bukkit/** - **/com/boydti/fawe/forge/** - **/com/boydti/fawe/sponge/** - - - - - - - maven-compiler-plugin - 2.3.2 - - 1.7 - 1.7 - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.10.3 - - -Xdoclint:none - - + + maven-compiler-plugin + 2.3.2 + + + **/forge/src/main/**/*.* + + 1.7 + 1.7 + + + + org.codehaus.mojo + build-helper-maven-plugin + + + generate-sources + + add-source + + + + core/src/main/java + + + + + @@ -234,11 +183,6 @@ jar compile - - org.apache.commons - commons-math3 - 3.2 - junit junit @@ -250,10 +194,5 @@ 1.5 provided - - com.google.code.gson - gson - 2.3.1 - \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..32327a97 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,3 @@ +rootProject.name = 'FastAsyncWorldEdit' + +include 'core', 'bukkit', 'forge' \ No newline at end of file