Update to forge 1.11

This commit is contained in:
Jesse Boyd 2016-11-29 22:17:25 +11:00
parent 875a978c5c
commit 768230c916
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
17 changed files with 2171 additions and 114 deletions

View File

@ -153,6 +153,8 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
@Override @Override
public ForgeChunk_All call() { public ForgeChunk_All call() {
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk(); net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
nmsChunk.setModified(true); nmsChunk.setModified(true);
net.minecraft.world.World nmsWorld = getParent().getWorld(); net.minecraft.world.World nmsWorld = getParent().getWorld();
try { try {
@ -209,13 +211,19 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
float yaw = rotTag.getFloat(0); float yaw = rotTag.getFloat(0);
float pitch = rotTag.getFloat(1); float pitch = rotTag.getFloat(1);
String id = idTag.getValue(); String id = idTag.getValue();
NBTTagCompound tag = (NBTTagCompound)ForgeQueue_All.methodFromNative.invoke(null, nativeTag); if (id != null) {
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld); Entity entity = EntityList.createEntityByName(id, nmsWorld);
if (entity != null) { if (entity != null) {
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
tag.removeTag("UUIDMost");
tag.removeTag("UUIDLeast");
System.out.println(tag);
entity.readFromNBT(tag);
entity.setPositionAndRotation(x, y, z, yaw, pitch); entity.setPositionAndRotation(x, y, z, yaw, pitch);
nmsWorld.spawnEntityInWorld(entity); nmsWorld.spawnEntityInWorld(entity);
} }
} }
}
// Run change task if applicable // Run change task if applicable
if (getParent().getChangeTask() != null) { if (getParent().getChangeTask() != null) {
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
@ -281,6 +289,8 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
sections[j] = section = new ExtendedBlockStorage(j << 4, flag); sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
} }
} }
IBlockState existing;
int by = j << 4;
BlockStateContainer nibble = section.getData(); BlockStateContainer nibble = section.getData();
int nonEmptyBlockCount = 0; int nonEmptyBlockCount = 0;
for (int y = 0; y < 16; y++) { for (int y = 0; y < 16; y++) {
@ -289,22 +299,32 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
char combinedId = array[FaweCache.CACHE_J[y][z][x]]; char combinedId = array[FaweCache.CACHE_J[y][z][x]];
switch (combinedId) { switch (combinedId) {
case 0: case 0:
IBlockState existing = nibble.get(x, y, z);
if (existing != ForgeQueue_All.air) {
nonEmptyBlockCount++;
}
continue; continue;
case 1: 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); nibble.set(x, y, z, ForgeQueue_All.air);
continue; continue;
default: 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++; nonEmptyBlockCount++;
}
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF)); nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
} }
} }
} }
} }
getParent().setCount(0, nonEmptyBlockCount, section); getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
} }
// Set biomes // Set biomes
int[][] biomes = this.biomes; int[][] biomes = this.biomes;
@ -325,8 +345,6 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
} }
// Set tiles // Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles(); Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) { for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue(); CompoundTag nativeTag = entry.getValue();

View File

@ -50,31 +50,35 @@ import net.minecraftforge.common.DimensionManager;
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> { public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
protected static Method methodFromNative; protected final static Method methodFromNative;
protected static Method methodToNative; protected final static Method methodToNative;
protected final static Field fieldTickingBlockCount;
protected final static Field fieldNonEmptyBlockCount;
public ForgeQueue_All(com.sk89q.worldedit.world.World world) { static {
super(world);
init();
}
public ForgeQueue_All(String world) {
super(world);
init();
}
private void init() {
if (methodFromNative == null) {
try { try {
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter"); Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
this.methodFromNative = converter.getDeclaredMethod("toNative", Tag.class); methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
this.methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class); methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
methodFromNative.setAccessible(true); methodFromNative.setAccessible(true);
methodToNative.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) { } catch (Throwable e) {
throw new RuntimeException(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(); getImpWorld();
} }
@ -152,7 +156,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
mcChunk = chunkServer.loadChunk(x, z); mcChunk = chunkServer.loadChunk(x, z);
PlayerChunkMapEntry entry = playerManager.getEntry(x, z); PlayerChunkMapEntry entry = playerManager.getEntry(x, z);
if (entry != null) { if (entry != null) {
Field fieldPlayers = PlayerChunkMap.class.getDeclaredField("field_72699_b"); Field fieldPlayers = PlayerChunkMapEntry.class.getDeclaredField("field_187283_c");
fieldPlayers.setAccessible(true); fieldPlayers.setAccessible(true);
oldWatchers = (List<EntityPlayerMP>) fieldPlayers.get(entry); oldWatchers = (List<EntityPlayerMP>) fieldPlayers.get(entry);
playerManager.removeEntry(entry); playerManager.removeEntry(entry);
@ -222,12 +226,11 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
return world.getChunkProvider().getLoadedChunk(x, z) != null; return world.getChunkProvider().getLoadedChunk(x, z) != null;
} }
public int getNonEmptyBlockCount(ExtendedBlockStorage section) throws IllegalAccessException {
return (int) fieldNonEmptyBlockCount.get(section);
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException { 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");
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount); fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
} }

87
forge111/build.gradle Normal file
View File

@ -0,0 +1,87 @@
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'
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(':core'))
include(dependency('org.yaml:snakeyaml:1.16'))
}
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
destinationDir = file '../target'
}
shadowJar.doLast {
task ->
ant.checksum file: task.archivePath
}
reobf {
shadowJar {
mappingType = 'SEARGE'
}
}
task deobfJar(type: Jar) {
from sourceSets.main.output
classifier = 'dev'
}
artifacts {
archives deobfJar
}
build.dependsOn(shadowJar)

View File

@ -0,0 +1,174 @@
package com.boydti.fawe.forge;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.IFawe;
import com.boydti.fawe.forge.v0.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);
} catch (InstanceAlreadyExistsException e) {
MainUtil.handleError(e);
}
}
@Override
public void debug(String s) {
logger.debug(s);
}
@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;
}
}

View File

@ -0,0 +1,42 @@
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);
}
}
}

View File

@ -0,0 +1,75 @@
package com.boydti.fawe.forge;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer;
import java.io.File;
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 = "*")
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);
}
@Mod.EventHandler
public void serverLoad(FMLServerStartingEvent event) {
IMP.insertCommands();
}
@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);
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;
}
FawePlayer fp = FawePlayer.wrap(player);
if (fp.getMeta("lastWorld") != event.getWorld()) {
fp.setMeta("lastWorld", event.getWorld());
}
}
}

View File

@ -0,0 +1,476 @@
/*
* 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");
}
}

View File

@ -0,0 +1,77 @@
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.QUEUE.PROGRESS.DISPLAY = false;
}
@Override
public void resetTitle() { // Not supported
Settings.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 getPlayer() {
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
}
}

View File

@ -0,0 +1,168 @@
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);
}
}

View File

@ -0,0 +1,393 @@
package com.boydti.fawe.forge.v0;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.object.BytePair;
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("storage");
fieldBits.setAccessible(true);
Field fieldPalette = BlockStateContainer.class.getDeclaredField("palette");
fieldPalette.setAccessible(true);
Field fieldSize = BlockStateContainer.class.getDeclaredField("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.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) {
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
} else {
char[] array = this.getIdArray(i);
Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) {
if (entity instanceof EntityPlayer) {
continue;
}
int x = ((int) Math.round(entity.posX) & 15);
int z = ((int) Math.round(entity.posZ) & 15);
int y = (int) Math.round(entity.posY);
if (array == null) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
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
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();
}
}
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);
}
}
}
}
// 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;
}
ExtendedBlockStorage section = sections[j];
if (section == null) {
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 (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
getParent().setPalette(section, this.sectionPalettes[j]);
getParent().setCount(0, count - this.getAir(j), section);
continue;
} else {
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
}
}
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
int[][] biomes = this.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
}
}
}
// Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue();
BytePair pair = entry.getKey();
BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
tileEntity.readFromNBT(tag); // ReadTagIntoTile
}
}
} catch (Throwable e) {
MainUtil.handleError(e);
}
int[][] biomes = this.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
}
}
}
return this;
}
}

View File

@ -0,0 +1,487 @@
package com.boydti.fawe.forge.v0;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.FaweChunk;
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 java.io.File;
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.play.server.SPacketChunkData;
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;
static {
try {
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 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 Chunk getChunk(World world, int x, int z) {
Chunk chunk = world.getChunkProvider().provideChunk(x, z);
if (chunk != null && !chunk.isLoaded()) {
chunk.onChunkLoad();
}
return chunk;
}
@Override
public boolean isChunkLoaded(int x, int z) {
return getWorld().getChunkProvider().getLoadedChunk(x, z) != null;
}
@Override
public boolean regenerateChunk(World world, int x, int z) {
IChunkProvider provider = world.getChunkProvider();
if (!(provider instanceof ChunkProviderServer)) {
return false;
}
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;
}
}
@Override
public boolean loadChunk(World world, int x, int z, boolean generate) {
return getCachedSections(world, x, z) != null;
}
@Override
public ExtendedBlockStorage[] getCachedSections(World world, int x, int z) {
Chunk chunk = world.getChunkProvider().provideChunk(x, z);
if (chunk != null && !chunk.isLoaded()) {
chunk.onChunkLoad();
}
return chunk == null ? null : chunk.getBlockStorageArray();
}
@Override
public ExtendedBlockStorage getCachedSection(ExtendedBlockStorage[] chunk, int cy) {
return chunk[cy];
}
@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;
}
}
@Override
public boolean isChunkLoaded(World world, int x, int z) {
return world.getChunkProvider().getLoadedChunk(x, z) != null;
}
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.readFromNBT(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 = ((int) Math.round(ent.posX) & 15);
int z = ((int) Math.round(ent.posZ) & 15);
int y = (int) Math.round(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 refreshChunk(FaweChunk fc) {
ForgeChunk_All fs = (ForgeChunk_All) fc;
ensureChunkLoaded(fc.getX(), fc.getZ());
Chunk nmsChunk = fs.getChunk();
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;
});
int mask = fc.getBitMask();
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);
}
} 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 removeLighting(ExtendedBlockStorage[] sections, RelightMode mode, boolean sky) {
if (mode == RelightMode.ALL) {
for (int i = 0; i < sections.length; i++) {
ExtendedBlockStorage section = sections[i];
if (section != null) {
section.setBlocklightArray(new NibbleArray());
if (sky) {
section.setSkylightArray(new NibbleArray());
}
}
}
}
return true;
}
@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");
}
}

View File

@ -187,9 +187,12 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
float yaw = rotTag.getFloat(0); float yaw = rotTag.getFloat(0);
float pitch = rotTag.getFloat(1); float pitch = rotTag.getFloat(1);
String id = idTag.getValue(); String id = idTag.getValue();
NBTTagCompound tag = (NBTTagCompound)ForgeQueue_All.methodFromNative.invoke(null, nativeTag); Entity entity = EntityList.createEntityByName(id, nmsWorld);
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
if (entity != null) { 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); entity.setPositionAndRotation(x, y, z, yaw, pitch);
nmsWorld.spawnEntityInWorld(entity); nmsWorld.spawnEntityInWorld(entity);
} }

View File

@ -71,6 +71,8 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
@Override @Override
public ForgeChunk_All call() { public ForgeChunk_All call() {
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk(); net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
nmsChunk.setModified(true); nmsChunk.setModified(true);
nmsChunk.setHasEntities(true); nmsChunk.setHasEntities(true);
net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
@ -128,9 +130,12 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
float yaw = rotTag.getFloat(0); float yaw = rotTag.getFloat(0);
float pitch = rotTag.getFloat(1); float pitch = rotTag.getFloat(1);
String id = idTag.getValue(); String id = idTag.getValue();
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag); Entity entity = EntityList.createEntityByName(id, nmsWorld);
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
if (entity != null) { 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); entity.setPositionAndRotation(x, y, z, yaw, pitch);
nmsWorld.spawnEntityInWorld(entity); nmsWorld.spawnEntityInWorld(entity);
} }
@ -196,26 +201,40 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
char[] currentArray = section.getData(); char[] currentArray = section.getData();
boolean fill = true; boolean fill = true;
int solid = 0; int solid = 0;
char existingId;
for (int k = 0; k < newArray.length; k++) { for (int k = 0; k < newArray.length; k++) {
char n = newArray[k]; char n = newArray[k];
switch (n) { switch (n) {
case 0: case 0:
fill = false;
continue; continue;
case 1: case 1:
fill = false; existingId = currentArray[k];
if (currentArray[k] > 1) { if (existingId > 1) {
solid++; 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; currentArray[k] = 0;
}
continue; continue;
default: default:
existingId = currentArray[k];
if (existingId <= 1) {
solid++; 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; currentArray[k] = n;
continue; continue;
} }
} }
getParent().setCount(0, solid, section); getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + solid, section);
if (fill) { if (fill) {
this.setCount(j, Short.MAX_VALUE); this.setCount(j, Short.MAX_VALUE);
} }
@ -240,9 +259,6 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
} }
// Set tiles // Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles(); Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) { for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue(); CompoundTag nativeTag = entry.getValue();
BytePair pair = entry.getKey(); BytePair pair = entry.getKey();

View File

@ -44,31 +44,34 @@ import net.minecraftforge.common.DimensionManager;
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> { public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
protected static Method methodFromNative; protected final static Method methodFromNative;
protected static Method methodToNative; protected final static Method methodToNative;
private static final Field fieldTickingBlockCount;
private static final Field fieldNonEmptyBlockCount;
public ForgeQueue_All(com.sk89q.worldedit.world.World world) { static {
super(world);
init();
}
public ForgeQueue_All(String world) {
super(world);
init();
}
private void init() {
if (methodFromNative == null) {
try { try {
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter"); Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
this.methodFromNative = converter.getDeclaredMethod("toNative", Tag.class); methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
this.methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class); methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
methodFromNative.setAccessible(true); methodFromNative.setAccessible(true);
methodToNative.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) { } catch (Throwable e) {
throw new RuntimeException(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(); getImpWorld();
} }
@ -186,15 +189,14 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
} }
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException { 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");
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount); fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
} }
public int getNonEmptyBlockCount(ExtendedBlockStorage section) throws IllegalAccessException {
return (int) fieldNonEmptyBlockCount.get(section);
}
@Override @Override
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception { 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; Map<BlockPos, TileEntity> tiles = (Map<BlockPos, TileEntity>) tilesGeneric;

View File

@ -69,7 +69,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
copy.biomes = biomes.clone(); copy.biomes = biomes.clone();
copy.chunk = chunk; copy.chunk = chunk;
} }
if (copy != null) { if (sectionPalettes != null) {
copy.sectionPalettes = new BlockStateContainer[16]; copy.sectionPalettes = new BlockStateContainer[16];
try { try {
Field fieldBits = BlockStateContainer.class.getDeclaredField("storage"); Field fieldBits = BlockStateContainer.class.getDeclaredField("storage");
@ -153,8 +153,10 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
@Override @Override
public ForgeChunk_All call() { public ForgeChunk_All call() {
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk(); net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
nmsChunk.setModified(true); nmsChunk.setModified(true);
net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); net.minecraft.world.World nmsWorld = getParent().getWorld();
try { try {
boolean flag = !nmsWorld.provider.getHasNoSky(); boolean flag = !nmsWorld.provider.getHasNoSky();
// Sections // Sections
@ -209,9 +211,12 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
float yaw = rotTag.getFloat(0); float yaw = rotTag.getFloat(0);
float pitch = rotTag.getFloat(1); float pitch = rotTag.getFloat(1);
String id = idTag.getValue(); String id = idTag.getValue();
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag); Entity entity = EntityList.createEntityByName(id, nmsWorld);
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
if (entity != null) { 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); entity.setPositionAndRotation(x, y, z, yaw, pitch);
nmsWorld.spawnEntityInWorld(entity); nmsWorld.spawnEntityInWorld(entity);
} }
@ -281,6 +286,8 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
sections[j] = section = new ExtendedBlockStorage(j << 4, flag); sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
} }
} }
IBlockState existing;
int by = j << 4;
BlockStateContainer nibble = section.getData(); BlockStateContainer nibble = section.getData();
int nonEmptyBlockCount = 0; int nonEmptyBlockCount = 0;
for (int y = 0; y < 16; y++) { for (int y = 0; y < 16; y++) {
@ -289,22 +296,32 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
char combinedId = array[FaweCache.CACHE_J[y][z][x]]; char combinedId = array[FaweCache.CACHE_J[y][z][x]];
switch (combinedId) { switch (combinedId) {
case 0: case 0:
IBlockState existing = nibble.get(x, y, z);
if (existing != ForgeQueue_All.air) {
nonEmptyBlockCount++;
}
continue; continue;
case 1: 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); nibble.set(x, y, z, ForgeQueue_All.air);
continue; continue;
default: 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++; nonEmptyBlockCount++;
}
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF)); nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
} }
} }
} }
} }
getParent().setCount(0, nonEmptyBlockCount, section); getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
} }
// Set biomes // Set biomes
int[][] biomes = this.biomes; int[][] biomes = this.biomes;
@ -325,8 +342,6 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
} }
// Set tiles // Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles(); Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) { for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue(); CompoundTag nativeTag = entry.getValue();

View File

@ -16,6 +16,7 @@ import java.lang.reflect.Method;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -49,35 +50,37 @@ import net.minecraftforge.common.DimensionManager;
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> { public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
protected static Method methodFromNative; protected final static Method methodFromNative;
protected static Method methodToNative; protected final static Method methodToNative;
protected final static Field fieldTickingBlockCount;
protected final static Field fieldNonEmptyBlockCount;
public ForgeQueue_All(com.sk89q.worldedit.world.World world) { static {
super(world);
init();
}
public ForgeQueue_All(String world) {
super(world);
init();
}
private void init() {
if (methodFromNative == null) {
try { try {
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter"); Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
this.methodFromNative = converter.getDeclaredMethod("toNative", Tag.class); methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
this.methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class); methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
methodFromNative.setAccessible(true); methodFromNative.setAccessible(true);
methodToNative.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) { } catch (Throwable e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
super(world);
getImpWorld(); getImpWorld();
} }
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0); public ForgeQueue_All(String world) {
super(world);
getImpWorld();
}
@Override @Override
public void setHeightMap(FaweChunk chunk, byte[] heightMap) { public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
@ -94,6 +97,8 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
} }
} }
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
@Override @Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) { public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
Map<BlockPos, TileEntity> tiles = chunk.getTileEntityMap(); Map<BlockPos, TileEntity> tiles = chunk.getTileEntityMap();
@ -106,7 +111,8 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
try { try {
NBTTagCompound tag = new NBTTagCompound(); NBTTagCompound tag = new NBTTagCompound();
tile.writeToNBT(tag); // readTagIntoEntity tile.writeToNBT(tag); // readTagIntoEntity
return (CompoundTag) methodToNative.invoke(null, tag); CompoundTag result = (CompoundTag) methodToNative.invoke(null, tag);
return result;
} catch (Exception e) { } catch (Exception e) {
MainUtil.handleError(e); MainUtil.handleError(e);
return null; return null;
@ -144,8 +150,17 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
mcChunk = chunkServer.loadChunk(x, z); mcChunk = chunkServer.loadChunk(x, z);
mcChunk.onChunkUnload(); mcChunk.onChunkUnload();
} }
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
List<EntityPlayerMP> oldWatchers = null;
if (chunkServer.chunkExists(x, z)) { if (chunkServer.chunkExists(x, z)) {
mcChunk = chunkServer.loadChunk(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(); mcChunk.onChunkUnload();
} }
try { try {
@ -163,6 +178,11 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
mcChunk.onChunkLoad(); mcChunk.onChunkLoad();
mcChunk.populateChunk(chunkServer, chunkServer.chunkGenerator); mcChunk.populateChunk(chunkServer, chunkServer.chunkGenerator);
} }
if (oldWatchers != null) {
for (EntityPlayerMP player : oldWatchers) {
playerManager.addPlayer(player);
}
}
return true; return true;
} catch (Throwable t) { } catch (Throwable t) {
MainUtil.handleError(t); MainUtil.handleError(t);
@ -206,12 +226,11 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
return world.getChunkProvider().getLoadedChunk(x, z) != null; return world.getChunkProvider().getLoadedChunk(x, z) != null;
} }
public int getNonEmptyBlockCount(ExtendedBlockStorage section) throws IllegalAccessException {
return (int) fieldNonEmptyBlockCount.get(section);
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException { 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");
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount); fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
} }
@ -351,6 +370,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
return false; return false;
} }
@Override @Override
public FaweChunk<Chunk> getFaweChunk(int x, int z) { public FaweChunk<Chunk> getFaweChunk(int x, int z) {
return new ForgeChunk_All(this, x, z); return new ForgeChunk_All(this, x, z);
@ -403,7 +423,8 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
} }
String[] split = getWorldName().split(";"); String[] split = getWorldName().split(";");
int id = Integer.parseInt(split[split.length - 1]); int id = Integer.parseInt(split[split.length - 1]);
return nmsWorld = DimensionManager.getWorld(id); nmsWorld = DimensionManager.getWorld(id);
return nmsWorld;
} }
@Override @Override

View File

@ -1,3 +1,3 @@
rootProject.name = 'FastAsyncWorldEdit' rootProject.name = 'FastAsyncWorldEdit'
include 'core', 'bukkit', 'forge1710', 'forge189', 'forge194', 'forge110', 'favs', 'nukkit' include 'core', 'bukkit', 'forge1710', 'forge189', 'forge194', 'forge110', 'forge111', 'favs', 'nukkit'