We don't need these
This commit is contained in:
parent
95d25927ef
commit
938d1f0c79
|
@ -50,28 +50,7 @@ processResources {
|
|||
|
||||
jar.archiveName="fawe-bukkit-${project.parent.version}.jar"
|
||||
jar.destinationDir = file '../mvn/com/boydti/fawe-bukkit/' + project.parent.version
|
||||
task createPom << {
|
||||
pom {
|
||||
project {
|
||||
groupId 'com.boydti'
|
||||
artifactId 'fawe-bukkit'
|
||||
version project.parent.version
|
||||
}
|
||||
}
|
||||
.getEffectivePom()
|
||||
.setDependencies(new ArrayList<>())
|
||||
.writeTo("../mvn/com/boydti/fawe-bukkit/${project.parent.version}/fawe-bukkit-${project.parent.version}.pom")
|
||||
pom {
|
||||
project {
|
||||
groupId 'com.boydti'
|
||||
artifactId 'fawe-bukkit'
|
||||
version 'latest'
|
||||
}
|
||||
}
|
||||
.getEffectivePom()
|
||||
.setDependencies(new ArrayList<>())
|
||||
.writeTo("../mvn/com/boydti/fawe-bukkit/latest/fawe-bukkit-latest.pom")
|
||||
}
|
||||
|
||||
task copyFiles {
|
||||
doLast {
|
||||
copy {
|
||||
|
@ -83,7 +62,7 @@ task copyFiles {
|
|||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
/*apply plugin: 'com.github.johnrengelman.shadow'
|
||||
// We only want the shadow jar produced
|
||||
shadowJar {
|
||||
dependencies {
|
||||
|
@ -100,4 +79,6 @@ shadowJar.doLast {
|
|||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar);
|
||||
build.dependsOn(shadowJar);
|
||||
|
||||
*/
|
|
@ -29,28 +29,6 @@ processResources {
|
|||
|
||||
jar.archiveName="fawe-api-${project.parent.version}.jar"
|
||||
jar.destinationDir = file '../mvn/com/boydti/fawe-api/' + project.parent.version
|
||||
task createPom << {
|
||||
pom {
|
||||
project {
|
||||
groupId 'com.boydti'
|
||||
artifactId 'fawe-api'
|
||||
version project.parent.version
|
||||
}
|
||||
}
|
||||
.getEffectivePom()
|
||||
.setDependencies(new ArrayList<>())
|
||||
.writeTo("../mvn/com/boydti/fawe-api/${project.parent.version}/fawe-api-${project.parent.version}.pom")
|
||||
pom {
|
||||
project {
|
||||
groupId 'com.boydti'
|
||||
artifactId 'fawe-api'
|
||||
version 'latest'
|
||||
}
|
||||
}
|
||||
.getEffectivePom()
|
||||
.setDependencies(new ArrayList<>())
|
||||
.writeTo("../mvn/com/boydti/fawe-api/latest/fawe-api-latest.pom")
|
||||
}
|
||||
|
||||
task copyFiles {
|
||||
doLast {
|
||||
|
@ -63,5 +41,4 @@ task copyFiles {
|
|||
}
|
||||
}
|
||||
|
||||
build.finalizedBy(copyFiles)
|
||||
copyFiles.dependsOn(createPom)
|
||||
build.finalizedBy(copyFiles)
|
|
@ -1,95 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {url = "https://oss.sonatype.org/content/repositories/snapshots/"}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle.forge'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
clean { delete "../target" }
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'org.spongepowered:spongeapi:4.+'
|
||||
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
|
||||
}
|
||||
|
||||
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.10.2-12.18.3.2511"
|
||||
mappings = "snapshot_20160629"
|
||||
runDir = 'run'
|
||||
}
|
||||
|
||||
project.archivesBaseName = "${project.archivesBaseName}-mc${minecraft.version}"
|
||||
|
||||
processResources {
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
expand 'version': project.version,
|
||||
'mcVersion': project.minecraft.version
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
|
||||
dependencies {
|
||||
include(dependency('com.github.luben:zstd-jni:1.1.1'))
|
||||
// include(dependency('org.javassist:javassist:3.22.0-CR1'))
|
||||
include(dependency('co.aikar:fastutil-lite:1.0'))
|
||||
include(dependency(':core'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
|
||||
destinationDir = file '../target'
|
||||
manifest {
|
||||
attributes("Main-Class": "com.boydti.fawe.installer.InstallerFrame")
|
||||
}
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
|
||||
reobf {
|
||||
shadowJar {
|
||||
mappingType = 'SEARGE'
|
||||
}
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar)
|
|
@ -1,194 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.forge.v110.ForgeQueue_All;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.forge.ForgeWorld;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.ModMetadata;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FaweForge implements IFawe {
|
||||
|
||||
private final ForgeMain parent;
|
||||
private final File directory;
|
||||
private final Logger logger;
|
||||
private final ModMetadata mod;
|
||||
|
||||
public FaweForge(ForgeMain plugin, Logger logger, ModMetadata mod, File directory) {
|
||||
this.parent = plugin;
|
||||
this.logger = logger;
|
||||
this.directory = directory;
|
||||
this.mod = mod;
|
||||
try {
|
||||
Fawe.set(this);
|
||||
setupInjector();
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupInjector() {
|
||||
try {
|
||||
Fawe.setupInjector();
|
||||
com.sk89q.worldedit.forge.ForgePlayer.inject();
|
||||
} catch (Throwable e) {
|
||||
Fawe.debug("Failed to inject WorldEdit classes.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String s) {
|
||||
logger.debug(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnlineMode() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().isServerInOnlineMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().getMinecraftVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().getCurrentPlayerCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
private HashMap<String, FaweCommand> commands = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void setupCommand(String label, FaweCommand cmd) {
|
||||
this.commands.put(label, cmd);
|
||||
}
|
||||
|
||||
public HashMap<String, FaweCommand> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
EntityPlayerMP player = null;
|
||||
if (obj instanceof String) {
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
player = server.getPlayerList().getPlayerByUsername((String) obj);
|
||||
} else if (obj instanceof UUID) {
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
player = server.getPlayerList().getPlayerByUUID((UUID) obj);
|
||||
} else if (obj instanceof EntityPlayerMP) {
|
||||
player = (EntityPlayerMP) obj;
|
||||
}
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getName());
|
||||
return existing != null ? existing : new ForgePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVault() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new com.boydti.fawe.forge.ForgeTaskMan(512);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
if (world instanceof WorldWrapper) {
|
||||
return getWorldName(((WorldWrapper) world).getParent());
|
||||
}
|
||||
else if (world instanceof EditSession) {
|
||||
return getWorldName(((EditSession) world).getWorld());
|
||||
}
|
||||
return getWorldName(((ForgeWorld) world).getWorld());
|
||||
|
||||
}
|
||||
|
||||
public String getWorldName(net.minecraft.world.World w) {
|
||||
return w.getWorldInfo().getWorldName() + ";" + w.provider.getDimension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(World world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
try {
|
||||
com.boydti.fawe.forge.ForgeMetrics metrics = new com.boydti.fawe.forge.ForgeMetrics("FastAsyncWorldEdit", "3.5.1");
|
||||
metrics.start();
|
||||
} catch (Throwable e) {
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatform() {
|
||||
return "forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try {
|
||||
GameProfile profile = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerProfileCache().getGameProfileForUsername(name);
|
||||
return profile.getId();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
try {
|
||||
GameProfile profile = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerProfileCache().getProfileByUUID(uuid);
|
||||
return profile.getName();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBlocksHubApi() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class ForgeCommand extends CommandBase {
|
||||
|
||||
private final String name;
|
||||
private final FaweCommand cmd;
|
||||
|
||||
public ForgeCommand(String name, FaweCommand cmd) {
|
||||
this.name = name;
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender iCommandSender) {
|
||||
return "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(MinecraftServer minecraftServer, ICommandSender sender, String[] args) throws CommandException {
|
||||
if ((sender instanceof EntityPlayerMP)) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) sender;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
cmd.executeSafe(fp, args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.5.1", acceptableRemoteVersions = "*", dependencies = "before:worldedit")
|
||||
public class ForgeMain {
|
||||
private static com.boydti.fawe.forge.FaweForge IMP;
|
||||
private Logger logger;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
this.logger = event.getModLog();
|
||||
File directory = new File(event.getModConfigurationDirectory() + File.separator + "FastAsyncWorldEdit");
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
this.IMP = new FaweForge(this, event.getModLog(), event.getModMetadata(), directory);
|
||||
try {
|
||||
Class.forName("org.spongepowered.api.Sponge");
|
||||
Settings.IMP.QUEUE.PARALLEL_THREADS = 1;
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverLoad(FMLServerStartingEvent event) {
|
||||
for (Map.Entry<String, FaweCommand> entry : IMP.getCommands().entrySet()) {
|
||||
event.registerServerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onPlayerQuit(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (event.player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
handleQuit((EntityPlayerMP) event.player);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverStopping(FMLServerStoppingEvent event) {
|
||||
for (EntityPlayerMP player : (List<EntityPlayerMP>)FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayerList()) {
|
||||
handleQuit(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleQuit(EntityPlayerMP player) {
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
if (fp != null) {
|
||||
fp.unregister();
|
||||
}
|
||||
Fawe.get().unregister(player.getName());
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerChangedWorld(EntityJoinWorldEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof EntityPlayerMP)) {
|
||||
return;
|
||||
}
|
||||
EntityPlayerMP player = (EntityPlayerMP) entity;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,476 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
||||
* Ported to Minecraft Forge by Mike Primm
|
||||
* 1.7.x update by Dries007
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.object.io.PGZIPOutputStream;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import java.io.*;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeMetrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 7;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://report.mcstats.org";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/plugin/%s";
|
||||
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 15;
|
||||
|
||||
/**
|
||||
* The mod this metrics submits for
|
||||
*/
|
||||
private final String modName;
|
||||
|
||||
private final String modVersion;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final Configuration configuration;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
|
||||
private Thread thread = null;
|
||||
private boolean firstPost = true;
|
||||
int tickCount;
|
||||
|
||||
public ForgeMetrics(final String modName, final String modVersion) throws IOException {
|
||||
if (modName == null || modVersion == null) {
|
||||
throw new IllegalArgumentException("modName and modVersion cannot be null");
|
||||
}
|
||||
|
||||
this.modName = modName;
|
||||
this.modVersion = modVersion;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = new Configuration(configurationFile);
|
||||
|
||||
// Get values, and add some defaults, if needed
|
||||
configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false, "Set to true to disable all reporting");
|
||||
guid = configuration.get(Configuration.CATEGORY_GENERAL, "guid", UUID.randomUUID().toString(), "Server unique ID").getString();
|
||||
debug = configuration.get(Configuration.CATEGORY_GENERAL, "debug", false, "Set to true for verbose debug").getBoolean(false);
|
||||
configuration.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async
|
||||
* repeating task as the plugin and send the initial data to the metrics
|
||||
* backend, and then after that it will post in increments of PING_INTERVAL
|
||||
* * 1200 ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void tick(TickEvent.ServerTickEvent tick) {
|
||||
if (tick.phase != TickEvent.Phase.END) return;
|
||||
|
||||
if (tickCount++ % (PING_INTERVAL * 1200) != 0) return;
|
||||
|
||||
if (thread == null) {
|
||||
thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Disable Task, if it is running and the server owner decided
|
||||
// to opt-out
|
||||
if (isOptOut()) {
|
||||
FMLCommonHandler.instance().bus().unregister(ForgeMetrics.this);
|
||||
return;
|
||||
}
|
||||
// We use the inverse of firstPost because if it
|
||||
// is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to
|
||||
// FALSE
|
||||
// Each time thereafter it will evaluate to
|
||||
// TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
// After the first post we set firstPost to
|
||||
// false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
FMLLog.info("[Metrics] Exception - %s", e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
// Reload the metrics file
|
||||
configuration.load();
|
||||
return configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false).getBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the
|
||||
* config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("false");
|
||||
configuration.save();
|
||||
}
|
||||
// Enable Task, if it is not running
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the
|
||||
* config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("true");
|
||||
configuration.save();
|
||||
}
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data
|
||||
* such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
return new File(Loader.instance().getConfigDir(), "PluginMetrics.cfg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
String pluginName = modName;
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
boolean onlineMode = server.isServerInOnlineMode();
|
||||
String pluginVersion = modVersion;
|
||||
String serverVersion;
|
||||
if (server.isDedicatedServer()) {
|
||||
serverVersion = "MinecraftForge (MC: " + server.getMinecraftVersion() + ")";
|
||||
} else {
|
||||
serverVersion = "MinecraftForgeSSP (MC: " + server.getMinecraftVersion() + ")";
|
||||
}
|
||||
int playersOnline = server.getCurrentPlayerCount();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
StringBuilder json = new StringBuilder(1024);
|
||||
json.append('{');
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
appendJSONPair(json, "guid", guid);
|
||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
||||
appendJSONPair(json, "server_version", serverVersion);
|
||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
appendJSONPair(json, "osname", osname);
|
||||
appendJSONPair(json, "osarch", osarch);
|
||||
appendJSONPair(json, "osversion", osversion);
|
||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
||||
appendJSONPair(json, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
appendJSONPair(json, "ping", "1");
|
||||
}
|
||||
|
||||
// close json
|
||||
json.append('}');
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
|
||||
byte[] uncompressed = json.toString().getBytes();
|
||||
byte[] compressed = gzip(json.toString());
|
||||
|
||||
// Headers
|
||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
||||
connection.addRequestProperty("Content-Type", "application/json");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(compressed);
|
||||
os.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
os.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
||||
if (response == null) {
|
||||
response = "null";
|
||||
} else if (response.startsWith("7")) {
|
||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
||||
}
|
||||
|
||||
throw new IOException(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GZip compress a string of bytes
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static byte[] gzip(String input) {
|
||||
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
|
||||
PGZIPOutputStream gzos = null;
|
||||
|
||||
try {
|
||||
gzos = new PGZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
MainUtil.handleError(e);
|
||||
} finally {
|
||||
if (gzos != null) try {
|
||||
gzos.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
||||
*
|
||||
* @return true if mineshafter is installed on the server
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a json encoded key/value pair to the given string builder.
|
||||
*
|
||||
* @param json
|
||||
* @param key
|
||||
* @param value
|
||||
* @throws java.io.UnsupportedEncodingException
|
||||
*/
|
||||
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
|
||||
boolean isValueNumeric = false;
|
||||
|
||||
try {
|
||||
if (value.equals("0") || !value.endsWith("0")) {
|
||||
Double.parseDouble(value);
|
||||
isValueNumeric = true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
isValueNumeric = false;
|
||||
}
|
||||
|
||||
if (json.charAt(json.length() - 1) != '{') {
|
||||
json.append(',');
|
||||
}
|
||||
|
||||
json.append(escapeJSON(key));
|
||||
json.append(':');
|
||||
|
||||
if (isValueNumeric) {
|
||||
json.append(value);
|
||||
} else {
|
||||
json.append(escapeJSON(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string to create a valid JSON string
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
private static String escapeJSON(String text) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append('"');
|
||||
for (int index = 0; index < text.length(); index++) {
|
||||
char chr = text.charAt(index);
|
||||
|
||||
switch (chr) {
|
||||
case '"':
|
||||
case '\\':
|
||||
builder.append('\\');
|
||||
builder.append(chr);
|
||||
break;
|
||||
case '\b':
|
||||
builder.append("\\b");
|
||||
break;
|
||||
case '\t':
|
||||
builder.append("\\t");
|
||||
break;
|
||||
case '\n':
|
||||
builder.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.append("\\r");
|
||||
break;
|
||||
default:
|
||||
if (chr < ' ') {
|
||||
String t = "000" + Integer.toHexString(chr);
|
||||
builder.append("\\u" + t.substring(t.length() - 4));
|
||||
} else {
|
||||
builder.append(chr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.append('"');
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text, as UTF-8
|
||||
*/
|
||||
private static String urlEncode(final String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.wrappers.PlayerWrapper;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
|
||||
public ForgePlayer(EntityPlayerMP parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String head, String sub) { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTitle() { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return parent.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
Object meta = getMeta(perm);
|
||||
return meta instanceof Boolean ? (boolean) meta : ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(parent, perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(String perm, boolean flag) {
|
||||
setMeta(perm, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
msg = BBC.color(msg);
|
||||
for (String line : msg.split("\n")) {
|
||||
this.parent.addChatMessage(new TextComponentString(line));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(String substring) {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweLocation getLocation() {
|
||||
World world = parent.worldObj;
|
||||
BlockPos pos = parent.getPosition();
|
||||
return new FaweLocation(Fawe.<FaweForge>imp().getWorldName(world), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player toWorldEditPlayer() {
|
||||
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBagException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class ForgePlayerBlockBag extends BlockBag {
|
||||
|
||||
private EntityPlayerMP player;
|
||||
private ItemStack[] items;
|
||||
private boolean changed;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public ForgePlayerBlockBag(EntityPlayerMP player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads inventory on first use.
|
||||
*/
|
||||
private void loadInventory() {
|
||||
if (items == null) {
|
||||
items = new ItemStack[player.inventory.getSizeInventory()];
|
||||
for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
|
||||
items[i] = player.inventory.getStackInSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public EntityPlayerMP getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount == 1);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't fetch air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
continue;
|
||||
}
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.stackSize;
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
if (currentAmount > 1) {
|
||||
forgeItem.stackSize--;
|
||||
found = true;
|
||||
} else {
|
||||
items[slot] = null;
|
||||
found = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new OutOfBlocksException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount <= 64);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't store air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
int freeSlot = -1;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
// Delay using up a free slot until we know there are no stacks
|
||||
// of this item to merge into
|
||||
|
||||
if (freeSlot == -1) {
|
||||
freeSlot = slot;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.stackSize;
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
if (currentAmount >= 64) {
|
||||
// Full stack
|
||||
continue;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
int spaceLeft = 64 - currentAmount;
|
||||
if (spaceLeft >= amount) {
|
||||
forgeItem.stackSize += amount;
|
||||
return;
|
||||
}
|
||||
|
||||
forgeItem.stackSize = (64);
|
||||
amount -= spaceLeft;
|
||||
}
|
||||
|
||||
if (freeSlot > -1) {
|
||||
changed = true;
|
||||
items[freeSlot] = new ItemStack(Item.getItemById(id), amount);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new OutOfSpaceException(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushChanges() {
|
||||
if (items != null && changed) {
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
player.inventory.setInventorySlotContents(i, items[i]);
|
||||
}
|
||||
items = null;
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSingleSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeTaskMan extends TaskManager {
|
||||
|
||||
private final ConcurrentLinkedDeque<Runnable> syncTasks = new ConcurrentLinkedDeque<>();
|
||||
private final ConcurrentLinkedDeque<Runnable> asyncTasks = new ConcurrentLinkedDeque<>();
|
||||
|
||||
private final ConcurrentHashMap<Integer, Runnable> taskIdMap = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
|
||||
|
||||
private final AtomicInteger taskId = new AtomicInteger();
|
||||
private final ExecutorService executor;
|
||||
|
||||
public ForgeTaskMan(int size) {
|
||||
this.executor = Executors.newFixedThreadPool(size);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int repeat(final Runnable r, final int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
later(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
Fawe.get().setMainThread();
|
||||
int asyncSize = asyncTasks.size();
|
||||
for (int i = 0; i < asyncSize; i++) {
|
||||
Runnable item = asyncTasks.poll();
|
||||
if (item != null) {
|
||||
async(item);
|
||||
}
|
||||
}
|
||||
int syncSize = syncTasks.size();
|
||||
for (int i = 0; i < syncSize; i++) {
|
||||
Runnable item = syncTasks.poll();
|
||||
if (item != null) {
|
||||
try {
|
||||
item.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(Runnable r, int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
laterAsync(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
executor.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
syncTasks.add(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
async(r);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int task) {
|
||||
taskIdMap.remove(task);
|
||||
}
|
||||
}
|
|
@ -1,369 +0,0 @@
|
|||
package com.boydti.fawe.forge.v110;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BitArray;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IBlockStatePalette;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
|
||||
public BlockStateContainer[] sectionPalettes;
|
||||
|
||||
/**
|
||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||
*
|
||||
* @param parent
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
}
|
||||
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
|
||||
super(parent, x, z, ids, count, air, heightMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk copy(boolean shallow) {
|
||||
ForgeChunk_All copy;
|
||||
if (shallow) {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), ids, count, air, heightMap);
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
} else {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
copy.biomes = biomes.clone();
|
||||
copy.chunk = chunk;
|
||||
}
|
||||
if (sectionPalettes != null) {
|
||||
copy.sectionPalettes = new BlockStateContainer[16];
|
||||
try {
|
||||
Field fieldBits = BlockStateContainer.class.getDeclaredField("field_186021_b");
|
||||
fieldBits.setAccessible(true);
|
||||
Field fieldPalette = BlockStateContainer.class.getDeclaredField("field_186022_c");
|
||||
fieldPalette.setAccessible(true);
|
||||
Field fieldSize = BlockStateContainer.class.getDeclaredField("field_186024_e");
|
||||
fieldSize.setAccessible(true);
|
||||
for (int i = 0; i < sectionPalettes.length; i++) {
|
||||
BlockStateContainer current = sectionPalettes[i];
|
||||
if (current == null) {
|
||||
continue;
|
||||
}
|
||||
// Clone palette
|
||||
IBlockStatePalette currentPalette = (IBlockStatePalette) fieldPalette.get(current);
|
||||
if (!(currentPalette instanceof BlockStatePaletteRegistry)) {
|
||||
current.onResize(128, null);
|
||||
}
|
||||
BlockStateContainer paletteBlock = new BlockStateContainer();
|
||||
currentPalette = (IBlockStatePalette) fieldPalette.get(current);
|
||||
if (!(currentPalette instanceof BlockStatePaletteRegistry)) {
|
||||
throw new RuntimeException("Palette must be global!");
|
||||
}
|
||||
fieldPalette.set(paletteBlock, currentPalette);
|
||||
// Clone size
|
||||
fieldSize.set(paletteBlock, fieldSize.get(current));
|
||||
// Clone palette
|
||||
BitArray currentBits = (BitArray) fieldBits.get(current);
|
||||
BitArray newBits = new BitArray(1, 0);
|
||||
for (Field field : BitArray.class.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
Object currentValue = field.get(currentBits);
|
||||
if (currentValue instanceof long[]) {
|
||||
currentValue = ((long[]) currentValue).clone();
|
||||
}
|
||||
field.set(newBits, currentValue);
|
||||
}
|
||||
fieldBits.set(paletteBlock, newBits);
|
||||
copy.sectionPalettes[i] = paletteBlock;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getNewChunk() {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
return world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
if (sectionPalettes != null) {
|
||||
return;
|
||||
}
|
||||
char[][] arrays = getCombinedIdArrays();
|
||||
char lastChar = Character.MAX_VALUE;
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
if (getCount(layer) > 0) {
|
||||
if (sectionPalettes == null) {
|
||||
sectionPalettes = new BlockStateContainer[16];
|
||||
}
|
||||
BlockStateContainer palette = new BlockStateContainer();
|
||||
char[] blocks = getIdArray(layer);
|
||||
int index = 0;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
char combinedId = blocks[index++];
|
||||
if (combinedId > 1) {
|
||||
palette.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForgeChunk_All call() {
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||
int bx = this.getX() << 4;
|
||||
int bz = this.getZ() << 4;
|
||||
nmsChunk.setModified(true);
|
||||
net.minecraft.world.World nmsWorld = getParent().getWorld();
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||
// Sections
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
|
||||
// Set heightmap
|
||||
getParent().setHeightMap(this, heightMap);
|
||||
|
||||
// Remove entities
|
||||
for (int i = 0; i < 16; i++) {
|
||||
int count = this.getCount(i);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
} else if (count >= 4096) {
|
||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||
} else if (!getParent().getSettings().EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) {
|
||||
char[] array = this.getIdArray(i);
|
||||
if (array == null || entities[i] == null || entities[i].isEmpty()) continue;
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entity instanceof EntityPlayer) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(entity.posX) & 15);
|
||||
int z = (MathMan.roundInt(entity.posZ) & 15);
|
||||
int y = MathMan.roundInt(entity.posY);
|
||||
if (y < 0 || y > 255) continue;
|
||||
if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashSet<UUID> entsToRemove = this.getEntityRemoves();
|
||||
if (entsToRemove.size() > 0) {
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entsToRemove.contains(entity.getUniqueID())) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set entities
|
||||
Set<UUID> createdEntities = new HashSet<>();
|
||||
Set<CompoundTag> entitiesToSpawn = this.getEntities();
|
||||
for (CompoundTag nativeTag : entitiesToSpawn) {
|
||||
Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||
if (idTag == null || posTag == null || rotTag == null) {
|
||||
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||
continue;
|
||||
}
|
||||
double x = posTag.getDouble(0);
|
||||
double y = posTag.getDouble(1);
|
||||
double z = posTag.getDouble(2);
|
||||
float yaw = rotTag.getFloat(0);
|
||||
float pitch = rotTag.getFloat(1);
|
||||
String id = idTag.getValue();
|
||||
if (id != null) {
|
||||
Entity entity = EntityList.createEntityByName(id, nmsWorld);
|
||||
if (entity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.removeTag("UUIDMost");
|
||||
tag.removeTag("UUIDLeast");
|
||||
entity.readFromNBT(tag);
|
||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||
nmsWorld.spawnEntityInWorld(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Run change task if applicable
|
||||
if (getParent().getChangeTask() != null) {
|
||||
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||
getParent().getChangeTask().run(previous, this);
|
||||
}
|
||||
// Trim tiles
|
||||
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||
BlockPos pos = tile.getKey();
|
||||
int lx = pos.getX() & 15;
|
||||
int ly = pos.getY();
|
||||
int lz = pos.getZ() & 15;
|
||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||
char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||
if (array[k] != 0) {
|
||||
tile.getValue().invalidate();;
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
int count = this.getCount(j);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
}
|
||||
final char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int countAir = this.getAir(j);
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if (section == null) {
|
||||
if (count == countAir) {
|
||||
continue;
|
||||
}
|
||||
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||
section = sections[j] = new ExtendedBlockStorage(j << 4, flag);
|
||||
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||
getParent().setCount(0, count - this.getAir(j), section);
|
||||
continue;
|
||||
} else {
|
||||
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
||||
}
|
||||
} else if (count >= 4096) {
|
||||
if (count == countAir) {
|
||||
sections[j] = null;
|
||||
continue;
|
||||
}
|
||||
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||
getParent().setCount(0, count - this.getAir(j), section);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
IBlockState existing;
|
||||
int by = j << 4;
|
||||
BlockStateContainer nibble = section.getData();
|
||||
int nonEmptyBlockCount = 0;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
||||
switch (combinedId) {
|
||||
case 0:
|
||||
continue;
|
||||
case 1:
|
||||
existing = nibble.get(x, y, z);
|
||||
if (existing != ForgeQueue_All.air) {
|
||||
if (existing.getLightValue() > 0) {
|
||||
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
|
||||
}
|
||||
nonEmptyBlockCount--;
|
||||
}
|
||||
nibble.set(x, y, z, ForgeQueue_All.air);
|
||||
continue;
|
||||
default:
|
||||
existing = nibble.get(x, y, z);
|
||||
if (existing != ForgeQueue_All.air) {
|
||||
if (existing.getLightValue() > 0) {
|
||||
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
|
||||
}
|
||||
} else {
|
||||
nonEmptyBlockCount++;
|
||||
}
|
||||
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
|
||||
}
|
||||
// Set biomes
|
||||
if (this.biomes != null) {
|
||||
byte[] currentBiomes = nmsChunk.getBiomeArray();
|
||||
for (int i = 0 ; i < this.biomes.length; i++) {
|
||||
byte biome = this.biomes[i];
|
||||
if (biome != 0) {
|
||||
if (biome == -1) biome = 0;
|
||||
currentBiomes[i] = biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set tiles
|
||||
Map<Short, CompoundTag> tilesToSpawn = this.getTiles();
|
||||
|
||||
for (Map.Entry<Short, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||
CompoundTag nativeTag = entry.getValue();
|
||||
short blockHash = entry.getKey();
|
||||
int x = (blockHash >> 12 & 0xF) + bx;
|
||||
int y = (blockHash & 0xFF);
|
||||
int z = (blockHash >> 8 & 0xF) + bz;
|
||||
BlockPos pos = new BlockPos(x, y, z); // Set pos
|
||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||
if (tileEntity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.setInteger("x", pos.getX());
|
||||
tag.setInteger("y", pos.getY());
|
||||
tag.setInteger("z", pos.getZ());
|
||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
sectionPalettes = null;
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,578 +0,0 @@
|
|||
package com.boydti.fawe.forge.v110;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.brush.visualization.VisualChunk;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.SPacketChunkData;
|
||||
import net.minecraft.network.play.server.SPacketMultiBlockChange;
|
||||
import net.minecraft.server.management.PlayerChunkMap;
|
||||
import net.minecraft.server.management.PlayerChunkMapEntry;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.EnumSkyBlock;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkGenerator;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.NibbleArray;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
protected final static Method methodFromNative;
|
||||
protected final static Method methodToNative;
|
||||
protected final static Field fieldTickingBlockCount;
|
||||
protected final static Field fieldNonEmptyBlockCount;
|
||||
protected static ExtendedBlockStorage emptySection;
|
||||
|
||||
static {
|
||||
try {
|
||||
emptySection = new ExtendedBlockStorage(0, true);
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
|
||||
methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
|
||||
methodFromNative.setAccessible(true);
|
||||
methodToNative.setAccessible(true);
|
||||
|
||||
fieldTickingBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76683_c");
|
||||
fieldNonEmptyBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76682_b");
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(Chunk chunk) {
|
||||
chunk.setChunkModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
|
||||
Chunk forgeChunk = (Chunk) chunk.getChunk();
|
||||
if (forgeChunk != null) {
|
||||
int[] otherMap = forgeChunk.getHeightMap();
|
||||
for (int i = 0; i < heightMap.length; i++) {
|
||||
int newHeight = heightMap[i] & 0xFF;
|
||||
int currentHeight = otherMap[i];
|
||||
if (newHeight > currentHeight) {
|
||||
otherMap[i] = newHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getSections(Chunk chunk) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiome(Chunk chunk, int x, int z) {
|
||||
return chunk.getBiomeArray()[((z & 15) << 4) + (x & 15)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk loadChunk(World world, int x, int z, boolean generate) {
|
||||
ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider();
|
||||
if (generate) {
|
||||
return provider.provideChunk(x, z);
|
||||
} else {
|
||||
return provider.loadChunk(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getCachedSections(World world, int cx, int cz) {
|
||||
Chunk chunk = world.getChunkProvider().getLoadedChunk(cx, cz);
|
||||
if (chunk != null) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getCachedChunk(World world, int cx, int cz) {
|
||||
return world.getChunkProvider().getLoadedChunk(cx, cz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage getCachedSection(ExtendedBlockStorage[] ExtendedBlockStorages, int cy) {
|
||||
return ExtendedBlockStorages[cy];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
|
||||
try {
|
||||
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
|
||||
boolean watching = false;
|
||||
boolean[] watchingArr = new boolean[players.length];
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) ((ForgePlayer) players[i]).parent;
|
||||
if (playerManager.isPlayerWatchingChunk(player, chunk.getX(), chunk.getZ())) {
|
||||
watchingArr[i] = true;
|
||||
watching = true;
|
||||
}
|
||||
}
|
||||
if (!watching) return;
|
||||
final LongAdder size = new LongAdder();
|
||||
if (chunk instanceof VisualChunk) {
|
||||
size.add(((VisualChunk) chunk).size());
|
||||
} else if (chunk instanceof CharFaweChunk) {
|
||||
size.add(((CharFaweChunk) chunk).getTotalCount());
|
||||
} else {
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
size.add(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (size.intValue() == 0) return;
|
||||
SPacketMultiBlockChange packet = new SPacketMultiBlockChange();
|
||||
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
|
||||
final PacketBuffer buffer = new PacketBuffer(byteBuf);
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
buffer.writeVarIntToBuffer(size.intValue());
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
short index = (short) (localX << 12 | localZ << 8 | y);
|
||||
buffer.writeShort(index);
|
||||
buffer.writeVarIntToBuffer(combined);
|
||||
}
|
||||
});
|
||||
packet.readPacketData(buffer);
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
if (watchingArr[i]) ((EntityPlayerMP) ((ForgePlayer) players[i]).parent).connection.sendPacket(packet);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
|
||||
@Override
|
||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||
Map<BlockPos, TileEntity> tiles = chunk.getTileEntityMap();
|
||||
pos.setPos(x, y, z);
|
||||
TileEntity tile = tiles.get(pos);
|
||||
return tile != null ? getTag(tile) : null;
|
||||
}
|
||||
|
||||
public CompoundTag getTag(TileEntity tile) {
|
||||
try {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTagIntoEntity
|
||||
CompoundTag result = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
MainUtil.handleError(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) {
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
IChunkGenerator gen = chunkServer.chunkGenerator;
|
||||
long pos = ChunkPos.chunkXZ2Int(x, z);
|
||||
Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
|
||||
List<EntityPlayerMP> oldWatchers = null;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
PlayerChunkMapEntry entry = playerManager.getEntry(x, z);
|
||||
if (entry != null) {
|
||||
Field fieldPlayers = PlayerChunkMapEntry.class.getDeclaredField("field_187283_c");
|
||||
fieldPlayers.setAccessible(true);
|
||||
oldWatchers = (List<EntityPlayerMP>) fieldPlayers.get(entry);
|
||||
playerManager.removeEntry(entry);
|
||||
}
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
try {
|
||||
Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b");
|
||||
droppedChunksSetField.setAccessible(true);
|
||||
Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer);
|
||||
droppedChunksSet.remove(pos);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
chunkServer.id2ChunkMap.remove(pos);
|
||||
mcChunk = gen.provideChunk(x, z);
|
||||
chunkServer.id2ChunkMap.put(pos, mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkServer, chunkServer.chunkGenerator);
|
||||
}
|
||||
if (oldWatchers != null) {
|
||||
for (EntityPlayerMP player : oldWatchers) {
|
||||
playerManager.addPlayer(player);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
MainUtil.handleError(t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
IBlockState ibd = section.getData().get(x & 15, y & 15, z & 15);
|
||||
Block block = ibd.getBlock();
|
||||
int id = Block.getIdFromBlock(block);
|
||||
if (FaweCache.hasData(id)) {
|
||||
return (id << 4) + block.getMetaFromState(ibd);
|
||||
} else {
|
||||
return id << 4;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNonEmptyBlockCount(ExtendedBlockStorage section) throws IllegalAccessException {
|
||||
return (int) fieldNonEmptyBlockCount.get(section);
|
||||
}
|
||||
|
||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||
Map<BlockPos, TileEntity> tiles = (Map<BlockPos, TileEntity>) tilesGeneric;
|
||||
ClassInheritanceMultiMap<Entity>[] entities = (ClassInheritanceMultiMap<Entity>[]) entitiesGeneric;
|
||||
CharFaweChunk previous = (CharFaweChunk) getFaweChunk(fs.getX(), fs.getZ());
|
||||
char[][] idPrevious = previous.getCombinedIdArrays();
|
||||
for (int layer = 0; layer < sections.length; layer++) {
|
||||
if (fs.getCount(layer) != 0 || all) {
|
||||
ExtendedBlockStorage section = sections[layer];
|
||||
if (section != null) {
|
||||
short solid = 0;
|
||||
char[] previousLayer = idPrevious[layer] = new char[4096];
|
||||
BlockStateContainer blocks = section.getData();
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int x = FaweCache.CACHE_X[0][j];
|
||||
int y = FaweCache.CACHE_Y[0][j];
|
||||
int z = FaweCache.CACHE_Z[0][j];
|
||||
IBlockState ibd = blocks.get(x, y, z);
|
||||
Block block = ibd.getBlock();
|
||||
int combined = Block.getIdFromBlock(block);
|
||||
if (FaweCache.hasData(combined)) {
|
||||
combined = (combined << 4) + block.getMetaFromState(ibd);
|
||||
} else {
|
||||
combined = combined << 4;
|
||||
}
|
||||
if (combined > 1) {
|
||||
solid++;
|
||||
}
|
||||
previousLayer[j] = (char) combined;
|
||||
}
|
||||
previous.count[layer] = solid;
|
||||
previous.air[layer] = (short) (4096 - solid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tiles != null) {
|
||||
for (Map.Entry<BlockPos, TileEntity> entry : tiles.entrySet()) {
|
||||
TileEntity tile = entry.getValue();
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTileEntityIntoTag
|
||||
BlockPos pos = entry.getKey();
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
|
||||
}
|
||||
}
|
||||
if (entities != null) {
|
||||
for (Collection<Entity> entityList : entities) {
|
||||
for (Entity ent : entityList) {
|
||||
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && createdEntities.contains(ent.getUniqueID()))) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(ent.posX) & 15);
|
||||
int z = (MathMan.roundInt(ent.posZ) & 15);
|
||||
int y = MathMan.roundInt(ent.posY);
|
||||
int i = FaweCache.CACHE_I[y][z][x];
|
||||
char[] array = fs.getIdArray(i);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int j = FaweCache.CACHE_J[y][z][x];
|
||||
if (array[j] != 0) {
|
||||
String id = EntityList.getEntityString(ent);
|
||||
if (id != null) {
|
||||
NBTTagCompound tag = ent.getEntityData(); // readEntityIntoTag
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
||||
map.put("Id", new StringTag(id));
|
||||
previous.setEntity(nativeTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
protected final static IBlockState air = Blocks.AIR.getDefaultState();
|
||||
|
||||
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
||||
fieldSection.setAccessible(true);
|
||||
fieldSection.set(section, palette);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int x, int z, int bitMask) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), x, z);
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, bitMask);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChunk(FaweChunk fc) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, fc.getBitMask());
|
||||
}
|
||||
}
|
||||
|
||||
public void sendChunk(Chunk nmsChunk, int mask) {
|
||||
if (!nmsChunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ChunkPos pos = nmsChunk.getChunkCoordIntPair();
|
||||
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
||||
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
||||
int x = pos.chunkXPos;
|
||||
int z = pos.chunkZPos;
|
||||
PlayerChunkMapEntry chunkMapEntry = chunkMap.getEntry(x, z);
|
||||
if (chunkMapEntry == null) {
|
||||
return;
|
||||
}
|
||||
final ArrayDeque<EntityPlayerMP> players = new ArrayDeque<>();
|
||||
chunkMapEntry.hasPlayerMatching(input -> {
|
||||
players.add(input);
|
||||
return false;
|
||||
});
|
||||
boolean empty = false;
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == null) {
|
||||
sections[i] = emptySection;
|
||||
empty = true;
|
||||
}
|
||||
}
|
||||
if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
|
||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65280);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.connection.sendPacket(packet);
|
||||
}
|
||||
mask = 255;
|
||||
}
|
||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, mask);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.connection.sendPacket(packet);
|
||||
}
|
||||
if (empty) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == emptySection) {
|
||||
sections[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEntities(Chunk nmsChunk) {
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
ClassInheritanceMultiMap<Entity> slice = entities[i];
|
||||
if (slice != null && !slice.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSectionLighting(ExtendedBlockStorage section, int layer, boolean sky) {
|
||||
if (section != null) {
|
||||
section.setBlocklightArray(new NibbleArray());
|
||||
if (sky) {
|
||||
section.setSkylightArray(new NibbleArray());
|
||||
}
|
||||
}
|
||||
return section != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSky() {
|
||||
return !nmsWorld.provider.getHasNoSky();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullbright(ExtendedBlockStorage[] sections) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section != null) {
|
||||
byte[] bytes = section.getSkylightArray().getData();
|
||||
Arrays.fill(bytes, (byte) 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relight(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
if (nmsWorld != null || getWorldName() == null) {
|
||||
return nmsWorld;
|
||||
}
|
||||
String[] split = getWorldName().split(";");
|
||||
int id = Integer.parseInt(split[split.length - 1]);
|
||||
nmsWorld = DimensionManager.getWorld(id);
|
||||
return nmsWorld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getSkylightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getBlocklightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtSkylightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtBlocklightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return ibd.getLightOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return ibd.getLightValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacityBrightnessPair(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return MathMan.pair16(ibd.getLightOpacity(), ibd.getLightValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightBlock(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.BLOCK, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightSky(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.SKY, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSaveFolder() {
|
||||
return new File(((WorldServer) getWorld()).getChunkSaveLocation(), "region");
|
||||
}
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.forge;
|
||||
|
||||
import com.boydti.fawe.forge.ForgePlayerBlockBag;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.SPacketCustomPayload;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
|
||||
public class ForgePlayer extends AbstractPlayerActor {
|
||||
|
||||
private final ForgePlatform platform;
|
||||
private final EntityPlayerMP player;
|
||||
|
||||
protected ForgePlayer(ForgePlatform platform, EntityPlayerMP player) {
|
||||
this.platform = platform;
|
||||
this.player = player;
|
||||
ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return player.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
ItemStack is = this.player.getHeldItem(EnumHand.MAIN_HAND);
|
||||
return is == null ? 0 : Item.getIdFromItem(is.getItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockInHand() {
|
||||
ItemStack is = this.player.getHeldItem(EnumHand.MAIN_HAND);
|
||||
return is == null ? EditSession.nullBlock : new BaseBlock(Item.getIdFromItem(is.getItem()), is.isItemStackDamageable() ? 0 : is.getItemDamage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.player.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
throw new UnsupportedOperationException("Cannot create a state from this object");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ);
|
||||
return new Location(
|
||||
ForgeWorldEdit.inst.getWorld(this.player.worldObj),
|
||||
position,
|
||||
this.player.rotationYaw,
|
||||
this.player.rotationPitch);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public WorldVector getPosition() {
|
||||
return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sk89q.worldedit.world.World getWorld() {
|
||||
return ForgeWorldEdit.inst.getWorld(this.player.worldObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPitch() {
|
||||
return this.player.rotationPitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return this.player.rotationYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(int type, int amt) {
|
||||
this.player.inventory.addItemStackToInventory(new ItemStack(Item.getItemById(type), amt, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
String[] params = event.getParameters();
|
||||
String send = event.getTypeId();
|
||||
if (params.length > 0) {
|
||||
send = send + "|" + StringUtil.joinString(params, "|");
|
||||
}
|
||||
PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)));
|
||||
SPacketCustomPayload packet = new SPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer);
|
||||
this.player.connection.sendPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.addChatMessage(new TextComponentString(part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
sendColorized(msg, TextFormatting.GRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
sendColorized(msg, TextFormatting.LIGHT_PURPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
sendColorized(msg, TextFormatting.RED);
|
||||
}
|
||||
|
||||
private void sendColorized(String msg, TextFormatting formatting) {
|
||||
for (String part : msg.split("\n")) {
|
||||
TextComponentString component = new TextComponentString(part);
|
||||
component.getStyle().setColor(formatting);
|
||||
this.player.addChatMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||
this.player.connection.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return new ForgePlayerBlockBag(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return new SessionKeyImpl(player.getUniqueID(), player.getName());
|
||||
}
|
||||
|
||||
private static class SessionKeyImpl implements SessionKey {
|
||||
// If not static, this will leak a reference
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
private SessionKeyImpl(UUID uuid, String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
// We can't directly check if the player is online because
|
||||
// the list of players is not thread safe
|
||||
return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Class<ForgePlayer> inject() {
|
||||
return ForgePlayer.class;
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {url = "https://oss.sonatype.org/content/repositories/snapshots/"}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle.forge'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
clean { delete "../target" }
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'org.spongepowered:spongeapi:3.1.0-SNAPSHOT'
|
||||
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
|
||||
}
|
||||
|
||||
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.11-13.19.0.2157"
|
||||
mappings = "snapshot_20161123"
|
||||
runDir = 'run'
|
||||
}
|
||||
|
||||
project.archivesBaseName = "${project.archivesBaseName}-mc${minecraft.version}"
|
||||
|
||||
processResources {
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
expand 'version': project.version,
|
||||
'mcVersion': project.minecraft.version
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
|
||||
dependencies {
|
||||
include(dependency('com.github.luben:zstd-jni:1.1.1'))
|
||||
// include(dependency('org.javassist:javassist:3.22.0-CR1'))
|
||||
include(dependency('co.aikar:fastutil-lite:1.0'))
|
||||
include(dependency(':core'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
|
||||
destinationDir = file '../target'
|
||||
manifest {
|
||||
attributes("Main-Class": "com.boydti.fawe.installer.InstallerFrame")
|
||||
}
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
|
||||
reobf {
|
||||
shadowJar {
|
||||
mappingType = 'SEARGE'
|
||||
}
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar)
|
|
@ -1,194 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.forge.v111.ForgeQueue_All;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.forge.ForgeWorld;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.ModMetadata;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FaweForge implements IFawe {
|
||||
|
||||
private final ForgeMain parent;
|
||||
private final File directory;
|
||||
private final Logger logger;
|
||||
private final ModMetadata mod;
|
||||
|
||||
public FaweForge(ForgeMain plugin, Logger logger, ModMetadata mod, File directory) {
|
||||
this.parent = plugin;
|
||||
this.logger = logger;
|
||||
this.directory = directory;
|
||||
this.mod = mod;
|
||||
try {
|
||||
Fawe.set(this);
|
||||
setupInjector();
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupInjector() {
|
||||
try {
|
||||
Fawe.setupInjector();
|
||||
com.sk89q.worldedit.forge.ForgePlayer.inject();
|
||||
} catch (Throwable e) {
|
||||
Fawe.debug("Failed to inject WorldEdit classes.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String s) {
|
||||
logger.debug(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnlineMode() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().isServerInOnlineMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().getMinecraftVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().getCurrentPlayerCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
private HashMap<String, FaweCommand> commands = new HashMap<>();
|
||||
|
||||
public HashMap<String, FaweCommand> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupCommand(String label, FaweCommand cmd) {
|
||||
this.commands.put(label, cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
EntityPlayerMP player = null;
|
||||
if (obj instanceof String) {
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
player = server.getPlayerList().getPlayerByUsername((String) obj);
|
||||
} else if (obj instanceof UUID) {
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
player = server.getPlayerList().getPlayerByUUID((UUID) obj);
|
||||
} else if (obj instanceof EntityPlayerMP) {
|
||||
player = (EntityPlayerMP) obj;
|
||||
}
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getName());
|
||||
return existing != null ? existing : new ForgePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVault() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new com.boydti.fawe.forge.ForgeTaskMan(512);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
if (world instanceof WorldWrapper) {
|
||||
return getWorldName(((WorldWrapper) world).getParent());
|
||||
}
|
||||
else if (world instanceof EditSession) {
|
||||
return getWorldName(((EditSession) world).getWorld());
|
||||
}
|
||||
return getWorldName(((ForgeWorld) world).getWorld());
|
||||
|
||||
}
|
||||
|
||||
public String getWorldName(net.minecraft.world.World w) {
|
||||
return w.getWorldInfo().getWorldName() + ";" + w.provider.getDimension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(World world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
try {
|
||||
com.boydti.fawe.forge.ForgeMetrics metrics = new com.boydti.fawe.forge.ForgeMetrics("FastAsyncWorldEdit", "3.5.1");
|
||||
metrics.start();
|
||||
} catch (Throwable e) {
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatform() {
|
||||
return "forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try {
|
||||
GameProfile profile = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerProfileCache().getGameProfileForUsername(name);
|
||||
return profile.getId();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
try {
|
||||
GameProfile profile = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerProfileCache().getProfileByUUID(uuid);
|
||||
return profile.getName();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBlocksHubApi() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class ForgeCommand extends CommandBase {
|
||||
|
||||
private final String name;
|
||||
private final FaweCommand cmd;
|
||||
|
||||
public ForgeCommand(String name, FaweCommand cmd) {
|
||||
this.name = name;
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(ICommandSender iCommandSender) {
|
||||
return "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(MinecraftServer minecraftServer, ICommandSender sender, String[] args) throws CommandException {
|
||||
if ((sender instanceof EntityPlayerMP)) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) sender;
|
||||
if (player.world.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
cmd.executeSafe(fp, args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.5.1", acceptableRemoteVersions = "*", dependencies = "before:worldedit")
|
||||
public class ForgeMain {
|
||||
private static com.boydti.fawe.forge.FaweForge IMP;
|
||||
private Logger logger;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
this.logger = event.getModLog();
|
||||
File directory = new File(event.getModConfigurationDirectory() + File.separator + "FastAsyncWorldEdit");
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
this.IMP = new FaweForge(this, event.getModLog(), event.getModMetadata(), directory);
|
||||
try {
|
||||
Class.forName("org.spongepowered.api.Sponge");
|
||||
Settings.IMP.QUEUE.PARALLEL_THREADS = 1;
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverLoad(FMLServerStartingEvent event) {
|
||||
for (Map.Entry<String, FaweCommand> entry : IMP.getCommands().entrySet()) {
|
||||
event.registerServerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onPlayerQuit(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (event.player.world.isRemote) {
|
||||
return;
|
||||
}
|
||||
handleQuit((EntityPlayerMP) event.player);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverStopping(FMLServerStoppingEvent event) {
|
||||
for (EntityPlayerMP player : FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayers()) {
|
||||
handleQuit(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleQuit(EntityPlayerMP player) {
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
if (fp != null) {
|
||||
fp.unregister();
|
||||
}
|
||||
Fawe.get().unregister(player.getName());
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerChangedWorld(EntityJoinWorldEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof EntityPlayerMP)) {
|
||||
return;
|
||||
}
|
||||
EntityPlayerMP player = (EntityPlayerMP) entity;
|
||||
if (player.world.isRemote) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,476 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
||||
* Ported to Minecraft Forge by Mike Primm
|
||||
* 1.7.x update by Dries007
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.object.io.PGZIPOutputStream;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import java.io.*;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeMetrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 7;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://report.mcstats.org";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/plugin/%s";
|
||||
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 15;
|
||||
|
||||
/**
|
||||
* The mod this metrics submits for
|
||||
*/
|
||||
private final String modName;
|
||||
|
||||
private final String modVersion;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final Configuration configuration;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
|
||||
private Thread thread = null;
|
||||
private boolean firstPost = true;
|
||||
int tickCount;
|
||||
|
||||
public ForgeMetrics(final String modName, final String modVersion) throws IOException {
|
||||
if (modName == null || modVersion == null) {
|
||||
throw new IllegalArgumentException("modName and modVersion cannot be null");
|
||||
}
|
||||
|
||||
this.modName = modName;
|
||||
this.modVersion = modVersion;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = new Configuration(configurationFile);
|
||||
|
||||
// Get values, and add some defaults, if needed
|
||||
configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false, "Set to true to disable all reporting");
|
||||
guid = configuration.get(Configuration.CATEGORY_GENERAL, "guid", UUID.randomUUID().toString(), "Server unique ID").getString();
|
||||
debug = configuration.get(Configuration.CATEGORY_GENERAL, "debug", false, "Set to true for verbose debug").getBoolean(false);
|
||||
configuration.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async
|
||||
* repeating task as the plugin and send the initial data to the metrics
|
||||
* backend, and then after that it will post in increments of PING_INTERVAL
|
||||
* * 1200 ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void tick(TickEvent.ServerTickEvent tick) {
|
||||
if (tick.phase != TickEvent.Phase.END) return;
|
||||
|
||||
if (tickCount++ % (PING_INTERVAL * 1200) != 0) return;
|
||||
|
||||
if (thread == null) {
|
||||
thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Disable Task, if it is running and the server owner decided
|
||||
// to opt-out
|
||||
if (isOptOut()) {
|
||||
FMLCommonHandler.instance().bus().unregister(ForgeMetrics.this);
|
||||
return;
|
||||
}
|
||||
// We use the inverse of firstPost because if it
|
||||
// is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to
|
||||
// FALSE
|
||||
// Each time thereafter it will evaluate to
|
||||
// TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
// After the first post we set firstPost to
|
||||
// false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
FMLLog.info("[Metrics] Exception - %s", e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
// Reload the metrics file
|
||||
configuration.load();
|
||||
return configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false).getBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the
|
||||
* config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("false");
|
||||
configuration.save();
|
||||
}
|
||||
// Enable Task, if it is not running
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the
|
||||
* config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("true");
|
||||
configuration.save();
|
||||
}
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data
|
||||
* such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
return new File(Loader.instance().getConfigDir(), "PluginMetrics.cfg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
String pluginName = modName;
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
boolean onlineMode = server.isServerInOnlineMode();
|
||||
String pluginVersion = modVersion;
|
||||
String serverVersion;
|
||||
if (server.isDedicatedServer()) {
|
||||
serverVersion = "MinecraftForge (MC: " + server.getMinecraftVersion() + ")";
|
||||
} else {
|
||||
serverVersion = "MinecraftForgeSSP (MC: " + server.getMinecraftVersion() + ")";
|
||||
}
|
||||
int playersOnline = server.getCurrentPlayerCount();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
StringBuilder json = new StringBuilder(1024);
|
||||
json.append('{');
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
appendJSONPair(json, "guid", guid);
|
||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
||||
appendJSONPair(json, "server_version", serverVersion);
|
||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
appendJSONPair(json, "osname", osname);
|
||||
appendJSONPair(json, "osarch", osarch);
|
||||
appendJSONPair(json, "osversion", osversion);
|
||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
||||
appendJSONPair(json, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
appendJSONPair(json, "ping", "1");
|
||||
}
|
||||
|
||||
// close json
|
||||
json.append('}');
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
|
||||
byte[] uncompressed = json.toString().getBytes();
|
||||
byte[] compressed = gzip(json.toString());
|
||||
|
||||
// Headers
|
||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
||||
connection.addRequestProperty("Content-Type", "application/json");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(compressed);
|
||||
os.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
os.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
||||
if (response == null) {
|
||||
response = "null";
|
||||
} else if (response.startsWith("7")) {
|
||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
||||
}
|
||||
|
||||
throw new IOException(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GZip compress a string of bytes
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static byte[] gzip(String input) {
|
||||
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
|
||||
PGZIPOutputStream gzos = null;
|
||||
|
||||
try {
|
||||
gzos = new PGZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
MainUtil.handleError(e);
|
||||
} finally {
|
||||
if (gzos != null) try {
|
||||
gzos.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
||||
*
|
||||
* @return true if mineshafter is installed on the server
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a json encoded key/value pair to the given string builder.
|
||||
*
|
||||
* @param json
|
||||
* @param key
|
||||
* @param value
|
||||
* @throws java.io.UnsupportedEncodingException
|
||||
*/
|
||||
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
|
||||
boolean isValueNumeric = false;
|
||||
|
||||
try {
|
||||
if (value.equals("0") || !value.endsWith("0")) {
|
||||
Double.parseDouble(value);
|
||||
isValueNumeric = true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
isValueNumeric = false;
|
||||
}
|
||||
|
||||
if (json.charAt(json.length() - 1) != '{') {
|
||||
json.append(',');
|
||||
}
|
||||
|
||||
json.append(escapeJSON(key));
|
||||
json.append(':');
|
||||
|
||||
if (isValueNumeric) {
|
||||
json.append(value);
|
||||
} else {
|
||||
json.append(escapeJSON(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string to create a valid JSON string
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
private static String escapeJSON(String text) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append('"');
|
||||
for (int index = 0; index < text.length(); index++) {
|
||||
char chr = text.charAt(index);
|
||||
|
||||
switch (chr) {
|
||||
case '"':
|
||||
case '\\':
|
||||
builder.append('\\');
|
||||
builder.append(chr);
|
||||
break;
|
||||
case '\b':
|
||||
builder.append("\\b");
|
||||
break;
|
||||
case '\t':
|
||||
builder.append("\\t");
|
||||
break;
|
||||
case '\n':
|
||||
builder.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.append("\\r");
|
||||
break;
|
||||
default:
|
||||
if (chr < ' ') {
|
||||
String t = "000" + Integer.toHexString(chr);
|
||||
builder.append("\\u" + t.substring(t.length() - 4));
|
||||
} else {
|
||||
builder.append(chr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.append('"');
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text, as UTF-8
|
||||
*/
|
||||
private static String urlEncode(final String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.wrappers.PlayerWrapper;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
|
||||
public ForgePlayer(EntityPlayerMP parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String head, String sub) { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTitle() { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return parent.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
Object meta = getMeta(perm);
|
||||
return meta instanceof Boolean ? (boolean) meta : ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(parent, perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(String perm, boolean flag) {
|
||||
setMeta(perm, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
msg = BBC.color(msg);
|
||||
for (String line : msg.split("\n")) {
|
||||
this.parent.sendMessage(new TextComponentString(line));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(String substring) {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweLocation getLocation() {
|
||||
World world = parent.world;
|
||||
BlockPos pos = parent.getPosition();
|
||||
return new FaweLocation(Fawe.<FaweForge>imp().getWorldName(world), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player toWorldEditPlayer() {
|
||||
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBagException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class ForgePlayerBlockBag extends BlockBag {
|
||||
|
||||
private EntityPlayerMP player;
|
||||
private ItemStack[] items;
|
||||
private boolean changed;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public ForgePlayerBlockBag(EntityPlayerMP player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads inventory on first use.
|
||||
*/
|
||||
private void loadInventory() {
|
||||
if (items == null) {
|
||||
items = new ItemStack[player.inventory.getSizeInventory()];
|
||||
for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
|
||||
items[i] = player.inventory.getStackInSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public EntityPlayerMP getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount == 1);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't fetch air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
continue;
|
||||
}
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.getCount();
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
if (currentAmount > 1) {
|
||||
forgeItem.setCount(forgeItem.getCount() - 1);;
|
||||
found = true;
|
||||
} else {
|
||||
items[slot] = null;
|
||||
found = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new OutOfBlocksException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount <= 64);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't store air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
int freeSlot = -1;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
// Delay using up a free slot until we know there are no stacks
|
||||
// of this item to merge into
|
||||
|
||||
if (freeSlot == -1) {
|
||||
freeSlot = slot;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.getCount();
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
if (currentAmount >= 64) {
|
||||
// Full stack
|
||||
continue;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
int spaceLeft = 64 - currentAmount;
|
||||
if (spaceLeft >= amount) {
|
||||
forgeItem.setCount(forgeItem.getCount() + amount);
|
||||
return;
|
||||
}
|
||||
|
||||
forgeItem.setCount(64);
|
||||
amount -= spaceLeft;
|
||||
}
|
||||
|
||||
if (freeSlot > -1) {
|
||||
changed = true;
|
||||
items[freeSlot] = new ItemStack(Item.getItemById(id), amount);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new OutOfSpaceException(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushChanges() {
|
||||
if (items != null && changed) {
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
player.inventory.setInventorySlotContents(i, items[i]);
|
||||
}
|
||||
items = null;
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSingleSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeTaskMan extends TaskManager {
|
||||
|
||||
private final ConcurrentLinkedDeque<Runnable> syncTasks = new ConcurrentLinkedDeque<>();
|
||||
private final ConcurrentLinkedDeque<Runnable> asyncTasks = new ConcurrentLinkedDeque<>();
|
||||
|
||||
private final ConcurrentHashMap<Integer, Runnable> taskIdMap = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
|
||||
|
||||
private final AtomicInteger taskId = new AtomicInteger();
|
||||
private final ExecutorService executor;
|
||||
|
||||
public ForgeTaskMan(int size) {
|
||||
this.executor = Executors.newFixedThreadPool(size);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int repeat(final Runnable r, final int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
later(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
Fawe.get().setMainThread();
|
||||
int asyncSize = asyncTasks.size();
|
||||
for (int i = 0; i < asyncSize; i++) {
|
||||
Runnable item = asyncTasks.poll();
|
||||
if (item != null) {
|
||||
async(item);
|
||||
}
|
||||
}
|
||||
int syncSize = syncTasks.size();
|
||||
for (int i = 0; i < syncSize; i++) {
|
||||
Runnable item = syncTasks.poll();
|
||||
if (item != null) {
|
||||
try {
|
||||
item.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(Runnable r, int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
laterAsync(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
executor.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
syncTasks.add(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
async(r);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int task) {
|
||||
taskIdMap.remove(task);
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.world.gen.layer.GenLayer;
|
||||
import net.minecraft.world.gen.layer.IntCache;
|
||||
|
||||
public class MutableGenLayer extends GenLayer {
|
||||
|
||||
private int biome;
|
||||
|
||||
public MutableGenLayer(long seed) {
|
||||
super(seed);
|
||||
}
|
||||
|
||||
public MutableGenLayer set(int biome) {
|
||||
this.biome = biome;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight) {
|
||||
int[] biomes = IntCache.getIntCache(areaWidth * areaHeight);
|
||||
Arrays.fill(biomes, biome);
|
||||
return biomes;
|
||||
}
|
||||
}
|
|
@ -1,391 +0,0 @@
|
|||
package com.boydti.fawe.forge.v111;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BitArray;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IBlockStatePalette;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
|
||||
public BlockStateContainer[] sectionPalettes;
|
||||
|
||||
public static Map<String, ResourceLocation> entityKeys;
|
||||
|
||||
/**
|
||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||
*
|
||||
* @param parent
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
}
|
||||
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
|
||||
super(parent, x, z, ids, count, air, heightMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk copy(boolean shallow) {
|
||||
ForgeChunk_All copy;
|
||||
if (shallow) {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), ids, count, air, heightMap);
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
} else {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
copy.biomes = biomes.clone();
|
||||
copy.chunk = chunk;
|
||||
}
|
||||
if (sectionPalettes != null) {
|
||||
copy.sectionPalettes = new BlockStateContainer[16];
|
||||
try {
|
||||
Field fieldBits = BlockStateContainer.class.getDeclaredField("field_186021_b");
|
||||
fieldBits.setAccessible(true);
|
||||
Field fieldPalette = BlockStateContainer.class.getDeclaredField("field_186022_c");
|
||||
fieldPalette.setAccessible(true);
|
||||
Field fieldSize = BlockStateContainer.class.getDeclaredField("field_186024_e");
|
||||
fieldSize.setAccessible(true);
|
||||
for (int i = 0; i < sectionPalettes.length; i++) {
|
||||
BlockStateContainer current = sectionPalettes[i];
|
||||
if (current == null) {
|
||||
continue;
|
||||
}
|
||||
// Clone palette
|
||||
IBlockStatePalette currentPalette = (IBlockStatePalette) fieldPalette.get(current);
|
||||
if (!(currentPalette instanceof BlockStatePaletteRegistry)) {
|
||||
current.onResize(128, null);
|
||||
}
|
||||
BlockStateContainer paletteBlock = new BlockStateContainer();
|
||||
currentPalette = (IBlockStatePalette) fieldPalette.get(current);
|
||||
if (!(currentPalette instanceof BlockStatePaletteRegistry)) {
|
||||
throw new RuntimeException("Palette must be global!");
|
||||
}
|
||||
fieldPalette.set(paletteBlock, currentPalette);
|
||||
// Clone size
|
||||
fieldSize.set(paletteBlock, fieldSize.get(current));
|
||||
// Clone palette
|
||||
BitArray currentBits = (BitArray) fieldBits.get(current);
|
||||
BitArray newBits = new BitArray(1, 0);
|
||||
for (Field field : BitArray.class.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
Object currentValue = field.get(currentBits);
|
||||
if (currentValue instanceof long[]) {
|
||||
currentValue = ((long[]) currentValue).clone();
|
||||
}
|
||||
field.set(newBits, currentValue);
|
||||
}
|
||||
fieldBits.set(paletteBlock, newBits);
|
||||
copy.sectionPalettes[i] = paletteBlock;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getNewChunk() {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
return world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
if (sectionPalettes != null) {
|
||||
return;
|
||||
}
|
||||
char[][] arrays = getCombinedIdArrays();
|
||||
char lastChar = Character.MAX_VALUE;
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
if (getCount(layer) > 0) {
|
||||
if (sectionPalettes == null) {
|
||||
sectionPalettes = new BlockStateContainer[16];
|
||||
}
|
||||
BlockStateContainer palette = new BlockStateContainer();
|
||||
char[] blocks = getIdArray(layer);
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
char combinedId = blocks[FaweCache.CACHE_J[y][z][x]];
|
||||
if (combinedId > 1) {
|
||||
palette.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForgeChunk_All call() {
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||
int bx = this.getX() << 4;
|
||||
int bz = this.getZ() << 4;
|
||||
nmsChunk.setModified(true);
|
||||
net.minecraft.world.World nmsWorld = getParent().getWorld();
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.hasNoSky();
|
||||
// Sections
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
|
||||
// Set heightmap
|
||||
getParent().setHeightMap(this, heightMap);
|
||||
// Remove entities
|
||||
for (int i = 0; i < 16; i++) {
|
||||
int count = this.getCount(i);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
} else if (count >= 4096) {
|
||||
ClassInheritanceMultiMap<Entity> ents = entities[i];
|
||||
if (ents != null && !ents.isEmpty()) {
|
||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||
for (Entity ent : ents) {
|
||||
nmsWorld.removeEntity(ent);
|
||||
}
|
||||
}
|
||||
} else if (!getParent().getSettings().EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) {
|
||||
char[] array = this.getIdArray(i);
|
||||
if (array == null || entities[i] == null || entities[i].isEmpty()) continue;
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entity instanceof EntityPlayer) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(entity.posX) & 15);
|
||||
int z = (MathMan.roundInt(entity.posZ) & 15);
|
||||
int y = MathMan.roundInt(entity.posY);
|
||||
if (y < 0 || y > 255) continue;
|
||||
if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashSet<UUID> entsToRemove = this.getEntityRemoves();
|
||||
if (!entsToRemove.isEmpty()) {
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entsToRemove.contains(entity.getUniqueID())) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set entities
|
||||
Set<UUID> createdEntities = new HashSet<>();
|
||||
Set<CompoundTag> entitiesToSpawn = this.getEntities();
|
||||
for (CompoundTag nativeTag : entitiesToSpawn) {
|
||||
Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||
if (idTag == null || posTag == null || rotTag == null) {
|
||||
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||
continue;
|
||||
}
|
||||
double x = posTag.getDouble(0);
|
||||
double y = posTag.getDouble(1);
|
||||
double z = posTag.getDouble(2);
|
||||
float yaw = rotTag.getFloat(0);
|
||||
float pitch = rotTag.getFloat(1);
|
||||
String id = idTag.getValue();
|
||||
if (entityKeys == null) {
|
||||
entityKeys = new HashMap<>();
|
||||
for (ResourceLocation key : EntityList.getEntityNameList()) {
|
||||
String currentId = EntityList.getTranslationName(key);
|
||||
entityKeys.put(currentId, key);
|
||||
entityKeys.put(key.getResourcePath(), key);
|
||||
}
|
||||
}
|
||||
ResourceLocation entityKey = entityKeys.get(id);
|
||||
if (entityKey != null) {
|
||||
Entity entity = EntityList.createEntityByIDFromName(entityKey, nmsWorld);
|
||||
if (entity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound)ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
entity.readFromNBT(tag);
|
||||
tag.removeTag("UUIDMost");
|
||||
tag.removeTag("UUIDLeast");
|
||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||
nmsWorld.spawnEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Run change task if applicable
|
||||
if (getParent().getChangeTask() != null) {
|
||||
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||
getParent().getChangeTask().run(previous, this);
|
||||
}
|
||||
// Trim tiles
|
||||
if (!tiles.isEmpty()) {
|
||||
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||
BlockPos pos = tile.getKey();
|
||||
int lx = pos.getX() & 15;
|
||||
int ly = pos.getY();
|
||||
int lz = pos.getZ() & 15;
|
||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||
char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||
if (array[k] != 0) {
|
||||
synchronized (ForgeChunk_All.class) {
|
||||
iterator.remove();
|
||||
tile.getValue().invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
int count = this.getCount(j);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
}
|
||||
final char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int countAir = this.getAir(j);
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if (section == null) {
|
||||
if (count == countAir) {
|
||||
continue;
|
||||
}
|
||||
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||
section = sections[j] = new ExtendedBlockStorage(j << 4, flag);
|
||||
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||
getParent().setCount(0, count - this.getAir(j), section);
|
||||
continue;
|
||||
} else {
|
||||
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
||||
}
|
||||
} else if (count >= 4096) {
|
||||
if (count == countAir) {
|
||||
sections[j] = null;
|
||||
continue;
|
||||
}
|
||||
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||
getParent().setCount(0, count - this.getAir(j), section);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
IBlockState existing;
|
||||
int by = j << 4;
|
||||
BlockStateContainer nibble = section.getData();
|
||||
int nonEmptyBlockCount = 0;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
||||
switch (combinedId) {
|
||||
case 0:
|
||||
continue;
|
||||
case 1:
|
||||
existing = nibble.get(x, y, z);
|
||||
if (existing != ForgeQueue_All.air) {
|
||||
if (existing.getLightValue() > 0) {
|
||||
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
|
||||
}
|
||||
nonEmptyBlockCount--;
|
||||
}
|
||||
nibble.set(x, y, z, ForgeQueue_All.air);
|
||||
continue;
|
||||
default:
|
||||
existing = nibble.get(x, y, z);
|
||||
if (existing != ForgeQueue_All.air) {
|
||||
if (existing.getLightValue() > 0) {
|
||||
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
|
||||
}
|
||||
} else {
|
||||
nonEmptyBlockCount++;
|
||||
}
|
||||
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
|
||||
}
|
||||
// Set biomes
|
||||
if (this.biomes != null) {
|
||||
byte[] currentBiomes = nmsChunk.getBiomeArray();
|
||||
for (int i = 0 ; i < this.biomes.length; i++) {
|
||||
byte biome = this.biomes[i];
|
||||
if (biome != 0) {
|
||||
if (biome == -1) biome = 0;
|
||||
currentBiomes[i] = biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set tiles
|
||||
Map<Short, CompoundTag> tilesToSpawn = this.getTiles();
|
||||
|
||||
for (Map.Entry<Short, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||
CompoundTag nativeTag = entry.getValue();
|
||||
short blockHash = entry.getKey();
|
||||
int x = (blockHash >> 12 & 0xF) + bx;
|
||||
int y = (blockHash & 0xFF);
|
||||
int z = (blockHash >> 8 & 0xF) + bz;
|
||||
BlockPos pos = new BlockPos(x, y, z); // Set pos
|
||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||
if (tileEntity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.setInteger("x", pos.getX());
|
||||
tag.setInteger("y", pos.getY());
|
||||
tag.setInteger("z", pos.getZ());
|
||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
sectionPalettes = null;
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,654 +0,0 @@
|
|||
package com.boydti.fawe.forge.v111;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
import com.boydti.fawe.forge.MutableGenLayer;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.brush.visualization.VisualChunk;
|
||||
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.SPacketChunkData;
|
||||
import net.minecraft.network.play.server.SPacketMultiBlockChange;
|
||||
import net.minecraft.server.management.PlayerChunkMap;
|
||||
import net.minecraft.server.management.PlayerChunkMapEntry;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.EnumSkyBlock;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.biome.BiomeCache;
|
||||
import net.minecraft.world.biome.BiomeProvider;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkGenerator;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.NibbleArray;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderOverworld;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
protected final static Method methodFromNative;
|
||||
protected final static Method methodToNative;
|
||||
protected final static Field fieldTickingBlockCount;
|
||||
protected final static Field fieldNonEmptyBlockCount;
|
||||
|
||||
protected static Field fieldBiomes;
|
||||
protected static Field fieldChunkGenerator;
|
||||
protected static Field fieldSeed;
|
||||
protected static Field fieldBiomeCache;
|
||||
protected static Field fieldBiomes2;
|
||||
protected static Field fieldGenLayer1;
|
||||
protected static Field fieldGenLayer2;
|
||||
protected static ExtendedBlockStorage emptySection;
|
||||
private static MutableGenLayer genLayer;
|
||||
|
||||
static {
|
||||
try {
|
||||
emptySection = new ExtendedBlockStorage(0, true);
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
|
||||
methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
|
||||
methodFromNative.setAccessible(true);
|
||||
methodToNative.setAccessible(true);
|
||||
|
||||
fieldBiomes = ChunkProviderOverworld.class.getDeclaredField("field_185981_C"); // biomesForGeneration
|
||||
fieldBiomes.setAccessible(true);
|
||||
fieldChunkGenerator = ChunkProviderServer.class.getDeclaredField("field_186029_c"); // chunkGenerator
|
||||
fieldChunkGenerator.setAccessible(true);
|
||||
fieldSeed = WorldInfo.class.getDeclaredField("field_76100_a"); // randomSeed
|
||||
fieldSeed.setAccessible(true);
|
||||
fieldBiomeCache = BiomeProvider.class.getDeclaredField("field_76942_f"); // biomeCache
|
||||
fieldBiomeCache.setAccessible(true);
|
||||
fieldBiomes2 = BiomeProvider.class.getDeclaredField("field_76943_g"); // biomesToSpawnIn
|
||||
fieldBiomes2.setAccessible(true);
|
||||
fieldGenLayer1 = BiomeProvider.class.getDeclaredField("field_76944_d"); // genBiomes
|
||||
fieldGenLayer2 = BiomeProvider.class.getDeclaredField("field_76945_e"); // biomeIndexLayer
|
||||
fieldGenLayer1.setAccessible(true);
|
||||
fieldGenLayer2.setAccessible(true);
|
||||
|
||||
fieldTickingBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76683_c");
|
||||
fieldNonEmptyBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76682_b");
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(Chunk chunk) {
|
||||
chunk.setChunkModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getSections(Chunk chunk) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiome(Chunk chunk, int x, int z) {
|
||||
return chunk.getBiomeArray()[((z & 15) << 4) + (x & 15)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk loadChunk(World world, int x, int z, boolean generate) {
|
||||
ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider();
|
||||
if (generate) {
|
||||
return provider.provideChunk(x, z);
|
||||
} else {
|
||||
return provider.loadChunk(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getCachedSections(World world, int cx, int cz) {
|
||||
Chunk chunk = world.getChunkProvider().getLoadedChunk(cx, cz);
|
||||
if (chunk != null) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getCachedChunk(World world, int cx, int cz) {
|
||||
return world.getChunkProvider().getLoadedChunk(cx, cz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage getCachedSection(ExtendedBlockStorage[] ExtendedBlockStorages, int cy) {
|
||||
return ExtendedBlockStorages[cy];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
|
||||
try {
|
||||
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
|
||||
boolean watching = false;
|
||||
boolean[] watchingArr = new boolean[players.length];
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) ((ForgePlayer) players[i]).parent;
|
||||
if (playerManager.isPlayerWatchingChunk(player, chunk.getX(), chunk.getZ())) {
|
||||
watchingArr[i] = true;
|
||||
watching = true;
|
||||
}
|
||||
}
|
||||
if (!watching) return;
|
||||
final LongAdder size = new LongAdder();
|
||||
if (chunk instanceof VisualChunk) {
|
||||
size.add(((VisualChunk) chunk).size());
|
||||
} else if (chunk instanceof CharFaweChunk) {
|
||||
size.add(((CharFaweChunk) chunk).getTotalCount());
|
||||
} else {
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
size.add(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (size.intValue() == 0) return;
|
||||
SPacketMultiBlockChange packet = new SPacketMultiBlockChange();
|
||||
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
|
||||
final PacketBuffer buffer = new PacketBuffer(byteBuf);
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
buffer.writeVarInt(size.intValue());
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
short index = (short) (localX << 12 | localZ << 8 | y);
|
||||
buffer.writeShort(index);
|
||||
buffer.writeVarInt(combined);
|
||||
}
|
||||
});
|
||||
packet.readPacketData(buffer);
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
if (watchingArr[i]) ((EntityPlayerMP) ((ForgePlayer) players[i]).parent).connection.sendPacket(packet);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
|
||||
Chunk forgeChunk = (Chunk) chunk.getChunk();
|
||||
if (forgeChunk != null) {
|
||||
int[] otherMap = forgeChunk.getHeightMap();
|
||||
for (int i = 0; i < heightMap.length; i++) {
|
||||
int newHeight = heightMap[i] & 0xFF;
|
||||
int currentHeight = otherMap[i];
|
||||
if (newHeight > currentHeight) {
|
||||
otherMap[i] = newHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
|
||||
@Override
|
||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||
Map<BlockPos, TileEntity> tiles = chunk.getTileEntityMap();
|
||||
pos.setPos(x, y, z);
|
||||
TileEntity tile = tiles.get(pos);
|
||||
return tile != null ? getTag(tile) : null;
|
||||
}
|
||||
|
||||
public CompoundTag getTag(TileEntity tile) {
|
||||
try {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTagIntoEntity
|
||||
CompoundTag result = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
MainUtil.handleError(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(net.minecraft.world.World world, int x, int z, BaseBiome biome, Long seed) {
|
||||
if (biome != null) {
|
||||
try {
|
||||
if (seed == null) {
|
||||
seed = world.getSeed();
|
||||
}
|
||||
nmsWorld.getWorldInfo().getSeed();
|
||||
boolean result;
|
||||
ChunkProviderOverworld generator = new ChunkProviderOverworld(nmsWorld, seed, false, "");
|
||||
net.minecraft.world.biome.Biome base = net.minecraft.world.biome.Biome.getBiome(biome.getId());
|
||||
fieldBiomes.set(generator, new net.minecraft.world.biome.Biome[]{base});
|
||||
boolean cold = base.getTemperature() <= 1;
|
||||
IChunkGenerator existingGenerator = nmsWorld.getChunkProvider().chunkGenerator;
|
||||
long existingSeed = world.getSeed();
|
||||
{
|
||||
if (genLayer == null) genLayer = new MutableGenLayer(seed);
|
||||
genLayer.set(biome.getId());
|
||||
Object existingGenLayer1 = fieldGenLayer1.get(nmsWorld.provider.getBiomeProvider());
|
||||
Object existingGenLayer2 = fieldGenLayer2.get(nmsWorld.provider.getBiomeProvider());
|
||||
fieldGenLayer1.set(nmsWorld.provider.getBiomeProvider(), genLayer);
|
||||
fieldGenLayer2.set(nmsWorld.provider.getBiomeProvider(), genLayer);
|
||||
|
||||
fieldSeed.set(nmsWorld.getWorldInfo(), seed);
|
||||
|
||||
ReflectionUtils.setFailsafeFieldValue(fieldBiomeCache, this.nmsWorld.provider.getBiomeProvider(), new BiomeCache(this.nmsWorld.provider.getBiomeProvider()));
|
||||
|
||||
ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProvider(), generator);
|
||||
|
||||
result = regenerateChunk(world, x, z);
|
||||
|
||||
ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProvider(), existingGenerator);
|
||||
|
||||
fieldSeed.set(nmsWorld.getWorldInfo(), existingSeed);
|
||||
|
||||
fieldGenLayer1.set(nmsWorld.provider.getBiomeProvider(), existingGenLayer1);
|
||||
fieldGenLayer2.set(nmsWorld.provider.getBiomeProvider(), existingGenLayer2);
|
||||
}
|
||||
return result;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return regenerateChunk(world, x, z);
|
||||
}
|
||||
|
||||
public boolean regenerateChunk(World world, int x, int z) {
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
BlockFalling.fallInstantly = true;
|
||||
try {
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
IChunkGenerator gen = chunkServer.chunkGenerator;
|
||||
long pos = ChunkPos.asLong(x, z);
|
||||
Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
|
||||
List<EntityPlayerMP> oldWatchers = null;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
PlayerChunkMapEntry entry = playerManager.getEntry(x, z);
|
||||
if (entry != null) {
|
||||
Field fieldPlayers = PlayerChunkMapEntry.class.getDeclaredField("field_187283_c");
|
||||
fieldPlayers.setAccessible(true);
|
||||
oldWatchers = (List<EntityPlayerMP>) fieldPlayers.get(entry);
|
||||
playerManager.removeEntry(entry);
|
||||
}
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
try {
|
||||
Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b");
|
||||
droppedChunksSetField.setAccessible(true);
|
||||
Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer);
|
||||
droppedChunksSet.remove(pos);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
chunkServer.id2ChunkMap.remove(pos);
|
||||
mcChunk = gen.provideChunk(x, z);
|
||||
chunkServer.id2ChunkMap.put(pos, mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkServer, chunkServer.chunkGenerator);
|
||||
}
|
||||
if (oldWatchers != null) {
|
||||
for (EntityPlayerMP player : oldWatchers) {
|
||||
playerManager.addPlayer(player);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
MainUtil.handleError(t);
|
||||
return false;
|
||||
} finally {
|
||||
BlockFalling.fallInstantly = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
IBlockState ibd = section.getData().get(x & 15, y & 15, z & 15);
|
||||
Block block = ibd.getBlock();
|
||||
int id = Block.getIdFromBlock(block);
|
||||
if (FaweCache.hasData(id)) {
|
||||
return (id << 4) + block.getMetaFromState(ibd);
|
||||
} else {
|
||||
return id << 4;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNonEmptyBlockCount(ExtendedBlockStorage section) throws IllegalAccessException {
|
||||
return (int) fieldNonEmptyBlockCount.get(section);
|
||||
}
|
||||
|
||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||
Map<BlockPos, TileEntity> tiles = (Map<BlockPos, TileEntity>) tilesGeneric;
|
||||
ClassInheritanceMultiMap<Entity>[] entities = (ClassInheritanceMultiMap<Entity>[]) entitiesGeneric;
|
||||
CharFaweChunk previous = (CharFaweChunk) getFaweChunk(fs.getX(), fs.getZ());
|
||||
char[][] idPrevious = previous.getCombinedIdArrays();
|
||||
for (int layer = 0; layer < sections.length; layer++) {
|
||||
if (fs.getCount(layer) != 0 || all) {
|
||||
ExtendedBlockStorage section = sections[layer];
|
||||
if (section != null) {
|
||||
short solid = 0;
|
||||
char[] previousLayer = idPrevious[layer] = new char[4096];
|
||||
BlockStateContainer blocks = section.getData();
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int x = FaweCache.CACHE_X[0][j];
|
||||
int y = FaweCache.CACHE_Y[0][j];
|
||||
int z = FaweCache.CACHE_Z[0][j];
|
||||
IBlockState ibd = blocks.get(x, y, z);
|
||||
Block block = ibd.getBlock();
|
||||
int combined = Block.getIdFromBlock(block);
|
||||
if (FaweCache.hasData(combined)) {
|
||||
combined = (combined << 4) + block.getMetaFromState(ibd);
|
||||
} else {
|
||||
combined = combined << 4;
|
||||
}
|
||||
if (combined > 1) {
|
||||
solid++;
|
||||
}
|
||||
previousLayer[j] = (char) combined;
|
||||
}
|
||||
previous.count[layer] = solid;
|
||||
previous.air[layer] = (short) (4096 - solid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tiles != null) {
|
||||
for (Map.Entry<BlockPos, TileEntity> entry : tiles.entrySet()) {
|
||||
TileEntity tile = entry.getValue();
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTileEntityIntoTag
|
||||
BlockPos pos = entry.getKey();
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
|
||||
}
|
||||
}
|
||||
if (entities != null) {
|
||||
for (Collection<Entity> entityList : entities) {
|
||||
for (Entity ent : entityList) {
|
||||
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && createdEntities.contains(ent.getUniqueID()))) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(ent.posX) & 15);
|
||||
int z = (MathMan.roundInt(ent.posZ) & 15);
|
||||
int y = MathMan.roundInt(ent.posY);
|
||||
int i = FaweCache.CACHE_I[y][z][x];
|
||||
char[] array = fs.getIdArray(i);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int j = FaweCache.CACHE_J[y][z][x];
|
||||
if (array[j] != 0) {
|
||||
String id = EntityList.getEntityString(ent);
|
||||
if (id != null) {
|
||||
NBTTagCompound tag = ent.getEntityData(); // readEntityIntoTag
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
||||
map.put("Id", new StringTag(id));
|
||||
previous.setEntity(nativeTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
protected final static IBlockState air = Blocks.AIR.getDefaultState();
|
||||
|
||||
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
||||
fieldSection.setAccessible(true);
|
||||
fieldSection.set(section, palette);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int x, int z, int bitMask) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), x, z);
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, bitMask);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChunk(FaweChunk fc) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, fc.getBitMask());
|
||||
}
|
||||
}
|
||||
|
||||
public void sendChunk(Chunk nmsChunk, int mask) {
|
||||
if (!nmsChunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ChunkPos pos = nmsChunk.getChunkCoordIntPair();
|
||||
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
||||
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
||||
int x = pos.chunkXPos;
|
||||
int z = pos.chunkZPos;
|
||||
PlayerChunkMapEntry chunkMapEntry = chunkMap.getEntry(x, z);
|
||||
if (chunkMapEntry == null) {
|
||||
return;
|
||||
}
|
||||
final ArrayDeque<EntityPlayerMP> players = new ArrayDeque<>();
|
||||
chunkMapEntry.hasPlayerMatching(input -> {
|
||||
players.add(input);
|
||||
return false;
|
||||
});
|
||||
boolean empty = false;
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == null) {
|
||||
sections[i] = emptySection;
|
||||
empty = true;
|
||||
}
|
||||
}
|
||||
if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
|
||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65280);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.connection.sendPacket(packet);
|
||||
}
|
||||
mask = 255;
|
||||
}
|
||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, mask);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.connection.sendPacket(packet);
|
||||
}
|
||||
if (empty) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == emptySection) {
|
||||
sections[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEntities(Chunk nmsChunk) {
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
ClassInheritanceMultiMap<Entity> slice = entities[i];
|
||||
if (slice != null && !slice.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSectionLighting(ExtendedBlockStorage section, int layer, boolean sky) {
|
||||
if (section != null) {
|
||||
section.setBlocklightArray(new NibbleArray());
|
||||
if (sky) {
|
||||
section.setSkylightArray(new NibbleArray());
|
||||
}
|
||||
}
|
||||
return section != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSky() {
|
||||
return !nmsWorld.provider.hasNoSky();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullbright(ExtendedBlockStorage[] sections) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section != null) {
|
||||
byte[] bytes = section.getSkylightArray().getData();
|
||||
Arrays.fill(bytes, (byte) 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relight(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
if (nmsWorld != null || getWorldName() == null) {
|
||||
return nmsWorld;
|
||||
}
|
||||
String[] split = getWorldName().split(";");
|
||||
int id = Integer.parseInt(split[split.length - 1]);
|
||||
nmsWorld = DimensionManager.getWorld(id);
|
||||
return nmsWorld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getSkylightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getBlocklightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtSkylightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtBlocklightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return ibd.getLightOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return ibd.getLightValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacityBrightnessPair(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return MathMan.pair16(ibd.getLightOpacity(), ibd.getLightValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightBlock(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.BLOCK, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightSky(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.SKY, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSaveFolder() {
|
||||
return new File(((WorldServer) getWorld()).getChunkSaveLocation(), "region");
|
||||
}
|
||||
}
|
|
@ -1,231 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.forge;
|
||||
|
||||
import com.boydti.fawe.forge.ForgePlayerBlockBag;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.SPacketCustomPayload;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
|
||||
public class ForgePlayer extends AbstractPlayerActor {
|
||||
|
||||
private final EntityPlayerMP player;
|
||||
|
||||
protected ForgePlayer(EntityPlayerMP player) {
|
||||
this.player = player;
|
||||
ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return player.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
ItemStack is = this.player.getHeldItem(EnumHand.MAIN_HAND);
|
||||
return is == null ? 0 : Item.getIdFromItem(is.getItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockInHand() {
|
||||
ItemStack is = this.player.getHeldItem(EnumHand.MAIN_HAND);
|
||||
return is == null ? EditSession.nullBlock : new BaseBlock(Item.getIdFromItem(is.getItem()), is.isItemStackDamageable() ? 0 : is.getItemDamage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.player.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
throw new UnsupportedOperationException("Cannot create a state from this object");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ);
|
||||
return new Location(
|
||||
ForgeWorldEdit.inst.getWorld(this.player.world),
|
||||
position,
|
||||
this.player.rotationYaw,
|
||||
this.player.rotationPitch);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public WorldVector getPosition() {
|
||||
return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.world)), this.player.posX, this.player.posY, this.player.posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sk89q.worldedit.world.World getWorld() {
|
||||
return ForgeWorldEdit.inst.getWorld(this.player.world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPitch() {
|
||||
return this.player.rotationPitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return this.player.rotationYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(int type, int amt) {
|
||||
this.player.inventory.addItemStackToInventory(new ItemStack(Item.getItemById(type), amt, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
String[] params = event.getParameters();
|
||||
String send = event.getTypeId();
|
||||
if (params.length > 0) {
|
||||
send = send + "|" + StringUtil.joinString(params, "|");
|
||||
}
|
||||
PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)));
|
||||
SPacketCustomPayload packet = new SPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer);
|
||||
this.player.connection.sendPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.sendMessage(new TextComponentString(part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
sendColorized(msg, TextFormatting.GRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
sendColorized(msg, TextFormatting.LIGHT_PURPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
sendColorized(msg, TextFormatting.RED);
|
||||
}
|
||||
|
||||
private void sendColorized(String msg, TextFormatting formatting) {
|
||||
for (String part : msg.split("\n")) {
|
||||
TextComponentString component = new TextComponentString(part);
|
||||
component.getStyle().setColor(formatting);
|
||||
this.player.sendMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||
this.player.connection.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return new ForgePlayerBlockBag(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return new SessionKeyImpl(player.getUniqueID(), player.getName());
|
||||
}
|
||||
|
||||
private static class SessionKeyImpl implements SessionKey {
|
||||
// If not static, this will leak a reference
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
private SessionKeyImpl(UUID uuid, String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
// We can't directly check if the player is online because
|
||||
// the list of players is not thread safe
|
||||
return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Class<ForgePlayer> inject() {
|
||||
return ForgePlayer.class;
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {url = "https://oss.sonatype.org/content/repositories/snapshots/"}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle.forge'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
clean { delete "../target" }
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'org.spongepowered:spongeapi:6.0.0-SNAPSHOT'
|
||||
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
|
||||
}
|
||||
|
||||
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.12.2-14.23.0.2532"
|
||||
mappings = "snapshot_20171108"
|
||||
runDir = 'run'
|
||||
}
|
||||
|
||||
project.archivesBaseName = "${project.archivesBaseName}-mc${minecraft.version}"
|
||||
|
||||
processResources {
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
expand 'version': project.version,
|
||||
'mcVersion': project.minecraft.version
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
|
||||
dependencies {
|
||||
include(dependency('com.github.luben:zstd-jni:1.1.1'))
|
||||
// include(dependency('org.javassist:javassist:3.22.0-CR1'))
|
||||
include(dependency('co.aikar:fastutil-lite:1.0'))
|
||||
include(dependency(':core'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
|
||||
destinationDir = file '../target'
|
||||
manifest {
|
||||
attributes("Main-Class": "com.boydti.fawe.installer.InstallerFrame")
|
||||
}
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
|
||||
reobf {
|
||||
shadowJar {
|
||||
mappingType = 'SEARGE'
|
||||
}
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar)
|
|
@ -1,194 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.forge.v112.ForgeQueue_All;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.forge.ForgeWorld;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.ModMetadata;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FaweForge implements IFawe {
|
||||
|
||||
private final ForgeMain parent;
|
||||
private final File directory;
|
||||
private final Logger logger;
|
||||
private final ModMetadata mod;
|
||||
|
||||
public FaweForge(ForgeMain plugin, Logger logger, ModMetadata mod, File directory) {
|
||||
this.parent = plugin;
|
||||
this.logger = logger;
|
||||
this.directory = directory;
|
||||
this.mod = mod;
|
||||
try {
|
||||
Fawe.set(this);
|
||||
setupInjector();
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupInjector() {
|
||||
try {
|
||||
Fawe.setupInjector();
|
||||
com.sk89q.worldedit.forge.ForgePlayer.inject();
|
||||
} catch (Throwable e) {
|
||||
Fawe.debug("Failed to inject WorldEdit classes.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String s) {
|
||||
logger.debug(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnlineMode() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().isServerInOnlineMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return "1.12";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().getCurrentPlayerCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
private HashMap<String, FaweCommand> commands = new HashMap<>();
|
||||
|
||||
public HashMap<String, FaweCommand> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupCommand(String label, FaweCommand cmd) {
|
||||
this.commands.put(label, cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
EntityPlayerMP player = null;
|
||||
if (obj instanceof String) {
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
player = server.getPlayerList().getPlayerByUsername((String) obj);
|
||||
} else if (obj instanceof UUID) {
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
player = server.getPlayerList().getPlayerByUUID((UUID) obj);
|
||||
} else if (obj instanceof EntityPlayerMP) {
|
||||
player = (EntityPlayerMP) obj;
|
||||
}
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getName());
|
||||
return existing != null ? existing : new ForgePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVault() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new com.boydti.fawe.forge.ForgeTaskMan(512);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
if (world instanceof WorldWrapper) {
|
||||
return getWorldName(((WorldWrapper) world).getParent());
|
||||
}
|
||||
else if (world instanceof EditSession) {
|
||||
return getWorldName(((EditSession) world).getWorld());
|
||||
}
|
||||
return getWorldName(((ForgeWorld) world).getWorld());
|
||||
|
||||
}
|
||||
|
||||
public String getWorldName(net.minecraft.world.World w) {
|
||||
return w.getWorldInfo().getWorldName() + ";" + w.provider.getDimension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(World world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
try {
|
||||
com.boydti.fawe.forge.ForgeMetrics metrics = new com.boydti.fawe.forge.ForgeMetrics("FastAsyncWorldEdit", "3.5.1");
|
||||
metrics.start();
|
||||
} catch (Throwable e) {
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatform() {
|
||||
return "forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try {
|
||||
GameProfile profile = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerProfileCache().getGameProfileForUsername(name);
|
||||
return profile.getId();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
try {
|
||||
GameProfile profile = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerProfileCache().getProfileByUUID(uuid);
|
||||
return profile.getName();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBlocksHubApi() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class ForgeCommand extends CommandBase {
|
||||
|
||||
private final String name;
|
||||
private final FaweCommand cmd;
|
||||
|
||||
public ForgeCommand(String name, FaweCommand cmd) {
|
||||
this.name = name;
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(ICommandSender iCommandSender) {
|
||||
return "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(MinecraftServer minecraftServer, ICommandSender sender, String[] args) throws CommandException {
|
||||
if ((sender instanceof EntityPlayerMP)) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) sender;
|
||||
if (player.world.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
cmd.executeSafe(fp, args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.5.1", acceptableRemoteVersions = "*", dependencies = "before:worldedit")
|
||||
public class ForgeMain {
|
||||
private static com.boydti.fawe.forge.FaweForge IMP;
|
||||
private Logger logger;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
this.logger = event.getModLog();
|
||||
File directory = new File(event.getModConfigurationDirectory() + File.separator + "FastAsyncWorldEdit");
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
this.IMP = new FaweForge(this, event.getModLog(), event.getModMetadata(), directory);
|
||||
try {
|
||||
Class.forName("org.spongepowered.api.Sponge");
|
||||
Settings.IMP.QUEUE.PARALLEL_THREADS = 1;
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverLoad(FMLServerStartingEvent event) {
|
||||
for (Map.Entry<String, FaweCommand> entry : IMP.getCommands().entrySet()) {
|
||||
event.registerServerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onPlayerQuit(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (event.player.world.isRemote) {
|
||||
return;
|
||||
}
|
||||
handleQuit((EntityPlayerMP) event.player);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverStopping(FMLServerStoppingEvent event) {
|
||||
for (EntityPlayerMP player : FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayers()) {
|
||||
handleQuit(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleQuit(EntityPlayerMP player) {
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
if (fp != null) {
|
||||
fp.unregister();
|
||||
}
|
||||
Fawe.get().unregister(player.getName());
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerChangedWorld(EntityJoinWorldEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof EntityPlayerMP)) {
|
||||
return;
|
||||
}
|
||||
EntityPlayerMP player = (EntityPlayerMP) entity;
|
||||
if (player.world.isRemote) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,476 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
||||
* Ported to Minecraft Forge by Mike Primm
|
||||
* 1.7.x update by Dries007
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.object.io.PGZIPOutputStream;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import java.io.*;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeMetrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 7;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://report.mcstats.org";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/plugin/%s";
|
||||
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 15;
|
||||
|
||||
/**
|
||||
* The mod this metrics submits for
|
||||
*/
|
||||
private final String modName;
|
||||
|
||||
private final String modVersion;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final Configuration configuration;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
|
||||
private Thread thread = null;
|
||||
private boolean firstPost = true;
|
||||
int tickCount;
|
||||
|
||||
public ForgeMetrics(final String modName, final String modVersion) throws IOException {
|
||||
if (modName == null || modVersion == null) {
|
||||
throw new IllegalArgumentException("modName and modVersion cannot be null");
|
||||
}
|
||||
|
||||
this.modName = modName;
|
||||
this.modVersion = modVersion;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = new Configuration(configurationFile);
|
||||
|
||||
// Get values, and add some defaults, if needed
|
||||
configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false, "Set to true to disable all reporting");
|
||||
guid = configuration.get(Configuration.CATEGORY_GENERAL, "guid", UUID.randomUUID().toString(), "Server unique ID").getString();
|
||||
debug = configuration.get(Configuration.CATEGORY_GENERAL, "debug", false, "Set to true for verbose debug").getBoolean(false);
|
||||
configuration.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async
|
||||
* repeating task as the plugin and send the initial data to the metrics
|
||||
* backend, and then after that it will post in increments of PING_INTERVAL
|
||||
* * 1200 ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void tick(TickEvent.ServerTickEvent tick) {
|
||||
if (tick.phase != TickEvent.Phase.END) return;
|
||||
|
||||
if (tickCount++ % (PING_INTERVAL * 1200) != 0) return;
|
||||
|
||||
if (thread == null) {
|
||||
thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Disable Task, if it is running and the server owner decided
|
||||
// to opt-out
|
||||
if (isOptOut()) {
|
||||
FMLCommonHandler.instance().bus().unregister(ForgeMetrics.this);
|
||||
return;
|
||||
}
|
||||
// We use the inverse of firstPost because if it
|
||||
// is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to
|
||||
// FALSE
|
||||
// Each time thereafter it will evaluate to
|
||||
// TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
// After the first post we set firstPost to
|
||||
// false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
FMLLog.info("[Metrics] Exception - %s", e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
// Reload the metrics file
|
||||
configuration.load();
|
||||
return configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false).getBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the
|
||||
* config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("false");
|
||||
configuration.save();
|
||||
}
|
||||
// Enable Task, if it is not running
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the
|
||||
* config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("true");
|
||||
configuration.save();
|
||||
}
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data
|
||||
* such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
return new File(Loader.instance().getConfigDir(), "PluginMetrics.cfg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
String pluginName = modName;
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
boolean onlineMode = server.isServerInOnlineMode();
|
||||
String pluginVersion = modVersion;
|
||||
String serverVersion;
|
||||
if (server.isDedicatedServer()) {
|
||||
serverVersion = "MinecraftForge (MC: " + server.getMinecraftVersion() + ")";
|
||||
} else {
|
||||
serverVersion = "MinecraftForgeSSP (MC: " + server.getMinecraftVersion() + ")";
|
||||
}
|
||||
int playersOnline = server.getCurrentPlayerCount();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
StringBuilder json = new StringBuilder(1024);
|
||||
json.append('{');
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
appendJSONPair(json, "guid", guid);
|
||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
||||
appendJSONPair(json, "server_version", serverVersion);
|
||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
appendJSONPair(json, "osname", osname);
|
||||
appendJSONPair(json, "osarch", osarch);
|
||||
appendJSONPair(json, "osversion", osversion);
|
||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
||||
appendJSONPair(json, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
appendJSONPair(json, "ping", "1");
|
||||
}
|
||||
|
||||
// close json
|
||||
json.append('}');
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
|
||||
byte[] uncompressed = json.toString().getBytes();
|
||||
byte[] compressed = gzip(json.toString());
|
||||
|
||||
// Headers
|
||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
||||
connection.addRequestProperty("Content-Type", "application/json");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(compressed);
|
||||
os.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
os.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
||||
if (response == null) {
|
||||
response = "null";
|
||||
} else if (response.startsWith("7")) {
|
||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
||||
}
|
||||
|
||||
throw new IOException(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GZip compress a string of bytes
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static byte[] gzip(String input) {
|
||||
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
|
||||
PGZIPOutputStream gzos = null;
|
||||
|
||||
try {
|
||||
gzos = new PGZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
MainUtil.handleError(e);
|
||||
} finally {
|
||||
if (gzos != null) try {
|
||||
gzos.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
||||
*
|
||||
* @return true if mineshafter is installed on the server
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a json encoded key/value pair to the given string builder.
|
||||
*
|
||||
* @param json
|
||||
* @param key
|
||||
* @param value
|
||||
* @throws java.io.UnsupportedEncodingException
|
||||
*/
|
||||
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
|
||||
boolean isValueNumeric = false;
|
||||
|
||||
try {
|
||||
if (value.equals("0") || !value.endsWith("0")) {
|
||||
Double.parseDouble(value);
|
||||
isValueNumeric = true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
isValueNumeric = false;
|
||||
}
|
||||
|
||||
if (json.charAt(json.length() - 1) != '{') {
|
||||
json.append(',');
|
||||
}
|
||||
|
||||
json.append(escapeJSON(key));
|
||||
json.append(':');
|
||||
|
||||
if (isValueNumeric) {
|
||||
json.append(value);
|
||||
} else {
|
||||
json.append(escapeJSON(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string to create a valid JSON string
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
private static String escapeJSON(String text) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append('"');
|
||||
for (int index = 0; index < text.length(); index++) {
|
||||
char chr = text.charAt(index);
|
||||
|
||||
switch (chr) {
|
||||
case '"':
|
||||
case '\\':
|
||||
builder.append('\\');
|
||||
builder.append(chr);
|
||||
break;
|
||||
case '\b':
|
||||
builder.append("\\b");
|
||||
break;
|
||||
case '\t':
|
||||
builder.append("\\t");
|
||||
break;
|
||||
case '\n':
|
||||
builder.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.append("\\r");
|
||||
break;
|
||||
default:
|
||||
if (chr < ' ') {
|
||||
String t = "000" + Integer.toHexString(chr);
|
||||
builder.append("\\u" + t.substring(t.length() - 4));
|
||||
} else {
|
||||
builder.append(chr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.append('"');
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text, as UTF-8
|
||||
*/
|
||||
private static String urlEncode(final String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.wrappers.PlayerWrapper;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
|
||||
public ForgePlayer(EntityPlayerMP parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String head, String sub) { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTitle() { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return parent.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
Object meta = getMeta(perm);
|
||||
return meta instanceof Boolean ? (boolean) meta : ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(parent, perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(String perm, boolean flag) {
|
||||
setMeta(perm, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
msg = BBC.color(msg);
|
||||
for (String line : msg.split("\n")) {
|
||||
this.parent.sendMessage(new TextComponentString(line));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(String substring) {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweLocation getLocation() {
|
||||
World world = parent.world;
|
||||
BlockPos pos = parent.getPosition();
|
||||
return new FaweLocation(Fawe.<FaweForge>imp().getWorldName(world), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player toWorldEditPlayer() {
|
||||
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBagException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class ForgePlayerBlockBag extends BlockBag {
|
||||
|
||||
private EntityPlayerMP player;
|
||||
private ItemStack[] items;
|
||||
private boolean changed;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public ForgePlayerBlockBag(EntityPlayerMP player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads inventory on first use.
|
||||
*/
|
||||
private void loadInventory() {
|
||||
if (items == null) {
|
||||
items = new ItemStack[player.inventory.getSizeInventory()];
|
||||
for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
|
||||
items[i] = player.inventory.getStackInSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public EntityPlayerMP getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount == 1);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't fetch air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
continue;
|
||||
}
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.getCount();
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
if (currentAmount > 1) {
|
||||
forgeItem.setCount(forgeItem.getCount() - 1);;
|
||||
found = true;
|
||||
} else {
|
||||
items[slot] = null;
|
||||
found = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new OutOfBlocksException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount <= 64);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't store air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
int freeSlot = -1;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
// Delay using up a free slot until we know there are no stacks
|
||||
// of this item to merge into
|
||||
|
||||
if (freeSlot == -1) {
|
||||
freeSlot = slot;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.getCount();
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
if (currentAmount >= 64) {
|
||||
// Full stack
|
||||
continue;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
int spaceLeft = 64 - currentAmount;
|
||||
if (spaceLeft >= amount) {
|
||||
forgeItem.setCount(forgeItem.getCount() + amount);
|
||||
return;
|
||||
}
|
||||
|
||||
forgeItem.setCount(64);
|
||||
amount -= spaceLeft;
|
||||
}
|
||||
|
||||
if (freeSlot > -1) {
|
||||
changed = true;
|
||||
items[freeSlot] = new ItemStack(Item.getItemById(id), amount);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new OutOfSpaceException(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushChanges() {
|
||||
if (items != null && changed) {
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
player.inventory.setInventorySlotContents(i, items[i]);
|
||||
}
|
||||
items = null;
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSingleSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeTaskMan extends TaskManager {
|
||||
|
||||
private final ConcurrentLinkedDeque<Runnable> syncTasks = new ConcurrentLinkedDeque<>();
|
||||
private final ConcurrentLinkedDeque<Runnable> asyncTasks = new ConcurrentLinkedDeque<>();
|
||||
|
||||
private final ConcurrentHashMap<Integer, Runnable> taskIdMap = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
|
||||
|
||||
private final AtomicInteger taskId = new AtomicInteger();
|
||||
private final ExecutorService executor;
|
||||
|
||||
public ForgeTaskMan(int size) {
|
||||
this.executor = Executors.newFixedThreadPool(size);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int repeat(final Runnable r, final int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
later(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
Fawe.get().setMainThread();
|
||||
int asyncSize = asyncTasks.size();
|
||||
for (int i = 0; i < asyncSize; i++) {
|
||||
Runnable item = asyncTasks.poll();
|
||||
if (item != null) {
|
||||
async(item);
|
||||
}
|
||||
}
|
||||
int syncSize = syncTasks.size();
|
||||
for (int i = 0; i < syncSize; i++) {
|
||||
Runnable item = syncTasks.poll();
|
||||
if (item != null) {
|
||||
try {
|
||||
item.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(Runnable r, int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
laterAsync(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
executor.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
syncTasks.add(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
async(r);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int task) {
|
||||
taskIdMap.remove(task);
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.world.gen.layer.GenLayer;
|
||||
import net.minecraft.world.gen.layer.IntCache;
|
||||
|
||||
public class MutableGenLayer extends GenLayer {
|
||||
|
||||
private int biome;
|
||||
|
||||
public MutableGenLayer(long seed) {
|
||||
super(seed);
|
||||
}
|
||||
|
||||
public MutableGenLayer set(int biome) {
|
||||
this.biome = biome;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight) {
|
||||
int[] biomes = IntCache.getIntCache(areaWidth * areaHeight);
|
||||
Arrays.fill(biomes, biome);
|
||||
return biomes;
|
||||
}
|
||||
}
|
|
@ -1,391 +0,0 @@
|
|||
package com.boydti.fawe.forge.v112;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BitArray;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IBlockStatePalette;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
|
||||
public BlockStateContainer[] sectionPalettes;
|
||||
|
||||
public static Map<String, ResourceLocation> entityKeys;
|
||||
|
||||
/**
|
||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||
*
|
||||
* @param parent
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
}
|
||||
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
|
||||
super(parent, x, z, ids, count, air, heightMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk copy(boolean shallow) {
|
||||
ForgeChunk_All copy;
|
||||
if (shallow) {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), ids, count, air, heightMap);
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
} else {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
copy.biomes = biomes.clone();
|
||||
copy.chunk = chunk;
|
||||
}
|
||||
if (sectionPalettes != null) {
|
||||
copy.sectionPalettes = new BlockStateContainer[16];
|
||||
try {
|
||||
Field fieldBits = BlockStateContainer.class.getDeclaredField("field_186021_b"); // storage
|
||||
fieldBits.setAccessible(true);
|
||||
Field fieldPalette = BlockStateContainer.class.getDeclaredField("field_186022_c"); // palettes
|
||||
fieldPalette.setAccessible(true);
|
||||
Field fieldSize = BlockStateContainer.class.getDeclaredField("field_186024_e"); // bits
|
||||
fieldSize.setAccessible(true);
|
||||
for (int i = 0; i < sectionPalettes.length; i++) {
|
||||
BlockStateContainer current = sectionPalettes[i];
|
||||
if (current == null) {
|
||||
continue;
|
||||
}
|
||||
// Clone palette
|
||||
IBlockStatePalette currentPalette = (IBlockStatePalette) fieldPalette.get(current);
|
||||
if (!(currentPalette instanceof BlockStatePaletteRegistry)) {
|
||||
current.onResize(128, null);
|
||||
}
|
||||
BlockStateContainer paletteBlock = new BlockStateContainer();
|
||||
currentPalette = (IBlockStatePalette) fieldPalette.get(current);
|
||||
if (!(currentPalette instanceof BlockStatePaletteRegistry)) {
|
||||
throw new RuntimeException("Palette must be global!");
|
||||
}
|
||||
fieldPalette.set(paletteBlock, currentPalette);
|
||||
// Clone size
|
||||
fieldSize.set(paletteBlock, fieldSize.get(current));
|
||||
// Clone palette
|
||||
BitArray currentBits = (BitArray) fieldBits.get(current);
|
||||
BitArray newBits = new BitArray(1, 0);
|
||||
for (Field field : BitArray.class.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
Object currentValue = field.get(currentBits);
|
||||
if (currentValue instanceof long[]) {
|
||||
currentValue = ((long[]) currentValue).clone();
|
||||
}
|
||||
field.set(newBits, currentValue);
|
||||
}
|
||||
fieldBits.set(paletteBlock, newBits);
|
||||
copy.sectionPalettes[i] = paletteBlock;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getNewChunk() {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
return world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
if (sectionPalettes != null) {
|
||||
return;
|
||||
}
|
||||
char[][] arrays = getCombinedIdArrays();
|
||||
char lastChar = Character.MAX_VALUE;
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
if (getCount(layer) > 0) {
|
||||
if (sectionPalettes == null) {
|
||||
sectionPalettes = new BlockStateContainer[16];
|
||||
}
|
||||
BlockStateContainer palette = new BlockStateContainer();
|
||||
char[] blocks = getIdArray(layer);
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
char combinedId = blocks[FaweCache.CACHE_J[y][z][x]];
|
||||
if (combinedId > 1) {
|
||||
palette.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForgeChunk_All call() {
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||
int bx = this.getX() << 4;
|
||||
int bz = this.getZ() << 4;
|
||||
nmsChunk.setModified(true);
|
||||
net.minecraft.world.World nmsWorld = getParent().getWorld();
|
||||
try {
|
||||
boolean flag = nmsWorld.provider.hasSkyLight();
|
||||
// Sections
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
|
||||
// Set heightmap
|
||||
getParent().setHeightMap(this, heightMap);
|
||||
// Remove entities
|
||||
for (int i = 0; i < 16; i++) {
|
||||
int count = this.getCount(i);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
} else if (count >= 4096) {
|
||||
ClassInheritanceMultiMap<Entity> ents = entities[i];
|
||||
if (ents != null && !ents.isEmpty()) {
|
||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||
for (Entity ent : ents) {
|
||||
nmsWorld.removeEntity(ent);
|
||||
}
|
||||
}
|
||||
} else if (!getParent().getSettings().EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) {
|
||||
char[] array = this.getIdArray(i);
|
||||
if (array == null || entities[i] == null || entities[i].isEmpty()) continue;
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entity instanceof EntityPlayer) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(entity.posX) & 15);
|
||||
int z = (MathMan.roundInt(entity.posZ) & 15);
|
||||
int y = MathMan.roundInt(entity.posY);
|
||||
if (y < 0 || y > 255) continue;
|
||||
if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashSet<UUID> entsToRemove = this.getEntityRemoves();
|
||||
if (!entsToRemove.isEmpty()) {
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entsToRemove.contains(entity.getUniqueID())) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set entities
|
||||
Set<UUID> createdEntities = new HashSet<>();
|
||||
Set<CompoundTag> entitiesToSpawn = this.getEntities();
|
||||
for (CompoundTag nativeTag : entitiesToSpawn) {
|
||||
Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||
if (idTag == null || posTag == null || rotTag == null) {
|
||||
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||
continue;
|
||||
}
|
||||
double x = posTag.getDouble(0);
|
||||
double y = posTag.getDouble(1);
|
||||
double z = posTag.getDouble(2);
|
||||
float yaw = rotTag.getFloat(0);
|
||||
float pitch = rotTag.getFloat(1);
|
||||
String id = idTag.getValue();
|
||||
if (entityKeys == null) {
|
||||
entityKeys = new HashMap<>();
|
||||
for (ResourceLocation key : EntityList.getEntityNameList()) {
|
||||
String currentId = EntityList.getTranslationName(key);
|
||||
entityKeys.put(currentId, key);
|
||||
entityKeys.put(key.getResourcePath(), key);
|
||||
}
|
||||
}
|
||||
ResourceLocation entityKey = entityKeys.get(id);
|
||||
if (entityKey != null) {
|
||||
Entity entity = EntityList.createEntityByIDFromName(entityKey, nmsWorld);
|
||||
if (entity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound)ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
entity.readFromNBT(tag);
|
||||
tag.removeTag("UUIDMost");
|
||||
tag.removeTag("UUIDLeast");
|
||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||
nmsWorld.spawnEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Run change task if applicable
|
||||
if (getParent().getChangeTask() != null) {
|
||||
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||
getParent().getChangeTask().run(previous, this);
|
||||
}
|
||||
// Trim tiles
|
||||
if (!tiles.isEmpty()) {
|
||||
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||
BlockPos pos = tile.getKey();
|
||||
int lx = pos.getX() & 15;
|
||||
int ly = pos.getY();
|
||||
int lz = pos.getZ() & 15;
|
||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||
char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||
if (array[k] != 0) {
|
||||
synchronized (ForgeChunk_All.class) {
|
||||
iterator.remove();
|
||||
tile.getValue().invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
int count = this.getCount(j);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
}
|
||||
final char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int countAir = this.getAir(j);
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if (section == null) {
|
||||
if (count == countAir) {
|
||||
continue;
|
||||
}
|
||||
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||
section = sections[j] = new ExtendedBlockStorage(j << 4, flag);
|
||||
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||
getParent().setCount(0, count - this.getAir(j), section);
|
||||
continue;
|
||||
} else {
|
||||
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
||||
}
|
||||
} else if (count >= 4096) {
|
||||
if (count == countAir) {
|
||||
sections[j] = null;
|
||||
continue;
|
||||
}
|
||||
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||
getParent().setCount(0, count - this.getAir(j), section);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
IBlockState existing;
|
||||
int by = j << 4;
|
||||
BlockStateContainer nibble = section.getData();
|
||||
int nonEmptyBlockCount = 0;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
||||
switch (combinedId) {
|
||||
case 0:
|
||||
continue;
|
||||
case 1:
|
||||
existing = nibble.get(x, y, z);
|
||||
if (existing != ForgeQueue_All.air) {
|
||||
if (existing.getLightValue() > 0) {
|
||||
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
|
||||
}
|
||||
nonEmptyBlockCount--;
|
||||
}
|
||||
nibble.set(x, y, z, ForgeQueue_All.air);
|
||||
continue;
|
||||
default:
|
||||
existing = nibble.get(x, y, z);
|
||||
if (existing != ForgeQueue_All.air) {
|
||||
if (existing.getLightValue() > 0) {
|
||||
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
|
||||
}
|
||||
} else {
|
||||
nonEmptyBlockCount++;
|
||||
}
|
||||
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
|
||||
}
|
||||
// Set biomes
|
||||
if (this.biomes != null) {
|
||||
byte[] currentBiomes = nmsChunk.getBiomeArray();
|
||||
for (int i = 0 ; i < this.biomes.length; i++) {
|
||||
byte biome = this.biomes[i];
|
||||
if (biome != 0) {
|
||||
if (biome == -1) biome = 0;
|
||||
currentBiomes[i] = biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set tiles
|
||||
Map<Short, CompoundTag> tilesToSpawn = this.getTiles();
|
||||
|
||||
for (Map.Entry<Short, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||
CompoundTag nativeTag = entry.getValue();
|
||||
short blockHash = entry.getKey();
|
||||
int x = (blockHash >> 12 & 0xF) + bx;
|
||||
int y = (blockHash & 0xFF);
|
||||
int z = (blockHash >> 8 & 0xF) + bz;
|
||||
BlockPos pos = new BlockPos(x, y, z); // Set pos
|
||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||
if (tileEntity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.setInteger("x", pos.getX());
|
||||
tag.setInteger("y", pos.getY());
|
||||
tag.setInteger("z", pos.getZ());
|
||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
sectionPalettes = null;
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,779 +0,0 @@
|
|||
package com.boydti.fawe.forge.v112;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
import com.boydti.fawe.forge.MutableGenLayer;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.brush.visualization.VisualChunk;
|
||||
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.SPacketChunkData;
|
||||
import net.minecraft.network.play.server.SPacketMultiBlockChange;
|
||||
import net.minecraft.server.management.PlayerChunkMap;
|
||||
import net.minecraft.server.management.PlayerChunkMapEntry;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.EnumSkyBlock;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.biome.BiomeCache;
|
||||
import net.minecraft.world.biome.BiomeProvider;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.NibbleArray;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkGeneratorOverworld;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import net.minecraft.world.gen.IChunkGenerator;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
protected final static Method methodFromNative;
|
||||
protected final static Method methodToNative;
|
||||
protected final static Field fieldTickingBlockCount;
|
||||
protected final static Field fieldNonEmptyBlockCount;
|
||||
|
||||
protected static Field fieldBiomes;
|
||||
protected static Field fieldChunkGenerator;
|
||||
protected static Field fieldSeed;
|
||||
protected static Field fieldBiomeCache;
|
||||
protected static Field fieldBiomes2;
|
||||
protected static Field fieldGenLayer1;
|
||||
protected static Field fieldGenLayer2;
|
||||
protected static ExtendedBlockStorage emptySection;
|
||||
private static MutableGenLayer genLayer;
|
||||
|
||||
static {
|
||||
try {
|
||||
emptySection = new ExtendedBlockStorage(0, true);
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
|
||||
methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
|
||||
methodFromNative.setAccessible(true);
|
||||
methodToNative.setAccessible(true);
|
||||
|
||||
fieldBiomes = ChunkGeneratorOverworld.class.getDeclaredField("field_185981_C"); // biomesForGeneration
|
||||
fieldBiomes.setAccessible(true);
|
||||
fieldChunkGenerator = ChunkProviderServer.class.getDeclaredField("field_186029_c"); // chunkGenerator
|
||||
fieldChunkGenerator.setAccessible(true);
|
||||
fieldSeed = WorldInfo.class.getDeclaredField("field_76100_a"); // randomSeed
|
||||
fieldSeed.setAccessible(true);
|
||||
fieldBiomeCache = BiomeProvider.class.getDeclaredField("field_76942_f"); // biomeCache
|
||||
fieldBiomeCache.setAccessible(true);
|
||||
fieldBiomes2 = BiomeProvider.class.getDeclaredField("field_76943_g"); // biomesToSpawnIn
|
||||
fieldBiomes2.setAccessible(true);
|
||||
fieldGenLayer1 = BiomeProvider.class.getDeclaredField("field_76944_d"); // genBiomes
|
||||
fieldGenLayer2 = BiomeProvider.class.getDeclaredField("field_76945_e"); // biomeIndexLayer
|
||||
fieldGenLayer1.setAccessible(true);
|
||||
fieldGenLayer2.setAccessible(true);
|
||||
|
||||
fieldTickingBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76683_c");
|
||||
fieldNonEmptyBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76682_b");
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(Chunk chunk) {
|
||||
chunk.setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getSections(Chunk chunk) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiome(Chunk chunk, int x, int z) {
|
||||
return chunk.getBiomeArray()[((z & 15) << 4) + (x & 15)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk loadChunk(World world, int x, int z, boolean generate) {
|
||||
ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider();
|
||||
if (generate) {
|
||||
return provider.provideChunk(x, z);
|
||||
} else {
|
||||
return provider.loadChunk(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getCachedSections(World world, int cx, int cz) {
|
||||
Chunk chunk = world.getChunkProvider().getLoadedChunk(cx, cz);
|
||||
if (chunk != null) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getCachedChunk(World world, int cx, int cz) {
|
||||
return world.getChunkProvider().getLoadedChunk(cx, cz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage getCachedSection(ExtendedBlockStorage[] ExtendedBlockStorages, int cy) {
|
||||
return ExtendedBlockStorages[cy];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
|
||||
try {
|
||||
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
|
||||
boolean watching = false;
|
||||
boolean[] watchingArr = new boolean[players.length];
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) ((ForgePlayer) players[i]).parent;
|
||||
if (playerManager.isPlayerWatchingChunk(player, chunk.getX(), chunk.getZ())) {
|
||||
watchingArr[i] = true;
|
||||
watching = true;
|
||||
}
|
||||
}
|
||||
if (!watching) return;
|
||||
final LongAdder size = new LongAdder();
|
||||
if (chunk instanceof VisualChunk) {
|
||||
size.add(((VisualChunk) chunk).size());
|
||||
} else if (chunk instanceof CharFaweChunk) {
|
||||
size.add(((CharFaweChunk) chunk).getTotalCount());
|
||||
} else {
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
size.add(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (size.intValue() == 0) return;
|
||||
SPacketMultiBlockChange packet = new SPacketMultiBlockChange();
|
||||
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
|
||||
final PacketBuffer buffer = new PacketBuffer(byteBuf);
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
buffer.writeVarInt(size.intValue());
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
short index = (short) (localX << 12 | localZ << 8 | y);
|
||||
buffer.writeShort(index);
|
||||
buffer.writeVarInt(combined);
|
||||
}
|
||||
});
|
||||
packet.readPacketData(buffer);
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
if (watchingArr[i]) ((EntityPlayerMP) ((ForgePlayer) players[i]).parent).connection.sendPacket(packet);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean load) {
|
||||
// TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
||||
// @Override
|
||||
// public void run(Boolean value) {
|
||||
// long start = System.currentTimeMillis();
|
||||
// long last = start;
|
||||
// synchronized (RegionFileCache.class) {
|
||||
// WorldServer world = (WorldServer) getWorld();
|
||||
// ChunkProviderServer provider = nmsWorld.getChunkProvider();
|
||||
//
|
||||
// boolean mustSave = false;
|
||||
// boolean[][] chunksUnloaded = null;
|
||||
// { // Unload chunks
|
||||
// Iterator<Chunk> iter = provider.getLoadedChunks().iterator();
|
||||
// while (iter.hasNext()) {
|
||||
// Chunk chunk = iter.next();
|
||||
// if (chunk.x >> 5 == mcaX && chunk.z >> 5 == mcaZ) {
|
||||
// boolean isIn = allowed.isInChunk(chunk.x, chunk.x);
|
||||
// if (isIn) {
|
||||
// if (!load) {
|
||||
// if (chunk.needsSaving(false)) {
|
||||
// mustSave = true;
|
||||
// try {
|
||||
// provider.chunkLoader.saveChunk(nmsWorld, chunk);
|
||||
// provider.chunkLoader.saveExtraChunkData(nmsWorld, chunk);
|
||||
// } catch (IOException | MinecraftException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// continue;
|
||||
// }
|
||||
// iter.remove();
|
||||
// boolean save = chunk.needsSaving(false);
|
||||
// mustSave |= save;
|
||||
// if (save) {
|
||||
// provider.queueUnload(chunk);
|
||||
// } else {
|
||||
// chunk.onUnload();
|
||||
// }
|
||||
// if (chunksUnloaded == null) {
|
||||
// chunksUnloaded = new boolean[32][];
|
||||
// }
|
||||
// int relX = chunk.x & 31;
|
||||
// boolean[] arr = chunksUnloaded[relX];
|
||||
// if (arr == null) {
|
||||
// arr = chunksUnloaded[relX] = new boolean[32];
|
||||
// }
|
||||
// arr[chunk.z & 31] = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (mustSave) provider.flushToDisk(); // TODO only the necessary chunks
|
||||
//
|
||||
// File unloadedRegion = null;
|
||||
// if (load && !RegionFileCache.a.isEmpty()) {
|
||||
// Map<File, RegionFile> map = RegionFileCache.a;
|
||||
// Iterator<Map.Entry<File, RegionFile>> iter = map.entrySet().iterator();
|
||||
// String requiredPath = world.getName() + File.separator + "region";
|
||||
// while (iter.hasNext()) {
|
||||
// Map.Entry<File, RegionFile> entry = iter.next();
|
||||
// File file = entry.getKey();
|
||||
// int[] regPos = MainUtil.regionNameToCoords(file.getPath());
|
||||
// if (regPos[0] == mcaX && regPos[1] == mcaZ && file.getPath().contains(requiredPath)) {
|
||||
// if (file.exists()) {
|
||||
// unloadedRegion = file;
|
||||
// RegionFile regionFile = entry.getValue();
|
||||
// iter.remove();
|
||||
// try {
|
||||
// regionFile.c();
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// long now = System.currentTimeMillis();
|
||||
// if (whileLocked != null) whileLocked.run();
|
||||
// if (!load) return;
|
||||
//
|
||||
// { // Load the region again
|
||||
// if (unloadedRegion != null && chunksUnloaded != null && unloadedRegion.exists()) {
|
||||
// final boolean[][] finalChunksUnloaded = chunksUnloaded;
|
||||
// TaskManager.IMP.async(() -> {
|
||||
// int bx = mcaX << 5;
|
||||
// int bz = mcaZ << 5;
|
||||
// for (int x = 0; x < finalChunksUnloaded.length; x++) {
|
||||
// boolean[] arr = finalChunksUnloaded[x];
|
||||
// if (arr != null) {
|
||||
// for (int z = 0; z < arr.length; z++) {
|
||||
// if (arr[z]) {
|
||||
// int cx = bx + x;
|
||||
// int cz = bz + z;
|
||||
// TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
// @Override
|
||||
// public void run(Object value1) {
|
||||
// Chunk chunk = provider.getChunkAt(cx, cz, null, false);
|
||||
// if (chunk != null) {
|
||||
// PlayerChunk pc = getPlayerChunk(nmsWorld, cx, cz);
|
||||
// if (pc != null) {
|
||||
// sendChunk(pc, chunk, 0);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// return true;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
|
||||
Chunk forgeChunk = (Chunk) chunk.getChunk();
|
||||
if (forgeChunk != null) {
|
||||
int[] otherMap = forgeChunk.getHeightMap();
|
||||
for (int i = 0; i < heightMap.length; i++) {
|
||||
int newHeight = heightMap[i] & 0xFF;
|
||||
int currentHeight = otherMap[i];
|
||||
if (newHeight > currentHeight) {
|
||||
otherMap[i] = newHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
|
||||
@Override
|
||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||
Map<BlockPos, TileEntity> tiles = chunk.getTileEntityMap();
|
||||
pos.setPos(x, y, z);
|
||||
TileEntity tile = tiles.get(pos);
|
||||
return tile != null ? getTag(tile) : null;
|
||||
}
|
||||
|
||||
public CompoundTag getTag(TileEntity tile) {
|
||||
try {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTagIntoEntity
|
||||
CompoundTag result = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
MainUtil.handleError(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(net.minecraft.world.World world, int x, int z, BaseBiome biome, Long seed) {
|
||||
if (biome != null) {
|
||||
try {
|
||||
if (seed == null) {
|
||||
seed = world.getSeed();
|
||||
}
|
||||
nmsWorld.getWorldInfo().getSeed();
|
||||
boolean result;
|
||||
ChunkGeneratorOverworld generator = new ChunkGeneratorOverworld(nmsWorld, seed, false, "");
|
||||
net.minecraft.world.biome.Biome base = net.minecraft.world.biome.Biome.getBiome(biome.getId());
|
||||
net.minecraft.world.biome.Biome[] existingBiomes = new net.minecraft.world.biome.Biome[256];
|
||||
Arrays.fill(existingBiomes, base);
|
||||
fieldBiomes.set(generator, existingBiomes);
|
||||
IChunkGenerator existingGenerator = (IChunkGenerator) fieldChunkGenerator.get(nmsWorld.getChunkProvider());
|
||||
long existingSeed = world.getSeed();
|
||||
{
|
||||
if (genLayer == null) genLayer = new MutableGenLayer(seed);
|
||||
genLayer.set(biome.getId());
|
||||
Object existingGenLayer1 = fieldGenLayer1.get(nmsWorld.provider.getBiomeProvider());
|
||||
Object existingGenLayer2 = fieldGenLayer2.get(nmsWorld.provider.getBiomeProvider());
|
||||
fieldGenLayer1.set(nmsWorld.provider.getBiomeProvider(), genLayer);
|
||||
fieldGenLayer2.set(nmsWorld.provider.getBiomeProvider(), genLayer);
|
||||
|
||||
fieldSeed.set(nmsWorld.getWorldInfo(), seed);
|
||||
|
||||
ReflectionUtils.setFailsafeFieldValue(fieldBiomeCache, this.nmsWorld.provider.getBiomeProvider(), new BiomeCache(this.nmsWorld.provider.getBiomeProvider()));
|
||||
|
||||
ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProvider(), generator);
|
||||
|
||||
result = regenerateChunk(world, x, z);
|
||||
|
||||
ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProvider(), existingGenerator);
|
||||
|
||||
fieldSeed.set(nmsWorld.getWorldInfo(), existingSeed);
|
||||
|
||||
fieldGenLayer1.set(nmsWorld.provider.getBiomeProvider(), existingGenLayer1);
|
||||
fieldGenLayer2.set(nmsWorld.provider.getBiomeProvider(), existingGenLayer2);
|
||||
}
|
||||
return result;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return regenerateChunk(world, x, z);
|
||||
}
|
||||
|
||||
public boolean regenerateChunk(World world, int x, int z) {
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
BlockFalling.fallInstantly = true;
|
||||
try {
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
IChunkGenerator gen = (IChunkGenerator) fieldChunkGenerator.get(chunkServer);
|
||||
long pos = ChunkPos.asLong(x, z);
|
||||
Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onUnload();
|
||||
}
|
||||
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
|
||||
List<EntityPlayerMP> oldWatchers = null;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
PlayerChunkMapEntry entry = playerManager.getEntry(x, z);
|
||||
if (entry != null) {
|
||||
Field fieldPlayers = PlayerChunkMapEntry.class.getDeclaredField("field_187283_c");
|
||||
fieldPlayers.setAccessible(true);
|
||||
oldWatchers = (List<EntityPlayerMP>) fieldPlayers.get(entry);
|
||||
playerManager.removeEntry(entry);
|
||||
}
|
||||
mcChunk.onUnload();
|
||||
}
|
||||
try {
|
||||
Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b");
|
||||
droppedChunksSetField.setAccessible(true);
|
||||
Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer);
|
||||
droppedChunksSet.remove(pos);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
Long2ObjectMap<Chunk> id2ChunkMap = chunkServer.id2ChunkMap;
|
||||
id2ChunkMap.remove(pos);
|
||||
mcChunk = gen.generateChunk(x, z);
|
||||
id2ChunkMap.put(pos, mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onLoad();
|
||||
mcChunk.populate(chunkServer, gen);
|
||||
}
|
||||
if (oldWatchers != null) {
|
||||
for (EntityPlayerMP player : oldWatchers) {
|
||||
playerManager.addPlayer(player);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
MainUtil.handleError(t);
|
||||
return false;
|
||||
} finally {
|
||||
BlockFalling.fallInstantly = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
IBlockState ibd = section.getData().get(x & 15, y & 15, z & 15);
|
||||
Block block = ibd.getBlock();
|
||||
int id = Block.getIdFromBlock(block);
|
||||
if (FaweCache.hasData(id)) {
|
||||
return (id << 4) + block.getMetaFromState(ibd);
|
||||
} else {
|
||||
return id << 4;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNonEmptyBlockCount(ExtendedBlockStorage section) throws IllegalAccessException {
|
||||
return (int) fieldNonEmptyBlockCount.get(section);
|
||||
}
|
||||
|
||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||
Map<BlockPos, TileEntity> tiles = (Map<BlockPos, TileEntity>) tilesGeneric;
|
||||
ClassInheritanceMultiMap<Entity>[] entities = (ClassInheritanceMultiMap<Entity>[]) entitiesGeneric;
|
||||
CharFaweChunk previous = (CharFaweChunk) getFaweChunk(fs.getX(), fs.getZ());
|
||||
char[][] idPrevious = previous.getCombinedIdArrays();
|
||||
for (int layer = 0; layer < sections.length; layer++) {
|
||||
if (fs.getCount(layer) != 0 || all) {
|
||||
ExtendedBlockStorage section = sections[layer];
|
||||
if (section != null) {
|
||||
short solid = 0;
|
||||
char[] previousLayer = idPrevious[layer] = new char[4096];
|
||||
BlockStateContainer blocks = section.getData();
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int x = FaweCache.CACHE_X[0][j];
|
||||
int y = FaweCache.CACHE_Y[0][j];
|
||||
int z = FaweCache.CACHE_Z[0][j];
|
||||
IBlockState ibd = blocks.get(x, y, z);
|
||||
Block block = ibd.getBlock();
|
||||
int combined = Block.getIdFromBlock(block);
|
||||
if (FaweCache.hasData(combined)) {
|
||||
combined = (combined << 4) + block.getMetaFromState(ibd);
|
||||
} else {
|
||||
combined = combined << 4;
|
||||
}
|
||||
if (combined > 1) {
|
||||
solid++;
|
||||
}
|
||||
previousLayer[j] = (char) combined;
|
||||
}
|
||||
previous.count[layer] = solid;
|
||||
previous.air[layer] = (short) (4096 - solid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tiles != null) {
|
||||
for (Map.Entry<BlockPos, TileEntity> entry : tiles.entrySet()) {
|
||||
TileEntity tile = entry.getValue();
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTileEntityIntoTag
|
||||
BlockPos pos = entry.getKey();
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
|
||||
}
|
||||
}
|
||||
if (entities != null) {
|
||||
for (Collection<Entity> entityList : entities) {
|
||||
for (Entity ent : entityList) {
|
||||
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && createdEntities.contains(ent.getUniqueID()))) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(ent.posX) & 15);
|
||||
int z = (MathMan.roundInt(ent.posZ) & 15);
|
||||
int y = MathMan.roundInt(ent.posY);
|
||||
int i = FaweCache.CACHE_I[y][z][x];
|
||||
char[] array = fs.getIdArray(i);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int j = FaweCache.CACHE_J[y][z][x];
|
||||
if (array[j] != 0) {
|
||||
String id = EntityList.getEntityString(ent);
|
||||
if (id != null) {
|
||||
NBTTagCompound tag = ent.getEntityData(); // readEntityIntoTag
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
||||
map.put("Id", new StringTag(id));
|
||||
previous.setEntity(nativeTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
protected final static IBlockState air = Blocks.AIR.getDefaultState();
|
||||
|
||||
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
||||
fieldSection.setAccessible(true);
|
||||
fieldSection.set(section, palette);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int x, int z, int bitMask) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), x, z);
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, bitMask);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChunk(FaweChunk fc) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, fc.getBitMask());
|
||||
}
|
||||
}
|
||||
|
||||
public void sendChunk(Chunk nmsChunk, int mask) {
|
||||
if (!nmsChunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ChunkPos pos = nmsChunk.getPos();
|
||||
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
||||
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
||||
int x = pos.x;
|
||||
int z = pos.z;
|
||||
PlayerChunkMapEntry chunkMapEntry = chunkMap.getEntry(x, z);
|
||||
if (chunkMapEntry == null) {
|
||||
return;
|
||||
}
|
||||
final ArrayDeque<EntityPlayerMP> players = new ArrayDeque<>();
|
||||
chunkMapEntry.hasPlayerMatching(input -> {
|
||||
players.add(input);
|
||||
return false;
|
||||
});
|
||||
boolean empty = false;
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == null) {
|
||||
sections[i] = emptySection;
|
||||
empty = true;
|
||||
}
|
||||
}
|
||||
if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
|
||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65280);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.connection.sendPacket(packet);
|
||||
}
|
||||
mask = 255;
|
||||
}
|
||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, mask);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.connection.sendPacket(packet);
|
||||
}
|
||||
if (empty) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == emptySection) {
|
||||
sections[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEntities(Chunk nmsChunk) {
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
ClassInheritanceMultiMap<Entity> slice = entities[i];
|
||||
if (slice != null && !slice.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSectionLighting(ExtendedBlockStorage section, int layer, boolean sky) {
|
||||
if (section != null) {
|
||||
section.setBlockLight(new NibbleArray());
|
||||
if (sky) {
|
||||
section.setSkyLight(new NibbleArray());
|
||||
}
|
||||
}
|
||||
return section != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSky() {
|
||||
return nmsWorld.provider.hasSkyLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullbright(ExtendedBlockStorage[] sections) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section != null) {
|
||||
byte[] bytes = section.getSkyLight().getData();
|
||||
Arrays.fill(bytes, (byte) 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relight(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
if (nmsWorld != null || getWorldName() == null) {
|
||||
return nmsWorld;
|
||||
}
|
||||
String[] split = getWorldName().split(";");
|
||||
int id = Integer.parseInt(split[split.length - 1]);
|
||||
nmsWorld = DimensionManager.getWorld(id);
|
||||
return nmsWorld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getSkyLight().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getBlockLight().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getSkyLight(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getBlockLight(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return ibd.getLightOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return ibd.getLightValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacityBrightnessPair(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return MathMan.pair16(ibd.getLightOpacity(), ibd.getLightValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightBlock(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.BLOCK, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightSky(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.SKY, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSaveFolder() {
|
||||
return new File(((WorldServer) getWorld()).getChunkSaveLocation(), "region");
|
||||
}
|
||||
}
|
|
@ -1,231 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.forge;
|
||||
|
||||
import com.boydti.fawe.forge.ForgePlayerBlockBag;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.SPacketCustomPayload;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
|
||||
public class ForgePlayer extends AbstractPlayerActor {
|
||||
|
||||
private final EntityPlayerMP player;
|
||||
|
||||
protected ForgePlayer(EntityPlayerMP player) {
|
||||
this.player = player;
|
||||
ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return player.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
ItemStack is = this.player.getHeldItem(EnumHand.MAIN_HAND);
|
||||
return is == null ? 0 : Item.getIdFromItem(is.getItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockInHand() {
|
||||
ItemStack is = this.player.getHeldItem(EnumHand.MAIN_HAND);
|
||||
return is == null ? EditSession.nullBlock : new BaseBlock(Item.getIdFromItem(is.getItem()), is.isItemStackDamageable() ? 0 : is.getItemDamage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.player.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
throw new UnsupportedOperationException("Cannot create a state from this object");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ);
|
||||
return new Location(
|
||||
ForgeWorldEdit.inst.getWorld(this.player.world),
|
||||
position,
|
||||
this.player.rotationYaw,
|
||||
this.player.rotationPitch);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public WorldVector getPosition() {
|
||||
return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.world)), this.player.posX, this.player.posY, this.player.posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sk89q.worldedit.world.World getWorld() {
|
||||
return ForgeWorldEdit.inst.getWorld(this.player.world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPitch() {
|
||||
return this.player.rotationPitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return this.player.rotationYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(int type, int amt) {
|
||||
this.player.inventory.addItemStackToInventory(new ItemStack(Item.getItemById(type), amt, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
String[] params = event.getParameters();
|
||||
String send = event.getTypeId();
|
||||
if (params.length > 0) {
|
||||
send = send + "|" + StringUtil.joinString(params, "|");
|
||||
}
|
||||
PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)));
|
||||
SPacketCustomPayload packet = new SPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer);
|
||||
this.player.connection.sendPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.sendMessage(new TextComponentString(part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
sendColorized(msg, TextFormatting.GRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
sendColorized(msg, TextFormatting.LIGHT_PURPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
sendColorized(msg, TextFormatting.RED);
|
||||
}
|
||||
|
||||
private void sendColorized(String msg, TextFormatting formatting) {
|
||||
for (String part : msg.split("\n")) {
|
||||
TextComponentString component = new TextComponentString(part);
|
||||
component.getStyle().setColor(formatting);
|
||||
this.player.sendMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||
this.player.connection.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return new ForgePlayerBlockBag(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return new SessionKeyImpl(player.getUniqueID(), player.getName());
|
||||
}
|
||||
|
||||
private static class SessionKeyImpl implements SessionKey {
|
||||
// If not static, this will leak a reference
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
private SessionKeyImpl(UUID uuid, String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
// We can't directly check if the player is online because
|
||||
// the list of players is not thread safe
|
||||
return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Class<ForgePlayer> inject() {
|
||||
return ForgePlayer.class;
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {url = "https://oss.sonatype.org/content/repositories/snapshots/"}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'forge'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
clean { delete "../target" }
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'com.sk89q.worldedit:worldedit-forge-mc1.7.10:6.1.1-20151030.011615-19'
|
||||
compile 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = 'forge'
|
||||
url = 'http://files.minecraftforge.net/maven'
|
||||
}
|
||||
}
|
||||
minecraft {
|
||||
version = "10.13.4.1614-1.7.10"
|
||||
runDir = 'run'
|
||||
}
|
||||
|
||||
project.archivesBaseName = "${project.archivesBaseName}-mc${minecraft.version}"
|
||||
|
||||
processResources {
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
expand 'version': project.version,
|
||||
'mcVersion': project.minecraft.version
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
|
||||
dependencies {
|
||||
include(dependency('com.github.luben:zstd-jni:1.1.1'))
|
||||
// include(dependency('org.javassist:javassist:3.22.0-CR1'))
|
||||
include(dependency('co.aikar:fastutil-lite:1.0'))
|
||||
include(dependency(':core'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
|
||||
destinationDir = file '../target'
|
||||
manifest {
|
||||
attributes("Main-Class": "com.boydti.fawe.installer.InstallerFrame")
|
||||
}
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
|
||||
reobf.reobf(shadowJar) { spec ->
|
||||
spec.classpath = sourceSets.main.compileClasspath;
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar)
|
|
@ -1,217 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.forge.v1710.ForgeQueue_All;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.forge.ForgeWorld;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.ModMetadata;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import net.minecraft.command.ServerCommandManager;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FaweForge implements IFawe {
|
||||
|
||||
private final ForgeMain parent;
|
||||
private final File directory;
|
||||
private final Logger logger;
|
||||
private final ModMetadata mod;
|
||||
|
||||
public FaweForge(ForgeMain plugin, Logger logger, ModMetadata mod, File directory) {
|
||||
this.parent = plugin;
|
||||
this.logger = logger;
|
||||
this.directory = directory;
|
||||
this.mod = mod;
|
||||
try {
|
||||
Fawe.set(this);
|
||||
setupInjector();
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupInjector() {
|
||||
try {
|
||||
Fawe.setupInjector();
|
||||
com.sk89q.worldedit.forge.ForgePlayer.inject();
|
||||
} catch (Throwable e) {
|
||||
Fawe.debug("Failed to inject WorldEdit classes.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String s) {
|
||||
logger.error(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnlineMode() {
|
||||
return MinecraftServer.getServer().isServerInOnlineMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return MinecraftServer.getServer().getMinecraftVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return MinecraftServer.getServer().getCurrentPlayerCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
private HashMap<String, FaweCommand> commands = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void setupCommand(String label, FaweCommand cmd) {
|
||||
this.commands.put(label, cmd);
|
||||
}
|
||||
|
||||
public void insertCommands() {
|
||||
for (Map.Entry<String, FaweCommand> entry : commands.entrySet()) {
|
||||
ServerCommandManager scm = (ServerCommandManager) FMLCommonHandler.instance().getMinecraftServerInstance().getCommandManager();
|
||||
scm.registerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
EntityPlayerMP player = null;
|
||||
if (obj instanceof String) {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
player = server.getConfigurationManager().func_152612_a((String) obj);
|
||||
} else if (obj instanceof EntityPlayerMP) {
|
||||
player = (EntityPlayerMP) obj;
|
||||
}
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getCommandSenderName());
|
||||
return existing != null ? existing : new ForgePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVault() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new ForgeTaskMan(512);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
if (world instanceof WorldWrapper) {
|
||||
return getWorldName(((WorldWrapper) world).getParent());
|
||||
}
|
||||
else if (world instanceof EditSession) {
|
||||
return getWorldName(((EditSession) world).getWorld());
|
||||
} else if (world.getClass().getName().equals("com.sk89q.worldedit.bukkit.BukkitWorld")) {
|
||||
try {
|
||||
Class<?> classBukkitWorld = world.getClass();
|
||||
Method methodGetWorld = classBukkitWorld.getDeclaredMethod("getWorld");
|
||||
methodGetWorld.setAccessible(true);
|
||||
Object craftWorld = methodGetWorld.invoke(world);
|
||||
Class<? extends Object> classCraftWorld = craftWorld.getClass();
|
||||
Method methodGetHandle = classCraftWorld.getDeclaredMethod("getHandle");
|
||||
methodGetHandle.setAccessible(true);
|
||||
Object nmsWorld = methodGetHandle.invoke(craftWorld);
|
||||
return getWorldName((net.minecraft.world.World) nmsWorld);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return world.getName();
|
||||
}
|
||||
}else if (world instanceof LocalWorldAdapter){
|
||||
return world.getName();
|
||||
}
|
||||
return getWorldName(((ForgeWorld) world).getWorld());
|
||||
}
|
||||
|
||||
public String getWorldName(net.minecraft.world.World w) {
|
||||
Integer[] ids = DimensionManager.getIDs();
|
||||
WorldServer[] worlds = DimensionManager.getWorlds();
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
if (worlds[i] == w) {
|
||||
return w.getWorldInfo().getWorldName() + ";" + ids[i];
|
||||
}
|
||||
}
|
||||
return w.getWorldInfo().getWorldName() + ";" + w.provider.dimensionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(World world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
try {
|
||||
ForgeMetrics metrics = new ForgeMetrics("FastAsyncWorldEdit", "3.5.1");
|
||||
metrics.start();
|
||||
} catch (Throwable e) {
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatform() {
|
||||
return "forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8));
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
return uuid.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBlocksHubApi() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
|
||||
public class ForgeCommand extends CommandBase {
|
||||
|
||||
private final String name;
|
||||
private final FaweCommand cmd;
|
||||
|
||||
public ForgeCommand(String name, FaweCommand cmd) {
|
||||
this.name = name;
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender iCommandSender) {
|
||||
return "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
|
||||
if ((sender instanceof EntityPlayerMP)) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) sender;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
cmd.executeSafe(fp, args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.Mod;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStartingEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
|
||||
import cpw.mods.fml.common.eventhandler.EventPriority;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.PlayerEvent;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.5.1", acceptableRemoteVersions = "*", dependencies = "before:worldedit")
|
||||
public class ForgeMain {
|
||||
private static FaweForge IMP;
|
||||
private Logger logger;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
this.logger = event.getModLog();
|
||||
File directory = new File(event.getModConfigurationDirectory() + File.separator + "FastAsyncWorldEdit");
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
this.IMP = new FaweForge(this, event.getModLog(), event.getModMetadata(), directory);
|
||||
try {
|
||||
Class.forName("org.spongepowered.api.Sponge");
|
||||
Settings.IMP.QUEUE.PARALLEL_THREADS = 1;
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverLoad(FMLServerStartingEvent event) {
|
||||
IMP.insertCommands();
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onPlayerQuit(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (event.player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
handleQuit((EntityPlayerMP) event.player);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverStopping(FMLServerStoppingEvent event) {
|
||||
for (EntityPlayerMP player : (List<EntityPlayerMP>)MinecraftServer.getServer().getConfigurationManager().playerEntityList) {
|
||||
handleQuit(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleQuit(EntityPlayerMP player) {
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
if (fp != null) {
|
||||
fp.unregister();
|
||||
}
|
||||
Fawe.get().unregister(player.getCommandSenderName());
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerChangedWorld(EntityJoinWorldEvent event) {
|
||||
Entity entity = event.entity;
|
||||
if (!(entity instanceof EntityPlayerMP)) {
|
||||
return;
|
||||
}
|
||||
EntityPlayerMP player = (EntityPlayerMP) entity;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,475 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
||||
* Ported to Minecraft Forge by Mike Primm
|
||||
* 1.7.x update by Dries007
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.object.io.PGZIPOutputStream;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
import java.io.*;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
|
||||
public class ForgeMetrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 7;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://report.mcstats.org";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/plugin/%s";
|
||||
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 15;
|
||||
|
||||
/**
|
||||
* The mod this metrics submits for
|
||||
*/
|
||||
private final String modName;
|
||||
|
||||
private final String modVersion;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final Configuration configuration;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
|
||||
private Thread thread = null;
|
||||
private boolean firstPost = true;
|
||||
int tickCount;
|
||||
|
||||
public ForgeMetrics(final String modName, final String modVersion) throws IOException {
|
||||
if (modName == null || modVersion == null) {
|
||||
throw new IllegalArgumentException("modName and modVersion cannot be null");
|
||||
}
|
||||
|
||||
this.modName = modName;
|
||||
this.modVersion = modVersion;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = new Configuration(configurationFile);
|
||||
|
||||
// Get values, and add some defaults, if needed
|
||||
configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false, "Set to true to disable all reporting");
|
||||
guid = configuration.get(Configuration.CATEGORY_GENERAL, "guid", UUID.randomUUID().toString(), "Server unique ID").getString();
|
||||
debug = configuration.get(Configuration.CATEGORY_GENERAL, "debug", false, "Set to true for verbose debug").getBoolean(false);
|
||||
configuration.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async
|
||||
* repeating task as the plugin and send the initial data to the metrics
|
||||
* backend, and then after that it will post in increments of PING_INTERVAL
|
||||
* * 1200 ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void tick(TickEvent.ServerTickEvent tick) {
|
||||
if (tick.phase != TickEvent.Phase.END) return;
|
||||
|
||||
if (tickCount++ % (PING_INTERVAL * 1200) != 0) return;
|
||||
|
||||
if (thread == null) {
|
||||
thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Disable Task, if it is running and the server owner decided
|
||||
// to opt-out
|
||||
if (isOptOut()) {
|
||||
FMLCommonHandler.instance().bus().unregister(ForgeMetrics.this);
|
||||
return;
|
||||
}
|
||||
// We use the inverse of firstPost because if it
|
||||
// is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to
|
||||
// FALSE
|
||||
// Each time thereafter it will evaluate to
|
||||
// TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
// After the first post we set firstPost to
|
||||
// false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
FMLLog.info("[Metrics] Exception - %s", e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
// Reload the metrics file
|
||||
configuration.load();
|
||||
return configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false).getBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the
|
||||
* config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("false");
|
||||
configuration.save();
|
||||
}
|
||||
// Enable Task, if it is not running
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the
|
||||
* config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("true");
|
||||
configuration.save();
|
||||
}
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data
|
||||
* such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
return new File(Loader.instance().getConfigDir(), "PluginMetrics.cfg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
String pluginName = modName;
|
||||
boolean onlineMode = MinecraftServer.getServer().isServerInOnlineMode();
|
||||
String pluginVersion = modVersion;
|
||||
String serverVersion;
|
||||
if (MinecraftServer.getServer().isDedicatedServer()) {
|
||||
serverVersion = "MinecraftForge (MC: " + MinecraftServer.getServer().getMinecraftVersion() + ")";
|
||||
} else {
|
||||
serverVersion = "MinecraftForgeSSP (MC: " + MinecraftServer.getServer().getMinecraftVersion() + ")";
|
||||
}
|
||||
int playersOnline = MinecraftServer.getServer().getCurrentPlayerCount();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
StringBuilder json = new StringBuilder(1024);
|
||||
json.append('{');
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
appendJSONPair(json, "guid", guid);
|
||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
||||
appendJSONPair(json, "server_version", serverVersion);
|
||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
appendJSONPair(json, "osname", osname);
|
||||
appendJSONPair(json, "osarch", osarch);
|
||||
appendJSONPair(json, "osversion", osversion);
|
||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
||||
appendJSONPair(json, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
appendJSONPair(json, "ping", "1");
|
||||
}
|
||||
|
||||
// close json
|
||||
json.append('}');
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
|
||||
byte[] uncompressed = json.toString().getBytes();
|
||||
byte[] compressed = gzip(json.toString());
|
||||
|
||||
// Headers
|
||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
||||
connection.addRequestProperty("Content-Type", "application/json");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(compressed);
|
||||
os.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
os.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
||||
if (response == null) {
|
||||
response = "null";
|
||||
} else if (response.startsWith("7")) {
|
||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
||||
}
|
||||
|
||||
throw new IOException(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GZip compress a string of bytes
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static byte[] gzip(String input) {
|
||||
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
|
||||
PGZIPOutputStream gzos = null;
|
||||
|
||||
try {
|
||||
gzos = new PGZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
MainUtil.handleError(e);
|
||||
} finally {
|
||||
if (gzos != null) try {
|
||||
gzos.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
||||
*
|
||||
* @return true if mineshafter is installed on the server
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a json encoded key/value pair to the given string builder.
|
||||
*
|
||||
* @param json
|
||||
* @param key
|
||||
* @param value
|
||||
* @throws java.io.UnsupportedEncodingException
|
||||
*/
|
||||
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
|
||||
boolean isValueNumeric = false;
|
||||
|
||||
try {
|
||||
if (value.equals("0") || !value.endsWith("0")) {
|
||||
Double.parseDouble(value);
|
||||
isValueNumeric = true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
isValueNumeric = false;
|
||||
}
|
||||
|
||||
if (json.charAt(json.length() - 1) != '{') {
|
||||
json.append(',');
|
||||
}
|
||||
|
||||
json.append(escapeJSON(key));
|
||||
json.append(':');
|
||||
|
||||
if (isValueNumeric) {
|
||||
json.append(value);
|
||||
} else {
|
||||
json.append(escapeJSON(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string to create a valid JSON string
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
private static String escapeJSON(String text) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append('"');
|
||||
for (int index = 0; index < text.length(); index++) {
|
||||
char chr = text.charAt(index);
|
||||
|
||||
switch (chr) {
|
||||
case '"':
|
||||
case '\\':
|
||||
builder.append('\\');
|
||||
builder.append(chr);
|
||||
break;
|
||||
case '\b':
|
||||
builder.append("\\b");
|
||||
break;
|
||||
case '\t':
|
||||
builder.append("\\t");
|
||||
break;
|
||||
case '\n':
|
||||
builder.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.append("\\r");
|
||||
break;
|
||||
default:
|
||||
if (chr < ' ') {
|
||||
String t = "000" + Integer.toHexString(chr);
|
||||
builder.append("\\u" + t.substring(t.length() - 4));
|
||||
} else {
|
||||
builder.append(chr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.append('"');
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text, as UTF-8
|
||||
*/
|
||||
private static String urlEncode(final String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.ChunkCoordinates;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
|
||||
public ForgePlayer(EntityPlayerMP parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String head, String sub) { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTitle() { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parent.getCommandSenderName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return parent.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
Object meta = getMeta(perm);
|
||||
return meta instanceof Boolean ? (boolean) meta : ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(parent, perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(String perm, boolean flag) {
|
||||
setMeta(perm, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
part = BBC.color(part);
|
||||
ChatComponentText component = new ChatComponentText(part);
|
||||
component.getChatStyle().setColor(EnumChatFormatting.LIGHT_PURPLE);
|
||||
this.parent.addChatMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(String substring) {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweLocation getLocation() {
|
||||
World world = parent.worldObj;
|
||||
ChunkCoordinates pos = parent.getPlayerCoordinates();
|
||||
return new FaweLocation(Fawe.<FaweForge>imp().getWorldName(world), pos.posX, pos.posY, pos.posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player toWorldEditPlayer() {
|
||||
return ForgeWorldEdit.inst.wrap(this.parent);
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBagException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class ForgePlayerBlockBag extends BlockBag {
|
||||
|
||||
private EntityPlayerMP player;
|
||||
private ItemStack[] items;
|
||||
private boolean changed;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public ForgePlayerBlockBag(EntityPlayerMP player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads inventory on first use.
|
||||
*/
|
||||
private void loadInventory() {
|
||||
if (items == null) {
|
||||
items = new ItemStack[player.inventory.getSizeInventory()];
|
||||
for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
|
||||
items[i] = player.inventory.getStackInSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public EntityPlayerMP getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount == 1);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't fetch air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
continue;
|
||||
}
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.stackSize;
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
if (currentAmount > 1) {
|
||||
forgeItem.stackSize--;
|
||||
found = true;
|
||||
} else {
|
||||
items[slot] = null;
|
||||
found = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new OutOfBlocksException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount <= 64);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't store air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
int freeSlot = -1;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
// Delay using up a free slot until we know there are no stacks
|
||||
// of this item to merge into
|
||||
|
||||
if (freeSlot == -1) {
|
||||
freeSlot = slot;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.stackSize;
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
if (currentAmount >= 64) {
|
||||
// Full stack
|
||||
continue;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
int spaceLeft = 64 - currentAmount;
|
||||
if (spaceLeft >= amount) {
|
||||
forgeItem.stackSize += amount;
|
||||
return;
|
||||
}
|
||||
|
||||
forgeItem.stackSize = (64);
|
||||
amount -= spaceLeft;
|
||||
}
|
||||
|
||||
if (freeSlot > -1) {
|
||||
changed = true;
|
||||
items[freeSlot] = new ItemStack(Item.getItemById(id), amount);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new OutOfSpaceException(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushChanges() {
|
||||
if (items != null && changed) {
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
player.inventory.setInventorySlotContents(i, items[i]);
|
||||
}
|
||||
items = null;
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSingleSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.EventPriority;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ForgeTaskMan extends TaskManager {
|
||||
|
||||
private final ConcurrentLinkedDeque<Runnable> syncTasks = new ConcurrentLinkedDeque<>();
|
||||
private final ConcurrentLinkedDeque<Runnable> asyncTasks = new ConcurrentLinkedDeque<>();
|
||||
|
||||
private final ConcurrentHashMap<Integer, Runnable> taskIdMap = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
|
||||
|
||||
private final AtomicInteger taskId = new AtomicInteger();
|
||||
private final ExecutorService executor;
|
||||
|
||||
public ForgeTaskMan(int size) {
|
||||
this.executor = Executors.newFixedThreadPool(size);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int repeat(final Runnable r, final int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
final int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
later(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
Fawe.get().setMainThread();
|
||||
int asyncSize = asyncTasks.size();
|
||||
for (int i = 0; i < asyncSize; i++) {
|
||||
Runnable item = asyncTasks.poll();
|
||||
if (item != null) {
|
||||
async(item);
|
||||
}
|
||||
}
|
||||
int syncSize = syncTasks.size();
|
||||
for (int i = 0; i < syncSize; i++) {
|
||||
Runnable item = syncTasks.poll();
|
||||
if (item != null) {
|
||||
try {
|
||||
item.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(final Runnable r, final int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
final int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
laterAsync(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
executor.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
syncTasks.add(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(final Runnable r, final int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
final AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(final Runnable r, final int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
final AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
async(r);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int task) {
|
||||
taskIdMap.remove(task);
|
||||
}
|
||||
}
|
|
@ -1,420 +0,0 @@
|
|||
package com.boydti.fawe.forge.v1710;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.ChunkPosition;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.NibbleArray;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
|
||||
public final byte[][] byteIds;
|
||||
public final NibbleArray[] extended;
|
||||
public final NibbleArray[] datas;
|
||||
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
this.byteIds = new byte[16][];
|
||||
this.extended = new NibbleArray[16];
|
||||
this.datas = new NibbleArray[16];
|
||||
}
|
||||
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap, byte[][] byteIds, NibbleArray[] datas, NibbleArray[] extended) {
|
||||
super(parent, x, z, ids, count, air, heightMap);
|
||||
this.byteIds = byteIds;
|
||||
this.datas = datas;
|
||||
this.extended = extended;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk copy(boolean shallow) {
|
||||
ForgeChunk_All copy;
|
||||
if (shallow) {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), ids, count, air, heightMap, byteIds, datas, extended);
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
} else {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone(), (byte[][]) MainUtil.copyNd(byteIds), datas.clone(), extended.clone());
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
copy.biomes = biomes.clone();
|
||||
copy.chunk = chunk;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getNewChunk() {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
return world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
|
||||
public byte[] getByteIdArray(int i) {
|
||||
return this.byteIds[i];
|
||||
}
|
||||
|
||||
public NibbleArray getDataArray(int i) {
|
||||
return datas[i];
|
||||
}
|
||||
|
||||
public NibbleArray getExtendedIdArray(int i) {
|
||||
return extended[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, int id) {
|
||||
setBlock(x, y, z, id, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, int id, int data) {
|
||||
int i = FaweCache.CACHE_I[y][z][x];
|
||||
int j = FaweCache.CACHE_J[y][z][x];
|
||||
byte[] vs = this.byteIds[i];
|
||||
char[] vs2 = this.ids[i];
|
||||
if (vs2 == null) {
|
||||
vs2 = this.ids[i] = new char[4096];
|
||||
}
|
||||
if (vs == null) {
|
||||
vs = this.byteIds[i] = new byte[4096];
|
||||
}
|
||||
this.count[i]++;
|
||||
switch (id) {
|
||||
case 0:
|
||||
this.air[i]++;
|
||||
vs[j] = 0;
|
||||
vs2[j] = (char) 1;
|
||||
return;
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 51:
|
||||
case 74:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 138:
|
||||
case 169:
|
||||
case 213:
|
||||
case 130:
|
||||
case 76:
|
||||
case 62:
|
||||
case 50:
|
||||
case 10:
|
||||
// this.relight[i]++;
|
||||
default:
|
||||
vs2[j] = (char) ((id << 4) + data);
|
||||
vs[j] = (byte) id;
|
||||
if (data != 0) {
|
||||
NibbleArray dataArray = datas[i];
|
||||
if (dataArray == null) {
|
||||
datas[i] = dataArray = new NibbleArray(4096, 4);
|
||||
}
|
||||
dataArray.set(x, y & 15, z, data);
|
||||
}
|
||||
if (id > 255) {
|
||||
NibbleArray nibble = extended[i];
|
||||
if (nibble == null) {
|
||||
extended[i] = nibble = new NibbleArray(4096, 4);
|
||||
}
|
||||
nibble.set(x, y & 15, z, id >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForgeChunk_All call() {
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||
net.minecraft.world.World nmsWorld = nmsChunk.worldObj;
|
||||
nmsChunk.setChunkModified();
|
||||
nmsChunk.sendUpdates = true;
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.hasNoSky;
|
||||
// Sections
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
Map<ChunkPosition, TileEntity> tiles = nmsChunk.chunkTileEntityMap;
|
||||
List<Entity>[] entities = nmsChunk.entityLists;
|
||||
|
||||
// Set heightmap
|
||||
getParent().setHeightMap(this, heightMap);
|
||||
|
||||
// Remove entities
|
||||
for (int i = 0; i < 16; i++) {
|
||||
int count = this.getCount(i);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
} else if (count >= 4096) {
|
||||
entities[i].clear();
|
||||
} else if (!getParent().getSettings().EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) {
|
||||
char[] array = this.getIdArray(i);
|
||||
if (array == null || entities[i] == null || entities[i].isEmpty()) continue;
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entity instanceof EntityPlayer) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(entity.posX) & 15);
|
||||
int z = (MathMan.roundInt(entity.posZ) & 15);
|
||||
int y = MathMan.roundInt(entity.posY);
|
||||
if (y < 0 || y > 255) continue;
|
||||
if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||
synchronized (ForgeQueue_All.class) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashSet<UUID> entsToRemove = this.getEntityRemoves();
|
||||
if (entsToRemove.size() > 0) {
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entsToRemove.contains(entity.getUniqueID())) {
|
||||
synchronized (ForgeQueue_All.class) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set entities
|
||||
Set<UUID> createdEntities = new HashSet<>();
|
||||
Set<CompoundTag> entitiesToSpawn = this.getEntities();
|
||||
for (CompoundTag nativeTag : entitiesToSpawn) {
|
||||
Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||
if (idTag == null || posTag == null || rotTag == null) {
|
||||
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||
continue;
|
||||
}
|
||||
double x = posTag.getDouble(0);
|
||||
double y = posTag.getDouble(1);
|
||||
double z = posTag.getDouble(2);
|
||||
float yaw = rotTag.getFloat(0);
|
||||
float pitch = rotTag.getFloat(1);
|
||||
String id = idTag.getValue();
|
||||
Entity entity = EntityList.createEntityByName(id, nmsWorld);
|
||||
if (entity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.removeTag("UUIDMost");
|
||||
tag.removeTag("UUIDLeast");
|
||||
entity.readFromNBT(tag);
|
||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||
synchronized (ForgeQueue_All.class) {
|
||||
nmsWorld.spawnEntityInWorld(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Run change task if applicable
|
||||
if (getParent().getChangeTask() != null) {
|
||||
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||
getParent().getChangeTask().run(previous, this);
|
||||
}
|
||||
// Trim tiles
|
||||
Set<Map.Entry<ChunkPosition, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<ChunkPosition, TileEntity>> iterator = entryset.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<ChunkPosition, TileEntity> tile = iterator.next();
|
||||
ChunkPosition pos = tile.getKey();
|
||||
int lx = pos.chunkPosX & 15;
|
||||
int ly = pos.chunkPosY;
|
||||
int lz = pos.chunkPosZ & 15;
|
||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||
char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||
if (array[k] != 0) {
|
||||
synchronized (ForgeQueue_All.class) {
|
||||
tile.getValue().invalidate();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
int count = this.getCount(j);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
}
|
||||
byte[] newIdArray = this.getByteIdArray(j);
|
||||
if (newIdArray == null) {
|
||||
continue;
|
||||
}
|
||||
int countAir = this.getAir(j);
|
||||
NibbleArray newDataArray = this.getDataArray(j);
|
||||
NibbleArray extendedArray = this.getExtendedIdArray(j);
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if ((section == null)) {
|
||||
if (count == countAir) {
|
||||
continue;
|
||||
}
|
||||
sections[j] = section = new ExtendedBlockStorage(j << 4, !getParent().getWorld().provider.hasNoSky);
|
||||
section.setBlockLSBArray(newIdArray);
|
||||
if (newDataArray != null) {
|
||||
section.setBlockMetadataArray(newDataArray);
|
||||
}
|
||||
if (extendedArray != null) {
|
||||
section.setBlockMSBArray(extendedArray);
|
||||
}
|
||||
continue;
|
||||
} else if (count >= 4096) {
|
||||
if (count == countAir) {
|
||||
sections[j] = null;
|
||||
continue;
|
||||
}
|
||||
section.setBlockLSBArray(newIdArray);
|
||||
if (newDataArray != null) {
|
||||
section.setBlockMetadataArray(newDataArray);
|
||||
} else if (section.getMetadataArray() != null) {
|
||||
Arrays.fill(section.getMetadataArray().data, (byte) 0);
|
||||
}
|
||||
if (extendedArray != null) {
|
||||
section.setBlockMSBArray(extendedArray);
|
||||
} else if (section.getBlockMSBArray() != null) {
|
||||
Arrays.fill(section.getBlockMSBArray().data, (byte) 0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
byte[] currentIdArray = section.getBlockLSBArray();
|
||||
NibbleArray currentDataArray = section.getMetadataArray();
|
||||
NibbleArray currentExtraArray = section.getBlockMSBArray();
|
||||
boolean data = currentDataArray != null && newDataArray != null;
|
||||
if (currentDataArray == null && newDataArray != null) {
|
||||
section.setBlockMetadataArray(newDataArray);
|
||||
}
|
||||
boolean extra = currentExtraArray != null && extendedArray != null;
|
||||
if (currentExtraArray == null && extendedArray != null) {
|
||||
section.setBlockMSBArray(extendedArray);
|
||||
}
|
||||
int solid = 0;
|
||||
char[] charArray = this.getIdArray(j);
|
||||
for (int k = 0; k < newIdArray.length; k++) {
|
||||
char combined = charArray[k];
|
||||
switch (combined) {
|
||||
case 0:
|
||||
if (currentIdArray[k] != 0) {
|
||||
solid++;
|
||||
}
|
||||
continue;
|
||||
case 1:
|
||||
currentIdArray[k] = 0;
|
||||
if (extra) {
|
||||
int x = FaweCache.CACHE_X[0][k];
|
||||
int y = FaweCache.CACHE_Y[0][k];
|
||||
int z = FaweCache.CACHE_Z[0][k];
|
||||
currentExtraArray.set(x, y, z, 0);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
solid++;
|
||||
currentIdArray[k] = newIdArray[k];
|
||||
if (data) {
|
||||
if (FaweCache.hasData(combined >> 4)) {
|
||||
int dataByte = FaweCache.getData(combined);
|
||||
int x = FaweCache.CACHE_X[0][k];
|
||||
int y = FaweCache.CACHE_Y[0][k];
|
||||
int z = FaweCache.CACHE_Z[0][k];
|
||||
int newData = newDataArray.get(x, y, z);
|
||||
currentDataArray.set(x, y, z, newData);
|
||||
}
|
||||
} else if (currentDataArray != null) {
|
||||
int x = FaweCache.CACHE_X[0][k];
|
||||
int y = FaweCache.CACHE_Y[0][k];
|
||||
int z = FaweCache.CACHE_Z[0][k];
|
||||
currentDataArray.set(x, y, z, 0);
|
||||
}
|
||||
int extraId = FaweCache.getId(combined) >> 8;
|
||||
if (extra && extraId != 0) {
|
||||
int x = FaweCache.CACHE_X[0][k];
|
||||
int y = FaweCache.CACHE_Y[0][k];
|
||||
int z = FaweCache.CACHE_Z[0][k];
|
||||
int newExtra = extendedArray.get(x, y, z);
|
||||
currentExtraArray.set(x, y, z, newExtra);
|
||||
} else if (currentExtraArray != null) {
|
||||
int x = FaweCache.CACHE_X[0][k];
|
||||
int y = FaweCache.CACHE_Y[0][k];
|
||||
int z = FaweCache.CACHE_Z[0][k];
|
||||
currentExtraArray.set(x, y, z, 0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
getParent().setCount(0, solid, section);
|
||||
}
|
||||
|
||||
// Set biomes
|
||||
if (this.biomes != null) {
|
||||
byte[] currentBiomes = nmsChunk.getBiomeArray();
|
||||
for (int i = 0 ; i < this.biomes.length; i++) {
|
||||
byte biome = this.biomes[i];
|
||||
if (biome != 0) {
|
||||
if (biome == -1) biome = 0;
|
||||
currentBiomes[i] = biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set tiles
|
||||
Map<Short, CompoundTag> tilesToSpawn = this.getTiles();
|
||||
int bx = this.getX() << 4;
|
||||
int bz = this.getZ() << 4;
|
||||
|
||||
for (Map.Entry<Short, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||
CompoundTag nativeTag = entry.getValue();
|
||||
short blockHash = entry.getKey();
|
||||
int x = (blockHash >> 12 & 0xF) + bx;
|
||||
int y = (blockHash & 0xFF);
|
||||
int z = (blockHash >> 8 & 0xF) + bz;
|
||||
TileEntity tileEntity = nmsWorld.getTileEntity(x, y, z);
|
||||
if (tileEntity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.setInteger("x", x);
|
||||
tag.setInteger("y", y);
|
||||
tag.setInteger("z", z);
|
||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasEntities(Chunk nmsChunk) {
|
||||
for (int i = 0; i < nmsChunk.entityLists.length; i++) {
|
||||
List slice = nmsChunk.entityLists[i];
|
||||
if (slice != null && !slice.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,585 +0,0 @@
|
|||
package com.boydti.fawe.forge.v1710;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.brush.visualization.VisualChunk;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.S21PacketChunkData;
|
||||
import net.minecraft.network.play.server.S22PacketMultiBlockChange;
|
||||
import net.minecraft.server.management.PlayerManager;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.LongHashMap;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
import net.minecraft.world.ChunkPosition;
|
||||
import net.minecraft.world.EnumSkyBlock;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.NibbleArray;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
protected static Method methodFromNative;
|
||||
protected static Method methodToNative;
|
||||
protected static ExtendedBlockStorage emptySection;
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
emptySection = new ExtendedBlockStorage(0, true);
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
|
||||
methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
|
||||
methodFromNative.setAccessible(true);
|
||||
methodToNative.setAccessible(true);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(Chunk chunk) {
|
||||
chunk.setChunkModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
|
||||
Chunk forgeChunk = (Chunk) chunk.getChunk();
|
||||
if (forgeChunk != null) {
|
||||
int[] otherMap = forgeChunk.heightMap;
|
||||
for (int i = 0; i < heightMap.length; i++) {
|
||||
int newHeight = heightMap[i] & 0xFF;
|
||||
int currentHeight = otherMap[i];
|
||||
if (newHeight > currentHeight) {
|
||||
otherMap[i] = newHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||
Map<ChunkPosition, TileEntity> tiles = chunk.chunkTileEntityMap;
|
||||
ChunkPosition pos = new ChunkPosition(x & 15, y, z & 15);
|
||||
TileEntity tile = tiles.get(pos);
|
||||
return tile != null ? getTag(tile) : null;
|
||||
}
|
||||
|
||||
public CompoundTag getTag(TileEntity tile) {
|
||||
try {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTagIntoEntity
|
||||
return (CompoundTag) methodToNative.invoke(null, tag);
|
||||
} catch (Exception e) {
|
||||
MainUtil.handleError(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getSections(Chunk chunk) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiome(Chunk chunk, int x, int z) {
|
||||
return chunk.getBiomeArray()[((z & 15) << 4) + (x & 15)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk loadChunk(World world, int x, int z, boolean generate) {
|
||||
ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider();
|
||||
if (generate) {
|
||||
return provider.originalLoadChunk(x, z);
|
||||
} else {
|
||||
return provider.loadChunk(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getCachedSections(World world, int cx, int cz) {
|
||||
Chunk chunk = (Chunk) ((ChunkProviderServer)world.getChunkProvider()).loadedChunkHashMap.getValueByKey(ChunkCoordIntPair.chunkXZ2Int(cx, cz));
|
||||
if (chunk != null) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getCachedChunk(World world, int cx, int cz) {
|
||||
return (Chunk) ((ChunkProviderServer)world.getChunkProvider()).loadedChunkHashMap.getValueByKey(ChunkCoordIntPair.chunkXZ2Int(cx, cz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage getCachedSection(ExtendedBlockStorage[] ExtendedBlockStorages, int cy) {
|
||||
return ExtendedBlockStorages[cy];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(ExtendedBlockStorage ls, int x, int y, int z) {
|
||||
byte[] ids = ls.getBlockLSBArray();
|
||||
NibbleArray currentDataArray = ls.getMetadataArray();
|
||||
NibbleArray currentExtraArray = ls.getBlockMSBArray();
|
||||
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
|
||||
int id = (ids[i] & 0xFF);
|
||||
if (currentExtraArray != null) {
|
||||
id += (currentExtraArray.get(x & 15, y & 15, z & 15)) << 8;
|
||||
}
|
||||
if (currentDataArray != null && FaweCache.hasData(id)) {
|
||||
return (id << 4) + currentDataArray.get(x & 15, y & 15, z & 15);
|
||||
} else {
|
||||
return (id << 4);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) {
|
||||
try {
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
|
||||
Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
Field u;
|
||||
try {
|
||||
u = ChunkProviderServer.class.getDeclaredField("field_73248_b"); // chunksToUnload
|
||||
} catch(NoSuchFieldException e) {
|
||||
u = ChunkProviderServer.class.getDeclaredField("chunksToUnload");
|
||||
}
|
||||
u.setAccessible(true);
|
||||
Set unloadQueue = (Set) u.get(chunkServer);
|
||||
Field m;
|
||||
try {
|
||||
m = ChunkProviderServer.class.getDeclaredField("field_73244_f"); // loadedChunkHashMap
|
||||
} catch(NoSuchFieldException e) {
|
||||
m = ChunkProviderServer.class.getDeclaredField("loadedChunkHashMap");
|
||||
}
|
||||
m.setAccessible(true);
|
||||
LongHashMap loadedMap = (LongHashMap) m.get(chunkServer);
|
||||
Field lc;
|
||||
try {
|
||||
lc = ChunkProviderServer.class.getDeclaredField("field_73245_g"); // loadedChunkHashMap
|
||||
} catch(NoSuchFieldException e) {
|
||||
lc = ChunkProviderServer.class.getDeclaredField("loadedChunks");
|
||||
}
|
||||
lc.setAccessible(true);
|
||||
@SuppressWarnings("unchecked") List loaded = (List) lc.get(chunkServer);
|
||||
Field p;
|
||||
try {
|
||||
p = ChunkProviderServer.class.getDeclaredField("field_73246_d"); // currentChunkProvider
|
||||
} catch(NoSuchFieldException e) {
|
||||
p = ChunkProviderServer.class.getDeclaredField("currentChunkProvider");
|
||||
}
|
||||
p.setAccessible(true);
|
||||
IChunkProvider chunkProvider = (IChunkProvider) p.get(chunkServer);
|
||||
long pos = ChunkCoordIntPair.chunkXZ2Int(x, z);
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
unloadQueue.remove(pos);
|
||||
loadedMap.remove(pos);
|
||||
mcChunk = chunkProvider.provideChunk(x, z);
|
||||
loadedMap.add(pos, mcChunk);
|
||||
loaded.add(mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkProvider, chunkProvider, x, z);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
MainUtil.handleError(t);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair loc) {
|
||||
Chunk chunk = getWorld().getChunkProvider().provideChunk(loc.x, loc.z);
|
||||
if (chunk != null && !chunk.isChunkLoaded) {
|
||||
chunk.onChunkLoad();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void sendChunk(int x, int z, int bitMask) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), x, z);
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, bitMask);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChunk(FaweChunk fc) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, fc.getBitMask());
|
||||
}
|
||||
}
|
||||
|
||||
public void sendChunk(Chunk nmsChunk, int mask) {
|
||||
if (!nmsChunk.isChunkLoaded) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
WorldServer w = (WorldServer) nmsChunk.worldObj;
|
||||
PlayerManager chunkMap = w.getPlayerManager();
|
||||
int x = nmsChunk.xPosition;
|
||||
int z = nmsChunk.zPosition;
|
||||
if (!chunkMap.func_152621_a(x, z)) {
|
||||
return;
|
||||
}
|
||||
HashSet<EntityPlayerMP> players = new HashSet<>();
|
||||
for (EntityPlayer player : (List<EntityPlayer>) w.playerEntities) {
|
||||
if (player instanceof EntityPlayerMP) {
|
||||
if (chunkMap.isPlayerWatchingChunk((EntityPlayerMP) player, x, z)) {
|
||||
players.add((EntityPlayerMP) player);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (players.size() == 0) {
|
||||
return;
|
||||
}
|
||||
boolean empty = false;
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == null) {
|
||||
sections[i] = emptySection;
|
||||
empty = true;
|
||||
}
|
||||
}
|
||||
if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
|
||||
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, 65280);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.playerNetServerHandler.sendPacket(packet);
|
||||
}
|
||||
mask = 255;
|
||||
}
|
||||
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, mask);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.playerNetServerHandler.sendPacket(packet);
|
||||
}
|
||||
if (empty) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == emptySection) {
|
||||
sections[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEntities(Chunk nmsChunk) {
|
||||
for (int i = 0; i < nmsChunk.entityLists.length; i++) {
|
||||
List slice = nmsChunk.entityLists[i];
|
||||
if (slice != null && !slice.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
|
||||
try {
|
||||
PlayerManager playerManager = ((WorldServer) getWorld()).getPlayerManager();
|
||||
boolean watching = false;
|
||||
boolean[] watchingArr = new boolean[players.length];
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) ((ForgePlayer) players[i]).parent;
|
||||
if (playerManager.isPlayerWatchingChunk(player, chunk.getX(), chunk.getZ())) {
|
||||
watchingArr[i] = true;
|
||||
watching = true;
|
||||
}
|
||||
}
|
||||
if (!watching) return;
|
||||
final LongAdder size = new LongAdder();
|
||||
if (chunk instanceof VisualChunk) {
|
||||
size.add(((VisualChunk) chunk).size());
|
||||
} else if (chunk instanceof CharFaweChunk) {
|
||||
size.add(((CharFaweChunk) chunk).getTotalCount());
|
||||
} else {
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
size.add(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (size.intValue() == 0) return;
|
||||
S22PacketMultiBlockChange packet = new S22PacketMultiBlockChange();
|
||||
ByteBuf byteBuf = new UnpooledByteBufAllocator(true).buffer();
|
||||
final PacketBuffer buffer = new PacketBuffer(byteBuf);
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
buffer.writeVarIntToBuffer(size.intValue());
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
short index = (short) (localX << 12 | localZ << 8 | y);
|
||||
buffer.writeShort(index);
|
||||
buffer.writeVarIntToBuffer(combined);
|
||||
}
|
||||
});
|
||||
packet.readPacketData(buffer);
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
if (watchingArr[i]) ((EntityPlayerMP) ((ForgePlayer) players[i]).parent).playerNetServerHandler.sendPacket(packet);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||
Class<? extends ExtendedBlockStorage> clazz = section.getClass();
|
||||
Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c"); // tickRefCount
|
||||
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b"); // blockRefCount
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||
Map<ChunkPosition, TileEntity> tiles = (Map<ChunkPosition, TileEntity>) tilesGeneric;
|
||||
Collection<Entity>[] entities = (Collection<Entity>[]) entitiesGeneric;
|
||||
CharFaweChunk previous = (CharFaweChunk) getFaweChunk(fs.getX(), fs.getZ());
|
||||
for (int layer = 0; layer < sections.length; layer++) {
|
||||
if (fs.getCount(layer) != 0 || all) {
|
||||
ExtendedBlockStorage section = sections[layer];
|
||||
if (section != null) {
|
||||
byte[] currentIdArray = section.getBlockLSBArray();
|
||||
NibbleArray currentDataArray = section.getMetadataArray();
|
||||
char[] array = new char[4096];
|
||||
for (int j = 0; j < currentIdArray.length; j++) {
|
||||
int x = FaweCache.CACHE_X[layer][j];
|
||||
int y = FaweCache.CACHE_Y[layer][j];
|
||||
int z = FaweCache.CACHE_Z[layer][j];
|
||||
int id = currentIdArray[j] & 0xFF;
|
||||
byte data = (byte) (currentDataArray != null ? currentDataArray.get(x, y & 15, z) : 0);
|
||||
previous.setBlock(x, y, z, id, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tiles != null) {
|
||||
for (Map.Entry<ChunkPosition, TileEntity> entry : tiles.entrySet()) {
|
||||
TileEntity tile = entry.getValue();
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTileEntityIntoTag
|
||||
ChunkPosition pos = entry.getKey();
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
previous.setTile(pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ, nativeTag);
|
||||
}
|
||||
}
|
||||
if (entities != null) {
|
||||
for (Collection<Entity> entityList : entities) {
|
||||
for (Entity ent : entityList) {
|
||||
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && createdEntities.contains(ent.getUniqueID()))) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(ent.posX) & 15);
|
||||
int z = (MathMan.roundInt(ent.posZ) & 15);
|
||||
int y = MathMan.roundInt(ent.posY);
|
||||
int i = FaweCache.CACHE_I[y][z][x];
|
||||
char[] array = fs.getIdArray(i);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int j = FaweCache.CACHE_J[y][z][x];
|
||||
if (array[j] != 0) {
|
||||
String id = EntityList.getEntityString(ent);
|
||||
if (id != null) {
|
||||
NBTTagCompound tag = ent.getEntityData(); // readEntityIntoTag
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
||||
map.put("Id", new StringTag(id));
|
||||
previous.setEntity(nativeTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk getFaweChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSectionLighting(ExtendedBlockStorage section, int layer, boolean sky) {
|
||||
if (section != null) {
|
||||
section.setBlocklightArray(new NibbleArray(4096, 4));
|
||||
if (sky) {
|
||||
section.setSkylightArray(new NibbleArray(4096, 4));
|
||||
}
|
||||
}
|
||||
return section != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSky() {
|
||||
return !nmsWorld.provider.hasNoSky;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullbright(ExtendedBlockStorage[] sections) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section != null) {
|
||||
byte[] bytes = section.getSkylightArray().data;
|
||||
Arrays.fill(bytes, (byte) 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relight(int x, int y, int z) {
|
||||
nmsWorld.func_147451_t(x, y, z);
|
||||
}
|
||||
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
if (nmsWorld != null || getWorldName() == null) {
|
||||
return nmsWorld;
|
||||
}
|
||||
String[] split = getWorldName().split(";");
|
||||
int id = Integer.parseInt(split[split.length - 1]);
|
||||
return nmsWorld = DimensionManager.getWorld(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getSkylightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getBlocklightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtSkylightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtBlocklightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
int combined = getCombinedId4Data(section, x, y, z);
|
||||
if (combined == 0) {
|
||||
return 0;
|
||||
}
|
||||
Block block = Block.getBlockById(FaweCache.getId(combined));
|
||||
return block.getLightOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
int combined = getCombinedId4Data(section, x, y, z);
|
||||
if (combined == 0) {
|
||||
return 0;
|
||||
}
|
||||
Block block = Block.getBlockById(FaweCache.getId(combined));
|
||||
return block.getLightValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacityBrightnessPair(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
int combined = getCombinedId4Data(section, x, y, z);
|
||||
if (combined == 0) {
|
||||
return 0;
|
||||
}
|
||||
Block block = Block.getBlockById(FaweCache.getId(combined));
|
||||
return MathMan.pair16(block.getLightOpacity(), block.getLightValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBlock(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
|
||||
return section.getBlockLSBArray()[i] != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightBlock(int x, int y, int z) {
|
||||
nmsWorld.updateLightByType(EnumSkyBlock.Block, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightSky(int x, int y, int z) {
|
||||
nmsWorld.updateLightByType(EnumSkyBlock.Sky, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSaveFolder() {
|
||||
return new File(((WorldServer) getWorld()).getChunkSaveLocation(), "region");
|
||||
}
|
||||
}
|
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.forge;
|
||||
|
||||
import com.boydti.fawe.forge.ForgePlayerBlockBag;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.play.server.S3FPacketCustomPayload;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
|
||||
public class ForgePlayer extends AbstractPlayerActor {
|
||||
|
||||
private final ForgePlatform platform;
|
||||
private final EntityPlayerMP player;
|
||||
|
||||
protected ForgePlayer(ForgePlatform platform, EntityPlayerMP player) {
|
||||
this.platform = platform;
|
||||
this.player = player;
|
||||
ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return player.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
ItemStack is = this.player.getCurrentEquippedItem();
|
||||
return is == null ? 0 : Item.getIdFromItem(is.getItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockInHand() {
|
||||
ItemStack is = this.player.getCurrentEquippedItem();
|
||||
return is == null ? EditSession.nullBlock : new BaseBlock(Item.getIdFromItem(is.getItem()), is.isItemStackDamageable() ? 0 : is.getItemDamage());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.player.getCommandSenderName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
throw new UnsupportedOperationException("Cannot create a state from this object");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ);
|
||||
return new Location(
|
||||
ForgeWorldEdit.inst.getWorld(this.player.worldObj),
|
||||
position,
|
||||
this.player.cameraYaw,
|
||||
this.player.cameraPitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getPosition() {
|
||||
return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sk89q.worldedit.world.World getWorld() {
|
||||
return ForgeWorldEdit.inst.getWorld(this.player.worldObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPitch() {
|
||||
return this.player.rotationPitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return this.player.rotationYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(int type, int amt) {
|
||||
this.player.inventory.addItemStackToInventory(new ItemStack(Item.getItemById(type), amt, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
String[] params = event.getParameters();
|
||||
String send = event.getTypeId();
|
||||
if (params.length > 0) {
|
||||
send = send + "|" + StringUtil.joinString(params, "|");
|
||||
}
|
||||
S3FPacketCustomPayload packet = new S3FPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, send.getBytes(WECUIPacketHandler.UTF_8_CHARSET));
|
||||
this.player.playerNetServerHandler.sendPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.addChatMessage(new ChatComponentText(part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.addChatMessage(new ChatComponentText("\u00a77" + part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.addChatMessage(new ChatComponentText("\u00a7d" + part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.addChatMessage(new ChatComponentText("\u00a7c" + part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||
this.player.playerNetServerHandler.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), pitch, yaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return new ForgePlayerBlockBag(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return new SessionKeyImpl(player.getUniqueID(), player.getCommandSenderName());
|
||||
}
|
||||
|
||||
private static class SessionKeyImpl implements SessionKey {
|
||||
// If not static, this will leak a reference
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
private SessionKeyImpl(UUID uuid, String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
// We can't directly check if the player is online because
|
||||
// the list of players is not thread safe
|
||||
return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Class<ForgePlayer> inject() {
|
||||
return ForgePlayer.class;
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
[{
|
||||
"modid": "com.boydti.fawe",
|
||||
"name": "FastAsyncWorldEdit",
|
||||
"description": "Extreme WorldEdit optimizations, no lag, low memory usage, area + tile + entity limits, block logging + rollback",
|
||||
"version": "3.5.1",
|
||||
"mcVersion": "1.7.10",
|
||||
"dependencies": [
|
||||
"WorldEdit"
|
||||
]
|
||||
}]
|
|
@ -1,95 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {url = "https://oss.sonatype.org/content/repositories/snapshots/"}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle.forge'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
clean { delete "../target" }
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'org.spongepowered:spongeapi:4.+'
|
||||
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
|
||||
}
|
||||
|
||||
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-11.15.1.1722"
|
||||
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
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
|
||||
dependencies {
|
||||
include(dependency('com.github.luben:zstd-jni:1.1.1'))
|
||||
// include(dependency('org.javassist:javassist:3.22.0-CR1'))
|
||||
include(dependency('co.aikar:fastutil-lite:1.0'))
|
||||
include(dependency(':core'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
|
||||
destinationDir = file '../target'
|
||||
manifest {
|
||||
attributes("Main-Class": "com.boydti.fawe.installer.InstallerFrame")
|
||||
}
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
|
||||
reobf {
|
||||
shadowJar {
|
||||
mappingType = 'SEARGE'
|
||||
}
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar)
|
|
@ -1,207 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.forge.v189.ForgeQueue_All;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.forge.ForgeWorld;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import net.minecraft.command.ServerCommandManager;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.ModMetadata;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FaweForge implements IFawe {
|
||||
|
||||
private final ForgeMain parent;
|
||||
private final File directory;
|
||||
private final Logger logger;
|
||||
private final ModMetadata mod;
|
||||
|
||||
public FaweForge(ForgeMain plugin, Logger logger, ModMetadata mod, File directory) {
|
||||
this.parent = plugin;
|
||||
this.logger = logger;
|
||||
this.directory = directory;
|
||||
this.mod = mod;
|
||||
try {
|
||||
Fawe.set(this);
|
||||
setupInjector();
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupInjector() {
|
||||
try {
|
||||
Fawe.setupInjector();
|
||||
com.sk89q.worldedit.forge.ForgePlayer.inject();
|
||||
} catch (Throwable e) {
|
||||
Fawe.debug("Failed to inject WorldEdit classes.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String s) {
|
||||
logger.debug(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnlineMode() {
|
||||
return MinecraftServer.getServer().isServerInOnlineMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return MinecraftServer.getServer().getMinecraftVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return MinecraftServer.getServer().getCurrentPlayerCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
private HashMap<String, FaweCommand> commands = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void setupCommand(String label, FaweCommand cmd) {
|
||||
this.commands.put(label, cmd);
|
||||
}
|
||||
|
||||
public void insertCommands() {
|
||||
for (Map.Entry<String, FaweCommand> entry : commands.entrySet()) {
|
||||
ServerCommandManager scm = (ServerCommandManager) FMLCommonHandler.instance().getMinecraftServerInstance().getCommandManager();
|
||||
scm.registerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
EntityPlayerMP player = null;
|
||||
if (obj instanceof String) {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
player = server.getConfigurationManager().getPlayerByUsername((String) obj);
|
||||
} else if (obj instanceof UUID) {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
player = server.getConfigurationManager().getPlayerByUUID((UUID) obj);
|
||||
} else if (obj instanceof EntityPlayerMP) {
|
||||
player = (EntityPlayerMP) obj;
|
||||
}
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getName());
|
||||
return existing != null ? existing : new ForgePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVault() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new com.boydti.fawe.forge.ForgeTaskMan(512);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
if (world instanceof WorldWrapper) {
|
||||
return getWorldName(((WorldWrapper) world).getParent());
|
||||
}
|
||||
else if (world instanceof EditSession) {
|
||||
return getWorldName(((EditSession) world).getWorld());
|
||||
}
|
||||
return getWorldName(((ForgeWorld) world).getWorld());
|
||||
}
|
||||
|
||||
public String getWorldName(net.minecraft.world.World w) {
|
||||
Integer[] ids = DimensionManager.getIDs();
|
||||
WorldServer[] worlds = DimensionManager.getWorlds();
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
if (worlds[i] == w) {
|
||||
return w.getWorldInfo().getWorldName() + ";" + ids[i];
|
||||
}
|
||||
}
|
||||
return w.getWorldInfo().getWorldName() + ";" + w.provider.getDimensionId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(World world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
try {
|
||||
com.boydti.fawe.forge.ForgeMetrics metrics = new com.boydti.fawe.forge.ForgeMetrics("FastAsyncWorldEdit", "3.5.1");
|
||||
metrics.start();
|
||||
} catch (Throwable e) {
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatform() {
|
||||
return "forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try {
|
||||
GameProfile profile = MinecraftServer.getServer().getPlayerProfileCache().getGameProfileForUsername(name);
|
||||
return profile.getId();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
try {
|
||||
GameProfile profile = MinecraftServer.getServer().getPlayerProfileCache().getProfileByUUID(uuid);
|
||||
return profile.getName();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBlocksHubApi() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
|
||||
public class ForgeCommand extends CommandBase {
|
||||
|
||||
private final String name;
|
||||
private final FaweCommand cmd;
|
||||
|
||||
public ForgeCommand(String name, FaweCommand cmd) {
|
||||
this.name = name;
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender iCommandSender) {
|
||||
return "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
|
||||
if ((sender instanceof EntityPlayerMP)) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) sender;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
cmd.executeSafe(fp, args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.5.1", acceptableRemoteVersions = "*", dependencies = "before:worldedit")
|
||||
public class ForgeMain {
|
||||
private static com.boydti.fawe.forge.FaweForge IMP;
|
||||
private Logger logger;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
this.logger = event.getModLog();
|
||||
File directory = new File(event.getModConfigurationDirectory() + File.separator + "FastAsyncWorldEdit");
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
this.IMP = new FaweForge(this, event.getModLog(), event.getModMetadata(), directory);
|
||||
try {
|
||||
Class.forName("org.spongepowered.api.Sponge");
|
||||
Settings.IMP.QUEUE.PARALLEL_THREADS = 1;
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverLoad(FMLServerStartingEvent event) {
|
||||
IMP.insertCommands();
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onPlayerQuit(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (event.player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
handleQuit((EntityPlayerMP) event.player);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverStopping(FMLServerStoppingEvent event) {
|
||||
for (EntityPlayerMP player : (List<EntityPlayerMP>)MinecraftServer.getServer().getConfigurationManager().playerEntityList) {
|
||||
handleQuit(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleQuit(EntityPlayerMP player) {
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
if (fp != null) {
|
||||
fp.unregister();
|
||||
}
|
||||
Fawe.get().unregister(player.getName());
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerChangedWorld(EntityJoinWorldEvent event) {
|
||||
Entity entity = event.entity;
|
||||
if (!(entity instanceof EntityPlayerMP)) {
|
||||
return;
|
||||
}
|
||||
EntityPlayerMP player = (EntityPlayerMP) entity;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,475 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
||||
* Ported to Minecraft Forge by Mike Primm
|
||||
* 1.7.x update by Dries007
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.object.io.PGZIPOutputStream;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import java.io.*;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeMetrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 7;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://report.mcstats.org";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/plugin/%s";
|
||||
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 15;
|
||||
|
||||
/**
|
||||
* The mod this metrics submits for
|
||||
*/
|
||||
private final String modName;
|
||||
|
||||
private final String modVersion;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final Configuration configuration;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
|
||||
private Thread thread = null;
|
||||
private boolean firstPost = true;
|
||||
int tickCount;
|
||||
|
||||
public ForgeMetrics(final String modName, final String modVersion) throws IOException {
|
||||
if (modName == null || modVersion == null) {
|
||||
throw new IllegalArgumentException("modName and modVersion cannot be null");
|
||||
}
|
||||
|
||||
this.modName = modName;
|
||||
this.modVersion = modVersion;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = new Configuration(configurationFile);
|
||||
|
||||
// Get values, and add some defaults, if needed
|
||||
configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false, "Set to true to disable all reporting");
|
||||
guid = configuration.get(Configuration.CATEGORY_GENERAL, "guid", UUID.randomUUID().toString(), "Server unique ID").getString();
|
||||
debug = configuration.get(Configuration.CATEGORY_GENERAL, "debug", false, "Set to true for verbose debug").getBoolean(false);
|
||||
configuration.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async
|
||||
* repeating task as the plugin and send the initial data to the metrics
|
||||
* backend, and then after that it will post in increments of PING_INTERVAL
|
||||
* * 1200 ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void tick(TickEvent.ServerTickEvent tick) {
|
||||
if (tick.phase != TickEvent.Phase.END) return;
|
||||
|
||||
if (tickCount++ % (PING_INTERVAL * 1200) != 0) return;
|
||||
|
||||
if (thread == null) {
|
||||
thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Disable Task, if it is running and the server owner decided
|
||||
// to opt-out
|
||||
if (isOptOut()) {
|
||||
FMLCommonHandler.instance().bus().unregister(ForgeMetrics.this);
|
||||
return;
|
||||
}
|
||||
// We use the inverse of firstPost because if it
|
||||
// is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to
|
||||
// FALSE
|
||||
// Each time thereafter it will evaluate to
|
||||
// TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
// After the first post we set firstPost to
|
||||
// false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
FMLLog.info("[Metrics] Exception - %s", e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
// Reload the metrics file
|
||||
configuration.load();
|
||||
return configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false).getBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the
|
||||
* config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("false");
|
||||
configuration.save();
|
||||
}
|
||||
// Enable Task, if it is not running
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the
|
||||
* config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("true");
|
||||
configuration.save();
|
||||
}
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data
|
||||
* such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
return new File(Loader.instance().getConfigDir(), "PluginMetrics.cfg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
String pluginName = modName;
|
||||
boolean onlineMode = MinecraftServer.getServer().isServerInOnlineMode();
|
||||
String pluginVersion = modVersion;
|
||||
String serverVersion;
|
||||
if (MinecraftServer.getServer().isDedicatedServer()) {
|
||||
serverVersion = "MinecraftForge (MC: " + MinecraftServer.getServer().getMinecraftVersion() + ")";
|
||||
} else {
|
||||
serverVersion = "MinecraftForgeSSP (MC: " + MinecraftServer.getServer().getMinecraftVersion() + ")";
|
||||
}
|
||||
int playersOnline = MinecraftServer.getServer().getCurrentPlayerCount();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
StringBuilder json = new StringBuilder(1024);
|
||||
json.append('{');
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
appendJSONPair(json, "guid", guid);
|
||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
||||
appendJSONPair(json, "server_version", serverVersion);
|
||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
appendJSONPair(json, "osname", osname);
|
||||
appendJSONPair(json, "osarch", osarch);
|
||||
appendJSONPair(json, "osversion", osversion);
|
||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
||||
appendJSONPair(json, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
appendJSONPair(json, "ping", "1");
|
||||
}
|
||||
|
||||
// close json
|
||||
json.append('}');
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
|
||||
byte[] uncompressed = json.toString().getBytes();
|
||||
byte[] compressed = gzip(json.toString());
|
||||
|
||||
// Headers
|
||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
||||
connection.addRequestProperty("Content-Type", "application/json");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(compressed);
|
||||
os.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
os.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
||||
if (response == null) {
|
||||
response = "null";
|
||||
} else if (response.startsWith("7")) {
|
||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
||||
}
|
||||
|
||||
throw new IOException(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GZip compress a string of bytes
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static byte[] gzip(String input) {
|
||||
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
|
||||
PGZIPOutputStream gzos = null;
|
||||
|
||||
try {
|
||||
gzos = new PGZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
MainUtil.handleError(e);
|
||||
} finally {
|
||||
if (gzos != null) try {
|
||||
gzos.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
||||
*
|
||||
* @return true if mineshafter is installed on the server
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a json encoded key/value pair to the given string builder.
|
||||
*
|
||||
* @param json
|
||||
* @param key
|
||||
* @param value
|
||||
* @throws java.io.UnsupportedEncodingException
|
||||
*/
|
||||
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
|
||||
boolean isValueNumeric = false;
|
||||
|
||||
try {
|
||||
if (value.equals("0") || !value.endsWith("0")) {
|
||||
Double.parseDouble(value);
|
||||
isValueNumeric = true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
isValueNumeric = false;
|
||||
}
|
||||
|
||||
if (json.charAt(json.length() - 1) != '{') {
|
||||
json.append(',');
|
||||
}
|
||||
|
||||
json.append(escapeJSON(key));
|
||||
json.append(':');
|
||||
|
||||
if (isValueNumeric) {
|
||||
json.append(value);
|
||||
} else {
|
||||
json.append(escapeJSON(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string to create a valid JSON string
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
private static String escapeJSON(String text) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append('"');
|
||||
for (int index = 0; index < text.length(); index++) {
|
||||
char chr = text.charAt(index);
|
||||
|
||||
switch (chr) {
|
||||
case '"':
|
||||
case '\\':
|
||||
builder.append('\\');
|
||||
builder.append(chr);
|
||||
break;
|
||||
case '\b':
|
||||
builder.append("\\b");
|
||||
break;
|
||||
case '\t':
|
||||
builder.append("\\t");
|
||||
break;
|
||||
case '\n':
|
||||
builder.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.append("\\r");
|
||||
break;
|
||||
default:
|
||||
if (chr < ' ') {
|
||||
String t = "000" + Integer.toHexString(chr);
|
||||
builder.append("\\u" + t.substring(t.length() - 4));
|
||||
} else {
|
||||
builder.append(chr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.append('"');
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text, as UTF-8
|
||||
*/
|
||||
private static String urlEncode(final String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.wrappers.PlayerWrapper;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
|
||||
public ForgePlayer(EntityPlayerMP parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String head, String sub) { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTitle() { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return parent.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
Object meta = getMeta(perm);
|
||||
return meta instanceof Boolean ? (boolean) meta : ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(parent, perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(String perm, boolean flag) {
|
||||
setMeta(perm, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
part = BBC.color(part);
|
||||
ChatComponentText component = new ChatComponentText(part);
|
||||
component.getChatStyle().setColor(EnumChatFormatting.LIGHT_PURPLE);
|
||||
this.parent.addChatMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(String substring) {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweLocation getLocation() {
|
||||
World world = parent.worldObj;
|
||||
BlockPos pos = parent.getPosition();
|
||||
return new FaweLocation(Fawe.<FaweForge>imp().getWorldName(world), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player toWorldEditPlayer() {
|
||||
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBagException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class ForgePlayerBlockBag extends BlockBag {
|
||||
|
||||
private EntityPlayerMP player;
|
||||
private ItemStack[] items;
|
||||
private boolean changed;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public ForgePlayerBlockBag(EntityPlayerMP player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads inventory on first use.
|
||||
*/
|
||||
private void loadInventory() {
|
||||
if (items == null) {
|
||||
items = new ItemStack[player.inventory.getSizeInventory()];
|
||||
for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
|
||||
items[i] = player.inventory.getStackInSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public EntityPlayerMP getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount == 1);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't fetch air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
continue;
|
||||
}
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.stackSize;
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
if (currentAmount > 1) {
|
||||
forgeItem.stackSize--;
|
||||
found = true;
|
||||
} else {
|
||||
items[slot] = null;
|
||||
found = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new OutOfBlocksException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount <= 64);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't store air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
int freeSlot = -1;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
// Delay using up a free slot until we know there are no stacks
|
||||
// of this item to merge into
|
||||
|
||||
if (freeSlot == -1) {
|
||||
freeSlot = slot;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.stackSize;
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
if (currentAmount >= 64) {
|
||||
// Full stack
|
||||
continue;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
int spaceLeft = 64 - currentAmount;
|
||||
if (spaceLeft >= amount) {
|
||||
forgeItem.stackSize += amount;
|
||||
return;
|
||||
}
|
||||
|
||||
forgeItem.stackSize = (64);
|
||||
amount -= spaceLeft;
|
||||
}
|
||||
|
||||
if (freeSlot > -1) {
|
||||
changed = true;
|
||||
items[freeSlot] = new ItemStack(Item.getItemById(id), amount);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new OutOfSpaceException(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushChanges() {
|
||||
if (items != null && changed) {
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
player.inventory.setInventorySlotContents(i, items[i]);
|
||||
}
|
||||
items = null;
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSingleSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeTaskMan extends TaskManager {
|
||||
|
||||
private final ConcurrentLinkedDeque<Runnable> syncTasks = new ConcurrentLinkedDeque<>();
|
||||
private final ConcurrentLinkedDeque<Runnable> asyncTasks = new ConcurrentLinkedDeque<>();
|
||||
|
||||
private final ConcurrentHashMap<Integer, Runnable> taskIdMap = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
|
||||
|
||||
private final AtomicInteger taskId = new AtomicInteger();
|
||||
private final ExecutorService executor;
|
||||
|
||||
public ForgeTaskMan(int size) {
|
||||
this.executor = Executors.newFixedThreadPool(size);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int repeat(final Runnable r, final int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
later(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
Fawe.get().setMainThread();
|
||||
int asyncSize = asyncTasks.size();
|
||||
for (int i = 0; i < asyncSize; i++) {
|
||||
Runnable item = asyncTasks.poll();
|
||||
if (item != null) {
|
||||
async(item);
|
||||
}
|
||||
}
|
||||
int syncSize = syncTasks.size();
|
||||
for (int i = 0; i < syncSize; i++) {
|
||||
Runnable item = syncTasks.poll();
|
||||
if (item != null) {
|
||||
try {
|
||||
item.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(Runnable r, int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
laterAsync(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
executor.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
syncTasks.add(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
async(r);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int task) {
|
||||
taskIdMap.remove(task);
|
||||
}
|
||||
}
|
|
@ -1,282 +0,0 @@
|
|||
package com.boydti.fawe.forge.v189;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
/**
|
||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||
*
|
||||
* @param parent
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
}
|
||||
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
|
||||
super(parent, x, z, ids, count, air, heightMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk copy(boolean shallow) {
|
||||
ForgeChunk_All copy;
|
||||
if (shallow) {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), ids, count, air, heightMap);
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
} else {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
copy.biomes = biomes.clone();
|
||||
copy.chunk = chunk;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getNewChunk() {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
return world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForgeChunk_All call() {
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||
int bx = this.getX() << 4;
|
||||
int bz = this.getZ() << 4;
|
||||
nmsChunk.setModified(true);
|
||||
nmsChunk.setHasEntities(true);
|
||||
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||
// Sections
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
|
||||
// Set heightmap
|
||||
getParent().setHeightMap(this, heightMap);
|
||||
|
||||
// Remove entities
|
||||
for (int i = 0; i < 16; i++) {
|
||||
int count = this.getCount(i);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
} else if (count >= 4096) {
|
||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||
} else if (!getParent().getSettings().EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) {
|
||||
char[] array = this.getIdArray(i);
|
||||
if (array == null || entities[i] == null || entities[i].isEmpty()) continue;
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entity instanceof EntityPlayer) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(entity.posX) & 15);
|
||||
int z = (MathMan.roundInt(entity.posZ) & 15);
|
||||
int y = MathMan.roundInt(entity.posY);
|
||||
if (y < 0 || y > 255) continue;
|
||||
if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashSet<UUID> entsToRemove = this.getEntityRemoves();
|
||||
if (entsToRemove.size() > 0) {
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entsToRemove.contains(entity.getUniqueID())) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set entities
|
||||
Set<UUID> createdEntities = new HashSet<>();
|
||||
Set<CompoundTag> entitiesToSpawn = this.getEntities();
|
||||
for (CompoundTag nativeTag : entitiesToSpawn) {
|
||||
Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||
if (idTag == null || posTag == null || rotTag == null) {
|
||||
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||
continue;
|
||||
}
|
||||
double x = posTag.getDouble(0);
|
||||
double y = posTag.getDouble(1);
|
||||
double z = posTag.getDouble(2);
|
||||
float yaw = rotTag.getFloat(0);
|
||||
float pitch = rotTag.getFloat(1);
|
||||
String id = idTag.getValue();
|
||||
Entity entity = EntityList.createEntityByName(id, nmsWorld);
|
||||
if (entity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.removeTag("UUIDMost");
|
||||
tag.removeTag("UUIDLeast");
|
||||
entity.readFromNBT(tag);
|
||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||
nmsWorld.spawnEntityInWorld(entity);
|
||||
}
|
||||
}
|
||||
// Run change task if applicable
|
||||
if (getParent().getChangeTask() != null) {
|
||||
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||
getParent().getChangeTask().run(previous, this);
|
||||
}
|
||||
// Trim tiles
|
||||
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||
BlockPos pos = tile.getKey();
|
||||
int lx = pos.getX() & 15;
|
||||
int ly = pos.getY();
|
||||
int lz = pos.getZ() & 15;
|
||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||
char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||
if (array[k] != 0) {
|
||||
tile.getValue().invalidate();;
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
int count = this.getCount(j);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
}
|
||||
char[] newArray = this.getIdArray(j);
|
||||
if (newArray == null) {
|
||||
continue;
|
||||
}
|
||||
int countAir = this.getAir(j);
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if ((section == null)) {
|
||||
if (count == countAir) {
|
||||
continue;
|
||||
}
|
||||
section = new ExtendedBlockStorage(j << 4, flag);
|
||||
section.setData(newArray);
|
||||
sections[j] = section;
|
||||
continue;
|
||||
} else if (count >= 4096){
|
||||
if (count == countAir) {
|
||||
sections[j] = null;
|
||||
continue;
|
||||
}
|
||||
section.setData(newArray);
|
||||
getParent().setCount(0, count - this.getAir(j), section);
|
||||
continue;
|
||||
}
|
||||
char[] currentArray = section.getData();
|
||||
boolean fill = true;
|
||||
int solid = 0;
|
||||
char existingId;
|
||||
for (int k = 0; k < newArray.length; k++) {
|
||||
char n = newArray[k];
|
||||
switch (n) {
|
||||
case 0:
|
||||
continue;
|
||||
case 1:
|
||||
existingId = currentArray[k];
|
||||
if (existingId > 1) {
|
||||
if (FaweCache.hasLight(existingId)) {
|
||||
int x = FaweCache.CACHE_X[j][k];
|
||||
int y = FaweCache.CACHE_Y[j][k];
|
||||
int z = FaweCache.CACHE_Z[j][k];
|
||||
getParent().getRelighter().addLightUpdate(bx + x, y, bz + z);
|
||||
}
|
||||
solid--;
|
||||
currentArray[k] = 0;
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
existingId = currentArray[k];
|
||||
if (existingId <= 1) {
|
||||
solid++;
|
||||
} else if (FaweCache.hasLight(existingId)) {
|
||||
int x = FaweCache.CACHE_X[j][k];
|
||||
int y = FaweCache.CACHE_Y[j][k];
|
||||
int z = FaweCache.CACHE_Z[j][k];
|
||||
getParent().getRelighter().addLightUpdate(bx + x, y, bz + z);
|
||||
}
|
||||
currentArray[k] = n;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + solid, section);
|
||||
if (fill) {
|
||||
this.setCount(j, Short.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
// Set biomes
|
||||
if (this.biomes != null) {
|
||||
byte[] currentBiomes = nmsChunk.getBiomeArray();
|
||||
for (int i = 0 ; i < this.biomes.length; i++) {
|
||||
byte biome = this.biomes[i];
|
||||
if (biome != 0) {
|
||||
if (biome == -1) biome = 0;
|
||||
currentBiomes[i] = biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set tiles
|
||||
Map<Short, CompoundTag> tilesToSpawn = this.getTiles();
|
||||
for (Map.Entry<Short, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||
CompoundTag nativeTag = entry.getValue();
|
||||
short blockHash = entry.getKey();
|
||||
int x = (blockHash >> 12 & 0xF) + bx;
|
||||
int y = (blockHash & 0xFF);
|
||||
int z = (blockHash >> 8 & 0xF) + bz;
|
||||
BlockPos pos = new BlockPos(x, y, z); // Set pos
|
||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||
if (tileEntity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.setInteger("x", pos.getX());
|
||||
tag.setInteger("y", pos.getY());
|
||||
tag.setInteger("z", pos.getZ());
|
||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,554 +0,0 @@
|
|||
package com.boydti.fawe.forge.v189;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.brush.visualization.VisualChunk;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.S21PacketChunkData;
|
||||
import net.minecraft.network.play.server.S22PacketMultiBlockChange;
|
||||
import net.minecraft.server.management.PlayerManager;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
import net.minecraft.world.EnumSkyBlock;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.NibbleArray;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
protected final static Method methodFromNative;
|
||||
protected final static Method methodToNative;
|
||||
private static final Field fieldTickingBlockCount;
|
||||
private static final Field fieldNonEmptyBlockCount;
|
||||
protected static ExtendedBlockStorage emptySection;
|
||||
|
||||
static {
|
||||
try {
|
||||
emptySection = new ExtendedBlockStorage(0, true);
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
|
||||
methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
|
||||
methodFromNative.setAccessible(true);
|
||||
methodToNative.setAccessible(true);
|
||||
fieldTickingBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76683_c");
|
||||
fieldNonEmptyBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76682_b");
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(Chunk chunk) {
|
||||
chunk.setChunkModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getSections(Chunk chunk) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiome(Chunk chunk, int x, int z) {
|
||||
return chunk.getBiomeArray()[((z & 15) << 4) + (x & 15)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk loadChunk(World world, int x, int z, boolean generate) {
|
||||
ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider();
|
||||
if (generate) {
|
||||
return provider.originalLoadChunk(x, z);
|
||||
} else {
|
||||
return provider.loadChunk(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getCachedSections(World world, int cx, int cz) {
|
||||
Chunk chunk = ((ChunkProviderServer)world.getChunkProvider()).id2ChunkMap.getValueByKey(ChunkCoordIntPair.chunkXZ2Int(cx, cz));
|
||||
if (chunk != null) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getCachedChunk(World world, int cx, int cz) {
|
||||
return ((ChunkProviderServer)world.getChunkProvider()).id2ChunkMap.getValueByKey(ChunkCoordIntPair.chunkXZ2Int(cx, cz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage getCachedSection(ExtendedBlockStorage[] ExtendedBlockStorages, int cy) {
|
||||
return ExtendedBlockStorages[cy];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
|
||||
Chunk forgeChunk = (Chunk) chunk.getChunk();
|
||||
if (forgeChunk != null) {
|
||||
int[] otherMap = forgeChunk.getHeightMap();
|
||||
for (int i = 0; i < heightMap.length; i++) {
|
||||
int newHeight = heightMap[i] & 0xFF;
|
||||
int currentHeight = otherMap[i];
|
||||
if (newHeight > currentHeight) {
|
||||
otherMap[i] = newHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
|
||||
@Override
|
||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||
Map<BlockPos, TileEntity> tiles = chunk.getTileEntityMap();
|
||||
pos.set(x, y, z);
|
||||
TileEntity tile = tiles.get(pos);
|
||||
return tile != null ? getTag(tile) : null;
|
||||
}
|
||||
|
||||
public CompoundTag getTag(TileEntity tile) {
|
||||
try {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTagIntoEntity
|
||||
return (CompoundTag) methodToNative.invoke(null, tag);
|
||||
} catch (Exception e) {
|
||||
MainUtil.handleError(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) {
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
IChunkProvider chunkProvider = chunkServer.serverChunkGenerator;
|
||||
|
||||
long pos = ChunkCoordIntPair.chunkXZ2Int(x, z);
|
||||
Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
try {
|
||||
Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b");
|
||||
droppedChunksSetField.setAccessible(true);
|
||||
Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer);
|
||||
droppedChunksSet.remove(pos);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
chunkServer.id2ChunkMap.remove(pos);
|
||||
mcChunk = chunkProvider.provideChunk(x, z);
|
||||
chunkServer.id2ChunkMap.add(pos, mcChunk);
|
||||
chunkServer.loadedChunks.add(mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkProvider, chunkProvider, x, z);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
public int getNonEmptyBlockCount(ExtendedBlockStorage section) throws IllegalAccessException {
|
||||
return (int) fieldNonEmptyBlockCount.get(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
|
||||
try {
|
||||
PlayerManager playerManager = ((WorldServer) getWorld()).getPlayerManager();
|
||||
boolean watching = false;
|
||||
boolean[] watchingArr = new boolean[players.length];
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) ((ForgePlayer) players[i]).parent;
|
||||
if (playerManager.isPlayerWatchingChunk(player, chunk.getX(), chunk.getZ())) {
|
||||
watchingArr[i] = true;
|
||||
watching = true;
|
||||
}
|
||||
}
|
||||
if (!watching) return;
|
||||
final LongAdder size = new LongAdder();
|
||||
if (chunk instanceof VisualChunk) {
|
||||
size.add(((VisualChunk) chunk).size());
|
||||
} else if (chunk instanceof CharFaweChunk) {
|
||||
size.add(((CharFaweChunk) chunk).getTotalCount());
|
||||
} else {
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
size.add(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (size.intValue() == 0) return;
|
||||
S22PacketMultiBlockChange packet = new S22PacketMultiBlockChange();
|
||||
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
|
||||
final PacketBuffer buffer = new PacketBuffer(byteBuf);
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
buffer.writeVarIntToBuffer(size.intValue());
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
short index = (short) (localX << 12 | localZ << 8 | y);
|
||||
buffer.writeShort(index);
|
||||
buffer.writeVarIntToBuffer(combined);
|
||||
}
|
||||
});
|
||||
packet.readPacketData(buffer);
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
if (watchingArr[i]) ((EntityPlayerMP) ((ForgePlayer) players[i]).parent).playerNetServerHandler.sendPacket(packet);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||
Map<BlockPos, TileEntity> tiles = (Map<BlockPos, TileEntity>) tilesGeneric;
|
||||
ClassInheritanceMultiMap<Entity>[] entities = (ClassInheritanceMultiMap<Entity>[]) entitiesGeneric;
|
||||
CharFaweChunk previous = (CharFaweChunk) getFaweChunk(fs.getX(), fs.getZ());
|
||||
char[][] idPrevious = previous.getCombinedIdArrays();
|
||||
for (int layer = 0; layer < sections.length; layer++) {
|
||||
if (fs.getCount(layer) != 0 || all) {
|
||||
ExtendedBlockStorage section = sections[layer];
|
||||
if (section != null) {
|
||||
idPrevious[layer] = section.getData().clone();
|
||||
short solid = 0;
|
||||
for (int combined : idPrevious[layer]) {
|
||||
if (combined > 1) {
|
||||
solid++;
|
||||
}
|
||||
}
|
||||
previous.count[layer] = 4096;
|
||||
previous.air[layer] = (short) (4096 - solid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tiles != null) {
|
||||
for (Map.Entry<BlockPos, TileEntity> entry : tiles.entrySet()) {
|
||||
TileEntity tile = entry.getValue();
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTileEntityIntoTag
|
||||
BlockPos pos = entry.getKey();
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
|
||||
}
|
||||
}
|
||||
if (entities != null) {
|
||||
for (Collection<Entity> entityList : entities) {
|
||||
for (Entity ent : entityList) {
|
||||
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && createdEntities.contains(ent.getUniqueID()))) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(ent.posX) & 15);
|
||||
int z = (MathMan.roundInt(ent.posZ) & 15);
|
||||
int y = MathMan.roundInt(ent.posY);
|
||||
int i = FaweCache.CACHE_I[y][z][x];
|
||||
char[] array = fs.getIdArray(i);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int j = FaweCache.CACHE_J[y][z][x];
|
||||
if (array[j] != 0) {
|
||||
String id = EntityList.getEntityString(ent);
|
||||
if (id != null) {
|
||||
NBTTagCompound tag = ent.getNBTTagCompound(); // readEntityIntoTag
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
||||
map.put("Id", new StringTag(id));
|
||||
previous.setEntity(nativeTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int x, int z, int bitMask) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), x, z);
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, bitMask);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChunk(FaweChunk fc) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, fc.getBitMask());
|
||||
}
|
||||
}
|
||||
|
||||
public void sendChunk(Chunk nmsChunk, int mask) {
|
||||
if (!nmsChunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
||||
PlayerManager chunkMap = w.getPlayerManager();
|
||||
int x = nmsChunk.xPosition;
|
||||
int z = nmsChunk.zPosition;
|
||||
if (!chunkMap.hasPlayerInstance(x, z)) {
|
||||
return;
|
||||
}
|
||||
HashSet<EntityPlayerMP> players = new HashSet<>();
|
||||
for (EntityPlayer player : w.playerEntities) {
|
||||
if (player instanceof EntityPlayerMP) {
|
||||
if (chunkMap.isPlayerWatchingChunk((EntityPlayerMP) player, x, z)) {
|
||||
players.add((EntityPlayerMP) player);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (players.size() == 0) {
|
||||
return;
|
||||
}
|
||||
boolean empty = false;
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == null) {
|
||||
sections[i] = emptySection;
|
||||
empty = true;
|
||||
}
|
||||
}
|
||||
if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
|
||||
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, 65280);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.playerNetServerHandler.sendPacket(packet);
|
||||
}
|
||||
mask = 255;
|
||||
}
|
||||
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, mask);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.playerNetServerHandler.sendPacket(packet);
|
||||
}
|
||||
if (empty) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == emptySection) {
|
||||
sections[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEntities(Chunk nmsChunk) {
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
ClassInheritanceMultiMap<Entity> slice = entities[i];
|
||||
if (slice != null && !slice.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(ExtendedBlockStorage ls, int x, int y, int z) {
|
||||
return ls.getData()[FaweCache.CACHE_J[y][z & 15][x & 15]];
|
||||
}
|
||||
|
||||
public int getId(ExtendedBlockStorage[] sections, int x, int y, int z) {
|
||||
if (x < 0 || x > 15 || z < 0 || z > 15) {
|
||||
return 1;
|
||||
}
|
||||
if (y < 0 || y > 255) {
|
||||
return 1;
|
||||
}
|
||||
int i = FaweCache.CACHE_I[y][z][x];
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
char[] array = section.getData();
|
||||
int j = FaweCache.CACHE_J[y][z][x];
|
||||
return array[j] >> 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSectionLighting(ExtendedBlockStorage section, int layer, boolean sky) {
|
||||
if (section != null) {
|
||||
section.setBlocklightArray(new NibbleArray());
|
||||
if (sky) {
|
||||
section.setSkylightArray(new NibbleArray());
|
||||
}
|
||||
}
|
||||
return section != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSky() {
|
||||
return !nmsWorld.provider.getHasNoSky();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullbright(ExtendedBlockStorage[] sections) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section != null) {
|
||||
byte[] bytes = section.getSkylightArray().getData();
|
||||
Arrays.fill(bytes, (byte) 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relight(int x, int y, int z) {
|
||||
pos.set(x, y, z);
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
if (nmsWorld != null || getWorldName() == null) {
|
||||
return nmsWorld;
|
||||
}
|
||||
String[] split = getWorldName().split(";");
|
||||
int id = Integer.parseInt(split[split.length - 1]);
|
||||
return nmsWorld = DimensionManager.getWorld(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getSkylightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getBlocklightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtSkylightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtBlocklightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
int combined = getCombinedId4Data(section, x, y, z);
|
||||
if (combined == 0) {
|
||||
return 0;
|
||||
}
|
||||
Block block = Block.getBlockById(FaweCache.getId(combined));
|
||||
return block.getLightOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
int combined = getCombinedId4Data(section, x, y, z);
|
||||
if (combined == 0) {
|
||||
return 0;
|
||||
}
|
||||
Block block = Block.getBlockById(FaweCache.getId(combined));
|
||||
return block.getLightValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacityBrightnessPair(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
int combined = getCombinedId4Data(section, x, y, z);
|
||||
if (combined == 0) {
|
||||
return 0;
|
||||
}
|
||||
Block block = Block.getBlockById(FaweCache.getId(combined));
|
||||
return MathMan.pair16(block.getLightOpacity(), block.getLightValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBlock(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
|
||||
return section.getData()[i] != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightBlock(int x, int y, int z) {
|
||||
pos.set(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.BLOCK, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightSky(int x, int y, int z) {
|
||||
pos.set(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.SKY, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSaveFolder() {
|
||||
return new File(((WorldServer) getWorld()).getChunkSaveLocation(), "region");
|
||||
}
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.forge;
|
||||
|
||||
import com.boydti.fawe.forge.ForgePlayerBlockBag;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.S3FPacketCustomPayload;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
public class ForgePlayer extends AbstractPlayerActor {
|
||||
|
||||
private final ForgePlatform platform;
|
||||
private final EntityPlayerMP player;
|
||||
|
||||
protected ForgePlayer(ForgePlatform platform, EntityPlayerMP player) {
|
||||
this.platform = platform;
|
||||
this.player = player;
|
||||
ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return player.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
ItemStack is = this.player.getCurrentEquippedItem();
|
||||
return is == null ? 0 : Item.getIdFromItem(is.getItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockInHand() {
|
||||
ItemStack is = this.player.getCurrentEquippedItem();
|
||||
return is == null ? EditSession.nullBlock : new BaseBlock(Item.getIdFromItem(is.getItem()), is.isItemStackDamageable() ? 0 : is.getItemDamage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.player.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
throw new UnsupportedOperationException("Cannot create a state from this object");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ);
|
||||
return new Location(
|
||||
ForgeWorldEdit.inst.getWorld(this.player.worldObj),
|
||||
position,
|
||||
this.player.rotationYaw,
|
||||
this.player.rotationPitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getPosition() {
|
||||
return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sk89q.worldedit.world.World getWorld() {
|
||||
return ForgeWorldEdit.inst.getWorld(this.player.worldObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPitch() {
|
||||
return this.player.rotationPitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return this.player.rotationYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(int type, int amt) {
|
||||
this.player.inventory.addItemStackToInventory(new ItemStack(Item.getItemById(type), amt, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
String[] params = event.getParameters();
|
||||
String send = event.getTypeId();
|
||||
if (params.length > 0) {
|
||||
send = send + "|" + StringUtil.joinString(params, "|");
|
||||
}
|
||||
PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)));
|
||||
S3FPacketCustomPayload packet = new S3FPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer);
|
||||
this.player.playerNetServerHandler.sendPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.addChatMessage(new ChatComponentText(part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
sendColorized(msg, EnumChatFormatting.GRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
sendColorized(msg, EnumChatFormatting.LIGHT_PURPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
sendColorized(msg, EnumChatFormatting.RED);
|
||||
}
|
||||
|
||||
private void sendColorized(String msg, EnumChatFormatting formatting) {
|
||||
for (String part : msg.split("\n")) {
|
||||
ChatComponentText component = new ChatComponentText(part);
|
||||
component.getChatStyle().setColor(formatting);
|
||||
this.player.addChatMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||
this.player.playerNetServerHandler.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return new ForgePlayerBlockBag(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return new SessionKeyImpl(player.getUniqueID(), player.getName());
|
||||
}
|
||||
|
||||
private static class SessionKeyImpl implements SessionKey {
|
||||
// If not static, this will leak a reference
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
private SessionKeyImpl(UUID uuid, String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
// We can't directly check if the player is online because
|
||||
// the list of players is not thread safe
|
||||
return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Class<ForgePlayer> inject() {
|
||||
return ForgePlayer.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {url = "https://oss.sonatype.org/content/repositories/snapshots/"}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle.forge'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
clean { delete "../target" }
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
|
||||
}
|
||||
|
||||
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.9.4-12.17.0.2051"
|
||||
mappings = "stable_26"
|
||||
runDir = 'run'
|
||||
}
|
||||
|
||||
project.archivesBaseName = "${project.archivesBaseName}-mc${minecraft.version}"
|
||||
|
||||
processResources {
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
expand 'version': project.version,
|
||||
'mcVersion': project.minecraft.version
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
|
||||
dependencies {
|
||||
include(dependency('com.github.luben:zstd-jni:1.1.1'))
|
||||
// include(dependency('org.javassist:javassist:3.22.0-CR1'))
|
||||
include(dependency('co.aikar:fastutil-lite:1.0'))
|
||||
include(dependency(':core'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
|
||||
destinationDir = file '../target'
|
||||
manifest {
|
||||
attributes("Main-Class": "com.boydti.fawe.installer.InstallerFrame")
|
||||
}
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
|
||||
reobf {
|
||||
shadowJar {
|
||||
mappingType = 'SEARGE'
|
||||
}
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
}
|
|
@ -1,198 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.forge.v194.ForgeQueue_All;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.forge.ForgeWorld;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import net.minecraft.command.ServerCommandManager;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.ModMetadata;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FaweForge implements IFawe {
|
||||
|
||||
private final ForgeMain parent;
|
||||
private final File directory;
|
||||
private final Logger logger;
|
||||
private final ModMetadata mod;
|
||||
|
||||
public FaweForge(ForgeMain plugin, Logger logger, ModMetadata mod, File directory) {
|
||||
this.parent = plugin;
|
||||
this.logger = logger;
|
||||
this.directory = directory;
|
||||
this.mod = mod;
|
||||
try {
|
||||
Fawe.set(this);
|
||||
setupInjector();
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupInjector() {
|
||||
try {
|
||||
Fawe.setupInjector();
|
||||
com.sk89q.worldedit.forge.ForgePlayer.inject();
|
||||
} catch (Throwable e) {
|
||||
Fawe.debug("Failed to inject WorldEdit classes.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String s) {
|
||||
logger.debug(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnlineMode() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().isServerInOnlineMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().getMinecraftVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance().getCurrentPlayerCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
private HashMap<String, FaweCommand> commands = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void setupCommand(String label, FaweCommand cmd) {
|
||||
this.commands.put(label, cmd);
|
||||
}
|
||||
|
||||
public void insertCommands() {
|
||||
for (Map.Entry<String, FaweCommand> entry : commands.entrySet()) {
|
||||
ServerCommandManager scm = (ServerCommandManager) FMLCommonHandler.instance().getMinecraftServerInstance().getCommandManager();
|
||||
scm.registerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
EntityPlayerMP player = null;
|
||||
if (obj instanceof String) {
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
player = server.getPlayerList().getPlayerByUsername((String) obj);
|
||||
} else if (obj instanceof UUID) {
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
player = server.getPlayerList().getPlayerByUUID((UUID) obj);
|
||||
} else if (obj instanceof EntityPlayerMP) {
|
||||
player = (EntityPlayerMP) obj;
|
||||
}
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getName());
|
||||
return existing != null ? existing : new ForgePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVault() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new com.boydti.fawe.forge.ForgeTaskMan(512);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
if (world instanceof WorldWrapper) {
|
||||
return getWorldName(((WorldWrapper) world).getParent());
|
||||
}
|
||||
else if (world instanceof EditSession) {
|
||||
return getWorldName(((EditSession) world).getWorld());
|
||||
}
|
||||
return getWorldName(((ForgeWorld) world).getWorld());
|
||||
}
|
||||
|
||||
public String getWorldName(net.minecraft.world.World w) {
|
||||
return w.getWorldInfo().getWorldName() + ";" + w.provider.getDimension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(World world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
try {
|
||||
com.boydti.fawe.forge.ForgeMetrics metrics = new com.boydti.fawe.forge.ForgeMetrics("FastAsyncWorldEdit", "3.5.1");
|
||||
metrics.start();
|
||||
} catch (Throwable e) {
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatform() {
|
||||
return "forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try {
|
||||
GameProfile profile = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerProfileCache().getGameProfileForUsername(name);
|
||||
return profile.getId();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
try {
|
||||
GameProfile profile = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerProfileCache().getProfileByUUID(uuid);
|
||||
return profile.getName();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBlocksHubApi() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class ForgeCommand extends CommandBase {
|
||||
|
||||
private final String name;
|
||||
private final FaweCommand cmd;
|
||||
|
||||
public ForgeCommand(String name, FaweCommand cmd) {
|
||||
this.name = name;
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender iCommandSender) {
|
||||
return "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(MinecraftServer minecraftServer, ICommandSender sender, String[] args) throws CommandException {
|
||||
if ((sender instanceof EntityPlayerMP)) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) sender;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
cmd.executeSafe(fp, args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.5.1", acceptableRemoteVersions = "*", dependencies = "before:worldedit")
|
||||
public class ForgeMain {
|
||||
private static com.boydti.fawe.forge.FaweForge IMP;
|
||||
private Logger logger;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
this.logger = event.getModLog();
|
||||
File directory = new File(event.getModConfigurationDirectory() + File.separator + "FastAsyncWorldEdit");
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
this.IMP = new FaweForge(this, event.getModLog(), event.getModMetadata(), directory);
|
||||
try {
|
||||
Class.forName("org.spongepowered.api.Sponge");
|
||||
Settings.IMP.QUEUE.PARALLEL_THREADS = 1;
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverLoad(FMLServerStartingEvent event) {
|
||||
IMP.insertCommands();
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onPlayerQuit(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (event.player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
handleQuit((EntityPlayerMP) event.player);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverStopping(FMLServerStoppingEvent event) {
|
||||
for (EntityPlayerMP player : (List<EntityPlayerMP>)FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayerList()) {
|
||||
handleQuit(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleQuit(EntityPlayerMP player) {
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
if (fp != null) {
|
||||
fp.unregister();
|
||||
}
|
||||
Fawe.get().unregister(player.getName());
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerChangedWorld(EntityJoinWorldEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof EntityPlayerMP)) {
|
||||
return;
|
||||
}
|
||||
EntityPlayerMP player = (EntityPlayerMP) entity;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,476 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
||||
* Ported to Minecraft Forge by Mike Primm
|
||||
* 1.7.x update by Dries007
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.object.io.PGZIPOutputStream;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import java.io.*;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeMetrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 7;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://report.mcstats.org";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/plugin/%s";
|
||||
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 15;
|
||||
|
||||
/**
|
||||
* The mod this metrics submits for
|
||||
*/
|
||||
private final String modName;
|
||||
|
||||
private final String modVersion;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final Configuration configuration;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
|
||||
private Thread thread = null;
|
||||
private boolean firstPost = true;
|
||||
int tickCount;
|
||||
|
||||
public ForgeMetrics(final String modName, final String modVersion) throws IOException {
|
||||
if (modName == null || modVersion == null) {
|
||||
throw new IllegalArgumentException("modName and modVersion cannot be null");
|
||||
}
|
||||
|
||||
this.modName = modName;
|
||||
this.modVersion = modVersion;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = new Configuration(configurationFile);
|
||||
|
||||
// Get values, and add some defaults, if needed
|
||||
configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false, "Set to true to disable all reporting");
|
||||
guid = configuration.get(Configuration.CATEGORY_GENERAL, "guid", UUID.randomUUID().toString(), "Server unique ID").getString();
|
||||
debug = configuration.get(Configuration.CATEGORY_GENERAL, "debug", false, "Set to true for verbose debug").getBoolean(false);
|
||||
configuration.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async
|
||||
* repeating task as the plugin and send the initial data to the metrics
|
||||
* backend, and then after that it will post in increments of PING_INTERVAL
|
||||
* * 1200 ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void tick(TickEvent.ServerTickEvent tick) {
|
||||
if (tick.phase != TickEvent.Phase.END) return;
|
||||
|
||||
if (tickCount++ % (PING_INTERVAL * 1200) != 0) return;
|
||||
|
||||
if (thread == null) {
|
||||
thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Disable Task, if it is running and the server owner decided
|
||||
// to opt-out
|
||||
if (isOptOut()) {
|
||||
FMLCommonHandler.instance().bus().unregister(ForgeMetrics.this);
|
||||
return;
|
||||
}
|
||||
// We use the inverse of firstPost because if it
|
||||
// is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to
|
||||
// FALSE
|
||||
// Each time thereafter it will evaluate to
|
||||
// TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
// After the first post we set firstPost to
|
||||
// false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
FMLLog.info("[Metrics] Exception - %s", e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
// Reload the metrics file
|
||||
configuration.load();
|
||||
return configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false).getBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the
|
||||
* config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("false");
|
||||
configuration.save();
|
||||
}
|
||||
// Enable Task, if it is not running
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the
|
||||
* config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("true");
|
||||
configuration.save();
|
||||
}
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data
|
||||
* such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
return new File(Loader.instance().getConfigDir(), "PluginMetrics.cfg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
String pluginName = modName;
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
boolean onlineMode = server.isServerInOnlineMode();
|
||||
String pluginVersion = modVersion;
|
||||
String serverVersion;
|
||||
if (server.isDedicatedServer()) {
|
||||
serverVersion = "MinecraftForge (MC: " + server.getMinecraftVersion() + ")";
|
||||
} else {
|
||||
serverVersion = "MinecraftForgeSSP (MC: " + server.getMinecraftVersion() + ")";
|
||||
}
|
||||
int playersOnline = server.getCurrentPlayerCount();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
StringBuilder json = new StringBuilder(1024);
|
||||
json.append('{');
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
appendJSONPair(json, "guid", guid);
|
||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
||||
appendJSONPair(json, "server_version", serverVersion);
|
||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
appendJSONPair(json, "osname", osname);
|
||||
appendJSONPair(json, "osarch", osarch);
|
||||
appendJSONPair(json, "osversion", osversion);
|
||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
||||
appendJSONPair(json, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
appendJSONPair(json, "ping", "1");
|
||||
}
|
||||
|
||||
// close json
|
||||
json.append('}');
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
|
||||
byte[] uncompressed = json.toString().getBytes();
|
||||
byte[] compressed = gzip(json.toString());
|
||||
|
||||
// Headers
|
||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
||||
connection.addRequestProperty("Content-Type", "application/json");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(compressed);
|
||||
os.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
os.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
||||
if (response == null) {
|
||||
response = "null";
|
||||
} else if (response.startsWith("7")) {
|
||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
||||
}
|
||||
|
||||
throw new IOException(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GZip compress a string of bytes
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static byte[] gzip(String input) {
|
||||
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
|
||||
PGZIPOutputStream gzos = null;
|
||||
|
||||
try {
|
||||
gzos = new PGZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
MainUtil.handleError(e);
|
||||
} finally {
|
||||
if (gzos != null) try {
|
||||
gzos.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
||||
*
|
||||
* @return true if mineshafter is installed on the server
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a json encoded key/value pair to the given string builder.
|
||||
*
|
||||
* @param json
|
||||
* @param key
|
||||
* @param value
|
||||
* @throws java.io.UnsupportedEncodingException
|
||||
*/
|
||||
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
|
||||
boolean isValueNumeric = false;
|
||||
|
||||
try {
|
||||
if (value.equals("0") || !value.endsWith("0")) {
|
||||
Double.parseDouble(value);
|
||||
isValueNumeric = true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
isValueNumeric = false;
|
||||
}
|
||||
|
||||
if (json.charAt(json.length() - 1) != '{') {
|
||||
json.append(',');
|
||||
}
|
||||
|
||||
json.append(escapeJSON(key));
|
||||
json.append(':');
|
||||
|
||||
if (isValueNumeric) {
|
||||
json.append(value);
|
||||
} else {
|
||||
json.append(escapeJSON(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string to create a valid JSON string
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
private static String escapeJSON(String text) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append('"');
|
||||
for (int index = 0; index < text.length(); index++) {
|
||||
char chr = text.charAt(index);
|
||||
|
||||
switch (chr) {
|
||||
case '"':
|
||||
case '\\':
|
||||
builder.append('\\');
|
||||
builder.append(chr);
|
||||
break;
|
||||
case '\b':
|
||||
builder.append("\\b");
|
||||
break;
|
||||
case '\t':
|
||||
builder.append("\\t");
|
||||
break;
|
||||
case '\n':
|
||||
builder.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.append("\\r");
|
||||
break;
|
||||
default:
|
||||
if (chr < ' ') {
|
||||
String t = "000" + Integer.toHexString(chr);
|
||||
builder.append("\\u" + t.substring(t.length() - 4));
|
||||
} else {
|
||||
builder.append(chr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.append('"');
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text, as UTF-8
|
||||
*/
|
||||
private static String urlEncode(final String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.wrappers.PlayerWrapper;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextComponentBase;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
|
||||
public ForgePlayer(EntityPlayerMP parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String head, String sub) { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTitle() { // Not supported
|
||||
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return parent.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
Object meta = getMeta(perm);
|
||||
return meta instanceof Boolean ? (boolean) meta : ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(parent, perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(String perm, boolean flag) {
|
||||
setMeta(perm, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
part = BBC.color(part);
|
||||
TextComponentBase text = new TextComponentString(part);
|
||||
this.parent.addChatMessage(text);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(String substring) {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweLocation getLocation() {
|
||||
World world = parent.worldObj;
|
||||
BlockPos pos = parent.getPosition();
|
||||
return new FaweLocation(Fawe.<FaweForge>imp().getWorldName(world), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player toWorldEditPlayer() {
|
||||
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBagException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class ForgePlayerBlockBag extends BlockBag {
|
||||
|
||||
private EntityPlayerMP player;
|
||||
private ItemStack[] items;
|
||||
private boolean changed;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public ForgePlayerBlockBag(EntityPlayerMP player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads inventory on first use.
|
||||
*/
|
||||
private void loadInventory() {
|
||||
if (items == null) {
|
||||
items = new ItemStack[player.inventory.getSizeInventory()];
|
||||
for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
|
||||
items[i] = player.inventory.getStackInSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public EntityPlayerMP getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount == 1);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't fetch air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
continue;
|
||||
}
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.stackSize;
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
if (currentAmount > 1) {
|
||||
forgeItem.stackSize--;
|
||||
found = true;
|
||||
} else {
|
||||
items[slot] = null;
|
||||
found = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new OutOfBlocksException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount <= 64);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't store air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
int freeSlot = -1;
|
||||
|
||||
for (int slot = 0; slot < items.length; ++slot) {
|
||||
ItemStack forgeItem = items[slot];
|
||||
|
||||
if (forgeItem == null) {
|
||||
// Delay using up a free slot until we know there are no stacks
|
||||
// of this item to merge into
|
||||
|
||||
if (freeSlot == -1) {
|
||||
freeSlot = slot;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int itemId = Item.getIdFromItem(forgeItem.getItem());
|
||||
if (itemId != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && forgeItem.getItemDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentAmount = forgeItem.stackSize;
|
||||
if (currentAmount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
if (currentAmount >= 64) {
|
||||
// Full stack
|
||||
continue;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
int spaceLeft = 64 - currentAmount;
|
||||
if (spaceLeft >= amount) {
|
||||
forgeItem.stackSize += amount;
|
||||
return;
|
||||
}
|
||||
|
||||
forgeItem.stackSize = (64);
|
||||
amount -= spaceLeft;
|
||||
}
|
||||
|
||||
if (freeSlot > -1) {
|
||||
changed = true;
|
||||
items[freeSlot] = new ItemStack(Item.getItemById(id), amount);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new OutOfSpaceException(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushChanges() {
|
||||
if (items != null && changed) {
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
player.inventory.setInventorySlotContents(i, items[i]);
|
||||
}
|
||||
items = null;
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSingleSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeTaskMan extends TaskManager {
|
||||
|
||||
private final ConcurrentLinkedDeque<Runnable> syncTasks = new ConcurrentLinkedDeque<>();
|
||||
private final ConcurrentLinkedDeque<Runnable> asyncTasks = new ConcurrentLinkedDeque<>();
|
||||
|
||||
private final ConcurrentHashMap<Integer, Runnable> taskIdMap = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
|
||||
|
||||
private final AtomicInteger taskId = new AtomicInteger();
|
||||
private final ExecutorService executor;
|
||||
|
||||
public ForgeTaskMan(int size) {
|
||||
this.executor = Executors.newFixedThreadPool(size);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int repeat(final Runnable r, final int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
later(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
Fawe.get().setMainThread();
|
||||
int asyncSize = asyncTasks.size();
|
||||
for (int i = 0; i < asyncSize; i++) {
|
||||
Runnable item = asyncTasks.poll();
|
||||
if (item != null) {
|
||||
async(item);
|
||||
}
|
||||
}
|
||||
int syncSize = syncTasks.size();
|
||||
for (int i = 0; i < syncSize; i++) {
|
||||
Runnable item = syncTasks.poll();
|
||||
if (item != null) {
|
||||
try {
|
||||
item.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(Runnable r, int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
laterAsync(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
executor.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
syncTasks.add(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(Runnable r, int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
async(r);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int task) {
|
||||
taskIdMap.remove(task);
|
||||
}
|
||||
}
|
|
@ -1,366 +0,0 @@
|
|||
package com.boydti.fawe.forge.v194;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BitArray;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IBlockStatePalette;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
|
||||
public BlockStateContainer[] sectionPalettes;
|
||||
|
||||
/**
|
||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||
*
|
||||
* @param parent
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
}
|
||||
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
|
||||
super(parent, x, z, ids, count, air, heightMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk copy(boolean shallow) {
|
||||
ForgeChunk_All copy;
|
||||
if (shallow) {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), ids, count, air, heightMap);
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
} else {
|
||||
copy = new ForgeChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
copy.biomes = biomes.clone();
|
||||
copy.chunk = chunk;
|
||||
}
|
||||
if (sectionPalettes != null) {
|
||||
copy.sectionPalettes = new BlockStateContainer[16];
|
||||
try {
|
||||
Field fieldBits = BlockStateContainer.class.getDeclaredField("field_186021_b");
|
||||
fieldBits.setAccessible(true);
|
||||
Field fieldPalette = BlockStateContainer.class.getDeclaredField("field_186022_c");
|
||||
fieldPalette.setAccessible(true);
|
||||
Field fieldSize = BlockStateContainer.class.getDeclaredField("field_186024_e");
|
||||
fieldSize.setAccessible(true);
|
||||
for (int i = 0; i < sectionPalettes.length; i++) {
|
||||
BlockStateContainer current = sectionPalettes[i];
|
||||
if (current == null) {
|
||||
continue;
|
||||
}
|
||||
// Clone palette
|
||||
IBlockStatePalette currentPalette = (IBlockStatePalette) fieldPalette.get(current);
|
||||
if (!(currentPalette instanceof BlockStatePaletteRegistry)) {
|
||||
current.onResize(128, null);
|
||||
}
|
||||
BlockStateContainer paletteBlock = new BlockStateContainer();
|
||||
currentPalette = (IBlockStatePalette) fieldPalette.get(current);
|
||||
if (!(currentPalette instanceof BlockStatePaletteRegistry)) {
|
||||
throw new RuntimeException("Palette must be global!");
|
||||
}
|
||||
fieldPalette.set(paletteBlock, currentPalette);
|
||||
// Clone size
|
||||
fieldSize.set(paletteBlock, fieldSize.get(current));
|
||||
// Clone palette
|
||||
BitArray currentBits = (BitArray) fieldBits.get(current);
|
||||
BitArray newBits = new BitArray(1, 0);
|
||||
for (Field field : BitArray.class.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
Object currentValue = field.get(currentBits);
|
||||
if (currentValue instanceof long[]) {
|
||||
currentValue = ((long[]) currentValue).clone();
|
||||
}
|
||||
field.set(newBits, currentValue);
|
||||
}
|
||||
fieldBits.set(paletteBlock, newBits);
|
||||
copy.sectionPalettes[i] = paletteBlock;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getNewChunk() {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
return world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
if (sectionPalettes != null) {
|
||||
return;
|
||||
}
|
||||
char[][] arrays = getCombinedIdArrays();
|
||||
char lastChar = Character.MAX_VALUE;
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
if (getCount(layer) > 0) {
|
||||
if (sectionPalettes == null) {
|
||||
sectionPalettes = new BlockStateContainer[16];
|
||||
}
|
||||
BlockStateContainer palette = new BlockStateContainer();
|
||||
char[] blocks = getIdArray(layer);
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
char combinedId = blocks[FaweCache.CACHE_J[y][z][x]];
|
||||
if (combinedId > 1) {
|
||||
palette.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForgeChunk_All call() {
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||
int bx = this.getX() << 4;
|
||||
int bz = this.getZ() << 4;
|
||||
nmsChunk.setModified(true);
|
||||
net.minecraft.world.World nmsWorld = getParent().getWorld();
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||
// Sections
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
|
||||
// Set heightmap
|
||||
getParent().setHeightMap(this, heightMap);
|
||||
|
||||
// Remove entities
|
||||
for (int i = 0; i < 16; i++) {
|
||||
int count = this.getCount(i);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
} else if (count >= 4096) {
|
||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||
} else if (!getParent().getSettings().EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) {
|
||||
char[] array = this.getIdArray(i);
|
||||
if (array == null || entities[i] == null || entities[i].isEmpty()) continue;
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entity instanceof EntityPlayer) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(entity.posX) & 15);
|
||||
int z = (MathMan.roundInt(entity.posZ) & 15);
|
||||
int y = MathMan.roundInt(entity.posY);
|
||||
if (y < 0 || y > 255) continue;
|
||||
if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashSet<UUID> entsToRemove = this.getEntityRemoves();
|
||||
if (entsToRemove.size() > 0) {
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
if (entsToRemove.contains(entity.getUniqueID())) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set entities
|
||||
Set<UUID> createdEntities = new HashSet<>();
|
||||
Set<CompoundTag> entitiesToSpawn = this.getEntities();
|
||||
for (CompoundTag nativeTag : entitiesToSpawn) {
|
||||
Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||
if (idTag == null || posTag == null || rotTag == null) {
|
||||
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||
continue;
|
||||
}
|
||||
double x = posTag.getDouble(0);
|
||||
double y = posTag.getDouble(1);
|
||||
double z = posTag.getDouble(2);
|
||||
float yaw = rotTag.getFloat(0);
|
||||
float pitch = rotTag.getFloat(1);
|
||||
String id = idTag.getValue();
|
||||
Entity entity = EntityList.createEntityByName(id, nmsWorld);
|
||||
if (entity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.removeTag("UUIDMost");
|
||||
tag.removeTag("UUIDLeast");
|
||||
entity.readFromNBT(tag);
|
||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||
nmsWorld.spawnEntityInWorld(entity);
|
||||
}
|
||||
}
|
||||
// Run change task if applicable
|
||||
if (getParent().getChangeTask() != null) {
|
||||
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||
getParent().getChangeTask().run(previous, this);
|
||||
}
|
||||
// Trim tiles
|
||||
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||
BlockPos pos = tile.getKey();
|
||||
int lx = pos.getX() & 15;
|
||||
int ly = pos.getY();
|
||||
int lz = pos.getZ() & 15;
|
||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||
char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||
if (array[k] != 0) {
|
||||
tile.getValue().invalidate();;
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
int count = this.getCount(j);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
}
|
||||
final char[] array = this.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int countAir = this.getAir(j);
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if (section == null) {
|
||||
if (count == countAir) {
|
||||
continue;
|
||||
}
|
||||
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||
section = sections[j] = new ExtendedBlockStorage(j << 4, flag);
|
||||
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||
getParent().setCount(0, count - this.getAir(j), section);
|
||||
continue;
|
||||
} else {
|
||||
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
||||
}
|
||||
} else if (count >= 4096) {
|
||||
if (count == countAir) {
|
||||
sections[j] = null;
|
||||
continue;
|
||||
}
|
||||
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||
getParent().setCount(0, count - this.getAir(j), section);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
IBlockState existing;
|
||||
int by = j << 4;
|
||||
BlockStateContainer nibble = section.getData();
|
||||
int nonEmptyBlockCount = 0;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
||||
switch (combinedId) {
|
||||
case 0:
|
||||
continue;
|
||||
case 1:
|
||||
existing = nibble.get(x, y, z);
|
||||
if (existing != ForgeQueue_All.air) {
|
||||
if (existing.getLightValue() > 0) {
|
||||
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
|
||||
}
|
||||
nonEmptyBlockCount--;
|
||||
}
|
||||
nibble.set(x, y, z, ForgeQueue_All.air);
|
||||
continue;
|
||||
default:
|
||||
existing = nibble.get(x, y, z);
|
||||
if (existing != ForgeQueue_All.air) {
|
||||
if (existing.getLightValue() > 0) {
|
||||
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
|
||||
}
|
||||
} else {
|
||||
nonEmptyBlockCount++;
|
||||
}
|
||||
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
|
||||
}
|
||||
// Set biomes
|
||||
if (this.biomes != null) {
|
||||
byte[] currentBiomes = nmsChunk.getBiomeArray();
|
||||
for (int i = 0 ; i < this.biomes.length; i++) {
|
||||
byte biome = this.biomes[i];
|
||||
if (biome != 0) {
|
||||
if (biome == -1) biome = 0;
|
||||
currentBiomes[i] = biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set tiles
|
||||
Map<Short, CompoundTag> tilesToSpawn = this.getTiles();
|
||||
|
||||
for (Map.Entry<Short, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||
CompoundTag nativeTag = entry.getValue();
|
||||
short blockHash = entry.getKey();
|
||||
int x = (blockHash >> 12 & 0xF) + bx;
|
||||
int y = (blockHash & 0xFF);
|
||||
int z = (blockHash >> 8 & 0xF) + bz;
|
||||
BlockPos pos = new BlockPos(x, y, z); // Set pos
|
||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||
if (tileEntity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||
tag.setInteger("x", pos.getX());
|
||||
tag.setInteger("y", pos.getY());
|
||||
tag.setInteger("z", pos.getZ());
|
||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
sectionPalettes = null;
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,576 +0,0 @@
|
|||
package com.boydti.fawe.forge.v194;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.brush.visualization.VisualChunk;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.SPacketChunkData;
|
||||
import net.minecraft.network.play.server.SPacketMultiBlockChange;
|
||||
import net.minecraft.server.management.PlayerChunkMap;
|
||||
import net.minecraft.server.management.PlayerChunkMapEntry;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.EnumSkyBlock;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkGenerator;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.NibbleArray;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
protected final static Method methodFromNative;
|
||||
protected final static Method methodToNative;
|
||||
protected final static Field fieldTickingBlockCount;
|
||||
protected final static Field fieldNonEmptyBlockCount;
|
||||
protected static ExtendedBlockStorage emptySection;
|
||||
|
||||
static {
|
||||
try {
|
||||
emptySection = new ExtendedBlockStorage(0, true);
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
|
||||
methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
|
||||
methodFromNative.setAccessible(true);
|
||||
methodToNative.setAccessible(true);
|
||||
|
||||
fieldTickingBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76683_c");
|
||||
fieldNonEmptyBlockCount = ExtendedBlockStorage.class.getDeclaredField("field_76682_b");
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(Chunk chunk) {
|
||||
chunk.setChunkModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getSections(Chunk chunk) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiome(Chunk chunk, int x, int z) {
|
||||
return chunk.getBiomeArray()[((z & 15) << 4) + (x & 15)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk loadChunk(World world, int x, int z, boolean generate) {
|
||||
ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider();
|
||||
if (generate) {
|
||||
return provider.provideChunk(x, z);
|
||||
} else {
|
||||
return provider.loadChunk(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getCachedSections(World world, int cx, int cz) {
|
||||
Chunk chunk = world.getChunkProvider().getLoadedChunk(cx, cz);
|
||||
if (chunk != null) {
|
||||
return chunk.getBlockStorageArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getCachedChunk(World world, int cx, int cz) {
|
||||
return world.getChunkProvider().getLoadedChunk(cx, cz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage getCachedSection(ExtendedBlockStorage[] ExtendedBlockStorages, int cy) {
|
||||
return ExtendedBlockStorages[cy];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
|
||||
Chunk forgeChunk = (Chunk) chunk.getChunk();
|
||||
if (forgeChunk != null) {
|
||||
int[] otherMap = forgeChunk.getHeightMap();
|
||||
for (int i = 0; i < heightMap.length; i++) {
|
||||
int newHeight = heightMap[i] & 0xFF;
|
||||
int currentHeight = otherMap[i];
|
||||
if (newHeight > currentHeight) {
|
||||
otherMap[i] = newHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
|
||||
@Override
|
||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||
Map<BlockPos, TileEntity> tiles = chunk.getTileEntityMap();
|
||||
pos.setPos(x, y, z);
|
||||
TileEntity tile = tiles.get(pos);
|
||||
return tile != null ? getTag(tile) : null;
|
||||
}
|
||||
|
||||
public CompoundTag getTag(TileEntity tile) {
|
||||
try {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTagIntoEntity
|
||||
CompoundTag result = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
MainUtil.handleError(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) {
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
IChunkGenerator gen = chunkServer.chunkGenerator;
|
||||
long pos = ChunkPos.chunkXZ2Int(x, z);
|
||||
Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
|
||||
List<EntityPlayerMP> oldWatchers = null;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
PlayerChunkMapEntry entry = playerManager.getEntry(x, z);
|
||||
if (entry != null) {
|
||||
Field fieldPlayers = PlayerChunkMapEntry.class.getDeclaredField("field_187283_c");
|
||||
fieldPlayers.setAccessible(true);
|
||||
oldWatchers = (List<EntityPlayerMP>) fieldPlayers.get(entry);
|
||||
playerManager.removeEntry(entry);
|
||||
}
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
try {
|
||||
Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b");
|
||||
droppedChunksSetField.setAccessible(true);
|
||||
Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer);
|
||||
droppedChunksSet.remove(pos);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
chunkServer.id2ChunkMap.remove(pos);
|
||||
mcChunk = gen.provideChunk(x, z);
|
||||
chunkServer.id2ChunkMap.put(pos, mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkServer, chunkServer.chunkGenerator);
|
||||
}
|
||||
if (oldWatchers != null) {
|
||||
for (EntityPlayerMP player : oldWatchers) {
|
||||
playerManager.addPlayer(player);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
MainUtil.handleError(t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
IBlockState ibd = section.getData().get(x & 15, y & 15, z & 15);
|
||||
Block block = ibd.getBlock();
|
||||
int id = Block.getIdFromBlock(block);
|
||||
if (FaweCache.hasData(id)) {
|
||||
return (id << 4) + block.getMetaFromState(ibd);
|
||||
} else {
|
||||
return id << 4;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNonEmptyBlockCount(ExtendedBlockStorage section) throws IllegalAccessException {
|
||||
return (int) fieldNonEmptyBlockCount.get(section);
|
||||
}
|
||||
|
||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
|
||||
try {
|
||||
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
|
||||
boolean watching = false;
|
||||
boolean[] watchingArr = new boolean[players.length];
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) ((ForgePlayer) players[i]).parent;
|
||||
if (playerManager.isPlayerWatchingChunk(player, chunk.getX(), chunk.getZ())) {
|
||||
watchingArr[i] = true;
|
||||
watching = true;
|
||||
}
|
||||
}
|
||||
if (!watching) return;
|
||||
final LongAdder size = new LongAdder();
|
||||
if (chunk instanceof VisualChunk) {
|
||||
size.add(((VisualChunk) chunk).size());
|
||||
} else if (chunk instanceof CharFaweChunk) {
|
||||
size.add(((CharFaweChunk) chunk).getTotalCount());
|
||||
} else {
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
size.add(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (size.intValue() == 0) return;
|
||||
SPacketMultiBlockChange packet = new SPacketMultiBlockChange();
|
||||
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
|
||||
final PacketBuffer buffer = new PacketBuffer(byteBuf);
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
buffer.writeVarIntToBuffer(size.intValue());
|
||||
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
||||
@Override
|
||||
public void run(int localX, int y, int localZ, int combined) {
|
||||
short index = (short) (localX << 12 | localZ << 8 | y);
|
||||
buffer.writeShort(index);
|
||||
buffer.writeVarIntToBuffer(combined);
|
||||
}
|
||||
});
|
||||
packet.readPacketData(buffer);
|
||||
for (int i = 0; i < players.length; i++) {
|
||||
if (watchingArr[i]) ((EntityPlayerMP) ((ForgePlayer) players[i]).parent).connection.sendPacket(packet);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||
Map<BlockPos, TileEntity> tiles = (Map<BlockPos, TileEntity>) tilesGeneric;
|
||||
ClassInheritanceMultiMap<Entity>[] entities = (ClassInheritanceMultiMap<Entity>[]) entitiesGeneric;
|
||||
CharFaweChunk previous = (CharFaweChunk) getFaweChunk(fs.getX(), fs.getZ());
|
||||
char[][] idPrevious = previous.getCombinedIdArrays();
|
||||
for (int layer = 0; layer < sections.length; layer++) {
|
||||
if (fs.getCount(layer) != 0 || all) {
|
||||
ExtendedBlockStorage section = sections[layer];
|
||||
if (section != null) {
|
||||
short solid = 0;
|
||||
char[] previousLayer = idPrevious[layer] = new char[4096];
|
||||
BlockStateContainer blocks = section.getData();
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int x = FaweCache.CACHE_X[0][j];
|
||||
int y = FaweCache.CACHE_Y[0][j];
|
||||
int z = FaweCache.CACHE_Z[0][j];
|
||||
IBlockState ibd = blocks.get(x, y, z);
|
||||
Block block = ibd.getBlock();
|
||||
int combined = Block.getIdFromBlock(block);
|
||||
if (FaweCache.hasData(combined)) {
|
||||
combined = (combined << 4) + block.getMetaFromState(ibd);
|
||||
} else {
|
||||
combined = combined << 4;
|
||||
}
|
||||
if (combined > 1) {
|
||||
solid++;
|
||||
}
|
||||
previousLayer[j] = (char) combined;
|
||||
}
|
||||
previous.count[layer] = solid;
|
||||
previous.air[layer] = (short) (4096 - solid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tiles != null) {
|
||||
for (Map.Entry<BlockPos, TileEntity> entry : tiles.entrySet()) {
|
||||
TileEntity tile = entry.getValue();
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.writeToNBT(tag); // readTileEntityIntoTag
|
||||
BlockPos pos = entry.getKey();
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
|
||||
}
|
||||
}
|
||||
if (entities != null) {
|
||||
for (Collection<Entity> entityList : entities) {
|
||||
for (Entity ent : entityList) {
|
||||
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && createdEntities.contains(ent.getUniqueID()))) {
|
||||
continue;
|
||||
}
|
||||
int x = (MathMan.roundInt(ent.posX) & 15);
|
||||
int z = (MathMan.roundInt(ent.posZ) & 15);
|
||||
int y = MathMan.roundInt(ent.posY);
|
||||
int i = FaweCache.CACHE_I[y][z][x];
|
||||
char[] array = fs.getIdArray(i);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int j = FaweCache.CACHE_J[y][z][x];
|
||||
if (array[j] != 0) {
|
||||
String id = EntityList.getEntityString(ent);
|
||||
if (id != null) {
|
||||
NBTTagCompound tag = ent.getEntityData(); // readEntityIntoTag
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
|
||||
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
||||
map.put("Id", new StringTag(id));
|
||||
previous.setEntity(nativeTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
protected final static IBlockState air = Blocks.AIR.getDefaultState();
|
||||
|
||||
@Override
|
||||
public void sendChunk(int x, int z, int bitMask) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), x, z);
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, bitMask);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChunk(FaweChunk fc) {
|
||||
Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
|
||||
if (chunk != null) {
|
||||
sendChunk(chunk, fc.getBitMask());
|
||||
}
|
||||
}
|
||||
|
||||
public void sendChunk(Chunk nmsChunk, int mask) {
|
||||
if (!nmsChunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ChunkPos pos = nmsChunk.getChunkCoordIntPair();
|
||||
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
||||
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
||||
int x = pos.chunkXPos;
|
||||
int z = pos.chunkZPos;
|
||||
PlayerChunkMapEntry chunkMapEntry = chunkMap.getEntry(x, z);
|
||||
if (chunkMapEntry == null) {
|
||||
return;
|
||||
}
|
||||
final ArrayDeque<EntityPlayerMP> players = new ArrayDeque<>();
|
||||
chunkMapEntry.hasPlayerMatching(input -> {
|
||||
players.add(input);
|
||||
return false;
|
||||
});
|
||||
boolean empty = false;
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == null) {
|
||||
sections[i] = emptySection;
|
||||
empty = true;
|
||||
}
|
||||
}
|
||||
if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
|
||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65280);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.connection.sendPacket(packet);
|
||||
}
|
||||
mask = 255;
|
||||
}
|
||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, mask);
|
||||
for (EntityPlayerMP player : players) {
|
||||
player.connection.sendPacket(packet);
|
||||
}
|
||||
if (empty) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == emptySection) {
|
||||
sections[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEntities(Chunk nmsChunk) {
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
for (int i = 0; i < entities.length; i++) {
|
||||
ClassInheritanceMultiMap<Entity> slice = entities[i];
|
||||
if (slice != null && !slice.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSectionLighting(ExtendedBlockStorage section, int layer, boolean sky) {
|
||||
if (section != null) {
|
||||
section.setBlocklightArray(new NibbleArray());
|
||||
if (sky) {
|
||||
section.setSkylightArray(new NibbleArray());
|
||||
}
|
||||
}
|
||||
return section != null;
|
||||
}
|
||||
|
||||
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
||||
fieldSection.setAccessible(true);
|
||||
fieldSection.set(section, palette);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSky() {
|
||||
return !nmsWorld.provider.getHasNoSky();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullbright(ExtendedBlockStorage[] sections) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section != null) {
|
||||
byte[] bytes = section.getSkylightArray().getData();
|
||||
Arrays.fill(bytes, (byte) 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relight(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
if (nmsWorld != null || getWorldName() == null) {
|
||||
return nmsWorld;
|
||||
}
|
||||
String[] split = getWorldName().split(";");
|
||||
int id = Integer.parseInt(split[split.length - 1]);
|
||||
nmsWorld = DimensionManager.getWorld(id);
|
||||
return nmsWorld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getSkylightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockLight(ExtendedBlockStorage section, int x, int y, int z, int value) {
|
||||
section.getBlocklightArray().set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtSkylightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
return section.getExtBlocklightValue(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return ibd.getLightOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return ibd.getLightValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacityBrightnessPair(ExtendedBlockStorage section, int x, int y, int z) {
|
||||
BlockStateContainer dataPalette = section.getData();
|
||||
IBlockState ibd = dataPalette.get(x & 15, y & 15, z & 15);
|
||||
return MathMan.pair16(ibd.getLightOpacity(), ibd.getLightValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightBlock(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.BLOCK, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relightSky(int x, int y, int z) {
|
||||
pos.setPos(x, y, z);
|
||||
nmsWorld.checkLightFor(EnumSkyBlock.SKY, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSaveFolder() {
|
||||
return new File(((WorldServer) getWorld()).getChunkSaveLocation(), "region");
|
||||
}
|
||||
}
|
|
@ -1,236 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.forge;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.forge.ForgePlayerBlockBag;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.SPacketCustomPayload;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
|
||||
public class ForgePlayer extends AbstractPlayerActor {
|
||||
|
||||
private final ForgePlatform platform;
|
||||
private final EntityPlayerMP player;
|
||||
|
||||
protected ForgePlayer(ForgePlatform platform, EntityPlayerMP player) {
|
||||
this.platform = platform;
|
||||
this.player = player;
|
||||
ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return player.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
ItemStack is = this.player.getHeldItem(EnumHand.MAIN_HAND);
|
||||
return is == null ? 0 : Item.getIdFromItem(is.getItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockInHand() {
|
||||
ItemStack is = this.player.getHeldItem(EnumHand.MAIN_HAND);
|
||||
return is == null ? EditSession.nullBlock : new BaseBlock(Item.getIdFromItem(is.getItem()), is.isItemStackDamageable() ? 0 : is.getItemDamage());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.player.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
throw new UnsupportedOperationException("Cannot create a state from this object");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ);
|
||||
return new Location(
|
||||
ForgeWorldEdit.inst.getWorld(this.player.worldObj),
|
||||
position,
|
||||
this.player.rotationYaw,
|
||||
this.player.rotationPitch);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public WorldVector getPosition() {
|
||||
return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sk89q.worldedit.world.World getWorld() {
|
||||
return ForgeWorldEdit.inst.getWorld(this.player.worldObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPitch() {
|
||||
return this.player.rotationPitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return this.player.rotationYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(int type, int amt) {
|
||||
this.player.inventory.addItemStackToInventory(new ItemStack(Item.getItemById(type), amt, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
String[] params = event.getParameters();
|
||||
String send = event.getTypeId();
|
||||
if (params.length > 0) {
|
||||
send = send + "|" + StringUtil.joinString(params, "|");
|
||||
}
|
||||
PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)));
|
||||
SPacketCustomPayload packet = new SPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer);
|
||||
this.player.connection.sendPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.addChatMessage(new TextComponentString(part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
sendColorized(msg, TextFormatting.GRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
sendColorized(msg, TextFormatting.LIGHT_PURPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
sendColorized(msg, TextFormatting.RED);
|
||||
}
|
||||
|
||||
private void sendColorized(String msg, TextFormatting formatting) {
|
||||
for (String part : msg.split("\n")) {
|
||||
TextComponentString component = new TextComponentString(part);
|
||||
component.getStyle().setColor(formatting);
|
||||
this.player.addChatMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||
this.player.connection.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return new ForgePlayerBlockBag(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return new SessionKeyImpl(player.getUniqueID(), player.getName());
|
||||
}
|
||||
|
||||
private static class SessionKeyImpl implements SessionKey {
|
||||
// If not static, this will leak a reference
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
private SessionKeyImpl(UUID uuid, String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
// We can't directly check if the player is online because
|
||||
// the list of players is not thread safe
|
||||
return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Class<ForgePlayer> inject() {
|
||||
return ForgePlayer.class;
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
repositories {
|
||||
flatDir {dirs 'lib'}
|
||||
// maven {url "https://repo.potestas.xyz/main/"}
|
||||
}
|
||||
|
||||
clean { delete "../target" }
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
// compile 'cn.nukkit:nukkit:1.0-SNAPSHOT'
|
||||
compile name: 'nukkit-1.0-SNAPSHOT'
|
||||
compile name: 'worldedit-core-6.1.4-SNAPSHOT-dist'
|
||||
}
|
||||
|
||||
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('com.github.luben:zstd-jni:1.1.1'))
|
||||
// include(dependency('org.javassist:javassist:3.22.0-CR1'))
|
||||
include(dependency('co.aikar:fastutil-lite:1.0'))
|
||||
include(dependency(name: 'worldedit-core-6.1.4-SNAPSHOT-dist'))
|
||||
include(dependency('com.google.code.gson:gson:2.2.4'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
include(dependency('com.google.guava:guava:17.0'))
|
||||
include(dependency(':core'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
|
||||
destinationDir = file '../target'
|
||||
manifest {
|
||||
attributes("Main-Class": "com.boydti.fawe.nukkit.core.converter.ConverterFrame")
|
||||
}
|
||||
|
||||
relocate('com.google.gson', 'com.sk89q.worldedit.internal.gson')
|
||||
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
|
||||
relocate 'com.google.common', 'com.sk89q.worldedit.internal.common'
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar);
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,41 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
|
||||
public class CommandInfo {
|
||||
|
||||
private final String[] aliases;
|
||||
private final String usage, desc;
|
||||
private final String[] permissions;
|
||||
|
||||
public CommandInfo(String usage, String desc, String[] aliases) {
|
||||
this(usage, desc, aliases, null);
|
||||
}
|
||||
|
||||
public CommandInfo(String usage, String desc, String[] aliases, String[] permissions) {
|
||||
this.usage = usage;
|
||||
this.desc = desc;
|
||||
this.aliases = aliases;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public String[] getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return aliases[0];
|
||||
}
|
||||
|
||||
public String getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public String[] getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.command.Command;
|
||||
import cn.nukkit.command.CommandExecutor;
|
||||
import cn.nukkit.command.CommandSender;
|
||||
import cn.nukkit.command.PluginIdentifiableCommand;
|
||||
import cn.nukkit.plugin.Plugin;
|
||||
import com.sk89q.util.StringUtil;
|
||||
|
||||
/**
|
||||
* An implementation of a dynamically registered {@link org.bukkit.command.Command} attached to a plugin
|
||||
*/
|
||||
public class DynamicPluginCommand extends Command implements PluginIdentifiableCommand {
|
||||
|
||||
protected final CommandExecutor owner;
|
||||
private final Plugin plugin;
|
||||
protected String[] permissions = new String[0];
|
||||
|
||||
public DynamicPluginCommand(String[] aliases, String desc, String usage, CommandExecutor owner, Plugin plugin) {
|
||||
super(aliases[0], desc, usage, aliases);
|
||||
this.owner = owner;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String label, String[] args) {
|
||||
return owner.onCommand(sender, this, label, args);
|
||||
}
|
||||
|
||||
public Object getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setPermissions(String[] permissions) {
|
||||
this.permissions = permissions;
|
||||
if (permissions != null) {
|
||||
super.setPermission(StringUtil.joinString(permissions, ";"));
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermissionSilent(CommandSender sender) {
|
||||
return super.testPermissionSilent(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
}
|
|
@ -1,280 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
|
||||
import com.sk89q.jnbt.ByteArrayTag;
|
||||
import com.sk89q.jnbt.ByteTag;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.DoubleTag;
|
||||
import com.sk89q.jnbt.EndTag;
|
||||
import com.sk89q.jnbt.FloatTag;
|
||||
import com.sk89q.jnbt.IntArrayTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.LongTag;
|
||||
import com.sk89q.jnbt.ShortTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* Converts between Jcn.nukkit.nbt.tag. and Minecraft cn.nukkit.nbt.tag. classes.
|
||||
*/
|
||||
public final class NBTConverter {
|
||||
|
||||
private static Field tagsField;
|
||||
|
||||
private NBTConverter() {
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
tagsField = cn.nukkit.nbt.tag.CompoundTag.class.getDeclaredField("tags");
|
||||
tagsField.setAccessible(true);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, cn.nukkit.nbt.tag.Tag> getMap(cn.nukkit.nbt.tag.CompoundTag other) {
|
||||
try {
|
||||
return (Map<String, cn.nukkit.nbt.tag.Tag>) tagsField.get(other);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static CompoundTag fromNativeLazy(cn.nukkit.nbt.tag.CompoundTag other) {
|
||||
try {
|
||||
Map tags = (Map) tagsField.get(other);
|
||||
CompoundTag ct = new CompoundTag(tags);
|
||||
return ct;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static cn.nukkit.nbt.tag.CompoundTag toNativeLazy(CompoundTag tag) {
|
||||
try {
|
||||
Map map = tag.getValue();
|
||||
cn.nukkit.nbt.tag.CompoundTag ct = new cn.nukkit.nbt.tag.CompoundTag();
|
||||
tagsField.set(ct, map);
|
||||
return ct;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static CompoundTag fromNative(cn.nukkit.nbt.tag.CompoundTag other) {
|
||||
Map<String, cn.nukkit.nbt.tag.Tag> tags = other.getTags();
|
||||
Map<String, Tag> map = new HashMap<String, Tag>();
|
||||
for (Entry<String, cn.nukkit.nbt.tag.Tag> entry : tags.entrySet()) {
|
||||
map.put(entry.getKey(), fromNative(entry.getValue()));
|
||||
}
|
||||
CompoundTag tag = new CompoundTag(map);
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static cn.nukkit.nbt.tag.Tag toNative(Tag tag) {
|
||||
if (tag instanceof IntArrayTag) {
|
||||
return toNative((IntArrayTag) tag);
|
||||
|
||||
} else if (tag instanceof ListTag) {
|
||||
return toNative((ListTag) tag);
|
||||
|
||||
} else if (tag instanceof LongTag) {
|
||||
return toNative((LongTag) tag);
|
||||
|
||||
} else if (tag instanceof StringTag) {
|
||||
return toNative((StringTag) tag);
|
||||
|
||||
} else if (tag instanceof IntTag) {
|
||||
return toNative((IntTag) tag);
|
||||
|
||||
} else if (tag instanceof ByteTag) {
|
||||
return toNative((ByteTag) tag);
|
||||
|
||||
} else if (tag instanceof ByteArrayTag) {
|
||||
return toNative((ByteArrayTag) tag);
|
||||
|
||||
} else if (tag instanceof CompoundTag) {
|
||||
return toNative((CompoundTag) tag);
|
||||
|
||||
} else if (tag instanceof FloatTag) {
|
||||
return toNative((FloatTag) tag);
|
||||
|
||||
} else if (tag instanceof ShortTag) {
|
||||
return toNative((ShortTag) tag);
|
||||
|
||||
} else if (tag instanceof DoubleTag) {
|
||||
return toNative((DoubleTag) tag);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can't convert tag of type " + tag.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.IntArrayTag toNative(IntArrayTag tag) {
|
||||
int[] value = tag.getValue();
|
||||
return new cn.nukkit.nbt.tag.IntArrayTag("", Arrays.copyOf(value, value.length));
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.ListTag toNative(ListTag tag) {
|
||||
cn.nukkit.nbt.tag.ListTag list = new cn.nukkit.nbt.tag.ListTag();
|
||||
for (Tag child : (List<? extends Tag>) tag.getValue()) {
|
||||
if (child instanceof EndTag) {
|
||||
continue;
|
||||
}
|
||||
list.add(toNative(child));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.LongTag toNative(LongTag tag) {
|
||||
return new cn.nukkit.nbt.tag.LongTag("", tag.getValue());
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.StringTag toNative(StringTag tag) {
|
||||
return new cn.nukkit.nbt.tag.StringTag("", tag.getValue());
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.IntTag toNative(IntTag tag) {
|
||||
return new cn.nukkit.nbt.tag.IntTag("", tag.getValue());
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.ByteTag toNative(ByteTag tag) {
|
||||
return new cn.nukkit.nbt.tag.ByteTag("", tag.getValue());
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.ByteArrayTag toNative(ByteArrayTag tag) {
|
||||
byte[] value = tag.getValue();
|
||||
return new cn.nukkit.nbt.tag.ByteArrayTag("", Arrays.copyOf(value, value.length));
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.CompoundTag toNative(CompoundTag tag) {
|
||||
cn.nukkit.nbt.tag.CompoundTag compound = new cn.nukkit.nbt.tag.CompoundTag();
|
||||
for (Entry<String, Tag> child : tag.getValue().entrySet()) {
|
||||
cn.nukkit.nbt.tag.Tag value = toNative(child.getValue());
|
||||
value.setName(child.getKey());
|
||||
compound.put(child.getKey(), value);
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.FloatTag toNative(FloatTag tag) {
|
||||
return new cn.nukkit.nbt.tag.FloatTag("", tag.getValue());
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.ShortTag toNative(ShortTag tag) {
|
||||
return new cn.nukkit.nbt.tag.ShortTag("", tag.getValue());
|
||||
}
|
||||
|
||||
private static cn.nukkit.nbt.tag.DoubleTag toNative(DoubleTag tag) {
|
||||
return new cn.nukkit.nbt.tag.DoubleTag("", tag.getValue());
|
||||
}
|
||||
|
||||
private static Tag fromNative(cn.nukkit.nbt.tag.Tag other) {
|
||||
if (other instanceof cn.nukkit.nbt.tag.IntArrayTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.IntArrayTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.ListTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.ListTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.EndTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.EndTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.LongTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.LongTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.StringTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.StringTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.IntTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.IntTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.ByteTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.ByteTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.ByteArrayTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.ByteArrayTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.CompoundTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.CompoundTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.FloatTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.FloatTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.ShortTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.ShortTag) other);
|
||||
|
||||
} else if (other instanceof cn.nukkit.nbt.tag.DoubleTag) {
|
||||
return fromNative((cn.nukkit.nbt.tag.DoubleTag) other);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can't convert other of type " + other.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
private static IntArrayTag fromNative(cn.nukkit.nbt.tag.IntArrayTag other) {
|
||||
int[] value = other.data;
|
||||
return new IntArrayTag(Arrays.copyOf(value, value.length));
|
||||
}
|
||||
|
||||
private static ListTag fromNative(cn.nukkit.nbt.tag.ListTag other) {
|
||||
other = (cn.nukkit.nbt.tag.ListTag) other.copy();
|
||||
List<Tag> list = new ArrayList<Tag>();
|
||||
Class<? extends Tag> listClass = StringTag.class;
|
||||
int tags = other.size();
|
||||
for (int i = 0; i < tags; i++) {
|
||||
Tag child = fromNative(other.get(0));
|
||||
other.remove(0);
|
||||
list.add(child);
|
||||
listClass = child.getClass();
|
||||
}
|
||||
return new ListTag(listClass, list);
|
||||
}
|
||||
|
||||
private static EndTag fromNative(cn.nukkit.nbt.tag.EndTag other) {
|
||||
return new EndTag();
|
||||
}
|
||||
|
||||
private static LongTag fromNative(cn.nukkit.nbt.tag.LongTag other) {
|
||||
return new LongTag(other.data);
|
||||
}
|
||||
|
||||
private static StringTag fromNative(cn.nukkit.nbt.tag.StringTag other) {
|
||||
return new StringTag(other.data);
|
||||
}
|
||||
|
||||
private static IntTag fromNative(cn.nukkit.nbt.tag.IntTag other) {
|
||||
return new IntTag(other.data);
|
||||
}
|
||||
|
||||
private static ByteTag fromNative(cn.nukkit.nbt.tag.ByteTag other) {
|
||||
return new ByteTag((byte) other.data);
|
||||
}
|
||||
|
||||
private static ByteArrayTag fromNative(cn.nukkit.nbt.tag.ByteArrayTag other) {
|
||||
byte[] value = other.data;
|
||||
return new ByteArrayTag(Arrays.copyOf(value, value.length));
|
||||
}
|
||||
|
||||
private static FloatTag fromNative(cn.nukkit.nbt.tag.FloatTag other) {
|
||||
return new FloatTag(other.data);
|
||||
}
|
||||
|
||||
private static ShortTag fromNative(cn.nukkit.nbt.tag.ShortTag other) {
|
||||
return new ShortTag((short) other.data);
|
||||
}
|
||||
|
||||
private static DoubleTag fromNative(cn.nukkit.nbt.tag.DoubleTag other) {
|
||||
return new DoubleTag(other.data);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.command.CommandExecutor;
|
||||
import cn.nukkit.command.SimpleCommandMap;
|
||||
import cn.nukkit.plugin.Plugin;
|
||||
|
||||
public class NukkitCommandManager {
|
||||
private final SimpleCommandMap commandMap;
|
||||
|
||||
public NukkitCommandManager(SimpleCommandMap map) {
|
||||
this.commandMap = map;
|
||||
}
|
||||
|
||||
public boolean register(CommandInfo command, Plugin plugin, CommandExecutor executor) {
|
||||
if (command == null || commandMap == null) {
|
||||
return false;
|
||||
}
|
||||
DynamicPluginCommand cmd = new DynamicPluginCommand(
|
||||
command.getAliases(),
|
||||
command.getDesc(), "/" + command.getAliases()[0] + " " + command.getUsage(),
|
||||
executor,
|
||||
plugin);
|
||||
cmd.setPermissions(command.getPermissions());
|
||||
for (String alias : command.getAliases()) {
|
||||
commandMap.register(alias, cmd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.Player;
|
||||
import cn.nukkit.command.CommandSender;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.auth.AuthorizationException;
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class NukkitCommandSender implements Actor {
|
||||
|
||||
/**
|
||||
* One time generated ID.
|
||||
*/
|
||||
private static final UUID DEFAULT_ID = UUID.fromString("a233eb4b-4cab-42cd-9fd9-7e7b9a3f74be");
|
||||
|
||||
private CommandSender sender;
|
||||
private NukkitWorldEdit plugin;
|
||||
|
||||
public NukkitCommandSender(NukkitWorldEdit plugin, CommandSender sender) {
|
||||
checkNotNull(plugin);
|
||||
checkNotNull(sender);
|
||||
checkArgument(!(sender instanceof Player), "Cannot wrap a player");
|
||||
|
||||
this.plugin = plugin;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return DEFAULT_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return sender.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
sender.sendMessage(part);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
sender.sendMessage("\u00A7d" + part);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
sender.sendMessage("\u00A77" + part);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
sender.sendMessage("\u00A7c" + part);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDestroyBedrock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(String permission) throws AuthorizationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File openFileOpenDialog(String[] extensions) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File openFileSaveDialog(String[] extensions) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return new SessionKey() {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return DEFAULT_ID;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import com.sk89q.util.yaml.YAMLProcessor;
|
||||
import com.sk89q.worldedit.util.YAMLConfiguration;
|
||||
import java.io.File;
|
||||
|
||||
public class NukkitConfiguration extends YAMLConfiguration {
|
||||
|
||||
public boolean noOpPermissions = false;
|
||||
private final NukkitWorldEdit plugin;
|
||||
|
||||
public NukkitConfiguration(YAMLProcessor config, NukkitWorldEdit plugin) {
|
||||
super(config, plugin.getWELogger());
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
super.load();
|
||||
noOpPermissions = config.getBoolean("no-op-permissions", false);
|
||||
migrateLegacyFolders();
|
||||
}
|
||||
|
||||
private void migrateLegacyFolders() {
|
||||
migrate(scriptsDir, "craftscripts");
|
||||
migrate(saveDir, "schematics");
|
||||
migrate("drawings", "draw.js images");
|
||||
}
|
||||
|
||||
private void migrate(String file, String name) {
|
||||
File fromDir = new File(".", file);
|
||||
File toDir = new File(getWorkingDirectory(), file);
|
||||
if (fromDir.exists() & !toDir.exists()) {
|
||||
if (fromDir.renameTo(toDir)) {
|
||||
plugin.getLogger().info("Migrated " + name + " folder '" + file +
|
||||
"' from server root to plugin data folder.");
|
||||
} else {
|
||||
plugin.getLogger().warning("Error while migrating " + name + " folder!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getWorkingDirectory() {
|
||||
return plugin.getDataFolder();
|
||||
}
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.entity.Entity;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityType;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.NullWorld;
|
||||
import java.lang.ref.WeakReference;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* An adapter to adapt a Bukkit entity into a WorldEdit one.
|
||||
*/
|
||||
class NukkitEntity implements com.sk89q.worldedit.entity.Entity {
|
||||
|
||||
private final WeakReference<cn.nukkit.entity.Entity> entityRef;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param entity the entity
|
||||
*/
|
||||
NukkitEntity(cn.nukkit.entity.Entity entity) {
|
||||
checkNotNull(entity);
|
||||
this.entityRef = new WeakReference<Entity>(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Extent getExtent() {
|
||||
Entity entity = entityRef.get();
|
||||
if (entity != null) {
|
||||
return new NukkitWorld(entity.getLevel());
|
||||
} else {
|
||||
return NullWorld.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
Entity entity = entityRef.get();
|
||||
if (entity != null) {
|
||||
return NukkitUtil.toLocation(entity.getLocation());
|
||||
} else {
|
||||
return new Location(NullWorld.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
Entity entity = entityRef.get();
|
||||
if (entity != null) {
|
||||
if (entity instanceof Player) {
|
||||
return null;
|
||||
}
|
||||
CompoundTag tag = NBTConverter.fromNative(entity.namedTag);
|
||||
return new BaseEntity(entity.getSaveId(), tag);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove() {
|
||||
Entity entity = entityRef.get();
|
||||
if (entity != null) {
|
||||
entity.kill();
|
||||
return !entity.isAlive();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
Entity entity = entityRef.get();
|
||||
if (entity != null && EntityType.class.isAssignableFrom(cls)) {
|
||||
return (T) new NukkitEntityType(entity);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.Player;
|
||||
import cn.nukkit.entity.Entity;
|
||||
import cn.nukkit.entity.EntityLiving;
|
||||
import cn.nukkit.entity.item.EntityBoat;
|
||||
import cn.nukkit.entity.item.EntityFallingBlock;
|
||||
import cn.nukkit.entity.item.EntityItem;
|
||||
import cn.nukkit.entity.item.EntityMinecartEmpty;
|
||||
import cn.nukkit.entity.item.EntityPainting;
|
||||
import cn.nukkit.entity.item.EntityPrimedTNT;
|
||||
import cn.nukkit.entity.item.EntityXPOrb;
|
||||
import cn.nukkit.entity.passive.EntityAnimal;
|
||||
import cn.nukkit.entity.passive.EntityNPC;
|
||||
import cn.nukkit.entity.passive.EntityTameable;
|
||||
import cn.nukkit.entity.projectile.EntityProjectile;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityType;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class NukkitEntityType implements EntityType {
|
||||
|
||||
private final Entity entity;
|
||||
|
||||
public NukkitEntityType(Entity entity) {
|
||||
checkNotNull(entity);
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerDerived() {
|
||||
return entity instanceof Player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProjectile() {
|
||||
return entity instanceof EntityProjectile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItem() {
|
||||
return entity instanceof EntityItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFallingBlock() {
|
||||
return entity instanceof EntityFallingBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPainting() {
|
||||
return entity instanceof EntityPainting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemFrame() {
|
||||
// No item frames on MCPE
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBoat() {
|
||||
return entity instanceof EntityBoat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinecart() {
|
||||
return entity instanceof EntityMinecartEmpty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTNT() {
|
||||
return entity instanceof EntityPrimedTNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExperienceOrb() {
|
||||
return entity instanceof EntityXPOrb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLiving() {
|
||||
return entity instanceof EntityLiving;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnimal() {
|
||||
return entity instanceof EntityAnimal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbient() {
|
||||
// No bats implemented on MCPE
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNPC() {
|
||||
return entity instanceof EntityNPC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGolem() {
|
||||
// No golem on MCPE
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTamed() {
|
||||
return entity instanceof EntityTameable && ((EntityTameable) entity).isTamed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTagged() {
|
||||
return entity.hasCustomName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArmorStand() {
|
||||
// No armor stand
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.item.Item;
|
||||
import cn.nukkit.level.Level;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlatform;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
|
||||
import com.sk89q.worldedit.extension.platform.Preference;
|
||||
import com.sk89q.worldedit.util.command.CommandMapping;
|
||||
import com.sk89q.worldedit.util.command.Description;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class NukkitPlatform extends AbstractPlatform implements MultiUserPlatform {
|
||||
|
||||
private final NukkitWorldEdit mod;
|
||||
private boolean hookingEvents = false;
|
||||
private NukkitCommandManager commandManager;
|
||||
|
||||
public NukkitPlatform(NukkitWorldEdit mod) {
|
||||
this.mod = mod;
|
||||
this.commandManager = new NukkitCommandManager(mod.getServer().getCommandMap());
|
||||
}
|
||||
|
||||
boolean isHookingEvents() {
|
||||
return hookingEvents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int resolveItem(String name) {
|
||||
Item item = Item.fromString(name);
|
||||
return item == null ? 0 : item.getId();
|
||||
}
|
||||
|
||||
public NukkitWorldEdit getMod() {
|
||||
return mod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidMobType(String type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
getConfiguration().load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int schedule(long delay, long period, Runnable task) {
|
||||
TaskManager.IMP.repeat(task, (int) period);
|
||||
return 0; // TODO This isn't right, but we only check for -1 values
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends com.sk89q.worldedit.world.World> getWorlds() {
|
||||
Collection<Level> levels = mod.getServer().getLevels().values();
|
||||
List<com.sk89q.worldedit.world.World> ret = new ArrayList<>(levels.size());
|
||||
for (Level level : levels) {
|
||||
ret.add(new NukkitWorld(level));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Player matchPlayer(Player player) {
|
||||
if (player instanceof NukkitPlayer) {
|
||||
return player;
|
||||
} else {
|
||||
cn.nukkit.Player currentPlayer = mod.getServer().getPlayer(player.getName());
|
||||
return currentPlayer != null ? new NukkitPlayer(this, currentPlayer) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public World matchWorld(World world) {
|
||||
if (world instanceof NukkitWorld) {
|
||||
return world;
|
||||
} else {
|
||||
Level level = NukkitWorldEdit.inst().getServer().getLevelByName(world.getName());
|
||||
return level != null ? new NukkitWorld(level) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCommands(Dispatcher dispatcher) {
|
||||
for (CommandMapping command : dispatcher.getCommands()) {
|
||||
Description description = command.getDescription();
|
||||
List<String> permissions = description.getPermissions();
|
||||
String[] permissionsArray = new String[permissions.size()];
|
||||
permissions.toArray(permissionsArray);
|
||||
commandManager.register(new CommandInfo(description.getUsage(), description.getDescription(), command.getAllAliases(), permissionsArray), mod, mod);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGameHooks() {
|
||||
// We registered the events already anyway, so we just 'turn them on'
|
||||
hookingEvents = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NukkitConfiguration getConfiguration() {
|
||||
return mod.getWEConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return mod.getInternalVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName() {
|
||||
return "Nukkit-Official";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return mod.getInternalVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Capability, Preference> getCapabilities() {
|
||||
Map<Capability, Preference> capabilities = new EnumMap<>(Capability.class);
|
||||
capabilities.put(Capability.CONFIGURATION, Preference.NORMAL);
|
||||
capabilities.put(Capability.WORLDEDIT_CUI, Preference.NORMAL);
|
||||
capabilities.put(Capability.GAME_HOOKS, Preference.NORMAL);
|
||||
capabilities.put(Capability.PERMISSIONS, Preference.NORMAL);
|
||||
capabilities.put(Capability.USER_COMMANDS, Preference.NORMAL);
|
||||
capabilities.put(Capability.WORLD_EDITING, Preference.PREFERRED);
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Actor> getConnectedUsers() {
|
||||
List<Actor> users = new ArrayList<Actor>();
|
||||
for (Map.Entry<UUID, cn.nukkit.Player> entry : mod.getServer().getOnlinePlayers().entrySet()) {
|
||||
users.add(new NukkitPlayer(this, entry.getValue()));
|
||||
}
|
||||
return users;
|
||||
}
|
||||
}
|
|
@ -1,244 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.AdventureSettings;
|
||||
import cn.nukkit.Player;
|
||||
import cn.nukkit.inventory.PlayerInventory;
|
||||
import cn.nukkit.item.Item;
|
||||
import cn.nukkit.level.Location;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class NukkitPlayer extends LocalPlayer {
|
||||
|
||||
private final NukkitPlatform platform;
|
||||
private Player player;
|
||||
|
||||
public NukkitPlayer(NukkitPlatform platform, Player player) {
|
||||
this.platform = platform;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
PlayerInventory inv = player.getInventory();
|
||||
Item itemStack = inv.getItemInHand();
|
||||
return itemStack != null ? itemStack.getId() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockInHand() throws WorldEditException {
|
||||
PlayerInventory inv = player.getInventory();
|
||||
Item itemStack = inv.getItemInHand();
|
||||
if (itemStack == null) {
|
||||
return EditSession.nullBlock;
|
||||
}
|
||||
return new BaseBlock(itemStack.getId(), itemStack.getMaxDurability() != 0 ? 0 : itemStack.getDamage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return player.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getPosition() {
|
||||
Location loc = player.getLocation();
|
||||
return new WorldVector(NukkitUtil.getLocalWorld(loc.getLevel()),
|
||||
loc.getX(), loc.getY(), loc.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPitch() {
|
||||
return player.getLocation().getPitch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return player.getLocation().getYaw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(int type, int amt) {
|
||||
player.getInventory().addItem(new Item(type, 0, amt));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
player.sendMessage(part);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
player.sendMessage("\u00A7d" + part);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
player.sendMessage("\u00A77" + part);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
player.sendMessage("\u00A7c" + part);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||
player.teleport(new Location(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch, player.getLevel()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
// Is this ever used?
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return new NukkitPlayerBlockBag(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
NukkitConfiguration config = platform.getMod().getWEConfig();
|
||||
return (!config.noOpPermissions && player.isOp()) || player.hasPermission(perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalWorld getWorld() {
|
||||
return NukkitUtil.getLocalWorld(player.getLevel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
// No WE-CUI on MCPE
|
||||
return;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCreativeMode() {
|
||||
return player.getGamemode() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void floatAt(int x, int y, int z, boolean alwaysGlass) {
|
||||
if (alwaysGlass || !player.getAllowFlight()) {
|
||||
super.floatAt(x, y, z, alwaysGlass);
|
||||
return;
|
||||
}
|
||||
|
||||
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
||||
player.getAdventureSettings().set(AdventureSettings.Type.ALLOW_FLIGHT, true);
|
||||
player.getAdventureSettings().set(AdventureSettings.Type.FLYING, true);
|
||||
player.getAdventureSettings().update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
throw new UnsupportedOperationException("Cannot create a state from this object");
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sk89q.worldedit.util.Location getLocation() {
|
||||
Location nativeLocation = player.getLocation();
|
||||
Vector position = NukkitUtil.toVector(nativeLocation);
|
||||
return new com.sk89q.worldedit.util.Location(
|
||||
getWorld(),
|
||||
position,
|
||||
(float) nativeLocation.getYaw(),
|
||||
(float) nativeLocation.getPitch());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return new SessionKeyImpl(this.player.getUniqueId(), player.getName());
|
||||
}
|
||||
|
||||
private static class SessionKeyImpl implements SessionKey {
|
||||
// If not static, this will leak a reference
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
private SessionKeyImpl(UUID uuid, String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
// This is a thread safe call on CraftNukkit because it uses a
|
||||
// CopyOnWrite list for the list of players, but the Nukkit
|
||||
// specification doesn't require thread safety (though the
|
||||
// spec is extremely incomplete)
|
||||
return NukkitWorldEdit.inst().getServer().getPlayer(name) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,214 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.Player;
|
||||
import cn.nukkit.inventory.PlayerInventory;
|
||||
import cn.nukkit.item.Item;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBagException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
|
||||
import java.util.Map;
|
||||
|
||||
public class NukkitPlayerBlockBag extends BlockBag {
|
||||
|
||||
private Player player;
|
||||
private Map<Integer, Item> items;
|
||||
private int size;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public NukkitPlayerBlockBag(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads inventory on first use.
|
||||
*/
|
||||
private void loadInventory() {
|
||||
if (items == null) {
|
||||
PlayerInventory inv = player.getInventory();
|
||||
items = inv.getContents();
|
||||
this.size = inv.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount == 1);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't fetch air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (Map.Entry<Integer, Item> entry : items.entrySet()) {
|
||||
int slot = entry.getKey();
|
||||
Item nukkitItem = entry.getValue();
|
||||
if (nukkitItem == null) {
|
||||
continue;
|
||||
}
|
||||
if (nukkitItem.getId() != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
if (usesDamageValue && nukkitItem.getDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentCount = nukkitItem.getCount();
|
||||
if (currentCount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentCount > 1) {
|
||||
nukkitItem.setCount(currentCount - 1);
|
||||
found = true;
|
||||
} else {
|
||||
items.remove(slot);
|
||||
found = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new OutOfBlocksException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeItem(BaseItem item) throws BlockBagException {
|
||||
final int id = item.getType();
|
||||
final int damage = item.getData();
|
||||
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
|
||||
assert(amount <= 64);
|
||||
boolean usesDamageValue = ItemType.usesDamageValue(id);
|
||||
|
||||
if (id == BlockID.AIR) {
|
||||
throw new IllegalArgumentException("Can't store air block");
|
||||
}
|
||||
|
||||
loadInventory();
|
||||
|
||||
int freeSlot = -1;
|
||||
for (int slot = 0; slot < size; ++slot) {
|
||||
Item nukkitItem = items.get(slot);
|
||||
|
||||
if (nukkitItem == null) {
|
||||
// Delay using up a free slot until we know there are no stacks
|
||||
// of this item to merge into
|
||||
|
||||
if (freeSlot == -1) {
|
||||
freeSlot = slot;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nukkitItem.getId() != id) {
|
||||
// Type id doesn't fit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usesDamageValue && nukkitItem.getDamage() != damage) {
|
||||
// Damage value doesn't fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
int currentCount = nukkitItem.getCount();
|
||||
if (currentCount < 0) {
|
||||
// Unlimited
|
||||
return;
|
||||
}
|
||||
if (currentCount >= 64) {
|
||||
// Full stack
|
||||
continue;
|
||||
}
|
||||
|
||||
int spaceLeft = 64 - currentCount;
|
||||
if (spaceLeft >= amount) {
|
||||
nukkitItem.setCount(currentCount + amount);
|
||||
return;
|
||||
}
|
||||
|
||||
nukkitItem.setCount(64);
|
||||
amount -= spaceLeft;
|
||||
}
|
||||
|
||||
if (freeSlot > -1) {
|
||||
items.put(freeSlot, new Item(id, 0, amount));
|
||||
return;
|
||||
}
|
||||
|
||||
throw new OutOfSpaceException(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushChanges() {
|
||||
if (items != null) {
|
||||
player.getInventory().setContents(items);
|
||||
items = null;
|
||||
player.getInventory().sendContents(player);
|
||||
player.getInventory().sendContents(player);
|
||||
player.getInventory().sendContents(player);
|
||||
player.getInventory().sendContents(player);
|
||||
player.getInventory().sendContents(player);
|
||||
player.getInventory().sendContents(player);
|
||||
player.getInventory().sendContents(player);
|
||||
player.getInventory().sendContents(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSingleSourcePosition(WorldVector pos) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.block.Block;
|
||||
import cn.nukkit.block.BlockLiquid;
|
||||
import cn.nukkit.item.Item;
|
||||
import cn.nukkit.math.Vector3;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class NukkitRegistryDumper {
|
||||
|
||||
private File file;
|
||||
private Gson gson;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
new NukkitRegistryDumper(new File("blocks.json")).run();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public NukkitRegistryDumper(File file) {
|
||||
this.file = file;
|
||||
GsonBuilder builder = new GsonBuilder().setPrettyPrinting();
|
||||
builder.registerTypeAdapter(Vector3.class, new Vec3iAdapter());
|
||||
this.gson = builder.create();
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
Block.init();
|
||||
Item.init();
|
||||
List<Map<String, Object>> list = new LinkedList<Map<String, Object>>();
|
||||
HashSet<String> visited = new HashSet<>();
|
||||
for (Item item : Item.getCreativeItems()) {
|
||||
try {
|
||||
if (item != null && item.getBlock() != null && !visited.contains(item.getBlock().getName())) {
|
||||
Block block = item.getBlock();
|
||||
visited.add(block.getName());
|
||||
list.add(getProperties(block));
|
||||
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// for (Block block : Block.fullList) {
|
||||
// if (block != null) {
|
||||
// try {
|
||||
// System.out.println("BLOCK " + block.getName());
|
||||
// list.add(getProperties(block));
|
||||
// } catch (Throwable e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
Collections.sort(list, new MapComparator());
|
||||
String out = gson.toJson(list);
|
||||
this.write(out);
|
||||
System.out.println("Wrote file: " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
private Map<String, Object> getProperties(Block b) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
Item item = Item.get(b.getId(), b.getDamage());
|
||||
map.put("legacyId", b.getId());
|
||||
map.put("id", b.getName());
|
||||
map.put("unlocalizedName", b.getName());
|
||||
map.put("localizedName", b.getName());
|
||||
map.put("material", getMaterial(b));
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
private Map<String, Object> getMaterial(Block b) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
Item item = Item.get(b.getId(), b.getDamage());
|
||||
map.put("powerSource", b.isPowerSource());
|
||||
map.put("lightOpacity", Block.lightFilter[b.getId()]);
|
||||
map.put("lightValue", b.getLightLevel());
|
||||
// map.put("usingNeighborLight", b.getUseNeighborBrightness(bs));
|
||||
map.put("hardness", b.getHardness());
|
||||
map.put("resistance", b.getResistance());
|
||||
// map.put("ticksRandomly", b.tickRate());
|
||||
map.put("tickRate", b.tickRate());
|
||||
map.put("fullCube", b.isSolid() && !b.isTransparent());
|
||||
map.put("slipperiness", b.getFrictionFactor());
|
||||
map.put("renderedAsNormalBlock", !b.isTransparent());
|
||||
//map.put("solidFullCube", b.isSolidFullCube());
|
||||
map.put("liquid", b instanceof BlockLiquid);
|
||||
map.put("solid", b.isSolid());
|
||||
map.put("movementBlocker", b.hasEntityCollision());
|
||||
//map.put("blocksLight", m.blocksLight());
|
||||
map.put("burnable", b.getBurnAbility() > 0);
|
||||
map.put("opaque", !b.isTransparent());
|
||||
map.put("replacedDuringPlacement", b.canBeReplaced());
|
||||
map.put("toolRequired", b.getToolType() != 0);
|
||||
map.put("canBeFlowedInto", b.canBeFlowedInto());
|
||||
// map.put("fragileWhenPushed", b instanceof BlockFlowable);
|
||||
// map.put("unpushable", m.getMobilityFlag() == EnumPushReaction.BLOCK);
|
||||
// map.put("adventureModeExempt", b.getField(m, Material.class, "isAdventureModeExempt", "field_85159_M"));
|
||||
map.put("mapColor", rgb(b.getColor().getRGB()));
|
||||
map.put("ambientOcclusionLightValue", b.isSolid() ? 0.2F : 1.0F);
|
||||
// try {
|
||||
// map.put("ambientOcclusionLightValue", b.b.getAmbientOcclusionLightValue(bs));
|
||||
// } catch (NoSuchMethodError ignored) {
|
||||
// map.put("ambientOcclusionLightValue", b.isBlockNormalCube(bs) ? 0.2F : 1.0F);
|
||||
// }
|
||||
map.put("grassBlocking", false); // idk what this property was originally supposed to be...grass uses a combination of light values to check growth
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
private String rgb(int i) {
|
||||
int r = (i >> 16) & 0xFF;
|
||||
int g = (i >> 8) & 0xFF;
|
||||
int b = i & 0xFF;
|
||||
return String.format("#%02x%02x%02x", r, g, b);
|
||||
}
|
||||
|
||||
private void write(String s) {
|
||||
try {
|
||||
FileOutputStream str = new FileOutputStream(file);
|
||||
str.write(s.getBytes());
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error writing registry dump: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Vec3iAdapter extends TypeAdapter<Vector3> {
|
||||
@Override
|
||||
public Vector3 read(final JsonReader in) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void write(final JsonWriter out, final Vector3 vec) throws IOException {
|
||||
out.beginArray();
|
||||
out.value(vec.getX());
|
||||
out.value(vec.getY());
|
||||
out.value(vec.getZ());
|
||||
out.endArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MapComparator implements Comparator<Map<String, Object>> {
|
||||
@Override
|
||||
public int compare(Map<String, Object> a, Map<String, Object> b) {
|
||||
return ((Integer) a.get("legacyId")).compareTo((Integer) b.get("legacyId"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.plugin.Plugin;
|
||||
import cn.nukkit.scheduler.TaskHandler;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class NukkitTaskManager extends TaskManager{
|
||||
|
||||
private final Plugin plugin;
|
||||
|
||||
public NukkitTaskManager(final Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeat(final Runnable r, final int interval) {
|
||||
TaskHandler task = this.plugin.getServer().getScheduler().scheduleRepeatingTask(r, interval, false);
|
||||
return task.getTaskId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(final Runnable r, final int interval) {
|
||||
TaskHandler task = this.plugin.getServer().getScheduler().scheduleRepeatingTask(r, interval, true);
|
||||
return task.getTaskId();
|
||||
}
|
||||
|
||||
private AtomicInteger index = new AtomicInteger(0);
|
||||
private HashMap<Integer, Integer> tasks = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void async(final Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
this.plugin.getServer().getScheduler().scheduleTask(r, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(final Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
this.plugin.getServer().getScheduler().scheduleTask(r, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(final Runnable r, final int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
this.plugin.getServer().getScheduler().scheduleDelayedTask(r, delay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(final Runnable r, final int delay) {
|
||||
this.plugin.getServer().getScheduler().scheduleDelayedTask(r, delay, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(final int task) {
|
||||
if (task != -1) {
|
||||
this.plugin.getServer().getScheduler().cancelTask(task);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* LevelEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) LevelEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.Player;
|
||||
import cn.nukkit.Server;
|
||||
import cn.nukkit.block.Block;
|
||||
import cn.nukkit.entity.Entity;
|
||||
import cn.nukkit.level.Level;
|
||||
import cn.nukkit.math.Vector3;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.BlockWorldVector;
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
|
||||
public final class NukkitUtil {
|
||||
|
||||
private NukkitUtil() {
|
||||
}
|
||||
|
||||
public static LocalWorld getLocalWorld(Level w) {
|
||||
return new NukkitWorld(w);
|
||||
}
|
||||
|
||||
public static BlockVector toVector(Block block) {
|
||||
return new BlockVector(block.getX(), block.getY(), block.getZ());
|
||||
}
|
||||
|
||||
public static BlockWorldVector toWorldVector(Block block) {
|
||||
return new BlockWorldVector(getLocalWorld(block.getLevel()), block.getX(), block.getY(), block.getZ());
|
||||
}
|
||||
|
||||
public static Vector toVector(cn.nukkit.level.Location loc) {
|
||||
return new Vector(loc.getX(), loc.getY(), loc.getZ());
|
||||
}
|
||||
|
||||
public static Location toLocation(cn.nukkit.level.Location loc) {
|
||||
return new Location(
|
||||
getLocalWorld(loc.getLevel()),
|
||||
new Vector(loc.getX(), loc.getY(), loc.getZ()),
|
||||
(float) loc.getYaw(), (float) loc.getPitch()
|
||||
);
|
||||
}
|
||||
|
||||
public static Vector toVector(Vector3 vector) {
|
||||
return new Vector(vector.getX(), vector.getY(), vector.getZ());
|
||||
}
|
||||
|
||||
public static cn.nukkit.level.Location toLocation(WorldVector pt) {
|
||||
return new cn.nukkit.level.Location(pt.getX(), pt.getY(), pt.getZ(), 0, 0, toLevel(pt));
|
||||
}
|
||||
|
||||
public static cn.nukkit.level.Location toLocation(Level world, Vector pt) {
|
||||
return new cn.nukkit.level.Location(pt.getX(), pt.getY(), pt.getZ(), 0, 0, world);
|
||||
}
|
||||
|
||||
public static cn.nukkit.level.Location center(cn.nukkit.level.Location loc) {
|
||||
return new cn.nukkit.level.Location(
|
||||
loc.getFloorX() + 0.5,
|
||||
loc.getFloorY() + 0.5,
|
||||
loc.getFloorZ() + 0.5,
|
||||
loc.getPitch(),
|
||||
loc.getYaw(),
|
||||
loc.getLevel()
|
||||
);
|
||||
}
|
||||
|
||||
public static Player matchSinglePlayer(Server server, String name) {
|
||||
Player[] players = server.matchPlayer(name);
|
||||
return players.length > 0 ? players[0] : null;
|
||||
}
|
||||
|
||||
public static Block toBlock(BlockWorldVector pt) {
|
||||
return toLevel(pt).getBlock(toLocation(pt));
|
||||
}
|
||||
|
||||
public static Level toLevel(WorldVector pt) {
|
||||
return ((NukkitWorld) pt.getWorld()).getLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Nukkit's Location class has serious problems with floating point
|
||||
* precision.
|
||||
*/
|
||||
@SuppressWarnings("RedundantIfStatement")
|
||||
public static boolean equals(cn.nukkit.level.Location a, cn.nukkit.level.Location b) {
|
||||
if (Math.abs(a.getX() - b.getX()) > EQUALS_PRECISION) return false;
|
||||
if (Math.abs(a.getY() - b.getY()) > EQUALS_PRECISION) return false;
|
||||
if (Math.abs(a.getZ() - b.getZ()) > EQUALS_PRECISION) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static final double EQUALS_PRECISION = 0.0001;
|
||||
|
||||
public static cn.nukkit.level.Location toLocation(Location location) {
|
||||
return new cn.nukkit.level.Location(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch(), toLevel((LocalWorld) location.getExtent()));
|
||||
}
|
||||
|
||||
public static Level toLevel(final LocalWorld world) {
|
||||
return ((NukkitWorld) world).getLevel();
|
||||
}
|
||||
|
||||
public static NukkitEntity toLocalEntity(Entity e) {
|
||||
return new NukkitEntity(e);
|
||||
}
|
||||
|
||||
public static com.sk89q.worldedit.entity.Entity createEntity(Level level, Location location, BaseEntity entity) {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BaseBlock getBlock(Level level, Vector position) {
|
||||
Vector3 pos = new Vector3(position.getX(), position.getY(), position.getZ());
|
||||
Block block = level.getBlock(pos);
|
||||
int id = block.getId();
|
||||
int data = block.getDamage();
|
||||
return new BaseBlock(id, data);
|
||||
}
|
||||
|
||||
public static boolean setBlock(Level level, Vector pos, BaseBlock block) {
|
||||
int x = pos.getBlockX();
|
||||
int y = pos.getBlockY();
|
||||
int z = pos.getBlockZ();
|
||||
level.setBlockIdAt(x, y, z, block.getId());
|
||||
level.setBlockDataAt(x, y, z, block.getData());
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
|
@ -1,313 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.blockentity.BlockEntity;
|
||||
import cn.nukkit.blockentity.BlockEntityChest;
|
||||
import cn.nukkit.entity.Entity;
|
||||
import cn.nukkit.inventory.InventoryHolder;
|
||||
import cn.nukkit.item.Item;
|
||||
import cn.nukkit.item.ItemPickaxeDiamond;
|
||||
import cn.nukkit.level.Level;
|
||||
import cn.nukkit.math.Vector3;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import com.sk89q.worldedit.world.registry.LegacyWorldData;
|
||||
import com.sk89q.worldedit.world.registry.WorldData;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class NukkitWorld extends LocalWorld {
|
||||
|
||||
private static final Logger logger = WorldEdit.logger;
|
||||
|
||||
private final WeakReference<Level> worldRef;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param world the world
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public NukkitWorld(Level world) {
|
||||
this.worldRef = new WeakReference<Level>(world);
|
||||
}
|
||||
|
||||
private Vector3 mutable = new Vector3(0, 0, 0);
|
||||
private Vector3 setMutable(Vector pt) {
|
||||
mutable.x = pt.getX();
|
||||
mutable.y = pt.getY();
|
||||
mutable.z = pt.getZ();
|
||||
return mutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<com.sk89q.worldedit.entity.Entity> getEntities(Region region) {
|
||||
Level world = getLevel();
|
||||
cn.nukkit.entity.Entity[] ents = world.getEntities();
|
||||
List<com.sk89q.worldedit.entity.Entity> entities = new ArrayList<com.sk89q.worldedit.entity.Entity>();
|
||||
for (cn.nukkit.entity.Entity ent : ents) {
|
||||
if (region.contains(NukkitUtil.toVector(ent.getLocation()))) {
|
||||
entities.add(new NukkitEntity(ent));
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<com.sk89q.worldedit.entity.Entity> getEntities() {
|
||||
List<com.sk89q.worldedit.entity.Entity> list = new ArrayList<com.sk89q.worldedit.entity.Entity>();
|
||||
for (Entity entity : getLevel().getEntities()) {
|
||||
list.add(new NukkitEntity(entity));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public com.sk89q.worldedit.entity.Entity createEntity(com.sk89q.worldedit.util.Location location, BaseEntity entity) {
|
||||
return NukkitUtil.createEntity(getLevel(), location, entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the world handle.
|
||||
*
|
||||
* @return the world
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return checkNotNull(worldRef.get(), "The world was unloaded and the reference is unavailable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getLevel().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLightLevel(Vector pt) {
|
||||
return getLevel().getBlockLightAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerate(Region region, EditSession editSession) {
|
||||
BaseBlock[] history = new BaseBlock[16 * 16 * (getMaxY() + 1)];
|
||||
|
||||
for (Vector2D chunk : region.getChunks()) {
|
||||
Vector min = new Vector(chunk.getBlockX() * 16, 0, chunk.getBlockZ() * 16);
|
||||
|
||||
// First save all the blocks inside
|
||||
for (int x = 0; x < 16; ++x) {
|
||||
for (int y = 0; y < (getMaxY() + 1); ++y) {
|
||||
for (int z = 0; z < 16; ++z) {
|
||||
Vector pt = min.add(x, y, z);
|
||||
int index = y * 16 * 16 + z * 16 + x;
|
||||
history[index] = editSession.getBlock(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
getLevel().regenerateChunk(chunk.getBlockX(), chunk.getBlockZ());
|
||||
} catch (Throwable t) {
|
||||
logger.log(java.util.logging.Level.WARNING, "Chunk generation via Nukkit raised an error", t);
|
||||
}
|
||||
|
||||
// Then restore
|
||||
for (int x = 0; x < 16; ++x) {
|
||||
for (int y = 0; y < (getMaxY() + 1); ++y) {
|
||||
for (int z = 0; z < 16; ++z) {
|
||||
Vector pt = min.add(x, y, z);
|
||||
int index = y * 16 * 16 + z * 16 + x;
|
||||
|
||||
// We have to restore the block if it was outside
|
||||
if (!region.contains(pt)) {
|
||||
editSession.smartSetBlock(pt, history[index]);
|
||||
} else { // Otherwise fool with history
|
||||
editSession.rememberChange(pt, history[index],
|
||||
editSession.rawGetBlock(pt));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearContainerBlockContents(Vector pt) {
|
||||
BlockEntity block = getLevel().getBlockEntity(setMutable(pt));
|
||||
if (block == null) {
|
||||
return false;
|
||||
}
|
||||
if (block instanceof InventoryHolder) {
|
||||
if (block instanceof BlockEntityChest) {
|
||||
((BlockEntityChest) block).getRealInventory().clearAll();
|
||||
} else {
|
||||
((InventoryHolder) block).getInventory().clearAll();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean generateTree(EditSession editSession, Vector pt) {
|
||||
return generateTree(TreeGenerator.TreeType.TREE, editSession, pt);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean generateBigTree(EditSession editSession, Vector pt) {
|
||||
return generateTree(TreeGenerator.TreeType.BIG_TREE, editSession, pt);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean generateBirchTree(EditSession editSession, Vector pt) {
|
||||
return generateTree(TreeGenerator.TreeType.BIRCH, editSession, pt);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean generateRedwoodTree(EditSession editSession, Vector pt) {
|
||||
return generateTree(TreeGenerator.TreeType.REDWOOD, editSession, pt);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean generateTallRedwoodTree(EditSession editSession, Vector pt) {
|
||||
return generateTree(TreeGenerator.TreeType.TALL_REDWOOD, editSession, pt);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pt) {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropItem(Vector pt, BaseItemStack item) {
|
||||
Level world = getLevel();
|
||||
Item nukkitItem = new Item(item.getType(), item.getAmount(),
|
||||
item.getData());
|
||||
world.dropItem(NukkitUtil.toLocation(world, pt), nukkitItem);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public boolean isValidBlockType(int type) {
|
||||
Item item = Item.get(type);
|
||||
if (item == null) {
|
||||
return false;
|
||||
}
|
||||
return item != null && item.getId() < 256 && item.getBlock() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkLoadedChunk(Vector pt) {
|
||||
Level world = getLevel();
|
||||
|
||||
if (!world.isChunkLoaded(pt.getBlockX() >> 4, pt.getBlockZ() >> 4)) {
|
||||
world.loadChunk(pt.getBlockX() >> 4, pt.getBlockZ() >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
} else if ((other instanceof NukkitWorld)) {
|
||||
return ((NukkitWorld) other).getLevel().equals(getLevel());
|
||||
} else if (other instanceof com.sk89q.worldedit.world.World) {
|
||||
return ((com.sk89q.worldedit.world.World) other).getName().equals(getName());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getLevel().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxY() {
|
||||
return 255;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getMinimumPoint() {
|
||||
return new Vector(-30000000, 0, -30000000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getMaximumPoint() {
|
||||
return new Vector(30000000, 255, 30000000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixAfterFastMode(Iterable<BlockVector2D> chunks) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playEffect(Vector position, int type, int data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldData getWorldData() {
|
||||
return LegacyWorldData.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simulateBlockMine(Vector pt) {
|
||||
ItemPickaxeDiamond item = new ItemPickaxeDiamond(Integer.MAX_VALUE);
|
||||
getLevel().useBreakOn(setMutable(pt), item, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlock(Vector position) {
|
||||
return NukkitUtil.getBlock(getLevel(), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) {
|
||||
return NukkitUtil.setBlock(getLevel(), position, block);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public BaseBlock getLazyBlock(Vector position) {
|
||||
return getBlock(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBiome getBiome(Vector2D position) {
|
||||
int id = getLevel().getBiomeId(position.getBlockX(), position.getBlockZ());
|
||||
return new BaseBiome(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(Vector2D position, BaseBiome biome) {
|
||||
getLevel().setBiomeId(position.getBlockX(), position.getBlockZ(), (byte) biome.getId());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
import cn.nukkit.Nukkit;
|
||||
import cn.nukkit.Player;
|
||||
import cn.nukkit.command.Command;
|
||||
import cn.nukkit.command.CommandSender;
|
||||
import cn.nukkit.plugin.PluginBase;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.nukkit.core.converter.ConvertCommands;
|
||||
import com.boydti.fawe.nukkit.optimization.FaweNukkit;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sk89q.util.yaml.YAMLProcessor;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.event.platform.CommandEvent;
|
||||
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.CommandManager;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* The Nukkit implementation of WorldEdit.
|
||||
*/
|
||||
public class NukkitWorldEdit extends PluginBase {
|
||||
|
||||
private Logger logger;
|
||||
|
||||
private static NukkitWorldEdit inst;
|
||||
|
||||
public static NukkitWorldEdit inst() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
private NukkitPlatform platform;
|
||||
|
||||
private NukkitConfiguration config;
|
||||
|
||||
private File workingDir;
|
||||
|
||||
public NukkitWorldEdit() {
|
||||
inst = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
try {
|
||||
{ // Defaults
|
||||
Settings.IMP.WEB.SHORTEN_URLS = true;
|
||||
}
|
||||
|
||||
Fawe.set(new FaweNukkit(this));
|
||||
Fawe.setupInjector();
|
||||
|
||||
Settings.IMP.HISTORY.COMBINE_STAGES = false;
|
||||
logger = Logger.getLogger(NukkitWorldEdit.class.getCanonicalName());
|
||||
createDefaultConfiguration("config-basic.yml");
|
||||
config = new NukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "config-basic.yml"), true), this);
|
||||
config.load();
|
||||
this.platform = new NukkitPlatform(this);
|
||||
getServer().getPluginManager().registerEvents(new WorldEditListener(this), this);
|
||||
WorldEdit.getInstance().getPlatformManager().register(platform);
|
||||
{
|
||||
CommandManager cmdMan = CommandManager.getInstance();
|
||||
cmdMan.registerCommands(new ConvertCommands(WorldEdit.getInstance()));
|
||||
}
|
||||
logger.info("WorldEdit for Nukkit (version " + getInternalVersion() + ") is loaded");
|
||||
WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
WorldEdit.getInstance().getPlatformManager().unregister(platform);
|
||||
}
|
||||
|
||||
protected void createDefaultConfiguration(String name) throws IOException {
|
||||
File actual = new File(getDataFolder(), name);
|
||||
if (!actual.exists()) {
|
||||
actual.getParentFile().mkdirs();
|
||||
actual.createNewFile();
|
||||
InputStream input = null;
|
||||
try {
|
||||
JarFile file = new JarFile(getFile());
|
||||
ZipEntry copy = file.getEntry(name);
|
||||
if (copy == null) throw new FileNotFoundException();
|
||||
input = file.getInputStream(copy);
|
||||
} catch (IOException e) {
|
||||
getWELogger().severe("Unable to read default configuration: " + name);
|
||||
}
|
||||
if (input != null) {
|
||||
FileOutputStream output = null;
|
||||
|
||||
try {
|
||||
output = new FileOutputStream(actual);
|
||||
byte[] buf = new byte[8192];
|
||||
int length;
|
||||
while ((length = input.read(buf)) > 0) {
|
||||
output.write(buf, 0, length);
|
||||
}
|
||||
getWELogger().info("Default configuration file written: " + name);
|
||||
} catch (IOException e) {
|
||||
getWELogger().log(Level.WARNING, "Failed to write default config file", e);
|
||||
} finally {
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException ignored) {}
|
||||
|
||||
try {
|
||||
if (output != null) {
|
||||
output.close();
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
|
||||
// Add the command to the array because the underlying command handling
|
||||
// code of WorldEdit expects it
|
||||
String[] split = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, split, 1, args.length);
|
||||
split[0] = cmd.getName();
|
||||
CommandEvent event = new CommandEvent(wrapCommandSender(sender), Joiner.on(" ").join(Arrays.asList(split)));
|
||||
WorldEdit.getInstance().getEventBus().post(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Actor wrapCommandSender(CommandSender sender) {
|
||||
if (sender instanceof Player) {
|
||||
return wrapPlayer((Player) sender);
|
||||
}
|
||||
|
||||
return new NukkitCommandSender(this, sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration.
|
||||
*
|
||||
* @return the Nukkit configuration
|
||||
*/
|
||||
public NukkitConfiguration getWEConfig() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
public Logger getWELogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WorldEdit proxy for the given player.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the WorldEdit player
|
||||
*/
|
||||
public NukkitPlayer wrapPlayer(Player player) {
|
||||
checkNotNull(player);
|
||||
return new NukkitPlayer(platform, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session for a player.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the session
|
||||
*/
|
||||
public LocalSession getSession(Player player) {
|
||||
checkNotNull(player);
|
||||
return WorldEdit.getInstance().getSessionManager().get(wrapPlayer(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WorldEdit proxy for the platform.
|
||||
*
|
||||
* @return the WorldEdit platform
|
||||
*/
|
||||
public NukkitPlatform getPlatform() {
|
||||
return this.platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the working directory where WorldEdit's files are stored.
|
||||
*
|
||||
* @return the working directory
|
||||
*/
|
||||
public File getWorkingDir() {
|
||||
return this.workingDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the WorldEdit Nukkit implementation.
|
||||
*
|
||||
* @return a version string
|
||||
*/
|
||||
public String getInternalVersion() {
|
||||
return Nukkit.API_VERSION;
|
||||
}
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// $Id$
|
||||
|
||||
package com.boydti.fawe.nukkit.core;
|
||||
|
||||
|
||||
import cn.nukkit.block.Block;
|
||||
import cn.nukkit.event.EventHandler;
|
||||
import cn.nukkit.event.EventPriority;
|
||||
import cn.nukkit.event.Listener;
|
||||
import cn.nukkit.event.block.BlockBreakEvent;
|
||||
import cn.nukkit.event.player.PlayerChatEvent;
|
||||
import cn.nukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import cn.nukkit.event.player.PlayerGameModeChangeEvent;
|
||||
import cn.nukkit.event.player.PlayerInteractEvent;
|
||||
import cn.nukkit.event.player.PlayerInteractEvent.Action;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.LocalPlayer;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.event.platform.CommandEvent;
|
||||
import com.sk89q.worldedit.extension.platform.CommandManager;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Handles all events thrown in relation to a Player
|
||||
*/
|
||||
public class WorldEditListener implements Listener {
|
||||
|
||||
private NukkitWorldEdit plugin;
|
||||
|
||||
/**
|
||||
* Called when a player plays an animation, such as an arm swing
|
||||
*
|
||||
* @param event Relevant event details
|
||||
*/
|
||||
|
||||
/**
|
||||
* Construct the object;
|
||||
*
|
||||
* @param plugin the plugin
|
||||
*/
|
||||
public WorldEditListener(NukkitWorldEdit plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onGamemode(PlayerGameModeChangeEvent event) {
|
||||
// this will automatically refresh their session, we don't have to do anything
|
||||
WorldEdit.getInstance().getSession(plugin.wrapPlayer(event.getPlayer()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player attempts to use a command
|
||||
*
|
||||
* @param event Relevant event details
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true,priority = EventPriority.MONITOR)
|
||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||
String[] split = event.getMessage().split(" ");
|
||||
|
||||
if (split.length > 0) {
|
||||
split[0] = split[0].substring(1);
|
||||
split = WorldEdit.getInstance().getPlatformManager().getCommandManager().commandDetection(split);
|
||||
}
|
||||
final String newMessage = "/" + StringUtil.joinString(split, " ");
|
||||
|
||||
if (!newMessage.equals(event.getMessage())) {
|
||||
event.setMessage(newMessage);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
if (!event.isCancelled()) {
|
||||
if (!event.getMessage().isEmpty()) {
|
||||
plugin.getServer().dispatchCommand(event.getPlayer(), event.getMessage().substring(1));
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true,priority = EventPriority.LOWEST)
|
||||
public void onPlayerChat(PlayerChatEvent event) {
|
||||
String message = event.getMessage();
|
||||
if (message.charAt(0) == '.') {
|
||||
String[] split = event.getMessage().split(" ");
|
||||
if (split.length > 0) {
|
||||
split[0] = split[0].substring(1).replace('.', '/');
|
||||
CommandManager cmdMan = WorldEdit.getInstance().getPlatformManager().getCommandManager();
|
||||
split = cmdMan.commandDetection(split);
|
||||
CommandEvent cmdEvent = new CommandEvent(plugin.wrapCommandSender(event.getPlayer()), Joiner.on(" ").join(Arrays.asList(split)));
|
||||
if (cmdMan.getDispatcher().contains(split[0])) {
|
||||
WorldEdit.getInstance().getEventBus().post(cmdEvent);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
final LocalPlayer player = plugin.wrapPlayer(event.getPlayer());
|
||||
final World world = player.getWorld();
|
||||
final WorldEdit we = WorldEdit.getInstance();
|
||||
final Block clickedBlock = event.getBlock();
|
||||
final WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ());
|
||||
if (we.handleBlockLeftClick(player, pos)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
if (we.handleArmSwing(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player interacts
|
||||
*
|
||||
* @param event Relevant event details
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
final LocalPlayer player = plugin.wrapPlayer(event.getPlayer());
|
||||
final World world = player.getWorld();
|
||||
final WorldEdit we = WorldEdit.getInstance();
|
||||
|
||||
Action action = event.getAction();
|
||||
if (action == PlayerInteractEvent.Action.LEFT_CLICK_BLOCK) {
|
||||
final Block clickedBlock = event.getBlock();
|
||||
final WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ());
|
||||
|
||||
if (we.handleBlockLeftClick(player, pos)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (we.handleArmSwing(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
} else if (action == PlayerInteractEvent.Action.LEFT_CLICK_AIR) {
|
||||
if (we.handleArmSwing(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
|
||||
} else if (action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
|
||||
final Block clickedBlock = event.getBlock();
|
||||
final WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), clickedBlock.getX(),
|
||||
clickedBlock.getY(), clickedBlock.getZ());
|
||||
|
||||
if (we.handleBlockRightClick(player, pos)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (we.handleRightClick(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
} else if (action == PlayerInteractEvent.Action.RIGHT_CLICK_AIR) {
|
||||
if (we.handleRightClick(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core.converter;
|
||||
|
||||
import com.boydti.fawe.command.AnvilCommands;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAChunk;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAFile;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAFilter;
|
||||
import com.boydti.fawe.jnbt.anvil.filters.DelegateMCAFilter;
|
||||
import com.boydti.fawe.jnbt.anvil.filters.RemapFilter;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
|
||||
import com.boydti.fawe.object.number.MutableLong;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.MethodCommands;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ConvertCommands extends MethodCommands {
|
||||
public ConvertCommands(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"anvil2leveldb"},
|
||||
usage = "<folder>",
|
||||
desc = "Convert the world between MCPE/PC values",
|
||||
help = "Convert the world between MCPE/PC values\n" +
|
||||
"The -r filter will skip block remapping",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.anvil.anvil2leveldb")
|
||||
public void anvil2leveldb(Player player, String folder, @Switch('f') boolean force, @Switch('r') boolean skipRemap) throws WorldEditException {
|
||||
ClipboardRemapper mapper;
|
||||
RemapFilter filter = new RemapFilter(ClipboardRemapper.RemapPlatform.PC, ClipboardRemapper.RemapPlatform.PE);
|
||||
|
||||
FaweQueue defaultQueue = SetQueue.IMP.getNewQueue(folder, true, false);
|
||||
try (MCAFile2LevelDB converter = new MCAFile2LevelDB(null, defaultQueue.getSaveFolder().getParentFile())) {
|
||||
|
||||
DelegateMCAFilter<MutableLong> delegate = new DelegateMCAFilter<MutableLong>(filter) {
|
||||
@Override
|
||||
public void finishFile(MCAFile file, MutableLong cache) {
|
||||
file.forEachChunk(new RunnableVal<MCAChunk>() {
|
||||
@Override
|
||||
public void run(MCAChunk value) {
|
||||
try {
|
||||
converter.write(value, !skipRemap, 0);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
file.clear();
|
||||
}
|
||||
};
|
||||
MCAFilter result = AnvilCommands.runWithWorld(player, folder, delegate, force);
|
||||
if (result != null) player.print(BBC.getPrefix() + BBC.VISITOR_BLOCK.format(filter.getTotal()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,475 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core.converter;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweVersion;
|
||||
import com.boydti.fawe.installer.BrowseButton;
|
||||
import com.boydti.fawe.installer.CloseButton;
|
||||
import com.boydti.fawe.installer.ImagePanel;
|
||||
import com.boydti.fawe.installer.InteractiveButton;
|
||||
import com.boydti.fawe.installer.InvisiblePanel;
|
||||
import com.boydti.fawe.installer.MinimizeButton;
|
||||
import com.boydti.fawe.installer.MovablePanel;
|
||||
import com.boydti.fawe.installer.TextAreaOutputStream;
|
||||
import com.boydti.fawe.installer.URLButton;
|
||||
import com.boydti.fawe.object.clipboard.remap.WikiScraper;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.wrappers.FakePlayer;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Font;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
public class ConverterFrame extends JFrame {
|
||||
private final InvisiblePanel loggerPanel;
|
||||
private final JProgressBar progressBar;
|
||||
private final JLabel title;
|
||||
private Color LIGHT_GRAY = new Color(0x66, 0x66, 0x66);
|
||||
private Color GRAY = new Color(0x44, 0x44, 0x46);
|
||||
private Color DARK_GRAY = new Color(0x33, 0x33, 0x36);
|
||||
private Color DARKER_GRAY = new Color(0x26, 0x26, 0x28);
|
||||
private Color INVISIBLE = new Color(0, 0, 0, 0);
|
||||
private Color OFF_WHITE = new Color(200, 200, 200);
|
||||
|
||||
private JTextArea loggerTextArea;
|
||||
private BrowseButton browseLoad;
|
||||
private BrowseButton browseSave;
|
||||
|
||||
public ConverterFrame() throws Exception {
|
||||
final MovablePanel movable = new MovablePanel(this);
|
||||
movable.setBorder(BorderFactory.createLineBorder(new Color(0x28, 0x28, 0x29)));
|
||||
|
||||
Container content = this.getContentPane();
|
||||
content.add(movable);
|
||||
this.setSize(720, 640);
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
this.setUndecorated(true);
|
||||
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
int x = (int) ((dimension.getWidth() - this.getWidth()) / 2);
|
||||
int y = (int) ((dimension.getHeight() - this.getHeight()) / 2);
|
||||
this.setLocation(x, y);
|
||||
this.setVisible(true);
|
||||
|
||||
if (this.transparency(0)) {
|
||||
fadeIn();
|
||||
}
|
||||
|
||||
movable.setBackground(DARK_GRAY);
|
||||
movable.setLayout(new BorderLayout());
|
||||
|
||||
JPanel topBar = new InvisiblePanel(new BorderLayout());
|
||||
{
|
||||
JPanel topBarLeft = new InvisiblePanel();
|
||||
JPanel topBarCenter = new InvisiblePanel();
|
||||
JPanel topBarRight = new InvisiblePanel();
|
||||
|
||||
this.title = new JLabel();
|
||||
title.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
title.setAlignmentX(Component.RIGHT_ALIGNMENT);
|
||||
title.setForeground(Color.LIGHT_GRAY);
|
||||
title.setFont(new Font("Lucida Sans Unicode", Font.PLAIN, 15));
|
||||
setTitle(null);
|
||||
|
||||
MinimizeButton minimize = new MinimizeButton(this);
|
||||
CloseButton exit = new CloseButton();
|
||||
|
||||
topBarLeft.setPreferredSize(new Dimension(96, 36));
|
||||
try {
|
||||
BufferedImage image = ImageIO.read(getClass().getResource("/axe-logo.png"));
|
||||
setIconImage(image);
|
||||
ImagePanel imgPanel = new ImagePanel(image);
|
||||
imgPanel.setPreferredSize(new Dimension(32, 36));
|
||||
topBarLeft.add(imgPanel);
|
||||
} catch (IOException ignore) {}
|
||||
|
||||
topBarCenter.add(title);
|
||||
topBarRight.add(minimize);
|
||||
topBarRight.add(exit);
|
||||
|
||||
topBar.add(topBarLeft, BorderLayout.WEST);
|
||||
topBar.add(topBarCenter, BorderLayout.CENTER);
|
||||
topBar.add(topBarRight, BorderLayout.EAST);
|
||||
}
|
||||
final JPanel mainContent = new InvisiblePanel(new BorderLayout());
|
||||
{
|
||||
File world = MainUtil.getWorkingDirectory("minecraft");
|
||||
long lastMod = Long.MIN_VALUE;
|
||||
if (world != null && world.exists()) {
|
||||
File saves = new File(world, "saves");
|
||||
if (saves.exists()) {
|
||||
for (File file : saves.listFiles()) {
|
||||
if (file.isDirectory()) {
|
||||
long modified = file.lastModified();
|
||||
if (modified > lastMod) {
|
||||
world = file;
|
||||
lastMod = modified;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final InteractiveButton browseLoadText = new InteractiveButton(world.getPath(), DARKER_GRAY) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
browseLoad.browse(new File(getText()).getParentFile());
|
||||
}
|
||||
};
|
||||
final InteractiveButton browseSaveText = new InteractiveButton(getDefaultOutput().getPath(), DARKER_GRAY) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
browseSave.browse(new File(getText()));
|
||||
}
|
||||
};
|
||||
for (JButton button : Arrays.asList(browseLoadText, browseSaveText)) {
|
||||
button.setForeground(OFF_WHITE);
|
||||
button.setBackground(DARKER_GRAY);
|
||||
button.setOpaque(true);
|
||||
button.setBorder(new EmptyBorder(4, 4, 4, 4));
|
||||
}
|
||||
browseLoad = new BrowseButton("_FROM") {
|
||||
@Override
|
||||
public void onSelect(File folder) {
|
||||
browseLoadText.setText(folder.getPath());
|
||||
movable.repaint();
|
||||
}
|
||||
};
|
||||
browseSave = new BrowseButton("_TO") {
|
||||
@Override
|
||||
public void onSelect(File folder) {
|
||||
browseSaveText.setText(folder.getPath());
|
||||
movable.repaint();
|
||||
}
|
||||
};
|
||||
|
||||
final JPanel browseContent = new InvisiblePanel(new BorderLayout());
|
||||
final JPanel browseLoadContent = new InvisiblePanel(new BorderLayout());
|
||||
final JPanel browseSaveContent = new InvisiblePanel(new BorderLayout());
|
||||
browseSaveContent.setBorder(new EmptyBorder(10, 0, 0, 0));
|
||||
JLabel selectWorld = new JLabel("Select World:");
|
||||
selectWorld.setForeground(OFF_WHITE);
|
||||
selectWorld.setPreferredSize(new Dimension(120, 0));
|
||||
JLabel output = new JLabel("Output:");
|
||||
output.setForeground(OFF_WHITE);
|
||||
output.setPreferredSize(new Dimension(120, 0));
|
||||
|
||||
browseLoadContent.add(selectWorld, BorderLayout.WEST);
|
||||
browseLoadContent.add(browseLoadText, BorderLayout.CENTER);
|
||||
browseLoadContent.add(browseLoad, BorderLayout.EAST);
|
||||
browseSaveContent.add(output, BorderLayout.WEST);
|
||||
browseSaveContent.add(browseSaveText, BorderLayout.CENTER);
|
||||
browseSaveContent.add(browseSave, BorderLayout.EAST);
|
||||
browseContent.add(browseLoadContent, BorderLayout.NORTH);
|
||||
browseContent.add(browseSaveContent, BorderLayout.SOUTH);
|
||||
|
||||
InteractiveButton install = new InteractiveButton(">> Convert World <<", DARKER_GRAY) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
install(browseLoadText.getText(), browseSaveText.getText());
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final JPanel installContent = new InvisiblePanel(new FlowLayout());
|
||||
install.setPreferredSize(new Dimension(Integer.MAX_VALUE, 32));
|
||||
installContent.add(install);
|
||||
installContent.setBorder(new EmptyBorder(10, 0, 10, 0));
|
||||
this.loggerPanel = new InvisiblePanel(new BorderLayout());
|
||||
loggerPanel.setPreferredSize(new Dimension(Integer.MAX_VALUE, 380));
|
||||
loggerTextArea = new JTextArea();
|
||||
loggerTextArea.setBackground(Color.GRAY);
|
||||
loggerTextArea.setForeground(Color.DARK_GRAY);
|
||||
loggerTextArea.setFont(new Font(loggerTextArea.getFont().getName(), Font.BOLD, 9));
|
||||
loggerTextArea.setBorder(BorderFactory.createCompoundBorder(loggerTextArea.getBorder(), BorderFactory.createEmptyBorder(6, 6, 6, 6)));
|
||||
JScrollPane scroll = new JScrollPane(loggerTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scroll.setBackground(DARK_GRAY);
|
||||
scroll.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
loggerPanel.add(scroll);
|
||||
loggerPanel.setVisible(false);
|
||||
|
||||
this.progressBar = new JProgressBar();
|
||||
progressBar.setVisible(false);
|
||||
progressBar.setStringPainted(true);
|
||||
progressBar.setBackground(DARK_GRAY);
|
||||
progressBar.setForeground(OFF_WHITE);
|
||||
|
||||
mainContent.setBorder(new EmptyBorder(6, 32, 6, 32));
|
||||
mainContent.add(browseContent, BorderLayout.NORTH);
|
||||
mainContent.add(installContent, BorderLayout.CENTER);
|
||||
|
||||
final JPanel console = new InvisiblePanel(new BorderLayout());
|
||||
console.setBorder(new EmptyBorder(6, 0, 6, 0));
|
||||
console.add(progressBar, BorderLayout.SOUTH);
|
||||
console.add(loggerPanel, BorderLayout.NORTH);
|
||||
|
||||
mainContent.add(console, BorderLayout.SOUTH);
|
||||
}
|
||||
JPanel bottomBar = new InvisiblePanel();
|
||||
{
|
||||
try {
|
||||
InputStream stream = getClass().getResourceAsStream("/fawe.properties");
|
||||
java.util.Scanner scanner = new java.util.Scanner(stream).useDelimiter("\\A");
|
||||
String versionString = scanner.next().trim();
|
||||
scanner.close();
|
||||
FaweVersion version = new FaweVersion(versionString);
|
||||
String date = new Date(100 + version.year, version.month, version.day).toGMTString();
|
||||
String build = "https://ci.athion.net/job/FastAsyncWorldEdit/" + version.build;
|
||||
String commit = "https://github.com/boy0001/FastAsyncWorldedit/commit/" + Integer.toHexString(version.hash);
|
||||
String footerMessage = "FAWE v" + version.major + "." + version.minor + "." + version.patch + " by Empire92 (c) 2017 (GPL v3.0)";
|
||||
URL licenseUrl = new URL("https://github.com/boy0001/FastAsyncWorldedit/blob/master/LICENSE");
|
||||
URLButton licenseButton = new URLButton(licenseUrl, footerMessage);
|
||||
bottomBar.add(licenseButton);
|
||||
} catch (Throwable ignore) {
|
||||
ignore.printStackTrace();
|
||||
}
|
||||
URL chat = new URL("https://discord.gg/ngZCzbU");
|
||||
URLButton chatButton = new URLButton(chat, "Chat");
|
||||
bottomBar.add(chatButton);
|
||||
URL wiki = new URL("https://github.com/boy0001/FastAsyncWorldedit/wiki");
|
||||
URLButton wikiButton = new URLButton(wiki, "Wiki");
|
||||
bottomBar.add(wikiButton);
|
||||
URL issue = new URL("https://github.com/boy0001/FastAsyncWorldedit/issues/new");
|
||||
URLButton issueButton = new URLButton(issue, "Report Issue");
|
||||
bottomBar.add(issueButton);
|
||||
bottomBar.setBackground(new Color(0x26, 0x26, 0x28));
|
||||
|
||||
bottomBar.add(new InteractiveButton("Debug") {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Map<Thread, StackTraceElement[]> stacks = Thread.getAllStackTraces();
|
||||
for (Map.Entry<Thread, StackTraceElement[]> entry : stacks.entrySet()) {
|
||||
Thread thread = entry.getKey();
|
||||
Fawe.debug("--------------------------------------------------------------------------------------------");
|
||||
Fawe.debug("Thread: " + thread.getName() + " | Id: " + thread.getId() + " | Alive: " + thread.isAlive());
|
||||
for (StackTraceElement elem : entry.getValue()) {
|
||||
Fawe.debug(elem.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We want to add these a bit later
|
||||
movable.add(topBar, BorderLayout.NORTH);
|
||||
this.setVisible(true);
|
||||
this.repaint();
|
||||
movable.add(mainContent, BorderLayout.CENTER);
|
||||
this.setVisible(true);
|
||||
this.repaint();
|
||||
movable.add(bottomBar, BorderLayout.SOUTH);
|
||||
this.setVisible(true);
|
||||
this.repaint();
|
||||
|
||||
async(() -> downloadDependencies());
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
if (title == null) title = "(FAWE) Anvil and LevelDB converter";
|
||||
this.title.setText(title);
|
||||
debug(title);
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void prompt(String message) {
|
||||
JOptionPane.showMessageDialog(null, message);
|
||||
Fawe.debug(message);
|
||||
}
|
||||
|
||||
public void debug(String m) {
|
||||
System.out.println(m);
|
||||
}
|
||||
|
||||
public void setProgress(String text, int percent) {
|
||||
Border border = BorderFactory.createTitledBorder(new EmptyBorder(0, 0, 0, 0), "Time remaining: " + text, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, new Font("Lucida Sans Unicode",Font.PLAIN,12), OFF_WHITE);
|
||||
progressBar.setVisible(true);
|
||||
progressBar.setBorder(border);
|
||||
progressBar.setValue(percent);
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void fadeIn() {
|
||||
async(() -> {
|
||||
for (float i = 0; i <= 1.015; i += 0.016) {
|
||||
if (!transparency(Math.min(1, i))) return;
|
||||
try {
|
||||
Thread.sleep(16);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (UnsupportedOperationException ignore) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean transparency(float val) {
|
||||
try {
|
||||
super.setOpacity(val);
|
||||
return true;
|
||||
} catch (UnsupportedOperationException ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private File getDefaultOutput() {
|
||||
if (MainUtil.getPlatform() == MainUtil.OS.WINDOWS) {
|
||||
String applicationData = System.getenv("APPDATA");
|
||||
if (applicationData != null && new File(applicationData).exists()) {
|
||||
File saves = new File(new File(applicationData).getParentFile(), "Local/Packages/Microsoft.MinecraftUWP_8wekyb3d8bbwe/LocalState/games/com.mojang/minecraftWorlds");
|
||||
if (saves.exists()) return saves.getAbsoluteFile();
|
||||
}
|
||||
}
|
||||
return new File(".");
|
||||
}
|
||||
|
||||
private void async(Runnable r) {
|
||||
new Thread(r).start();
|
||||
}
|
||||
|
||||
private AtomicBoolean dependenciesLoaded = new AtomicBoolean(false);
|
||||
private void downloadDependencies() {
|
||||
synchronized (dependenciesLoaded) {
|
||||
if (dependenciesLoaded.get()) return;
|
||||
try {
|
||||
ExecutorService pool = Executors.newCachedThreadPool();
|
||||
WikiScraper scraper = new WikiScraper();
|
||||
|
||||
File lib = new File("lib");
|
||||
File leveldb = new File(lib, "leveldb_v1.jar");
|
||||
URL levelDbUrl = new URL("https://git.io/vdZ9e");
|
||||
|
||||
pool.submit((Runnable) () -> {
|
||||
try {
|
||||
MainUtil.download(levelDbUrl, leveldb);
|
||||
MainUtil.loadURLClasspath(leveldb.toURL());
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
pool.submit((Runnable) () -> {
|
||||
try {
|
||||
scraper.scapeOrCache(WikiScraper.Wiki.ITEM_MAPPINGS_PE);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
pool.submit((Runnable) () -> {
|
||||
try {
|
||||
scraper.scapeOrCache(WikiScraper.Wiki.ITEM_MAPPINGS_PC);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
pool.submit((Runnable) () -> {
|
||||
try {
|
||||
scraper.scapeOrCache(WikiScraper.Wiki.ENTITY_MAPPINGS);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
pool.shutdown();
|
||||
try {
|
||||
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
dependenciesLoaded.set(true);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void install(String input, String output) throws Exception {
|
||||
if (!loggerPanel.isVisible()) {
|
||||
loggerPanel.setVisible(true);
|
||||
this.repaint();
|
||||
TextAreaOutputStream logger = new TextAreaOutputStream(loggerTextArea);
|
||||
System.setOut(logger);
|
||||
System.setErr(logger);
|
||||
}
|
||||
if (input == null || input.isEmpty()) {
|
||||
prompt("No world selected");
|
||||
return;
|
||||
}
|
||||
if (output == null || output.isEmpty()) {
|
||||
prompt("No output folder selection");
|
||||
return;
|
||||
}
|
||||
if (new File(output, new File(input).getName()).exists()) {
|
||||
prompt("Please select another output directory, or delete it, as there are files already there.");
|
||||
return;
|
||||
}
|
||||
final File dirMc = new File(input);
|
||||
if (!dirMc.exists()) {
|
||||
prompt("Folder does not exist");
|
||||
return;
|
||||
}
|
||||
if (!dirMc.isDirectory()) {
|
||||
prompt("You must select a folder, not a file");
|
||||
return;
|
||||
}
|
||||
Thread installThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FakePlayer console = FakePlayer.getConsole();
|
||||
try {
|
||||
debug("Downloading levedb.jar and mappings (~4MB), please wait...");
|
||||
downloadDependencies();
|
||||
debug("Starting converter...");
|
||||
File newWorldFile = new File(output, dirMc.getName());
|
||||
MapConverter converter = MapConverter.get(dirMc, newWorldFile);
|
||||
converter.accept(ConverterFrame.this);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
prompt("[ERROR] Conversion failed, you will have to do it manually (Nukkit server + anvil2leveldb command)");
|
||||
return;
|
||||
}
|
||||
System.gc();
|
||||
System.gc();
|
||||
}
|
||||
});
|
||||
installThread.start();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ConverterFrame window = new ConverterFrame();
|
||||
}
|
||||
}
|
|
@ -1,374 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core.converter;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAChunk;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAQueue;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAQueueMap;
|
||||
import com.boydti.fawe.jnbt.anvil.MutableMCABackedBaseBlock;
|
||||
import com.boydti.fawe.jnbt.anvil.filters.RemapFilter;
|
||||
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
|
||||
import com.boydti.fawe.object.io.PGZIPOutputStream;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.google.common.io.LittleEndianDataInputStream;
|
||||
import com.sk89q.jnbt.ByteTag;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.LongTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.jnbt.NamedTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.iq80.leveldb.DB;
|
||||
import org.iq80.leveldb.Options;
|
||||
import org.iq80.leveldb.impl.Iq80DBFactory;
|
||||
|
||||
public class LevelDBToMCAFile extends MapConverter {
|
||||
|
||||
private final DB db;
|
||||
private final ClipboardRemapper remapper;
|
||||
private final ForkJoinPool pool;
|
||||
|
||||
public LevelDBToMCAFile(File from, File to) {
|
||||
super(from, to);
|
||||
try {
|
||||
// BundledBlockData.getInstance().loadFromResource();
|
||||
this.pool = new ForkJoinPool();
|
||||
this.remapper = new ClipboardRemapper(ClipboardRemapper.RemapPlatform.PE, ClipboardRemapper.RemapPlatform.PC);
|
||||
int bufferSize = (int) Math.min(Integer.MAX_VALUE, Math.max((long) (MemUtil.getFreeBytes() * 0.8), 134217728));
|
||||
this.db = Iq80DBFactory.factory.open(new File(from, "db"),
|
||||
new Options()
|
||||
.createIfMissing(false)
|
||||
.verifyChecksums(false)
|
||||
.blockSize(262144) // 256K
|
||||
.cacheSize(bufferSize) // 8MB
|
||||
);
|
||||
try {
|
||||
this.db.suspendCompactions();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
pool.shutdown();
|
||||
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
db.close();
|
||||
Fawe.debug("Done!");
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ConverterFrame app) {
|
||||
try {
|
||||
// World name
|
||||
String worldName;
|
||||
File levelName = new File(folderFrom, "levelname.txt");
|
||||
if (levelName.exists()) {
|
||||
byte[] encoded = Files.readAllBytes(levelName.toPath());
|
||||
worldName = new String(encoded);
|
||||
} else {
|
||||
worldName = folderFrom.toString();
|
||||
}
|
||||
File worldOut = new File(folderTo, worldName);
|
||||
|
||||
// Level dat
|
||||
File levelDat = new File(folderFrom, "level.dat");
|
||||
copyLevelDat(levelDat);
|
||||
|
||||
// Chunks
|
||||
MCAQueue queue = new MCAQueue(worldName, new File(worldOut, "region"), true);
|
||||
RemapFilter filter = new RemapFilter(this.remapper);
|
||||
db.forEach(entry -> {
|
||||
byte[] key = entry.getKey();
|
||||
Tag tag = Tag.get(key);
|
||||
if (tag == null) {
|
||||
if (key.length > 8) {
|
||||
String name = new String(key);
|
||||
}
|
||||
return;
|
||||
}
|
||||
int cx = tag.getX(key);
|
||||
int cz = tag.getZ(key);
|
||||
byte[] value = entry.getValue();
|
||||
MCAChunk chunk = (MCAChunk) queue.getFaweChunk(cx, cz);
|
||||
|
||||
switch (tag) {
|
||||
case Data2D: {
|
||||
// height
|
||||
ByteBuffer buffer = ByteBuffer.wrap(value);
|
||||
int[] heightArray = chunk.getHeightMapArray();
|
||||
for (int i = 0, j = 0; i < heightArray.length; i++, j += 2) {
|
||||
heightArray[i] = buffer.getShort();
|
||||
}
|
||||
// biome
|
||||
int biomeOffset = (heightArray.length << 1);
|
||||
if (value.length > biomeOffset) {
|
||||
System.arraycopy(value, biomeOffset, chunk.biomes, 0, chunk.biomes.length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SubChunkPrefix: {
|
||||
int layer = key[9];
|
||||
byte[] ids = getOrCreate(chunk.ids, layer, 4096);
|
||||
byte[] data = getOrCreate(chunk.data, layer, 2048);
|
||||
byte[] blockLight = getOrCreate(chunk.blockLight, layer, 2048);
|
||||
byte[] skyLight = getOrCreate(chunk.skyLight, layer, 2048);
|
||||
|
||||
copySection(ids, value, 1);
|
||||
copySection(data, value, 1 + 4096);
|
||||
copySection(skyLight, value, 1 + 4096 + 2048);
|
||||
copySection(blockLight, value, 1 + 4096 + 2048 + 2048);
|
||||
|
||||
chunk.filterBlocks(new MutableMCABackedBaseBlock(), filter);
|
||||
break;
|
||||
}
|
||||
case BlockEntity: {
|
||||
List<NamedTag> tags = read(value);
|
||||
for (NamedTag nt : tags) {
|
||||
com.sk89q.jnbt.Tag tile = nt.getTag();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Entity:
|
||||
List<NamedTag> tags = read(value);
|
||||
for (NamedTag nt : tags) {
|
||||
com.sk89q.jnbt.Tag ent = nt.getTag();
|
||||
chunk.setEntity((CompoundTag) ent);
|
||||
}
|
||||
break;
|
||||
case PendingTicks:
|
||||
break;
|
||||
case BlockExtraData:
|
||||
break;
|
||||
case LegacyTerrain:
|
||||
case Data2DLegacy:
|
||||
Fawe.debug("Legacy terrain not supported, please update. " + tag);
|
||||
case BiomeState:
|
||||
case FinalizedState:
|
||||
case Version:
|
||||
break;
|
||||
}
|
||||
});
|
||||
MCAQueueMap map = (MCAQueueMap) queue.getFaweQueueMap();
|
||||
while (map.next(0, Long.MAX_VALUE));
|
||||
queue.clear();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
close();
|
||||
app.prompt("Conversion complete!");
|
||||
}
|
||||
}
|
||||
|
||||
private List<NamedTag> read(byte[] data) {
|
||||
ArrayList<NamedTag> list = new ArrayList<>();
|
||||
ByteArrayInputStream baos = new ByteArrayInputStream(data);
|
||||
try (NBTInputStream in = new NBTInputStream((DataInput) new LittleEndianDataInputStream(baos))) {
|
||||
while (baos.available() > 0) {
|
||||
NamedTag nt = in.readNamedTag();
|
||||
list.add(nt);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void copySection(byte[] dest, byte[] src, int srcPos) {
|
||||
if (src.length <= srcPos) return;
|
||||
switch (dest.length) {
|
||||
case 4096: {
|
||||
int index = 0;
|
||||
int i1, i2, i3;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
i1 = y;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
i2 = i1 + (z << 4);
|
||||
for (int x = 0; x < 16; x++) {
|
||||
i3 = i2 + (x << 8);
|
||||
dest[index] = src[srcPos + i3];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2048: {
|
||||
int index = 0;
|
||||
int i1, i2, i3, i4;
|
||||
for (int x = 0; x < 16;) {
|
||||
{
|
||||
i1 = x;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
i2 = i1 + (z << 4);
|
||||
for (int y = 0; y < 16; y += 2) {
|
||||
i3 = i2 + (y << 8);
|
||||
i4 = i2 + ((y + 1) << 8);
|
||||
byte newVal = (byte) ((src[srcPos + (i3 >> 1)] & 0xF) + ((src[srcPos + (i4 >> 1)] & 0xF) << 4));
|
||||
dest[index] = newVal;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
x++;
|
||||
{
|
||||
i1 = x;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
i2 = i1 + (z << 4);
|
||||
for (int y = 0; y < 16; y += 2) {
|
||||
i3 = i2 + (y << 8);
|
||||
i4 = i2 + ((y + 1) << 8);
|
||||
byte newVal = (byte) (((src[srcPos + (i3 >> 1)] & 0xF0) >> 4) + ((src[srcPos + (i4 >> 1)] & 0xF0)));
|
||||
dest[index] = newVal;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
x++;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
System.arraycopy(src, srcPos, dest, 0, dest.length);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getOrCreate(byte[][] arr, int index, int len) {
|
||||
byte[] data = arr[index];
|
||||
if (data == null) {
|
||||
arr[index] = data = new byte[len];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public void copyLevelDat(File in) throws IOException {
|
||||
copyLevelDat(this.folderTo, in);
|
||||
}
|
||||
|
||||
|
||||
public static void copyLevelDat(File folderTo, File in) throws IOException {
|
||||
File levelDat = new File(folderTo, "level.dat");
|
||||
if (!levelDat.exists()) {
|
||||
folderTo.mkdirs();
|
||||
levelDat.createNewFile();
|
||||
}
|
||||
try (LittleEndianDataInputStream ledis = new LittleEndianDataInputStream(new FileInputStream(in))) {
|
||||
int version = ledis.readInt(); // Ignored
|
||||
int length = ledis.readInt(); // Ignored
|
||||
NBTInputStream nis = new NBTInputStream((DataInput) ledis);
|
||||
NamedTag named = nis.readNamedTag();
|
||||
com.sk89q.jnbt.CompoundTag tag = (CompoundTag) named.getTag();
|
||||
Map<String, com.sk89q.jnbt.Tag> map = ReflectionUtils.getMap(tag.getValue());
|
||||
|
||||
Map<String, String> gameRules = new HashMap<>();
|
||||
gameRules.put("firedamage", "firedamage");
|
||||
gameRules.put("falldamage", "falldamage");
|
||||
gameRules.put("dofiretick", "doFireTick");
|
||||
gameRules.put("drowningdamage", "drowningdamage");
|
||||
gameRules.put("doentitydrops", "doEntityDrops");
|
||||
gameRules.put("keepinventory", "keepInventory");
|
||||
gameRules.put("sendcommandfeedback", "sendCommandFeedback");
|
||||
gameRules.put("dodaylightcycle", "doDaylightCycle");
|
||||
gameRules.put("commandblockoutput", "commandBlockOutput");
|
||||
gameRules.put("domobloot", "doMobLoot");
|
||||
gameRules.put("domobspawning", "doMobSpawning");
|
||||
gameRules.put("doweathercycle", "doWeatherCycle");
|
||||
gameRules.put("mobgriefing", "mobGriefing");
|
||||
gameRules.put("dotiledrops", "doTileDrops");
|
||||
|
||||
HashMap<String, com.sk89q.jnbt.Tag> ruleTagValue = new HashMap<>();
|
||||
for (Map.Entry<String, String> rule : gameRules.entrySet()) {
|
||||
com.sk89q.jnbt.Tag value = map.remove(rule.getKey());
|
||||
if (value instanceof ByteTag) {
|
||||
value = new StringTag((Byte) value.getValue() == 1 ? "true" : "false");
|
||||
}
|
||||
if (value != null) {
|
||||
ruleTagValue.put(rule.getValue(), value);
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<String> allowed = new HashSet<>(Arrays.asList(
|
||||
"lightningTime", "pvp", "LevelName", "Difficulty", "GameType", "Generator", "LastPlayed", "RandomSeed", "StorageVersion", "Time", "commandsEnabled", "currentTick", "rainTime", "SpawnX", "SpawnY", "SpawnZ", "SizeOnDisk"
|
||||
));
|
||||
Iterator<Map.Entry<String, com.sk89q.jnbt.Tag>> iterator = map.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, com.sk89q.jnbt.Tag> entry = iterator.next();
|
||||
if (!allowed.contains(entry.getKey())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
map.put("GameRules", new CompoundTag(ruleTagValue));
|
||||
|
||||
map.put("version", new IntTag(19133));
|
||||
map.put("DataVersion", new IntTag(1343));
|
||||
map.put("initialized", new ByteTag((byte) 1));
|
||||
map.putIfAbsent("SizeOnDisk", new LongTag(0));
|
||||
|
||||
// generator
|
||||
int generator = tag.getInt("Generator");
|
||||
String name;
|
||||
switch (generator) {
|
||||
default:
|
||||
case 1:
|
||||
name = "default";
|
||||
break;
|
||||
case 2:
|
||||
name = "flat";
|
||||
break;
|
||||
}
|
||||
map.put("generatorName", new StringTag(name));
|
||||
map.put("generatorOptions", new StringTag(""));
|
||||
map.put("generatorVersion", new IntTag(1));
|
||||
map.put("Difficulty", new ByteTag((byte) tag.getInt("Difficulty")));
|
||||
map.put("DifficultyLocked", new ByteTag((byte) 0));
|
||||
map.put("MapFeatures", new ByteTag((byte) 1));
|
||||
map.put("allowCommands", new ByteTag(tag.getByte("commandsEnabled")));
|
||||
long time = tag.getLong("Time");
|
||||
if (time == 0) time = tag.getLong("CurrentTick");
|
||||
map.put("Time", new LongTag(time));
|
||||
map.put("spawnMobs", new ByteTag((byte) 1));
|
||||
Long lastPlayed = tag.getLong("LastPlayed");
|
||||
if (lastPlayed != null && lastPlayed < Integer.MAX_VALUE) {
|
||||
lastPlayed = lastPlayed * 1000;
|
||||
map.put("LastPlayed", new LongTag(lastPlayed));
|
||||
}
|
||||
|
||||
HashMap<String, com.sk89q.jnbt.Tag> data = new HashMap<>();
|
||||
data.put("Data", new CompoundTag(map));
|
||||
CompoundTag root = new CompoundTag(data);
|
||||
|
||||
try (NBTOutputStream nos = new NBTOutputStream(new PGZIPOutputStream(new FileOutputStream(levelDat)))) {
|
||||
nos.writeNamedTag("level.dat", root);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,877 +0,0 @@
|
|||
package com.boydti.fawe.nukkit.core.converter;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAChunk;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAFile;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAFilter;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAQueue;
|
||||
import com.boydti.fawe.jnbt.anvil.filters.DelegateMCAFilter;
|
||||
import com.boydti.fawe.jnbt.anvil.filters.RemapFilter;
|
||||
import com.boydti.fawe.object.FaweInputStream;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
|
||||
import com.boydti.fawe.object.io.LittleEndianOutputStream;
|
||||
import com.boydti.fawe.object.number.MutableLong;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.github.luben.zstd.ZstdInputStream;
|
||||
import com.github.luben.zstd.ZstdOutputStream;
|
||||
import com.sk89q.jnbt.ByteTag;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.FloatTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.LongTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.jnbt.NamedTag;
|
||||
import com.sk89q.jnbt.ShortTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
import org.iq80.leveldb.CompressionType;
|
||||
import org.iq80.leveldb.DB;
|
||||
import org.iq80.leveldb.Options;
|
||||
import org.iq80.leveldb.impl.Iq80DBFactory;
|
||||
|
||||
public class MCAFile2LevelDB extends MapConverter {
|
||||
private final byte[] VERSION = new byte[] { 4 };
|
||||
private final byte[] COMPLETE_STATE = new byte[] { 2, 0, 0, 0 };
|
||||
|
||||
private final DB db;
|
||||
private final ClipboardRemapper remapper;
|
||||
private final ForkJoinPool pool;
|
||||
private boolean closed;
|
||||
private LongAdder submittedChunks = new LongAdder();
|
||||
private LongAdder submittedFiles = new LongAdder();
|
||||
|
||||
private LongAdder totalOperations = new LongAdder();
|
||||
private long estimatedOperations;
|
||||
|
||||
private long time;
|
||||
private boolean remap;
|
||||
|
||||
private long startTime;
|
||||
private ConverterFrame app;
|
||||
|
||||
private ConcurrentLinkedQueue<CompoundTag> portals = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public MCAFile2LevelDB(File folderFrom, File folderTo) {
|
||||
super(folderFrom, folderTo);
|
||||
this.startTime = System.currentTimeMillis();
|
||||
try {
|
||||
if (!folderTo.exists()) {
|
||||
folderTo.mkdirs();
|
||||
}
|
||||
String worldName = folderTo.getName();
|
||||
try (PrintStream out = new PrintStream(new FileOutputStream(new File(folderTo, "levelname.txt")))) {
|
||||
out.print(worldName);
|
||||
}
|
||||
|
||||
this.pool = new ForkJoinPool();
|
||||
this.remapper = new ClipboardRemapper(ClipboardRemapper.RemapPlatform.PC, ClipboardRemapper.RemapPlatform.PE);
|
||||
BundledBlockData.getInstance().loadFromResource();
|
||||
|
||||
int bufferSize = (int) Math.min(Integer.MAX_VALUE, Math.max((long) (MemUtil.getFreeBytes() * 0.8), 134217728));
|
||||
this.db = Iq80DBFactory.factory.open(new File(folderTo, "db"),
|
||||
new Options()
|
||||
.createIfMissing(true)
|
||||
.verifyChecksums(false)
|
||||
.compressionType(CompressionType.ZLIB)
|
||||
.blockSize(262144) // 256K
|
||||
.cacheSize(8388608) // 8MB
|
||||
.writeBufferSize(134217728) // >=512MB
|
||||
);
|
||||
// try {
|
||||
// this.db.suspendCompactions();
|
||||
// } catch (InterruptedException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private double lastPercent;
|
||||
private double lastTimeRatio;
|
||||
|
||||
private void resetProgress(int estimatedOperations) {
|
||||
startTime = System.currentTimeMillis();
|
||||
lastPercent = 0;
|
||||
lastTimeRatio = 0;
|
||||
this.totalOperations.reset();
|
||||
this.estimatedOperations = estimatedOperations;
|
||||
}
|
||||
|
||||
private void progress(int increment) {
|
||||
if (app == null) return;
|
||||
totalOperations.add(increment);
|
||||
|
||||
long completedOps = totalOperations.longValue();
|
||||
double percent = Math.max(0, Math.min(100, (Math.pow(completedOps, 1.3) * 100 / Math.pow(estimatedOperations, 1.3))));
|
||||
double lastPercent = (this.lastPercent == 0 ? percent : this.lastPercent);
|
||||
percent = (percent + lastPercent * 7) / 8;
|
||||
if (increment != 0) this.lastPercent = percent;
|
||||
|
||||
double remaining = estimatedOperations - completedOps;
|
||||
long timeSpent = System.currentTimeMillis() - startTime;
|
||||
|
||||
double totalTime = Math.pow(estimatedOperations, 1.3) * 1000;
|
||||
double estimatedTimeSpent = Math.pow(completedOps, 1.3) * 1000;
|
||||
|
||||
double timeRemaining;
|
||||
if (completedOps > 16) {
|
||||
double timeRatio = (timeSpent * totalTime / estimatedTimeSpent);
|
||||
double lastTimeRatio = this.lastTimeRatio == 0 ? timeRatio : this.lastTimeRatio;
|
||||
timeRatio = (timeRatio + lastTimeRatio * 7) / 8;
|
||||
if (increment != 0) this.lastTimeRatio = timeRatio;
|
||||
timeRemaining = timeRatio - timeSpent;
|
||||
} else {
|
||||
timeRemaining = ((long) totalTime >> 4) - timeSpent;
|
||||
}
|
||||
String msg = MainUtil.secToTime((long) (timeRemaining / 1000));
|
||||
app.setProgress(msg, (int) percent);
|
||||
}
|
||||
|
||||
public DelegateMCAFilter<MutableLong> toFilter(final int dimension) {
|
||||
RemapFilter filter = new RemapFilter(ClipboardRemapper.RemapPlatform.PC, ClipboardRemapper.RemapPlatform.PE);
|
||||
filter.setDimension(dimension);
|
||||
|
||||
DelegateMCAFilter<MutableLong> delegate = new DelegateMCAFilter<MutableLong>(filter) {
|
||||
@Override
|
||||
public void finishFile(MCAFile file, MutableLong cache) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
MCAChunk chunk = file.getCachedChunk(x, z);
|
||||
if (chunk != null) {
|
||||
try {
|
||||
write(chunk, !file.getFile().getName().endsWith(".mcapm"), dimension);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file.clear();
|
||||
|
||||
progress(1);
|
||||
submittedFiles.increment();
|
||||
if ((submittedFiles.longValue() & 7) == 0) {
|
||||
// flush();
|
||||
}
|
||||
}
|
||||
};
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void accept(ConverterFrame app) {
|
||||
this.app = app;
|
||||
|
||||
app.setTitle("Copying level data");
|
||||
File levelDat = new File(folderFrom, "level.dat");
|
||||
if (levelDat.exists()) {
|
||||
try {
|
||||
copyLevelDat(levelDat);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
app.setTitle("Scanning worlds...");
|
||||
List<CompoundTag> portals = new ArrayList<>();
|
||||
String[] dimDirs = {"DIM-1/region", "DIM1/region", "region"};
|
||||
int[] dimIds = {1, 2, 0};
|
||||
File[] regionFolders = new File[dimDirs.length];
|
||||
int totalFiles = 0;
|
||||
for (int i = 0; i < dimDirs.length; i++) {
|
||||
File source = new File(folderFrom, dimDirs[i]);
|
||||
if (source.exists()) {
|
||||
regionFolders[i] = source;
|
||||
totalFiles += source.listFiles().length;
|
||||
}
|
||||
}
|
||||
this.estimatedOperations = totalFiles;
|
||||
|
||||
Thread progressThread = new Thread(() -> {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
progress(0);
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
progressThread.start();
|
||||
|
||||
for (int i = 0; i < regionFolders.length; i++) {
|
||||
File source = regionFolders[i];
|
||||
if (source != null) {
|
||||
Fawe.debugPlain(" - dimension " + dimIds[i] + " (" + dimDirs[i] + ")");
|
||||
|
||||
DelegateMCAFilter filter = toFilter(dimIds[i]);
|
||||
MCAQueue queue = new MCAQueue(null, source, true);
|
||||
|
||||
Comparator<File> seqUnsPos = new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File f1, File f2) {
|
||||
int[] left = MainUtil.regionNameToCoords(f1.getPath());
|
||||
int[] right = MainUtil.regionNameToCoords(f2.getPath());
|
||||
//
|
||||
int minLength = Math.min(left.length, right.length);
|
||||
|
||||
for(int i = 0; i < minLength; ++i) {
|
||||
int lb = left[i] << 5;
|
||||
int rb = right[i] << 5;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
int shift = (j << 3);
|
||||
int sbl = (lb >> shift) & 0xFF;
|
||||
int sbr = (rb >> shift) & 0xFF;
|
||||
int result = sbl - sbr;
|
||||
if(result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return left.length - right.length;
|
||||
}
|
||||
};
|
||||
|
||||
MCAFilter result = queue.filterWorld(filter, seqUnsPos);
|
||||
portals.addAll(((RemapFilter) filter.getFilter()).getPortals());
|
||||
}
|
||||
}
|
||||
|
||||
Fawe.debugPlain(" - including portals");
|
||||
// Portals
|
||||
if (!portals.isEmpty()) {
|
||||
CompoundTag portalData = new CompoundTag(Collections.singletonMap("PortalRecords", new ListTag(CompoundTag.class, portals)));
|
||||
CompoundTag portalsTag = new CompoundTag(Collections.singletonMap("data", portalData));
|
||||
try {
|
||||
db.put("portals".getBytes(), write(Arrays.asList(portalsTag)));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
app.setTitle("Writing converted data...");
|
||||
close();
|
||||
progressThread.interrupt();
|
||||
app.setProgress("Done", 0);
|
||||
app.setTitle(null);
|
||||
app.prompt(
|
||||
"Conversion complete!\n" +
|
||||
" - The world save is still being compacted, but you can close the program anytime\n" +
|
||||
" - There will be another prompt when this finishes\n" +
|
||||
"\n" +
|
||||
"What is not converted?\n" +
|
||||
" - Inventory is not copied\n" +
|
||||
" - Some block nbt may not copy\n" +
|
||||
" - Any custom generator settings may not work\n" +
|
||||
" - May not match up with new terrain"
|
||||
);
|
||||
Fawe.debugPlain("Starting compaction");
|
||||
compact();
|
||||
app.prompt("Compaction complete!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
try {
|
||||
if (closed == (closed = true)) return;
|
||||
|
||||
Fawe.debugPlain("Collecting threads");
|
||||
pool.shutdown();
|
||||
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
|
||||
resetProgress(cache.size());
|
||||
ArrayList<FileCache> files = new ArrayList<>(cache.values());
|
||||
Collections.sort(files);
|
||||
for (FileCache file : files) {
|
||||
file.close();
|
||||
progress(1);
|
||||
}
|
||||
|
||||
Fawe.debugPlain("Closing");
|
||||
db.close();
|
||||
Fawe.debugPlain("Done! (but still compacting)");
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void compact() {
|
||||
// Since the library doesn't support it, only way to flush the cache is to loop over everything
|
||||
try (DB newDb = Iq80DBFactory.factory.open(new File(folderTo, "db"), new Options()
|
||||
.verifyChecksums(false)
|
||||
.blockSize(262144) // 256K
|
||||
.cacheSize(8388608) // 8MB
|
||||
.writeBufferSize(134217728) // >=128MB
|
||||
)) {
|
||||
newDb.close();
|
||||
} catch (Throwable ignore) {}
|
||||
Fawe.debug("Done compacting!");
|
||||
}
|
||||
|
||||
public void copyLevelDat(File in) throws IOException {
|
||||
File levelDat = new File(folderTo, "level.dat");
|
||||
try (NBTInputStream nis = new NBTInputStream(new GZIPInputStream(new FileInputStream(in)))) {
|
||||
if (!levelDat.exists()) {
|
||||
levelDat.createNewFile();
|
||||
}
|
||||
NamedTag named = nis.readNamedTag();
|
||||
com.sk89q.jnbt.CompoundTag tag = (CompoundTag) ((CompoundTag) (named.getTag())).getValue().get("Data");
|
||||
Map<String, com.sk89q.jnbt.Tag> map = ReflectionUtils.getMap(tag.getValue());
|
||||
|
||||
HashSet<String> allowed = new HashSet<>(Arrays.asList(
|
||||
"Difficulty", "GameType", "Generator", "LastPlayed", "RandomSeed", "StorageVersion", "Time", "commandsEnabled", "currentTick", "rainTime", "spawnMobs", "GameRules", "SpawnX", "SpawnY", "SpawnZ"
|
||||
));
|
||||
Iterator<Map.Entry<String, com.sk89q.jnbt.Tag>> iterator = map.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, com.sk89q.jnbt.Tag> entry = iterator.next();
|
||||
if (!allowed.contains(entry.getKey())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
{
|
||||
Map<String, com.sk89q.jnbt.Tag> gameRules = ((CompoundTag) map.remove("GameRules")).getValue();
|
||||
for (Map.Entry<String, com.sk89q.jnbt.Tag> entry : gameRules.entrySet()) {
|
||||
String key = entry.getKey().toLowerCase();
|
||||
String value = ((StringTag) entry.getValue()).getValue();
|
||||
if (StringMan.isEqualIgnoreCaseToAny(value, "true", "false")) {
|
||||
map.put(key, new ByteTag((byte) (value.equals("true") ? 1 : 0)));
|
||||
}
|
||||
}
|
||||
map.put("LevelName", new StringTag(folderTo.getName()));
|
||||
map.put("StorageVersion", new IntTag(5));
|
||||
Byte difficulty = tag.getByte("Difficulty");
|
||||
map.put("Difficulty", new IntTag(difficulty == null ? 2 : difficulty));
|
||||
String generatorName = tag.getString("generatorName");
|
||||
map.put("Generator", new IntTag("flat".equalsIgnoreCase(generatorName) ? 2 : 1));
|
||||
map.put("commandsEnabled", new ByteTag((byte) 1));
|
||||
Long time = tag.getLong("Time");
|
||||
if (time != null) this.time = time;
|
||||
map.put("CurrentTick", new LongTag(time == null ? 0L : time));
|
||||
map.put("spawnMobs", new ByteTag((byte) 1));
|
||||
Long lastPlayed = tag.getLong("LastPlayed");
|
||||
if (lastPlayed != null && lastPlayed > Integer.MAX_VALUE) {
|
||||
lastPlayed = lastPlayed / 1000;
|
||||
map.put("LastPlayed", new LongTag(lastPlayed));
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (NBTOutputStream nos = new NBTOutputStream((DataOutput) new LittleEndianOutputStream(baos))) {
|
||||
nos.writeNamedTag("Name", tag);
|
||||
}
|
||||
LittleEndianOutputStream leos = new LittleEndianOutputStream(new FileOutputStream(levelDat));
|
||||
leos.writeInt(5);
|
||||
leos.writeInt(baos.toByteArray().length);
|
||||
leos.write(baos.toByteArray());
|
||||
leos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void write(MCAChunk chunk, boolean remap, int dim) throws IOException {
|
||||
submittedChunks.add(1);
|
||||
long numChunks = submittedChunks.longValue();
|
||||
if ((numChunks & 1023) == 0) {
|
||||
long queued = pool.getQueuedTaskCount() + pool.getQueuedSubmissionCount();
|
||||
if (queued > 127) {
|
||||
System.gc();
|
||||
while (queued > 64) {
|
||||
try {
|
||||
Thread.sleep(5);
|
||||
queued = pool.getQueuedTaskCount() + pool.getQueuedSubmissionCount();
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
FileCache cached = getFileCache(chunk, dim);
|
||||
{ // Data2D
|
||||
ByteBuffer data2d = ByteBuffer.wrap(new byte[512 + 256]);
|
||||
int[] heightMap = chunk.getHeightMapArray();
|
||||
for (int i = 0; i < heightMap.length; i++) {
|
||||
data2d.putShort((short) heightMap[i]);
|
||||
}
|
||||
if (chunk.biomes != null) {
|
||||
System.arraycopy(chunk.biomes, 0, data2d.array(), 512, 256);
|
||||
}
|
||||
cached.update(getKey(chunk, Tag.Data2D, dim), data2d.array());
|
||||
}
|
||||
|
||||
{ // SubChunkPrefix
|
||||
int maxLayer = chunk.ids.length - 1;
|
||||
while (maxLayer >= 0 && chunk.ids[maxLayer] == null) maxLayer--;
|
||||
if (maxLayer >= 0) {
|
||||
for (int layer = 0; layer <= maxLayer; layer++) {
|
||||
// Set layer
|
||||
byte[] key = getSectionKey(chunk, layer, dim);
|
||||
byte[] value = new byte[1 + 4096 + 2048 + 2048 + 2048];
|
||||
byte[] ids = chunk.ids[layer];
|
||||
if (ids == null) {
|
||||
Arrays.fill(value, (byte) 0);
|
||||
} else {
|
||||
byte[] data = chunk.data[layer];
|
||||
byte[] skyLight = chunk.skyLight[layer];
|
||||
byte[] blockLight = chunk.blockLight[layer];
|
||||
|
||||
if (remap) {
|
||||
copySection(ids, value, 1);
|
||||
copySection(data, value, 1 + 4096);
|
||||
copySection(skyLight, value, 1 + 4096 + 2048);
|
||||
copySection(blockLight, value, 1 + 4096 + 2048 + 2048);
|
||||
} else {
|
||||
System.arraycopy(ids, 0, value, 1, ids.length);
|
||||
System.arraycopy(data, 0, value, 1 + 4096, data.length);
|
||||
System.arraycopy(skyLight, 0, value, 1 + 4096 + 2048, skyLight.length);
|
||||
System.arraycopy(blockLight, 0, value, 1 + 4096 + 2048 + 2048, blockLight.length);
|
||||
}
|
||||
}
|
||||
cached.update(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
List<CompoundTag> tickList = null;
|
||||
|
||||
// BlockEntity
|
||||
if (!chunk.tiles.isEmpty()) {
|
||||
List<com.sk89q.jnbt.Tag> tiles = new ArrayList<>();
|
||||
for (Map.Entry<Short, CompoundTag> entry : chunk.getTiles().entrySet()) {
|
||||
CompoundTag tag = entry.getValue();
|
||||
if (transform(chunk, tag, false) && time != 0l) {
|
||||
// Needs tick
|
||||
if (tickList == null) tickList = new ArrayList<>();
|
||||
|
||||
int x = tag.getInt("x");
|
||||
int y = tag.getInt("y");
|
||||
int z = tag.getInt("z");
|
||||
BaseBlock block = chunk.getBlock(x & 15, y, z & 15);
|
||||
|
||||
Map<String, com.sk89q.jnbt.Tag> tickable = new HashMap<>();
|
||||
tickable.put("tileID", new ByteTag((byte) block.getId()));
|
||||
tickable.put("x", new IntTag(x));
|
||||
tickable.put("y", new IntTag(y));
|
||||
tickable.put("z", new IntTag(z));
|
||||
tickable.put("time", new LongTag(1));
|
||||
tickList.add(new CompoundTag(tickable));
|
||||
}
|
||||
|
||||
tiles.add(tag);
|
||||
}
|
||||
cached.update(getKey(chunk, Tag.BlockEntity, dim), write(tiles));
|
||||
}
|
||||
|
||||
// Entity
|
||||
if (!chunk.entities.isEmpty()) {
|
||||
List<com.sk89q.jnbt.Tag> entities = new ArrayList<>();
|
||||
for (CompoundTag tag : chunk.getEntities()) {
|
||||
transform(chunk, tag, true);
|
||||
entities.add(tag);
|
||||
}
|
||||
cached.update(getKey(chunk, Tag.Entity, dim), write(entities));
|
||||
}
|
||||
|
||||
// PendingTicks
|
||||
if (tickList != null) {
|
||||
HashMap<String, com.sk89q.jnbt.Tag> root = new HashMap<String, com.sk89q.jnbt.Tag>();
|
||||
root.put("tickList", new ListTag(CompoundTag.class, tickList));
|
||||
cached.update(getKey(chunk, Tag.PendingTicks, dim), write(Arrays.asList(new CompoundTag(root))));
|
||||
}
|
||||
}
|
||||
|
||||
cached.update(getKey(chunk, Tag.FinalizedState, dim), COMPLETE_STATE);
|
||||
|
||||
cached.update(getKey(chunk, Tag.Version, dim), VERSION);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] last;
|
||||
|
||||
private class FileCache implements Comparable<FileCache>, Closeable {
|
||||
private FaweOutputStream os;
|
||||
private final File file;
|
||||
private int id;
|
||||
int numKeys = 0;
|
||||
|
||||
public FileCache(int id) throws IOException {
|
||||
this.id = id;
|
||||
this.file = new File(getFolderTo() + File.separator + "cache" + File.separator + Integer.toHexString(id));
|
||||
}
|
||||
|
||||
public void update(byte[] key, byte[] value) throws IOException {
|
||||
numKeys++;
|
||||
try {
|
||||
updateUnsafe(key, value);
|
||||
} catch (NullPointerException e) {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
this.os = new FaweOutputStream(new BufferedOutputStream(new ZstdOutputStream(new LZ4BlockOutputStream(new FileOutputStream(file)))));
|
||||
updateUnsafe(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUnsafe(byte[] key, byte[] value) throws IOException {
|
||||
os.writeVarInt(key.length);
|
||||
os.write(key);
|
||||
os.writeVarInt(value.length);
|
||||
os.write(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
this.os.close();
|
||||
|
||||
FaweInputStream in = new FaweInputStream(new ZstdInputStream(new LZ4BlockInputStream(new BufferedInputStream(new FileInputStream(file)))));
|
||||
for (int i = 0; i < numKeys; i++) {
|
||||
int len = in.readVarInt();
|
||||
byte[] key = new byte[len];
|
||||
in.readFully(key);
|
||||
|
||||
len = in.readVarInt();
|
||||
byte[] value = new byte[len];
|
||||
in.readFully(value);
|
||||
db.put(key, value);
|
||||
}
|
||||
in.close();
|
||||
file.delete();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(FileCache other) {
|
||||
return Integer.compareUnsigned(this.id, other.id);
|
||||
}
|
||||
}
|
||||
|
||||
private Int2ObjectOpenHashMap<FileCache> cache = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private FileCache getFileCache(MCAChunk chunk, int dim) throws IOException {
|
||||
synchronized (cache) {
|
||||
int key = (chunk.getX() & 0xFFFFFF);
|
||||
if (dim == 0) {
|
||||
// key += 0xFFFFFFF;
|
||||
}
|
||||
FileCache cached = cache.get(key);
|
||||
if (cached == null) {
|
||||
cached = new FileCache(key);
|
||||
cache.put(key, cached);
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
|
||||
private void copySection(byte[] src, byte[] dest, int destPos) {
|
||||
switch (src.length) {
|
||||
case 4096: {
|
||||
int index = 0;
|
||||
int i1, i2, i3;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
i1 = y;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
i2 = i1 + (z << 4);
|
||||
for (int x = 0; x < 16; x++) {
|
||||
i3 = i2 + (x << 8);
|
||||
dest[destPos + i3] = src[index];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2048: {
|
||||
int index = 0;
|
||||
int i1, i2, i3, i4;
|
||||
for (int x = 0; x < 16;) {
|
||||
{
|
||||
i1 = x;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
i2 = i1 + (z << 4);
|
||||
for (int y = 0; y < 16; y += 2) {
|
||||
i3 = i2 + (y << 8);
|
||||
i4 = i2 + ((y + 1) << 8);
|
||||
byte newVal = (byte) ((src[i3 >> 1] & 0xF) + ((src[i4 >> 1] & 0xF) << 4));
|
||||
dest[destPos + index] = newVal;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
x++;
|
||||
{
|
||||
i1 = x;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
i2 = i1 + (z << 4);
|
||||
for (int y = 0; y < 16; y += 2) {
|
||||
i3 = i2 + (y << 8);
|
||||
i4 = i2 + ((y + 1) << 8);
|
||||
byte newVal = (byte) (((src[i3 >> 1] & 0xF0) >> 4) + ((src[i4 >> 1] & 0xF0)));
|
||||
dest[destPos + index] = newVal;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
x++;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
System.arraycopy(src, 0, dest, destPos, src.length);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] write(Collection<com.sk89q.jnbt.Tag> tags) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
NBTOutputStream nos = new NBTOutputStream(baos);
|
||||
nos.setLittleEndian();
|
||||
for (com.sk89q.jnbt.Tag tag : tags) {
|
||||
nos.writeNamedTag("", tag);
|
||||
}
|
||||
nos.close();
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
private CompoundTag transformItem(CompoundTag item) {
|
||||
String itemId = item.getString("id");
|
||||
short damage = item.getShort("Damage");
|
||||
BaseItem remapped = remapper.remapItem(itemId, damage);
|
||||
Map<String, com.sk89q.jnbt.Tag> map = ReflectionUtils.getMap(item.getValue());
|
||||
map.put("id", new ShortTag((short) remapped.getType()));
|
||||
map.put("Damage", new ShortTag((short) remapped.getData()));
|
||||
if (!map.containsKey("Count")) map.put("Count", new ByteTag((byte) 0));
|
||||
|
||||
CompoundTag tag = (CompoundTag) item.getValue().get("tag");
|
||||
if (tag != null) {
|
||||
Map<String, com.sk89q.jnbt.Tag> tagMap = ReflectionUtils.getMap(tag.getValue());
|
||||
ListTag<CompoundTag> enchants = (ListTag<CompoundTag>) tagMap.get("ench");
|
||||
if (enchants != null) {
|
||||
for (CompoundTag ench : enchants.getValue()) {
|
||||
Map<String, com.sk89q.jnbt.Tag> value = ReflectionUtils.getMap(ench.getValue());
|
||||
String id = ench.getString("id");
|
||||
String lvl = ench.getString("lvl");
|
||||
if (id != null && !id.isEmpty()) value.put("id", new ShortTag(Short.parseShort(id)));
|
||||
if (lvl != null && !lvl.isEmpty()) value.put("lvl", new ShortTag(Short.parseShort(lvl)));
|
||||
}
|
||||
}
|
||||
CompoundTag tile = (CompoundTag) tagMap.get("BlockEntityTag");
|
||||
if (tile != null) {
|
||||
tagMap.putAll(tile.getValue());
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
private boolean transform(MCAChunk chunk, CompoundTag tag, boolean entity) {
|
||||
try {
|
||||
String id = tag.getString("id");
|
||||
if (id != null) {
|
||||
Map<String, com.sk89q.jnbt.Tag> map = ReflectionUtils.getMap(tag.getValue());
|
||||
if (entity) {
|
||||
int legacyId = remapper.remapEntityId(id);
|
||||
if (legacyId != -1) map.put("id", new IntTag(legacyId));
|
||||
} else {
|
||||
id = remapper.remapBlockEntityId(id);
|
||||
map.put("id", new StringTag(id));
|
||||
}
|
||||
{ // Hand items
|
||||
com.sk89q.jnbt.ListTag items = (ListTag) map.remove("HandItems");
|
||||
if (items != null) {
|
||||
CompoundTag hand = transformItem((CompoundTag) items.getValue().get(0));
|
||||
CompoundTag offHand = transformItem((CompoundTag) items.getValue().get(1));
|
||||
map.put("Mainhand", hand);
|
||||
map.put("Offhand", offHand);
|
||||
}
|
||||
}
|
||||
{ // Convert armor
|
||||
com.sk89q.jnbt.ListTag items = (ListTag) map.remove("ArmorItems");
|
||||
if (items != null) {
|
||||
((List<CompoundTag>) items.getValue()).forEach(this::transformItem);
|
||||
Collections.reverse(items.getValue());
|
||||
map.put("Armor", items);
|
||||
}
|
||||
}
|
||||
{ // Convert items
|
||||
com.sk89q.jnbt.ListTag items = tag.getListTag("Items");
|
||||
if (items != null) {
|
||||
((List<CompoundTag>) items.getValue()).forEach(this::transformItem);
|
||||
}
|
||||
}
|
||||
{ // Convert color
|
||||
for (String key : new String[] {"color", "Color"}) {
|
||||
com.sk89q.jnbt.Tag value = map.get(key);
|
||||
if (value instanceof IntTag) {
|
||||
map.put(key, new ByteTag((byte) (int) ((IntTag) value).getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
{ // Convert item
|
||||
String item = tag.getString("Item");
|
||||
if (item != null) {
|
||||
short damage = tag.getShort("Data");
|
||||
BaseItem remapped = remapper.remapItem(item, damage);
|
||||
map.put("Item", new ShortTag((short) remapped.getType()));
|
||||
map.put("mData", new IntTag(remapped.getData()));
|
||||
}
|
||||
}
|
||||
{ // Health
|
||||
com.sk89q.jnbt.Tag tVal = map.get("Health");
|
||||
if (tVal != null) {
|
||||
short newVal = ((Number) tVal.getValue()).shortValue();
|
||||
map.put("Health", new ShortTag((short) (newVal * 2)));
|
||||
}
|
||||
}
|
||||
for (String key : new String[] {"Age", "Health"}) {
|
||||
com.sk89q.jnbt.Tag tVal = map.get(key);
|
||||
if (tVal != null) {
|
||||
short newVal = ((Number) tVal.getValue()).shortValue();
|
||||
map.put(key, new ShortTag(newVal));
|
||||
}
|
||||
}
|
||||
{ // Orientation / Position
|
||||
for (String key : new String[] {"Orientation", "Position", "Rotation", "Pos", "Motion"}) {
|
||||
ListTag list = (ListTag) map.get(key);
|
||||
if (list != null) {
|
||||
List<com.sk89q.jnbt.Tag> value = list.getValue();
|
||||
ArrayList<FloatTag> newList = new ArrayList<>();
|
||||
for (com.sk89q.jnbt.Tag coord : value) {
|
||||
newList.add(new FloatTag(((Number) coord.getValue()).floatValue()));
|
||||
}
|
||||
map.put(key, new ListTag(FloatTag.class, newList));
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (id) {
|
||||
case "EndGateway":
|
||||
case "MobSpawner": {
|
||||
map.clear();
|
||||
break;
|
||||
}
|
||||
case "Sign": {
|
||||
for (int line = 1; line <= 4; line++) {
|
||||
String key = "Text" + line;
|
||||
String text = tag.getString(key);
|
||||
if (text != null && text.startsWith("{")) {
|
||||
map.put(key, new StringTag(BBC.jsonToString(text)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CommandBlock": {
|
||||
int x = tag.getInt("x");
|
||||
int y = tag.getInt("y");
|
||||
int z = tag.getInt("z");
|
||||
|
||||
map.put("Version", new IntTag(3));
|
||||
BaseBlock block = chunk.getBlock(x & 15, y, z & 15);
|
||||
|
||||
int LPCommandMode = 0;
|
||||
switch (block.getId()) {
|
||||
case 189:
|
||||
LPCommandMode = 2;
|
||||
break;
|
||||
case 188:
|
||||
LPCommandMode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// conditionMet
|
||||
|
||||
boolean conditional = block.getData() > 7;
|
||||
byte auto = tag.getByte("auto");
|
||||
map.putIfAbsent("isMovable", new ByteTag((byte) 1));
|
||||
map.put("LPCommandMode", new IntTag(LPCommandMode));
|
||||
map.put("LPCondionalMode", new ByteTag((byte) (conditional ? 1 : 0)));
|
||||
map.put("LPRedstoneMode", new ByteTag((byte) (auto == 0 ? 1 : 0)));
|
||||
|
||||
|
||||
if (LPCommandMode == 1 && ((auto == 1 || tag.getByte("powered") == 1) && (!conditional || tag.getByte("conditionMet") == 1))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Fawe.debug("Error converting tag: " + tag);
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private byte[] getSectionKey(MCAChunk chunk, int layer, int dimension) {
|
||||
return getSectionKey(chunk.getX(), chunk.getZ(), layer, dimension);
|
||||
}
|
||||
|
||||
private static byte[] getSectionKey(int x, int z, int layer, int dimension) {
|
||||
if (dimension == 0) {
|
||||
byte[] key = Tag.SubChunkPrefix.fill(x, z, new byte[10]);
|
||||
key[9] = (byte) layer;
|
||||
return key;
|
||||
}
|
||||
byte[] key = new byte[14];
|
||||
Tag.SubChunkPrefix.fill(x, z, key);
|
||||
key[12] = key[8];
|
||||
key[8] = (byte) dimension;
|
||||
key[13] = (byte) layer;
|
||||
return key;
|
||||
}
|
||||
|
||||
private byte[] getKey(MCAChunk chunk, Tag tag, int dimension) {
|
||||
if (dimension == 0) {
|
||||
return tag.fill(chunk.getX(), chunk.getZ(), new byte[9]);
|
||||
}
|
||||
byte[] key = new byte[13];
|
||||
tag.fill(chunk.getX(), chunk.getZ(), key);
|
||||
key[12] = key[8];
|
||||
key[8] = (byte) dimension;
|
||||
return key;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue