mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-28 13:45:36 +01:00
Various
This commit is contained in:
parent
f202a563fc
commit
9ed6880d1d
@ -204,6 +204,8 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
debug("NMS label: " + plugin.getClass().getSimpleName().split("_")[1]);
|
||||
debug("Fallback placer: " + BukkitQueue_All.class);
|
||||
debug("=======================================");
|
||||
debug("Download the version of FAWE for your platform");
|
||||
debug("=======================================");
|
||||
hasNMS = false;
|
||||
}
|
||||
return new BukkitQueue_All(world);
|
||||
|
@ -6,14 +6,15 @@ import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
@ -21,10 +22,12 @@ import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
|
||||
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> implements Listener {
|
||||
|
||||
@ -62,8 +65,8 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
|
||||
long pair = MathMan.pairInt(chunk.getX(), chunk.getZ());
|
||||
for (FaweQueue queue : queues) {
|
||||
if (queue.getWorldName().equals(world)) {
|
||||
HashSet<Long> relighting = ((NMSMappedFaweQueue) queue).relighting;
|
||||
if (!relighting.isEmpty() && relighting.contains(pair)) {
|
||||
Map<Long, Long> relighting = ((NMSMappedFaweQueue) queue).relighting;
|
||||
if (!relighting.isEmpty() && relighting.containsKey(pair)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
@ -71,6 +74,28 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean disableChunkLoad = false;
|
||||
|
||||
@EventHandler
|
||||
public static void onWorldLoad(WorldInitEvent event) {
|
||||
if (disableChunkLoad) {
|
||||
World world = event.getWorld();
|
||||
world.setKeepSpawnInMemory(false);
|
||||
}
|
||||
}
|
||||
|
||||
public World createWorld(final WorldCreator creator) {
|
||||
World world = TaskManager.IMP.sync(new RunnableVal<World>() {
|
||||
@Override
|
||||
public void run(World value) {
|
||||
disableChunkLoad = true;
|
||||
this.value = creator.createWorld();
|
||||
disableChunkLoad = false;
|
||||
}
|
||||
});
|
||||
return world;
|
||||
}
|
||||
|
||||
public void setupAdapter(BukkitImplAdapter adapter) {
|
||||
try {
|
||||
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
|
||||
|
@ -4,6 +4,7 @@ import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
@ -27,6 +28,7 @@ import org.bukkit.Sound;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldBorder;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
@ -47,21 +49,36 @@ import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* Modify the world from an async thread <br>
|
||||
* - Any Chunk/Block/BlockState objects returned should also be thread safe <br>
|
||||
* - Use world.commit() to execute the changes <br>
|
||||
* - Don't rely on autoQueue as behavior is determined by the settings.yml <br>
|
||||
* Modify the world from an async thread<br>
|
||||
* - Use world.commit() to execute all the changes<br>
|
||||
* - Any Chunk/Block/BlockState objects returned should also be safe to use from the same async thread<br>
|
||||
* - Only block read,write and biome write are fast, other methods will perform slower async<br>
|
||||
* -
|
||||
* @see #wrap(org.bukkit.World)
|
||||
* @see #create(org.bukkit.WorldCreator)
|
||||
*/
|
||||
public class AsyncWorld implements World {
|
||||
|
||||
public final World parent;
|
||||
public final FaweQueue queue;
|
||||
private final World parent;
|
||||
private final FaweQueue queue;
|
||||
private BukkitImplAdapter adapter;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #wrap(org.bukkit.World)} instead
|
||||
* @param parent Parent world
|
||||
* @param autoQueue
|
||||
*/
|
||||
@Deprecated
|
||||
public AsyncWorld(World parent, boolean autoQueue) {
|
||||
this(parent, FaweAPI.createQueue(parent.getName(), autoQueue));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #wrap(org.bukkit.World)} instead
|
||||
* @param parent
|
||||
* @param queue
|
||||
*/
|
||||
@Deprecated
|
||||
public AsyncWorld(World parent, FaweQueue queue) {
|
||||
this.parent = parent;
|
||||
this.queue = queue;
|
||||
@ -79,6 +96,11 @@ public class AsyncWorld implements World {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a world for async usage
|
||||
* @param world
|
||||
* @return
|
||||
*/
|
||||
public static AsyncWorld wrap(World world) {
|
||||
if (world instanceof AsyncWorld) {
|
||||
return (AsyncWorld) world;
|
||||
@ -86,6 +108,28 @@ public class AsyncWorld implements World {
|
||||
return new AsyncWorld(world, false);
|
||||
}
|
||||
|
||||
public World getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public FaweQueue getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a world async (untested)
|
||||
* - Only optimized for 1.10
|
||||
* @param creator
|
||||
* @return
|
||||
*/
|
||||
public static AsyncWorld create(final WorldCreator creator) {
|
||||
long start = System.currentTimeMillis();
|
||||
BukkitQueue_0 queue = (BukkitQueue_0) SetQueue.IMP.getNewQueue(creator.name(), true, false);
|
||||
World world = queue.createWorld(creator);
|
||||
System.out.println(System.currentTimeMillis() - start);
|
||||
return wrap(world);
|
||||
}
|
||||
|
||||
public void enqueue() {
|
||||
queue.enqueue();
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import com.sk89q.jnbt.LongTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
@ -44,22 +45,37 @@ import net.minecraft.server.v1_10_R1.EntityPlayer;
|
||||
import net.minecraft.server.v1_10_R1.EntityTracker;
|
||||
import net.minecraft.server.v1_10_R1.EntityTrackerEntry;
|
||||
import net.minecraft.server.v1_10_R1.EntityTypes;
|
||||
import net.minecraft.server.v1_10_R1.EnumDifficulty;
|
||||
import net.minecraft.server.v1_10_R1.EnumGamemode;
|
||||
import net.minecraft.server.v1_10_R1.IBlockData;
|
||||
import net.minecraft.server.v1_10_R1.IDataManager;
|
||||
import net.minecraft.server.v1_10_R1.MinecraftServer;
|
||||
import net.minecraft.server.v1_10_R1.NBTTagCompound;
|
||||
import net.minecraft.server.v1_10_R1.NibbleArray;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayOutEntityDestroy;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayOutMapChunk;
|
||||
import net.minecraft.server.v1_10_R1.PlayerChunk;
|
||||
import net.minecraft.server.v1_10_R1.PlayerChunkMap;
|
||||
import net.minecraft.server.v1_10_R1.ServerNBTManager;
|
||||
import net.minecraft.server.v1_10_R1.TileEntity;
|
||||
import net.minecraft.server.v1_10_R1.WorldData;
|
||||
import net.minecraft.server.v1_10_R1.WorldManager;
|
||||
import net.minecraft.server.v1_10_R1.WorldServer;
|
||||
import net.minecraft.server.v1_10_R1.WorldSettings;
|
||||
import net.minecraft.server.v1_10_R1.WorldType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataPaletteBlock> {
|
||||
|
||||
@ -82,6 +98,69 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataP
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public World createWorld(final WorldCreator creator) {
|
||||
final String name = creator.name();
|
||||
ChunkGenerator generator = creator.generator();
|
||||
final CraftServer server = (CraftServer) Bukkit.getServer();
|
||||
final MinecraftServer console = server.getServer();
|
||||
final File folder = new File(server.getWorldContainer(), name);
|
||||
final World world = server.getWorld(name);
|
||||
final WorldType type = WorldType.getType(creator.type().getName());
|
||||
final boolean generateStructures = creator.generateStructures();
|
||||
if (world != null) {
|
||||
return world;
|
||||
}
|
||||
if (folder.exists() && !folder.isDirectory()) {
|
||||
throw new IllegalArgumentException("File exists with the name '" + name + "' and isn't a folder");
|
||||
}
|
||||
if (generator == null) {
|
||||
generator = server.getGenerator(name);
|
||||
}
|
||||
int dimension = 10 + console.worlds.size();
|
||||
boolean used = false;
|
||||
do {
|
||||
for (final WorldServer ws : console.worlds) {
|
||||
used = (ws.dimension == dimension);
|
||||
if (used) {
|
||||
++dimension;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (used);
|
||||
final boolean hardcore = false;
|
||||
final IDataManager sdm = new ServerNBTManager(server.getWorldContainer(), name, true, server.getHandle().getServer().getDataConverterManager());
|
||||
WorldData worlddata = sdm.getWorldData();
|
||||
WorldSettings worldSettings = null;
|
||||
if (worlddata == null) {
|
||||
worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(server.getDefaultGameMode().getValue()), generateStructures, hardcore, type);
|
||||
worldSettings.setGeneratorSettings(creator.generatorSettings());
|
||||
worlddata = new WorldData(worldSettings, name);
|
||||
}
|
||||
worlddata.checkName(name);
|
||||
final WorldServer internal = (WorldServer)new WorldServer(console, sdm, worlddata, dimension, console.methodProfiler, creator.environment(), generator).b();
|
||||
if (worldSettings != null) {
|
||||
internal.a(worldSettings);
|
||||
}
|
||||
internal.scoreboard = server.getScoreboardManager().getMainScoreboard().getHandle();
|
||||
internal.tracker = new EntityTracker(internal);
|
||||
internal.addIWorldAccess(new WorldManager(console, internal));
|
||||
internal.worldData.setDifficulty(EnumDifficulty.EASY);
|
||||
internal.setSpawnFlags(true, true);
|
||||
console.worlds.add(internal);
|
||||
if (generator != null) {
|
||||
internal.getWorld().getPopulators().addAll(generator.getDefaultPopulators(internal.getWorld()));
|
||||
}
|
||||
return TaskManager.IMP.sync(new RunnableVal<World>() {
|
||||
@Override
|
||||
public void run(World value) {
|
||||
server.getPluginManager().callEvent(new WorldInitEvent(internal.getWorld()));
|
||||
server.getPluginManager().callEvent(new WorldLoadEvent(internal.getWorld()));
|
||||
this.value = internal.getWorld();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkSection[] getCachedSections(World world, int cx, int cz) {
|
||||
CraftChunk chunk = (CraftChunk) world.getChunkAt(cx, cz);
|
||||
|
@ -26,6 +26,7 @@ import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BlockData;
|
||||
import com.sk89q.worldedit.command.BrushCommands;
|
||||
import com.sk89q.worldedit.command.ClipboardCommands;
|
||||
import com.sk89q.worldedit.command.FlattenedClipboardTransform;
|
||||
import com.sk89q.worldedit.command.HistoryCommands;
|
||||
import com.sk89q.worldedit.command.NavigationCommands;
|
||||
import com.sk89q.worldedit.command.RegionCommands;
|
||||
@ -295,6 +296,8 @@ public class Fawe {
|
||||
RecursiveVisitor.inject(); // Optimizations
|
||||
RegionVisitor.inject(); // Translations + Optimizations
|
||||
ExtentEntityCopy.inject(); // Async entity create fix
|
||||
// Transforms
|
||||
FlattenedClipboardTransform.inject(); // public access
|
||||
// Entity create/remove
|
||||
EntityCreate.inject(); // Optimizations
|
||||
EntityRemove.inject(); // Optimizations
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.config;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.configuration.MemorySection;
|
||||
import com.boydti.fawe.configuration.file.YamlConfiguration;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
@ -255,24 +256,21 @@ public enum BBC {
|
||||
final HashSet<BBC> captions = new HashSet<>();
|
||||
boolean changed = false;
|
||||
for (final String key : keys) {
|
||||
if (!yml.isString(key)) {
|
||||
if (!allCats.contains(key)) {
|
||||
toRemove.add(key);
|
||||
}
|
||||
final Object value = yml.get(key);
|
||||
if (value instanceof MemorySection) {
|
||||
continue;
|
||||
}
|
||||
final String[] split = key.split("\\.");
|
||||
final String node = split[split.length - 1].toUpperCase();
|
||||
final BBC caption = allNames.contains(node) ? valueOf(node) : null;
|
||||
if (caption != null) {
|
||||
final String value = yml.getString(key);
|
||||
if (!split[0].equalsIgnoreCase(caption.cat)) {
|
||||
changed = true;
|
||||
yml.set(key, null);
|
||||
yml.set(caption.cat + "." + caption.name().toLowerCase(), value);
|
||||
}
|
||||
captions.add(caption);
|
||||
caption.s = value;
|
||||
caption.s = (String) value;
|
||||
} else {
|
||||
toRemove.add(key);
|
||||
}
|
||||
|
@ -182,7 +182,46 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(final int x, final int y, final int z, final int id, byte data) {
|
||||
public void setBlock(int x, int y, int z, int id) {
|
||||
final int i = FaweCache.CACHE_I[y][x][z];
|
||||
final int j = FaweCache.CACHE_J[y][x][z];
|
||||
char[] vs = this.ids[i];
|
||||
if (vs == null) {
|
||||
vs = this.ids[i] = new char[4096];
|
||||
this.count[i]++;
|
||||
} else if (vs[j] == 0) {
|
||||
this.count[i]++;
|
||||
}
|
||||
switch (id) {
|
||||
case 0:
|
||||
this.air[i]++;
|
||||
vs[j] = (char) 1;
|
||||
return;
|
||||
case 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:
|
||||
vs[j] = (char) (id << 4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(final int x, final int y, final int z, final int id, int data) {
|
||||
final int i = FaweCache.CACHE_I[y][x][z];
|
||||
final int j = FaweCache.CACHE_J[y][x][z];
|
||||
char[] vs = this.ids[i];
|
||||
|
@ -126,10 +126,7 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
private int lastZ = Integer.MIN_VALUE;
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, short id, byte data) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
return false;
|
||||
}
|
||||
public boolean setBlock(int x, int y, int z, int id, int data) {
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
@ -153,6 +150,31 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, int id) {
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastWrappedChunk = this.blocks.get(pair);
|
||||
if (lastWrappedChunk == null) {
|
||||
lastWrappedChunk = this.getFaweChunk(x >> 4, z >> 4);
|
||||
lastWrappedChunk.setBlock(x & 15, y, z & 15, id);
|
||||
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastWrappedChunk);
|
||||
return true;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastWrappedChunk = previous;
|
||||
}
|
||||
}
|
||||
lastWrappedChunk.setBlock(x & 15, y, z & 15, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTile(int x, int y, int z, CompoundTag tag) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
|
@ -9,10 +9,10 @@ import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> extends MappedFaweQueue<WORLD, CHUNKSECTION, SECTION> {
|
||||
public NMSMappedFaweQueue(String world) {
|
||||
@ -24,7 +24,7 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
||||
return relighting.contains(pair) || blocks.contains(pair);
|
||||
}
|
||||
|
||||
public final HashSet<Long> relighting = new HashSet<>();
|
||||
public final ConcurrentHashMap<Long, Long> relighting = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void sendChunk(final FaweChunk fc, RelightMode mode) {
|
||||
@ -36,7 +36,7 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
||||
@Override
|
||||
public void run() {
|
||||
final long pair = fc.longHash();
|
||||
relighting.add(pair);
|
||||
relighting.put(pair, pair);
|
||||
final boolean result = finalMode == RelightMode.NONE || fixLighting(fc, finalMode);
|
||||
TaskManager.IMP.taskSyncNow(new Runnable() {
|
||||
@Override
|
||||
@ -47,7 +47,7 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
||||
CHUNK chunk = (CHUNK) fc.getChunk();
|
||||
refreshChunk(getWorld(), chunk);
|
||||
relighting.remove(pair);
|
||||
if (relighting.isEmpty()) {
|
||||
if (relighting.isEmpty() && chunks.isEmpty()) {
|
||||
runTasks();
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class ChangeSetFaweQueue extends DelegateFaweQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, short id, byte data) {
|
||||
public boolean setBlock(int x, int y, int z, int id, int data) {
|
||||
if (super.setBlock(x, y, z, id, data)) {
|
||||
int combinedFrom = getParent().getCombinedId4Data(x, y, z);
|
||||
if (FaweCache.hasNBT(combinedFrom >> 4)) {
|
||||
|
@ -185,7 +185,11 @@ public abstract class FaweChunk<T> {
|
||||
|
||||
public abstract void removeEntity(UUID uuid);
|
||||
|
||||
public abstract void setBlock(final int x, final int y, final int z, final int id, final byte data);
|
||||
public void setBlock(int x, int y, int z, int id) {
|
||||
setBlock(x, y, z, id, 0);
|
||||
}
|
||||
|
||||
public abstract void setBlock(final int x, final int y, final int z, final int id, final int data);
|
||||
|
||||
public abstract Set<CompoundTag> getEntities();
|
||||
|
||||
|
@ -103,7 +103,19 @@ public abstract class FaweQueue {
|
||||
|
||||
public void optimize() {}
|
||||
|
||||
public abstract boolean setBlock(final int x, final int y, final int z, final short id, final byte data);
|
||||
public abstract boolean setBlock(final int x, final int y, final int z, final int id, final int data);
|
||||
|
||||
public boolean setBlock(int x, int y, int z, int id) {
|
||||
return setBlock(x, y, z, id, 0);
|
||||
}
|
||||
|
||||
public boolean setBlock(int x, int y, int z, int id, int data, CompoundTag nbt) {
|
||||
if (nbt != null) {
|
||||
MainUtil.setPosition(nbt, x, y, z);
|
||||
setTile(x, y, z, nbt);
|
||||
}
|
||||
return setBlock(x, y, z, id, data);
|
||||
}
|
||||
|
||||
public abstract void setTile(int x, int y, int z, CompoundTag tag);
|
||||
|
||||
@ -195,6 +207,13 @@ public abstract class FaweQueue {
|
||||
* Lock the thread until the queue is empty
|
||||
*/
|
||||
public void flush() {
|
||||
flush(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the thread until the queue is empty
|
||||
*/
|
||||
public void flush(int time) {
|
||||
if (size() > 0) {
|
||||
if (Fawe.get().isMainThread()) {
|
||||
SetQueue.IMP.flush(this);
|
||||
@ -207,7 +226,7 @@ public abstract class FaweQueue {
|
||||
TaskManager.IMP.notify(running);
|
||||
}
|
||||
});
|
||||
TaskManager.IMP.wait(running, 10000);
|
||||
TaskManager.IMP.wait(running, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public class MaskedFaweQueue extends DelegateFaweQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, short id, byte data) {
|
||||
public boolean setBlock(int x, int y, int z, int id, int data) {
|
||||
if (WEManager.IMP.maskContains(mask, x, z)) {
|
||||
return super.setBlock(x, y, z, id, data);
|
||||
}
|
||||
|
@ -252,9 +252,10 @@ public abstract class FaweChangeSet implements ChangeSet {
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
} finally {
|
||||
waiting.decrementAndGet();
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
if (waiting.decrementAndGet() <= 0) {
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
||||
stream.write((combinedTo) & 0xff);
|
||||
stream.write(((combinedTo) >> 8) & 0xff);
|
||||
}
|
||||
catch (IOException e) {
|
||||
catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.boydti.fawe.object.extent;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
@ -107,30 +106,286 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
|
||||
@Override
|
||||
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
|
||||
final short id = (short) block.getId();
|
||||
byte data = (byte) block.getData();
|
||||
final int x = location.getBlockX();
|
||||
final int y = location.getBlockY();
|
||||
final int z = location.getBlockZ();
|
||||
switch (id) {
|
||||
case 68: {
|
||||
if (data == 0) {
|
||||
data = 2;
|
||||
}
|
||||
}
|
||||
final int y = (int) location.y;
|
||||
switch (y) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
case 38:
|
||||
case 39:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 43:
|
||||
case 44:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 50:
|
||||
case 51:
|
||||
case 52:
|
||||
case 53:
|
||||
case 54:
|
||||
case 55:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 59:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 63:
|
||||
if (block.hasNbtData() && !MainUtil.isValidSign(block.getNbtData())) {
|
||||
queue.setBlock(x, y, z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0);
|
||||
return true;
|
||||
}
|
||||
case 64:
|
||||
case 65:
|
||||
case 66:
|
||||
case 67:
|
||||
case 68:
|
||||
case 69:
|
||||
case 70:
|
||||
case 71:
|
||||
case 72:
|
||||
case 73:
|
||||
case 74:
|
||||
case 75:
|
||||
case 76:
|
||||
case 77:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 84:
|
||||
case 85:
|
||||
case 86:
|
||||
case 87:
|
||||
case 88:
|
||||
case 89:
|
||||
case 90:
|
||||
case 91:
|
||||
case 92:
|
||||
case 93:
|
||||
case 94:
|
||||
case 95:
|
||||
case 96:
|
||||
case 97:
|
||||
case 98:
|
||||
case 99:
|
||||
case 100:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 104:
|
||||
case 105:
|
||||
case 106:
|
||||
case 107:
|
||||
case 108:
|
||||
case 109:
|
||||
case 110:
|
||||
case 111:
|
||||
case 112:
|
||||
case 113:
|
||||
case 114:
|
||||
case 115:
|
||||
case 116:
|
||||
case 117:
|
||||
case 118:
|
||||
case 119:
|
||||
case 120:
|
||||
case 121:
|
||||
case 122:
|
||||
case 123:
|
||||
case 124:
|
||||
case 125:
|
||||
case 126:
|
||||
case 127:
|
||||
case 128:
|
||||
case 129:
|
||||
case 130:
|
||||
case 131:
|
||||
case 132:
|
||||
case 133:
|
||||
case 134:
|
||||
case 135:
|
||||
case 136:
|
||||
case 137:
|
||||
case 138:
|
||||
case 139:
|
||||
case 140:
|
||||
case 141:
|
||||
case 142:
|
||||
case 143:
|
||||
case 144:
|
||||
case 145:
|
||||
case 146:
|
||||
case 147:
|
||||
case 148:
|
||||
case 149:
|
||||
case 150:
|
||||
case 151:
|
||||
case 152:
|
||||
case 153:
|
||||
case 154:
|
||||
case 155:
|
||||
case 156:
|
||||
case 157:
|
||||
case 158:
|
||||
case 159:
|
||||
case 160:
|
||||
case 161:
|
||||
case 162:
|
||||
case 163:
|
||||
case 164:
|
||||
case 165:
|
||||
case 166:
|
||||
case 167:
|
||||
case 168:
|
||||
case 169:
|
||||
case 170:
|
||||
case 171:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 175:
|
||||
case 176:
|
||||
case 177:
|
||||
case 178:
|
||||
case 179:
|
||||
case 180:
|
||||
case 181:
|
||||
case 182:
|
||||
case 183:
|
||||
case 184:
|
||||
case 185:
|
||||
case 186:
|
||||
case 187:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
case 193:
|
||||
case 194:
|
||||
case 195:
|
||||
case 196:
|
||||
case 197:
|
||||
case 198:
|
||||
case 199:
|
||||
case 200:
|
||||
case 201:
|
||||
case 202:
|
||||
case 203:
|
||||
case 204:
|
||||
case 205:
|
||||
case 206:
|
||||
case 207:
|
||||
case 208:
|
||||
case 209:
|
||||
case 210:
|
||||
case 211:
|
||||
case 212:
|
||||
case 213:
|
||||
case 214:
|
||||
case 215:
|
||||
case 216:
|
||||
case 217:
|
||||
case 218:
|
||||
case 219:
|
||||
case 220:
|
||||
case 221:
|
||||
case 222:
|
||||
case 223:
|
||||
case 224:
|
||||
case 225:
|
||||
case 226:
|
||||
case 227:
|
||||
case 228:
|
||||
case 229:
|
||||
case 230:
|
||||
case 231:
|
||||
case 232:
|
||||
case 233:
|
||||
case 234:
|
||||
case 235:
|
||||
case 236:
|
||||
case 237:
|
||||
case 238:
|
||||
case 239:
|
||||
case 240:
|
||||
case 241:
|
||||
case 242:
|
||||
case 243:
|
||||
case 244:
|
||||
case 245:
|
||||
case 246:
|
||||
case 247:
|
||||
case 248:
|
||||
case 249:
|
||||
case 250:
|
||||
case 251:
|
||||
case 252:
|
||||
case 253:
|
||||
case 254:
|
||||
case 255:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
final int x = (int) location.x;
|
||||
final int z = (int) location.z;
|
||||
final short id = (short) block.getId();
|
||||
switch (id) {
|
||||
case 63:
|
||||
// Fix for signs
|
||||
return queue.setBlock(x, y, z, id, (byte) block.getData(), block.hasNbtData() && !MainUtil.isValidSign(block.getNbtData()) ? null : block.getNbtData());
|
||||
case 65:
|
||||
case 68:
|
||||
case 54:
|
||||
case 146:
|
||||
case 61:
|
||||
{
|
||||
// Fix for default block rotation
|
||||
byte data = (byte) block.getData();
|
||||
if (data == 0) {
|
||||
data = 2;
|
||||
}
|
||||
}
|
||||
return queue.setBlock(x, y, z, id, data, block.getNbtData());
|
||||
case 130:
|
||||
case 142:
|
||||
case 27:
|
||||
@ -161,23 +416,73 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
case 29:
|
||||
case 33:
|
||||
case 151:
|
||||
case 178: {
|
||||
if (block.hasNbtData()) {
|
||||
CompoundTag nbt = block.getNbtData();
|
||||
MainUtil.setPosition(nbt, x, y, z);
|
||||
queue.setTile(x, y, z, nbt);
|
||||
}
|
||||
queue.setBlock(x, y, z, id, data);
|
||||
return true;
|
||||
}
|
||||
case 65: {
|
||||
if (data == 0) {
|
||||
data = 2;
|
||||
}
|
||||
}
|
||||
case 178:
|
||||
// Tile
|
||||
return queue.setBlock(x, y, z, id, (byte) block.getData(), block.getNbtData());
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 39:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 51:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 7:
|
||||
case 11:
|
||||
case 73:
|
||||
case 74:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 121:
|
||||
case 122:
|
||||
case 129:
|
||||
case 133:
|
||||
case 165:
|
||||
case 166:
|
||||
case 169:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
// No data
|
||||
return queue.setBlock(x, y, z, id);
|
||||
default: {
|
||||
queue.setBlock(x, y, z, id, data);
|
||||
return true;
|
||||
return queue.setBlock(x, y, z, id, (byte) block.getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ public class DelegateFaweQueue extends FaweQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, short id, byte data) {
|
||||
public boolean setBlock(int x, int y, int z, int id, int data) {
|
||||
return parent.setBlock(x, y, z, id, data);
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -1028,20 +1027,14 @@ public class EditSession implements Extent {
|
||||
queue.enqueue();
|
||||
} else {
|
||||
queue.dequeue();
|
||||
return;
|
||||
}
|
||||
if (getChangeSet() != null) {
|
||||
if (Settings.HISTORY.COMBINE_STAGES && queue.size() > 0) {
|
||||
if (Fawe.get().isMainThread()) {
|
||||
SetQueue.IMP.flush(queue);
|
||||
} else {
|
||||
final AtomicBoolean running = new AtomicBoolean(true);
|
||||
queue.addNotifyTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TaskManager.IMP.notify(running);
|
||||
}
|
||||
});
|
||||
TaskManager.IMP.wait(running, Settings.QUEUE.DISCARD_AFTER_MS);
|
||||
queue.flush();
|
||||
}
|
||||
}
|
||||
((FaweChangeSet) getChangeSet()).flush();
|
||||
|
@ -288,7 +288,6 @@ public class BrushCommands {
|
||||
public void command(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius, CommandContext args) throws WorldEditException {
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
String cmd = args.getJoinedStrings(1);
|
||||
System.out.println(cmd);
|
||||
tool.setBrush(new CommandBrush(player, cmd, radius), "worldedit.brush.copy");
|
||||
BBC.BRUSH_COMMAND.send(player, cmd);
|
||||
}
|
||||
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
|
||||
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.math.transform.CombinedTransform;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.registry.WorldData;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Helper class to 'bake' a transform into a clipboard.
|
||||
*
|
||||
* <p>This class needs a better name and may need to be made more generic.</p>
|
||||
*
|
||||
* @see Clipboard
|
||||
* @see Transform
|
||||
*/
|
||||
public class FlattenedClipboardTransform {
|
||||
|
||||
private final Clipboard original;
|
||||
private final Transform transform;
|
||||
private final WorldData worldData;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param original the original clipboard
|
||||
* @param transform the transform
|
||||
* @param worldData the world data instance
|
||||
*/
|
||||
private FlattenedClipboardTransform(Clipboard original, Transform transform, WorldData worldData) {
|
||||
checkNotNull(original);
|
||||
checkNotNull(transform);
|
||||
checkNotNull(worldData);
|
||||
this.original = original;
|
||||
this.transform = transform;
|
||||
this.worldData = worldData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transformed region.
|
||||
*
|
||||
* @return the transformed region
|
||||
*/
|
||||
public Region getTransformedRegion() {
|
||||
Region region = original.getRegion();
|
||||
Vector minimum = region.getMinimumPoint();
|
||||
Vector maximum = region.getMaximumPoint();
|
||||
|
||||
Transform transformAround =
|
||||
new CombinedTransform(
|
||||
new AffineTransform().translate(original.getOrigin().multiply(-1)),
|
||||
transform,
|
||||
new AffineTransform().translate(original.getOrigin()));
|
||||
|
||||
Vector[] corners = new Vector[] {
|
||||
minimum,
|
||||
maximum,
|
||||
minimum.setX(maximum.getX()),
|
||||
minimum.setY(maximum.getY()),
|
||||
minimum.setZ(maximum.getZ()),
|
||||
maximum.setX(minimum.getX()),
|
||||
maximum.setY(minimum.getY()),
|
||||
maximum.setZ(minimum.getZ()) };
|
||||
|
||||
for (int i = 0; i < corners.length; i++) {
|
||||
corners[i] = transformAround.apply(corners[i]);
|
||||
}
|
||||
|
||||
Vector newMinimum = corners[0];
|
||||
Vector newMaximum = corners[0];
|
||||
|
||||
for (int i = 1; i < corners.length; i++) {
|
||||
newMinimum = Vector.getMinimum(newMinimum, corners[i]);
|
||||
newMaximum = Vector.getMaximum(newMaximum, corners[i]);
|
||||
}
|
||||
|
||||
// After transformation, the points may not really sit on a block,
|
||||
// so we should expand the region for edge cases
|
||||
newMinimum = newMinimum.setX(Math.floor(newMinimum.getX()));
|
||||
newMinimum = newMinimum.setY(Math.floor(newMinimum.getY()));
|
||||
newMinimum = newMinimum.setZ(Math.floor(newMinimum.getZ()));
|
||||
|
||||
newMaximum = newMaximum.setX(Math.ceil(newMaximum.getX()));
|
||||
newMaximum = newMaximum.setY(Math.ceil(newMaximum.getY()));
|
||||
newMaximum = newMaximum.setZ(Math.ceil(newMaximum.getZ()));
|
||||
|
||||
return new CuboidRegion(newMinimum, newMaximum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an operation to copy from the original clipboard to the given extent.
|
||||
*
|
||||
* @param target the target
|
||||
* @return the operation
|
||||
*/
|
||||
public Operation copyTo(Extent target) {
|
||||
BlockTransformExtent extent = new BlockTransformExtent(original, transform, worldData.getBlockRegistry());
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(extent, original.getRegion(), original.getOrigin(), target, original.getOrigin());
|
||||
copy.setTransform(transform);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance to bake the transform with.
|
||||
*
|
||||
* @param original the original clipboard
|
||||
* @param transform the transform
|
||||
* @param worldData the world data instance
|
||||
* @return a builder
|
||||
*/
|
||||
public static FlattenedClipboardTransform transform(Clipboard original, Transform transform, WorldData worldData) {
|
||||
return new FlattenedClipboardTransform(original, transform, worldData);
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return FlattenedClipboardTransform.class;
|
||||
}
|
||||
}
|
@ -129,13 +129,9 @@ public class SchematicWriter implements ClipboardWriter {
|
||||
throw new IllegalArgumentException("Length of region too large for a .schematic");
|
||||
}
|
||||
|
||||
System.out.println(clipboard.getMinimumPoint());
|
||||
System.out.println(clipboard.getMaximumPoint());
|
||||
|
||||
// ====================================================================
|
||||
// Metadata
|
||||
// ====================================================================
|
||||
|
||||
HashMap<String, Tag> schematic = new HashMap<String, Tag>();
|
||||
schematic.put("Width", new ShortTag((short) width));
|
||||
schematic.put("Length", new ShortTag((short) length));
|
||||
|
@ -34,7 +34,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, int id, byte data) {
|
||||
public void setBlock(int x, int y, int z, int id, int data) {
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
byte[] vs = this.byteIds[i];
|
||||
|
Loading…
Reference in New Issue
Block a user