Restructure
This commit is contained in:
parent
00c9e40b1d
commit
053d7a6482
9
.gitignore
vendored
9
.gitignore
vendored
@ -10,8 +10,11 @@
|
||||
/target/
|
||||
/.gradle
|
||||
/.idea
|
||||
/forge/build
|
||||
forge/.gradle/gradle.log
|
||||
*.log
|
||||
gradle.log
|
||||
/lib
|
||||
/core/build
|
||||
/core/build
|
||||
/forge189/build
|
||||
/forge1710/build
|
||||
/sponge/build
|
||||
/bukkit/build
|
@ -10,7 +10,7 @@ buildscript {
|
||||
}
|
||||
|
||||
group = 'com.boydti.fawe'
|
||||
version = '3.3.21'
|
||||
version = '3.4.0'
|
||||
description = """FastAsyncWorldEdit"""
|
||||
|
||||
subprojects {
|
||||
@ -35,7 +35,6 @@ subprojects {
|
||||
maven {url "http://maven.sk89q.com/repo/"}
|
||||
maven {url "http://nexus.theyeticave.net/content/repositories/pub_releases"}
|
||||
maven {url "http://repo.maven.apache.org/maven2"}
|
||||
maven {url "http://repo.techcable.net/content/groups/public/"}
|
||||
maven {url "http://hub.spigotmc.org/nexus/content/groups/public/"}
|
||||
maven {url "http://ci.frostcast.net/plugin/repository/everything"}
|
||||
maven {url "http://maven.sk89q.com/artifactory/repo/"}
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.FaweBukkit
|
||||
version: 3.3.21
|
||||
version: 3.4.0
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
|
@ -28,13 +28,12 @@ import com.boydti.fawe.util.StringMan;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
@ -121,15 +120,6 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
debug("&6Metrics enabled.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FawePlayer> getPlayers() {
|
||||
HashSet<FawePlayer> players = new HashSet<>();
|
||||
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
|
||||
players.add(wrap(player));
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kinda a really messy class I just copied over from an old project<br>
|
||||
* - Still works, so cbf cleaning it up<br>
|
||||
@ -239,6 +229,11 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
return new BukkitQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
return world.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* The EditSessionWrapper should have the same functionality as the normal EditSessionWrapper but with some optimizations
|
||||
*/
|
||||
@ -358,7 +353,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
if (Settings.STORE_HISTORY_ON_DISK) {
|
||||
fp.getSession().clearHistory();
|
||||
fp.loadSessionFromDisk(fp.getWorld());
|
||||
fp.loadSessionsFromDisk(fp.getWorld());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,6 @@ public class LoggingExtent extends AbstractDelegateExtent {
|
||||
* @param changeSet the change set
|
||||
* @param api
|
||||
* @param player
|
||||
* @param thread
|
||||
*/
|
||||
public LoggingExtent(final Extent extent, final ChangeSet changeSet, final FawePlayer<Player> player, final IBlocksHubApi api) {
|
||||
super(extent);
|
||||
|
@ -246,7 +246,9 @@ public class BukkitQueue_1_8 extends BukkitQueue_All {
|
||||
}
|
||||
return true;
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
if (Thread.currentThread() == Fawe.get().getMainThread()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.FaweBukkit
|
||||
version: 3.3.21
|
||||
version: 3.4.0
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
|
@ -44,6 +44,7 @@ import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.MemoryPoolMXBean;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -154,14 +155,11 @@ public class Fawe {
|
||||
this.setupConfigs();
|
||||
MainUtil.deleteOlder(new File(IMP.getDirectory(), "history"), TimeUnit.DAYS.toMillis(Settings.DELETE_HISTORY_AFTER_DAYS));
|
||||
|
||||
this.setupCommands();
|
||||
|
||||
// TODO command event - queue?
|
||||
|
||||
TaskManager.IMP = this.IMP.getTaskManager();
|
||||
if (Settings.METRICS) {
|
||||
this.IMP.startMetrics();
|
||||
}
|
||||
this.setupCommands();
|
||||
|
||||
// Delayed setup
|
||||
TaskManager.IMP.later(new Runnable() {
|
||||
@ -337,6 +335,10 @@ public class Fawe {
|
||||
return players.get(name);
|
||||
}
|
||||
|
||||
public Collection<FawePlayer> getCachedPlayers() {
|
||||
return players.values();
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO FIXME
|
||||
* - Async packet sending
|
||||
|
@ -87,6 +87,15 @@ public class FaweAPI {
|
||||
return SetQueue.IMP.getNewQueue(worldName, autoqueue);
|
||||
}
|
||||
|
||||
public static World getWorld(String worldName) {
|
||||
for (World current : WorldEdit.getInstance().getServer().getWorlds()) {
|
||||
if (Fawe.imp().getWorldName(current).equals(worldName)) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of supported protection plugin masks.
|
||||
* @return Set of FaweMaskManager
|
||||
@ -155,13 +164,7 @@ public class FaweAPI {
|
||||
}
|
||||
String worldName = path[path.length - 3];
|
||||
String uuidString = path[path.length - 2];
|
||||
World world = null;
|
||||
for (World current : WorldEdit.getInstance().getServer().getWorlds()) {
|
||||
if (current.getName().equals(worldName)) {
|
||||
world = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
World world = getWorld(worldName);
|
||||
if (world == null) {
|
||||
throw new IllegalArgumentException("Corresponding world does not exist: " + worldName);
|
||||
}
|
||||
|
@ -7,9 +7,9 @@ import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface IFawe {
|
||||
@ -31,14 +31,14 @@ public interface IFawe {
|
||||
|
||||
public FaweQueue getNewQueue(String world);
|
||||
|
||||
public String getWorldName(World world);
|
||||
|
||||
public EditSessionWrapper getEditSessionWrapper(final EditSession session);
|
||||
|
||||
public Collection<FaweMaskManager> getMaskManagers();
|
||||
|
||||
public void startMetrics();
|
||||
|
||||
public Set<FawePlayer> getPlayers();
|
||||
|
||||
public String getPlatform();
|
||||
|
||||
public UUID getUUID(String name);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.command;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
@ -158,7 +159,7 @@ public class Rollback extends FaweCommand {
|
||||
}
|
||||
}
|
||||
FaweLocation origin = player.getLocation();
|
||||
List<DiskStorageHistory> edits = MainUtil.getBDFiles(origin, user, radius, time, shallow);
|
||||
List<DiskStorageHistory> edits = FaweAPI.getBDFiles(origin, user, radius, time, shallow);
|
||||
if (edits == null) {
|
||||
player.sendMessage("&cToo broad, try refining your search!");
|
||||
return;
|
||||
|
@ -30,7 +30,7 @@ public class Stream extends FaweCommand {
|
||||
BBC.SCHEMATIC_NOT_FOUND.send(player, args[0]);
|
||||
return false;
|
||||
}
|
||||
FaweAPI.streamSchematicAsync(file, player.getLocation());
|
||||
FaweAPI.streamSchematic(file, player.getLocation());
|
||||
BBC.SCHEMATIC_PASTING.send(player);
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,148 @@
|
||||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.yaml.snakeyaml;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.yaml.snakeyaml.nodes.Tag;
|
||||
|
||||
/**
|
||||
* Provides additional runtime information necessary to create a custom Java
|
||||
* instance.
|
||||
*/
|
||||
public final class TypeDescription {
|
||||
private final Class<? extends Object> type;
|
||||
private Tag tag;
|
||||
private Map<String, Class<? extends Object>> listProperties;
|
||||
private Map<String, Class<? extends Object>> keyProperties;
|
||||
private Map<String, Class<? extends Object>> valueProperties;
|
||||
|
||||
public TypeDescription(Class<? extends Object> clazz, Tag tag) {
|
||||
this.type = clazz;
|
||||
this.tag = tag;
|
||||
listProperties = new HashMap<String, Class<? extends Object>>();
|
||||
keyProperties = new HashMap<String, Class<? extends Object>>();
|
||||
valueProperties = new HashMap<String, Class<? extends Object>>();
|
||||
}
|
||||
|
||||
public TypeDescription(Class<? extends Object> clazz, String tag) {
|
||||
this(clazz, new Tag(tag));
|
||||
}
|
||||
|
||||
public TypeDescription(Class<? extends Object> clazz) {
|
||||
this(clazz, (Tag) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tag which shall be used to load or dump the type (class).
|
||||
*
|
||||
* @return tag to be used. It may be a tag for Language-Independent Types
|
||||
* (http://www.yaml.org/type/)
|
||||
*/
|
||||
public Tag getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set tag to be used to load or dump the type (class).
|
||||
*
|
||||
* @param tag
|
||||
* local or global tag
|
||||
*/
|
||||
public void setTag(Tag tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
setTag(new Tag(tag));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get represented type (class)
|
||||
*
|
||||
* @return type (class) to be described.
|
||||
*/
|
||||
public Class<? extends Object> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the property is a type-safe <code>List</code>.
|
||||
*
|
||||
* @param property
|
||||
* name of the JavaBean property
|
||||
* @param type
|
||||
* class of List values
|
||||
*/
|
||||
public void putListPropertyType(String property, Class<? extends Object> type) {
|
||||
listProperties.put(property, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get class of List values for provided JavaBean property.
|
||||
*
|
||||
* @param property
|
||||
* property name
|
||||
* @return class of List values
|
||||
*/
|
||||
public Class<? extends Object> getListPropertyType(String property) {
|
||||
return listProperties.get(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the property is a type-safe <code>Map</code>.
|
||||
*
|
||||
* @param property
|
||||
* property name of this JavaBean
|
||||
* @param key
|
||||
* class of keys in Map
|
||||
* @param value
|
||||
* class of values in Map
|
||||
*/
|
||||
public void putMapPropertyType(String property, Class<? extends Object> key,
|
||||
Class<? extends Object> value) {
|
||||
keyProperties.put(property, key);
|
||||
valueProperties.put(property, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get keys type info for this JavaBean
|
||||
*
|
||||
* @param property
|
||||
* property name of this JavaBean
|
||||
* @return class of keys in the Map
|
||||
*/
|
||||
public Class<? extends Object> getMapKeyType(String property) {
|
||||
return keyProperties.get(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get values type info for this JavaBean
|
||||
*
|
||||
* @param property
|
||||
* property name of this JavaBean
|
||||
* @return class of values in the Map
|
||||
*/
|
||||
public Class<? extends Object> getMapValueType(String property) {
|
||||
return valueProperties.get(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TypeDescription for " + getType() + " (tag='" + getTag() + "')";
|
||||
}
|
||||
}
|
661
core/src/main/java/com/boydti/fawe/configuration/Yaml.java
Normal file
661
core/src/main/java/com/boydti/fawe/configuration/Yaml.java
Normal file
@ -0,0 +1,661 @@
|
||||
/**
|
||||
* Copyright (c) 2008, http://www.snakeyaml.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.yaml.snakeyaml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
|
||||
import org.yaml.snakeyaml.composer.Composer;
|
||||
import org.yaml.snakeyaml.constructor.BaseConstructor;
|
||||
import org.yaml.snakeyaml.constructor.Constructor;
|
||||
import org.yaml.snakeyaml.emitter.Emitable;
|
||||
import org.yaml.snakeyaml.emitter.Emitter;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
import org.yaml.snakeyaml.events.Event;
|
||||
import org.yaml.snakeyaml.introspector.BeanAccess;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
import org.yaml.snakeyaml.nodes.Tag;
|
||||
import org.yaml.snakeyaml.parser.Parser;
|
||||
import org.yaml.snakeyaml.parser.ParserImpl;
|
||||
import org.yaml.snakeyaml.reader.StreamReader;
|
||||
import org.yaml.snakeyaml.reader.UnicodeReader;
|
||||
import org.yaml.snakeyaml.representer.Representer;
|
||||
import org.yaml.snakeyaml.resolver.Resolver;
|
||||
import org.yaml.snakeyaml.serializer.Serializer;
|
||||
|
||||
/**
|
||||
* Public YAML interface. Each Thread must have its own instance.
|
||||
*/
|
||||
public class Yaml {
|
||||
protected final Resolver resolver;
|
||||
private String name;
|
||||
protected BaseConstructor constructor;
|
||||
protected Representer representer;
|
||||
protected DumperOptions dumperOptions;
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*/
|
||||
public Yaml() {
|
||||
this(new Constructor(), new Representer(), new DumperOptions(), new Resolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance.
|
||||
*
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
*/
|
||||
public Yaml(DumperOptions dumperOptions) {
|
||||
this(new Constructor(), new Representer(), dumperOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
*/
|
||||
public Yaml(Representer representer) {
|
||||
this(new Constructor(), representer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor) {
|
||||
this(constructor, new Representer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor, Representer representer) {
|
||||
this(constructor, representer, new DumperOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
*/
|
||||
public Yaml(Representer representer, DumperOptions dumperOptions) {
|
||||
this(new Constructor(), representer, dumperOptions, new Resolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions) {
|
||||
this(constructor, representer, dumperOptions, new Resolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Yaml instance. It is safe to create a few instances and use them
|
||||
* in different Threads.
|
||||
*
|
||||
* @param constructor
|
||||
* BaseConstructor to construct incoming documents
|
||||
* @param representer
|
||||
* Representer to emit outgoing objects
|
||||
* @param dumperOptions
|
||||
* DumperOptions to configure outgoing objects
|
||||
* @param resolver
|
||||
* Resolver to detect implicit type
|
||||
*/
|
||||
public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions,
|
||||
Resolver resolver) {
|
||||
if (!constructor.isExplicitPropertyUtils()) {
|
||||
constructor.setPropertyUtils(representer.getPropertyUtils());
|
||||
} else if (!representer.isExplicitPropertyUtils()) {
|
||||
representer.setPropertyUtils(constructor.getPropertyUtils());
|
||||
}
|
||||
this.constructor = constructor;
|
||||
representer.setDefaultFlowStyle(dumperOptions.getDefaultFlowStyle());
|
||||
representer.setDefaultScalarStyle(dumperOptions.getDefaultScalarStyle());
|
||||
representer.getPropertyUtils().setAllowReadOnlyProperties(
|
||||
dumperOptions.isAllowReadOnlyProperties());
|
||||
representer.setTimeZone(dumperOptions.getTimeZone());
|
||||
this.representer = representer;
|
||||
this.dumperOptions = dumperOptions;
|
||||
this.resolver = resolver;
|
||||
this.name = "Yaml:" + System.identityHashCode(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a Java object into a YAML String.
|
||||
*
|
||||
* @param data
|
||||
* Java object to be Serialized to YAML
|
||||
* @return YAML String
|
||||
*/
|
||||
public String dump(Object data) {
|
||||
List<Object> list = new ArrayList<Object>(1);
|
||||
list.add(data);
|
||||
return dumpAll(list.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce the corresponding representation tree for a given Object.
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Figure 3.1. Processing
|
||||
* Overview</a>
|
||||
* @param data
|
||||
* instance to build the representation tree for
|
||||
* @return representation tree
|
||||
*/
|
||||
public Node represent(Object data) {
|
||||
return representer.represent(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a sequence of Java objects into a YAML String.
|
||||
*
|
||||
* @param data
|
||||
* Iterator with Objects
|
||||
* @return YAML String with all the objects in proper sequence
|
||||
*/
|
||||
public String dumpAll(Iterator<? extends Object> data) {
|
||||
StringWriter buffer = new StringWriter();
|
||||
dumpAll(data, buffer, null);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a Java object into a YAML stream.
|
||||
*
|
||||
* @param data
|
||||
* Java object to be serialized to YAML
|
||||
* @param output
|
||||
* stream to write to
|
||||
*/
|
||||
public void dump(Object data, Writer output) {
|
||||
List<Object> list = new ArrayList<Object>(1);
|
||||
list.add(data);
|
||||
dumpAll(list.iterator(), output, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a sequence of Java objects into a YAML stream.
|
||||
*
|
||||
* @param data
|
||||
* Iterator with Objects
|
||||
* @param output
|
||||
* stream to write to
|
||||
*/
|
||||
public void dumpAll(Iterator<? extends Object> data, Writer output) {
|
||||
dumpAll(data, output, null);
|
||||
}
|
||||
|
||||
private void dumpAll(Iterator<? extends Object> data, Writer output, Tag rootTag) {
|
||||
Serializer serializer = new Serializer(new Emitter(output, dumperOptions), resolver,
|
||||
dumperOptions, rootTag);
|
||||
try {
|
||||
serializer.open();
|
||||
while (data.hasNext()) {
|
||||
Node node = representer.represent(data.next());
|
||||
serializer.serialize(node);
|
||||
}
|
||||
serializer.close();
|
||||
} catch (IOException e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Serialize a Java object into a YAML string. Override the default root tag
|
||||
* with <code>rootTag</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This method is similar to <code>Yaml.dump(data)</code> except that the
|
||||
* root tag for the whole document is replaced with the given tag. This has
|
||||
* two main uses.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* First, if the root tag is replaced with a standard YAML tag, such as
|
||||
* <code>Tag.MAP</code>, then the object will be dumped as a map. The root
|
||||
* tag will appear as <code>!!map</code>, or blank (implicit !!map).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Second, if the root tag is replaced by a different custom tag, then the
|
||||
* document appears to be a different type when loaded. For example, if an
|
||||
* instance of MyClass is dumped with the tag !!YourClass, then it will be
|
||||
* handled as an instance of YourClass when loaded.
|
||||
* </p>
|
||||
*
|
||||
* @param data
|
||||
* Java object to be serialized to YAML
|
||||
* @param rootTag
|
||||
* the tag for the whole YAML document. The tag should be Tag.MAP
|
||||
* for a JavaBean to make the tag disappear (to use implicit tag
|
||||
* !!map). If <code>null</code> is provided then the standard tag
|
||||
* with the full class name is used.
|
||||
* @param flowStyle
|
||||
* flow style for the whole document. See Chapter 10. Collection
|
||||
* Styles http://yaml.org/spec/1.1/#id930798. If
|
||||
* <code>null</code> is provided then the flow style from
|
||||
* DumperOptions is used.
|
||||
*
|
||||
* @return YAML String
|
||||
*/
|
||||
public String dumpAs(Object data, Tag rootTag, FlowStyle flowStyle) {
|
||||
FlowStyle oldStyle = representer.getDefaultFlowStyle();
|
||||
if (flowStyle != null) {
|
||||
representer.setDefaultFlowStyle(flowStyle);
|
||||
}
|
||||
List<Object> list = new ArrayList<Object>(1);
|
||||
list.add(data);
|
||||
StringWriter buffer = new StringWriter();
|
||||
dumpAll(list.iterator(), buffer, rootTag);
|
||||
representer.setDefaultFlowStyle(oldStyle);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Serialize a Java object into a YAML string. Override the default root tag
|
||||
* with <code>Tag.MAP</code>.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method is similar to <code>Yaml.dump(data)</code> except that the
|
||||
* root tag for the whole document is replaced with <code>Tag.MAP</code> tag
|
||||
* (implicit !!map).
|
||||
* </p>
|
||||
* <p>
|
||||
* Block Mapping is used as the collection style. See 10.2.2. Block Mappings
|
||||
* (http://yaml.org/spec/1.1/#id934537)
|
||||
* </p>
|
||||
*
|
||||
* @param data
|
||||
* Java object to be serialized to YAML
|
||||
* @return YAML String
|
||||
*/
|
||||
public String dumpAsMap(Object data) {
|
||||
return dumpAs(data, Tag.MAP, FlowStyle.BLOCK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the representation tree into Events.
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Processing Overview</a>
|
||||
* @param data
|
||||
* representation tree
|
||||
* @return Event list
|
||||
*/
|
||||
public List<Event> serialize(Node data) {
|
||||
SilentEmitter emitter = new SilentEmitter();
|
||||
Serializer serializer = new Serializer(emitter, resolver, dumperOptions, null);
|
||||
try {
|
||||
serializer.open();
|
||||
serializer.serialize(data);
|
||||
serializer.close();
|
||||
} catch (IOException e) {
|
||||
throw new YAMLException(e);
|
||||
}
|
||||
return emitter.getEvents();
|
||||
}
|
||||
|
||||
private static class SilentEmitter implements Emitable {
|
||||
private List<Event> events = new ArrayList<Event>(100);
|
||||
|
||||
public List<Event> getEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
public void emit(Event event) throws IOException {
|
||||
events.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a String and produce the corresponding
|
||||
* Java object. (Because the encoding in known BOM is not respected.)
|
||||
*
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM must not be present)
|
||||
* @return parsed object
|
||||
*/
|
||||
public Object load(String yaml) {
|
||||
return loadFromReader(new StreamReader(yaml), Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a stream and produce the corresponding
|
||||
* Java object.
|
||||
*
|
||||
* @param io
|
||||
* data to load from (BOM is respected and removed)
|
||||
* @return parsed object
|
||||
*/
|
||||
public Object load(InputStream io) {
|
||||
return loadFromReader(new StreamReader(new UnicodeReader(io)), Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a stream and produce the corresponding
|
||||
* Java object.
|
||||
*
|
||||
* @param io
|
||||
* data to load from (BOM must not be present)
|
||||
* @return parsed object
|
||||
*/
|
||||
public Object load(Reader io) {
|
||||
return loadFromReader(new StreamReader(io), Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a stream and produce the corresponding
|
||||
* Java object.
|
||||
*
|
||||
* @param <T>
|
||||
* Class is defined by the second argument
|
||||
* @param io
|
||||
* data to load from (BOM must not be present)
|
||||
* @param type
|
||||
* Class of the object to be created
|
||||
* @return parsed object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T loadAs(Reader io, Class<T> type) {
|
||||
return (T) loadFromReader(new StreamReader(io), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a String and produce the corresponding
|
||||
* Java object. (Because the encoding in known BOM is not respected.)
|
||||
*
|
||||
* @param <T>
|
||||
* Class is defined by the second argument
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM must not be present)
|
||||
* @param type
|
||||
* Class of the object to be created
|
||||
* @return parsed object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T loadAs(String yaml, Class<T> type) {
|
||||
return (T) loadFromReader(new StreamReader(yaml), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the only YAML document in a stream and produce the corresponding
|
||||
* Java object.
|
||||
*
|
||||
* @param <T>
|
||||
* Class is defined by the second argument
|
||||
* @param input
|
||||
* data to load from (BOM is respected and removed)
|
||||
* @param type
|
||||
* Class of the object to be created
|
||||
* @return parsed object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T loadAs(InputStream input, Class<T> type) {
|
||||
return (T) loadFromReader(new StreamReader(new UnicodeReader(input)), type);
|
||||
}
|
||||
|
||||
private Object loadFromReader(StreamReader sreader, Class<?> type) {
|
||||
Composer composer = new Composer(new ParserImpl(sreader), resolver);
|
||||
constructor.setComposer(composer);
|
||||
return constructor.getSingleData(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all YAML documents in a String and produce corresponding Java
|
||||
* objects. The documents are parsed only when the iterator is invoked.
|
||||
*
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM must not be present)
|
||||
* @return an iterator over the parsed Java objects in this String in proper
|
||||
* sequence
|
||||
*/
|
||||
public Iterable<Object> loadAll(Reader yaml) {
|
||||
Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
|
||||
constructor.setComposer(composer);
|
||||
Iterator<Object> result = new Iterator<Object>() {
|
||||
public boolean hasNext() {
|
||||
return constructor.checkData();
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
return constructor.getData();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
return new YamlIterable(result);
|
||||
}
|
||||
|
||||
private static class YamlIterable implements Iterable<Object> {
|
||||
private Iterator<Object> iterator;
|
||||
|
||||
public YamlIterable(Iterator<Object> iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
public Iterator<Object> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all YAML documents in a String and produce corresponding Java
|
||||
* objects. (Because the encoding in known BOM is not respected.) The
|
||||
* documents are parsed only when the iterator is invoked.
|
||||
*
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM must not be present)
|
||||
* @return an iterator over the parsed Java objects in this String in proper
|
||||
* sequence
|
||||
*/
|
||||
public Iterable<Object> loadAll(String yaml) {
|
||||
return loadAll(new StringReader(yaml));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all YAML documents in a stream and produce corresponding Java
|
||||
* objects. The documents are parsed only when the iterator is invoked.
|
||||
*
|
||||
* @param yaml
|
||||
* YAML data to load from (BOM is respected and ignored)
|
||||
* @return an iterator over the parsed Java objects in this stream in proper
|
||||
* sequence
|
||||
*/
|
||||
public Iterable<Object> loadAll(InputStream yaml) {
|
||||
return loadAll(new UnicodeReader(yaml));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the first YAML document in a stream and produce the corresponding
|
||||
* representation tree. (This is the opposite of the represent() method)
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Figure 3.1. Processing
|
||||
* Overview</a>
|
||||
* @param yaml
|
||||
* YAML document
|
||||
* @return parsed root Node for the specified YAML document
|
||||
*/
|
||||
public Node compose(Reader yaml) {
|
||||
Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
|
||||
constructor.setComposer(composer);
|
||||
return composer.getSingleNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all YAML documents in a stream and produce corresponding
|
||||
* representation trees.
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Processing Overview</a>
|
||||
* @param yaml
|
||||
* stream of YAML documents
|
||||
* @return parsed root Nodes for all the specified YAML documents
|
||||
*/
|
||||
public Iterable<Node> composeAll(Reader yaml) {
|
||||
final Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
|
||||
constructor.setComposer(composer);
|
||||
Iterator<Node> result = new Iterator<Node>() {
|
||||
public boolean hasNext() {
|
||||
return composer.checkNode();
|
||||
}
|
||||
|
||||
public Node next() {
|
||||
return composer.getNode();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
return new NodeIterable(result);
|
||||
}
|
||||
|
||||
private static class NodeIterable implements Iterable<Node> {
|
||||
private Iterator<Node> iterator;
|
||||
|
||||
public NodeIterable(Iterator<Node> iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
public Iterator<Node> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an implicit scalar detector. If an implicit scalar value matches the
|
||||
* given regexp, the corresponding tag is assigned to the scalar.
|
||||
*
|
||||
* @param tag
|
||||
* tag to assign to the node
|
||||
* @param regexp
|
||||
* regular expression to match against
|
||||
* @param first
|
||||
* a sequence of possible initial characters or null (which means
|
||||
* any).
|
||||
*/
|
||||
public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
|
||||
resolver.addImplicitResolver(tag, regexp, first);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a meaningful name. It simplifies debugging in a multi-threaded
|
||||
* environment. If nothing is set explicitly the address of the instance is
|
||||
* returned.
|
||||
*
|
||||
* @return human readable name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a meaningful name to be shown in toString()
|
||||
*
|
||||
* @param name
|
||||
* human readable name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a YAML stream and produce parsing events.
|
||||
*
|
||||
* @see <a href="http://yaml.org/spec/1.1/#id859333">Processing Overview</a>
|
||||
* @param yaml
|
||||
* YAML document(s)
|
||||
* @return parsed events
|
||||
*/
|
||||
public Iterable<Event> parse(Reader yaml) {
|
||||
final Parser parser = new ParserImpl(new StreamReader(yaml));
|
||||
Iterator<Event> result = new Iterator<Event>() {
|
||||
public boolean hasNext() {
|
||||
return parser.peekEvent() != null;
|
||||
}
|
||||
|
||||
public Event next() {
|
||||
return parser.getEvent();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
return new EventIterable(result);
|
||||
}
|
||||
|
||||
private static class EventIterable implements Iterable<Event> {
|
||||
private Iterator<Event> iterator;
|
||||
|
||||
public EventIterable(Iterator<Event> iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
public Iterator<Event> iterator() {
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBeanAccess(BeanAccess beanAccess) {
|
||||
constructor.getPropertyUtils().setBeanAccess(beanAccess);
|
||||
representer.getPropertyUtils().setBeanAccess(beanAccess);
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
/**
|
||||
@ -36,12 +36,7 @@ public class FaweLocation {
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
for (World world : WorldEdit.getInstance().getServer().getWorlds()) {
|
||||
if (world.getName().equals(this.world)) {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return FaweAPI.getWorld(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,10 +1,13 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.util.WEManager;
|
||||
import com.boydti.fawe.wrappers.PlayerWrapper;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
@ -50,16 +53,27 @@ public abstract class FawePlayer<T> {
|
||||
}
|
||||
if (obj instanceof Player) {
|
||||
Player actor = (Player) obj;
|
||||
try {
|
||||
Field fieldBasePlayer = actor.getClass().getDeclaredField("basePlayer");
|
||||
fieldBasePlayer.setAccessible(true);
|
||||
Player player = (Player) fieldBasePlayer.get(actor);
|
||||
Field fieldPlayer = player.getClass().getDeclaredField("player");
|
||||
fieldPlayer.setAccessible(true);
|
||||
return Fawe.imp().wrap(fieldPlayer.get(player));
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return Fawe.imp().wrap(actor.getName());
|
||||
if (obj.getClass().getSimpleName().equals("PlayerProxy")) {
|
||||
try {
|
||||
Field fieldBasePlayer = actor.getClass().getDeclaredField("basePlayer");
|
||||
fieldBasePlayer.setAccessible(true);
|
||||
Player player = (Player) fieldBasePlayer.get(actor);
|
||||
return wrap(player);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return Fawe.imp().wrap(actor.getName());
|
||||
}
|
||||
} else if (obj instanceof PlayerWrapper){
|
||||
return wrap(((PlayerWrapper) obj).getParent());
|
||||
} else {
|
||||
try {
|
||||
Field fieldPlayer = actor.getClass().getDeclaredField("player");
|
||||
fieldPlayer.setAccessible(true);
|
||||
return wrap(fieldPlayer.get(actor));
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return Fawe.imp().wrap(actor.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return Fawe.imp().wrap(obj);
|
||||
@ -92,13 +106,7 @@ public abstract class FawePlayer<T> {
|
||||
* @return
|
||||
*/
|
||||
public World getWorld() {
|
||||
String currentWorldName = getLocation().world;
|
||||
for (World world : WorldEdit.getInstance().getServer().getWorlds()) {
|
||||
if (world.getName().equals(currentWorldName)) {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return FaweAPI.getWorld(getLocation().world);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,30 +114,39 @@ public abstract class FawePlayer<T> {
|
||||
* - Usually already called when a player joins or changes world
|
||||
* @param world
|
||||
*/
|
||||
public void loadSessionsFromDisk(World world) {
|
||||
public void loadSessionsFromDisk(final World world) {
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
UUID uuid = getUUID();
|
||||
List<Integer> editIds = new ArrayList<>();
|
||||
File folder = new File(Fawe.imp().getDirectory(), "history" + File.separator + world.getName() + File.separator + uuid);
|
||||
if (folder.isDirectory()) {
|
||||
for (File file : folder.listFiles()) {
|
||||
if (file.getName().endsWith(".bd")) {
|
||||
int index = Integer.parseInt(file.getName().split("\\.")[0]);
|
||||
editIds.add(index);
|
||||
TaskManager.IMP.async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UUID uuid = getUUID();
|
||||
List<Integer> editIds = new ArrayList<>();
|
||||
File folder = new File(Fawe.imp().getDirectory(), "history" + File.separator + world.getName() + File.separator + uuid);
|
||||
if (folder.isDirectory()) {
|
||||
for (File file : folder.listFiles()) {
|
||||
if (file.getName().endsWith(".bd")) {
|
||||
int index = Integer.parseInt(file.getName().split("\\.")[0]);
|
||||
editIds.add(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(editIds);
|
||||
if (editIds.size() > 0) {
|
||||
Fawe.debug(BBC.PREFIX.s() + " Indexing " + editIds.size() + " history objects for " + getName());
|
||||
for (int index : editIds) {
|
||||
DiskStorageHistory set = new DiskStorageHistory(world, uuid, index);
|
||||
EditSession edit = set.toEditSession(getPlayer());
|
||||
if (world.equals(getWorld())) {
|
||||
session.remember(edit);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(editIds);
|
||||
if (editIds.size() > 0) {
|
||||
Fawe.debug(BBC.PREFIX.s() + " Indexing " + editIds.size() + " history objects for " + getName());
|
||||
for (int index : editIds) {
|
||||
DiskStorageHistory set = new DiskStorageHistory(world, uuid, index);
|
||||
EditSession edit = set.toEditSession(getPlayer());
|
||||
session.remember(edit);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@ public class MainUtil {
|
||||
}
|
||||
|
||||
public static void sendAdmin(final String s) {
|
||||
for (final FawePlayer<?> player : Fawe.imp().getPlayers()) {
|
||||
for (final FawePlayer<?> player : Fawe.get().getCachedPlayers()) {
|
||||
if (player.hasPermission("fawe.admin")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
@ -34,6 +34,10 @@ public class PlayerWrapper implements Player {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Player getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return new WorldWrapper((AbstractWorld) parent.getWorld());
|
||||
|
@ -235,7 +235,7 @@ public class EditSession implements Extent {
|
||||
return;
|
||||
}
|
||||
this.actor = event.getActor();
|
||||
this.queue = SetQueue.IMP.getNewQueue(world.getName(), true);
|
||||
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true);
|
||||
// Set the world of the event to the actual world (workaround for CoreProtect)
|
||||
try {
|
||||
Class<? extends EditSessionEvent> eventClass = event.getClass();
|
||||
@ -266,8 +266,7 @@ public class EditSession implements Extent {
|
||||
}
|
||||
this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor);
|
||||
Extent extent;
|
||||
final String name = actor.getName();
|
||||
final FawePlayer<Object> fp = FawePlayer.wrap(name);
|
||||
final FawePlayer<Object> fp = FawePlayer.wrap(actor);
|
||||
final LocalSession session = fp.getSession();
|
||||
this.fastmode = session.hasFastMode();
|
||||
if (fp.hasWorldEditBypass()) {
|
||||
@ -372,6 +371,12 @@ public class EditSession implements Extent {
|
||||
final Extent toReturn = event.getExtent();
|
||||
if (toReturn != extent) {
|
||||
String className = toReturn.getClass().getName().toLowerCase();
|
||||
if (className.contains("coreprotect")) {
|
||||
Fawe.debug("&cUnsafe extent detected: " + toReturn.getClass().getCanonicalName() + " !");
|
||||
Fawe.debug("&8 - &7Use BlocksHub instead");
|
||||
Fawe.debug("&8 - &7Or use FAWE rollback");
|
||||
return extent;
|
||||
}
|
||||
for (String allowed : Settings.ALLOWED_3RDPARTY_EXTENTS) {
|
||||
if (className.contains(allowed.toLowerCase())) {
|
||||
return toReturn;
|
||||
|
@ -1,13 +0,0 @@
|
||||
package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
|
||||
/**
|
||||
* Created by Jesse on 4/2/2016.
|
||||
*/
|
||||
public class SpongeEditSessionWrapper_0 extends EditSessionWrapper {
|
||||
public SpongeEditSessionWrapper_0(EditSession session) {
|
||||
super(session);
|
||||
}
|
||||
}
|
77
forge1710/build.gradle
Normal file
77
forge1710/build.gradle
Normal file
@ -0,0 +1,77 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {url = "https://oss.sonatype.org/content/repositories/snapshots/"}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'forge'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'org.mcstats.sponge:metrics:R8-SNAPSHOT'
|
||||
compile 'com.sk89q.worldedit:worldedit-forge-mc1.7.10:6.1.1-20151030.011615-19'
|
||||
compile 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.7
|
||||
targetCompatibility = 1.7
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = 'forge'
|
||||
url = 'http://files.minecraftforge.net/maven'
|
||||
}
|
||||
}
|
||||
minecraft {
|
||||
version = "10.13.4.1614-1.7.10"
|
||||
runDir = 'run'
|
||||
}
|
||||
|
||||
project.archivesBaseName = "${project.archivesBaseName}-mc${minecraft.version}"
|
||||
|
||||
processResources {
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
expand 'version': project.version,
|
||||
'mcVersion': project.minecraft.version
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
|
||||
dependencies {
|
||||
include(dependency(':core'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}.jar"
|
||||
destinationDir = file '../target'
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
|
||||
reobf.reobf(shadowJar) { spec ->
|
||||
spec.classpath = sourceSets.main.compileClasspath;
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar)
|
159
forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java
Normal file
159
forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java
Normal file
@ -0,0 +1,159 @@
|
||||
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.EditSessionWrapper;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.forge.ForgeWorld;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
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 org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FaweForge implements IFawe {
|
||||
|
||||
private final ForgeMain parent;
|
||||
private final File directory;
|
||||
private final Logger logger;
|
||||
|
||||
public FaweForge(ForgeMain plugin, Logger logger, File directory) {
|
||||
this.parent = plugin;
|
||||
this.logger = logger;
|
||||
this.directory = directory;
|
||||
try {
|
||||
Fawe.set(this);
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String s) {
|
||||
logger.error(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupCommand(final String label, final FaweCommand cmd) {
|
||||
if (TaskManager.IMP != null) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ServerCommandManager scm = (ServerCommandManager) MinecraftServer.getServer().getCommandManager();
|
||||
scm.registerCommand(new ForgeCommand(label, cmd));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
EntityPlayerMP player = null;
|
||||
if (obj instanceof String) {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
List<EntityPlayerMP> list = server.getConfigurationManager().getPlayerList((String) obj);
|
||||
player = list.size() == 1 ? list.get(0) : null;
|
||||
} else if (obj instanceof EntityPlayerMP) {
|
||||
player = (EntityPlayerMP) obj;
|
||||
}
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getCommandSenderName());
|
||||
return existing != null ? existing : new ForgePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupWEListener() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVault() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new ForgeTaskMan(512);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getVersion() {
|
||||
String[] version = MinecraftServer.getServer().getMinecraftVersion().split("\\.");
|
||||
return new int[] {Integer.parseInt(version[0]), Integer.parseInt(version[1]), Integer.parseInt(version[2])};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
if (world instanceof WorldWrapper) {
|
||||
world = ((WorldWrapper) world).getParent();
|
||||
}
|
||||
return ((ForgeWorld) world).getWorld().provider.getDimensionName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditSessionWrapper getEditSessionWrapper(EditSession session) {
|
||||
return new EditSessionWrapper(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
try {
|
||||
ForgeMetrics metrics = new ForgeMetrics("FastAsyncWorldEdit", "3.4.0");
|
||||
metrics.start();
|
||||
debug("[FAWE] &6Metrics enabled.");
|
||||
} catch (Throwable e) {
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatform() {
|
||||
return "forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8));
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
return uuid.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
|
||||
public class ForgeCommand extends CommandBase {
|
||||
|
||||
private final String name;
|
||||
private final FaweCommand cmd;
|
||||
|
||||
public ForgeCommand(String name, FaweCommand cmd) {
|
||||
this.name = name;
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender iCommandSender) {
|
||||
return "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
|
||||
if ((sender instanceof EntityPlayerMP)) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) sender;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
cmd.executeSafe(fp, args);
|
||||
}
|
||||
}
|
||||
}
|
76
forge1710/src/main/java/com/boydti/fawe/forge/ForgeMain.java
Normal file
76
forge1710/src/main/java/com/boydti/fawe/forge/ForgeMain.java
Normal file
@ -0,0 +1,76 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.Mod;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
|
||||
import cpw.mods.fml.common.eventhandler.EventPriority;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.PlayerEvent;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.4.0", acceptableRemoteVersions = "*")
|
||||
public class ForgeMain {
|
||||
private static FaweForge IMP;
|
||||
private Logger logger;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
this.logger = event.getModLog();
|
||||
File directory = new File(event.getModConfigurationDirectory() + File.separator + "FastAsyncWorldEdit");
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
this.IMP = new FaweForge(this, event.getModLog(), directory);
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerQuit(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (event.player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
handleQuit((EntityPlayerMP) event.player);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverStopping(FMLServerStoppingEvent event) {
|
||||
for (EntityPlayerMP player : (List<EntityPlayerMP>)MinecraftServer.getServer().getConfigurationManager().playerEntityList) {
|
||||
handleQuit(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleQuit(EntityPlayerMP player) {
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
fp.unregister();
|
||||
Fawe.get().unregister(player.getCommandSenderName());
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerChangedWorld(EntityJoinWorldEvent event) {
|
||||
Entity entity = event.entity;
|
||||
if (!(entity instanceof EntityPlayerMP)) {
|
||||
return;
|
||||
}
|
||||
EntityPlayerMP player = (EntityPlayerMP) entity;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
if (fp.getMeta("lastWorld") != event.world) {
|
||||
fp.setMeta("lastWorld", event.world);
|
||||
if (Settings.STORE_HISTORY_ON_DISK) {
|
||||
fp.getSession().clearHistory();
|
||||
fp.loadSessionsFromDisk(fp.getWorld());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
479
forge1710/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java
Normal file
479
forge1710/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java
Normal file
@ -0,0 +1,479 @@
|
||||
/*
|
||||
* 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 cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
|
||||
public class ForgeMetrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 7;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://report.mcstats.org";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/plugin/%s";
|
||||
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 15;
|
||||
|
||||
/**
|
||||
* The mod this metrics submits for
|
||||
*/
|
||||
private final String modName;
|
||||
|
||||
private final String modVersion;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final Configuration configuration;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
|
||||
private Thread thread = null;
|
||||
private boolean firstPost = true;
|
||||
int tickCount;
|
||||
|
||||
public ForgeMetrics(final String modName, final String modVersion) throws IOException {
|
||||
if (modName == null || modVersion == null) {
|
||||
throw new IllegalArgumentException("modName and modVersion cannot be null");
|
||||
}
|
||||
|
||||
this.modName = modName;
|
||||
this.modVersion = modVersion;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = new Configuration(configurationFile);
|
||||
|
||||
// Get values, and add some defaults, if needed
|
||||
configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false, "Set to true to disable all reporting");
|
||||
guid = configuration.get(Configuration.CATEGORY_GENERAL, "guid", UUID.randomUUID().toString(), "Server unique ID").getString();
|
||||
debug = configuration.get(Configuration.CATEGORY_GENERAL, "debug", false, "Set to true for verbose debug").getBoolean(false);
|
||||
configuration.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async
|
||||
* repeating task as the plugin and send the initial data to the metrics
|
||||
* backend, and then after that it will post in increments of PING_INTERVAL
|
||||
* * 1200 ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void tick(TickEvent.ServerTickEvent tick) {
|
||||
if (tick.phase != TickEvent.Phase.END) return;
|
||||
|
||||
if (tickCount++ % (PING_INTERVAL * 1200) != 0) return;
|
||||
|
||||
if (thread == null) {
|
||||
thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Disable Task, if it is running and the server owner decided
|
||||
// to opt-out
|
||||
if (isOptOut()) {
|
||||
FMLCommonHandler.instance().bus().unregister(ForgeMetrics.this);
|
||||
return;
|
||||
}
|
||||
// We use the inverse of firstPost because if it
|
||||
// is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to
|
||||
// FALSE
|
||||
// Each time thereafter it will evaluate to
|
||||
// TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
// After the first post we set firstPost to
|
||||
// false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
FMLLog.info("[Metrics] Exception - %s", e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
// Reload the metrics file
|
||||
configuration.load();
|
||||
return configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false).getBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the
|
||||
* config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("false");
|
||||
configuration.save();
|
||||
}
|
||||
// Enable Task, if it is not running
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the
|
||||
* config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("true");
|
||||
configuration.save();
|
||||
}
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data
|
||||
* such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
return new File(Loader.instance().getConfigDir(), "PluginMetrics.cfg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
String pluginName = modName;
|
||||
boolean onlineMode = MinecraftServer.getServer().isServerInOnlineMode();
|
||||
String pluginVersion = modVersion;
|
||||
String serverVersion;
|
||||
if (MinecraftServer.getServer().isDedicatedServer()) {
|
||||
serverVersion = "MinecraftForge (MC: " + MinecraftServer.getServer().getMinecraftVersion() + ")";
|
||||
} else {
|
||||
serverVersion = "MinecraftForgeSSP (MC: " + MinecraftServer.getServer().getMinecraftVersion() + ")";
|
||||
}
|
||||
int playersOnline = MinecraftServer.getServer().getCurrentPlayerCount();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
StringBuilder json = new StringBuilder(1024);
|
||||
json.append('{');
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
appendJSONPair(json, "guid", guid);
|
||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
||||
appendJSONPair(json, "server_version", serverVersion);
|
||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
appendJSONPair(json, "osname", osname);
|
||||
appendJSONPair(json, "osarch", osarch);
|
||||
appendJSONPair(json, "osversion", osversion);
|
||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
||||
appendJSONPair(json, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
appendJSONPair(json, "ping", "1");
|
||||
}
|
||||
|
||||
// close json
|
||||
json.append('}');
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
|
||||
byte[] uncompressed = json.toString().getBytes();
|
||||
byte[] compressed = gzip(json.toString());
|
||||
|
||||
// Headers
|
||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
||||
connection.addRequestProperty("Content-Type", "application/json");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(compressed);
|
||||
os.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
os.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
||||
if (response == null) {
|
||||
response = "null";
|
||||
} else if (response.startsWith("7")) {
|
||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
||||
}
|
||||
|
||||
throw new IOException(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GZip compress a string of bytes
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static byte[] gzip(String input) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gzos = null;
|
||||
|
||||
try {
|
||||
gzos = new GZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} 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");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.ChunkCoordinates;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
|
||||
public ForgePlayer(EntityPlayerMP parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parent.getCommandSenderName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return parent.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
Object meta = getMeta(perm);
|
||||
return meta instanceof Boolean ? (boolean) meta : ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(parent, perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(String perm, boolean flag) {
|
||||
setMeta(perm, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
part = EnumChatFormatting.getTextWithoutFormattingCodes(msg);
|
||||
ChatComponentText component = new ChatComponentText(part);
|
||||
component.getChatStyle().setColor(EnumChatFormatting.LIGHT_PURPLE);
|
||||
this.parent.addChatMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(String substring) {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweLocation getLocation() {
|
||||
World world = parent.worldObj;
|
||||
ChunkCoordinates pos = parent.getPlayerCoordinates();
|
||||
return new FaweLocation(world.provider.getDimensionName(), pos.posX, pos.posY, pos.posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return ForgeWorldEdit.inst.wrap(this.parent);
|
||||
}
|
||||
}
|
165
forge1710/src/main/java/com/boydti/fawe/forge/ForgeTaskMan.java
Normal file
165
forge1710/src/main/java/com/boydti/fawe/forge/ForgeTaskMan.java
Normal file
@ -0,0 +1,165 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
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 cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.EventPriority;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
|
||||
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<>();
|
||||
|
||||
|
||||
private final AtomicInteger taskId = new AtomicInteger();
|
||||
private final ExecutorService executor;
|
||||
|
||||
public ForgeTaskMan(int size) {
|
||||
this.executor = Executors.newFixedThreadPool(size);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int repeat(final Runnable r, final int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
final int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
later(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(final Runnable r, final int interval) {
|
||||
if (r == null) {
|
||||
return -1;
|
||||
}
|
||||
final int id = taskId.incrementAndGet();
|
||||
taskIdMap.put(id, r);
|
||||
async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!taskIdMap.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
laterAsync(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
executor.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(Runnable r) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
syncTasks.add(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(final Runnable r, final int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
final AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
r.run();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(final Runnable r, final int delay) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
final AtomicInteger remaining = new AtomicInteger(delay);
|
||||
task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (remaining.decrementAndGet() <= 0) {
|
||||
try {
|
||||
async(r);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int task) {
|
||||
taskIdMap.remove(task);
|
||||
}
|
||||
}
|
@ -0,0 +1,254 @@
|
||||
package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.NibbleArray;
|
||||
|
||||
public class ForgeChunk_All extends FaweChunk<Chunk> {
|
||||
|
||||
public byte[][] ids;
|
||||
public NibbleArray[] datas;
|
||||
|
||||
public short[] count;
|
||||
public short[] air;
|
||||
public short[] relight;
|
||||
public byte[][] biomes;
|
||||
public Chunk chunk;
|
||||
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
this.ids = new byte[16][];
|
||||
this.datas = new NibbleArray[16];
|
||||
this.count = new short[16];
|
||||
this.air = new short[16];
|
||||
this.relight = new short[16];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Chunk getChunk() {
|
||||
if (this.chunk == null) {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
this.chunk = world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
return this.chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
||||
super.setLoc(parent, x, z);
|
||||
this.chunk = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getCount(int i) {
|
||||
return this.count[i];
|
||||
}
|
||||
|
||||
public int getAir(int i) {
|
||||
return this.air[i];
|
||||
}
|
||||
|
||||
public void setCount(int i, short value) {
|
||||
this.count[i] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getRelight(int i) {
|
||||
return this.relight[i];
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.count[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public int getTotalRelight() {
|
||||
if (getTotalCount() == 0) {
|
||||
Arrays.fill(this.count, (short) 1);
|
||||
Arrays.fill(this.relight, Short.MAX_VALUE);
|
||||
return Short.MAX_VALUE;
|
||||
}
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.relight[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw data for a section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public byte[] getIdArray(int i) {
|
||||
return this.ids[i];
|
||||
}
|
||||
|
||||
public NibbleArray getDataArray(int i) {
|
||||
return datas[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, int id, byte data) {
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
byte[] vs = this.ids[i];
|
||||
if (vs == null) {
|
||||
vs = this.ids[i] = new byte[4096];
|
||||
this.count[i]++;
|
||||
} else if (vs[j] == 0) {
|
||||
this.count[i]++;
|
||||
}
|
||||
switch (id) {
|
||||
case 0:
|
||||
this.air[i]++;
|
||||
vs[j] = -1;
|
||||
return;
|
||||
case 10:
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 51:
|
||||
case 74:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 138:
|
||||
case 169:
|
||||
this.relight[i]++;
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 55:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 73:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 121:
|
||||
case 129:
|
||||
case 133:
|
||||
case 165:
|
||||
case 166:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
vs[j] = (byte) (id);
|
||||
return;
|
||||
case 130:
|
||||
case 76:
|
||||
case 62:
|
||||
this.relight[i]++;
|
||||
case 54:
|
||||
case 146:
|
||||
case 61:
|
||||
case 65:
|
||||
case 68:
|
||||
case 50:
|
||||
if (data < 2) {
|
||||
data = 2;
|
||||
}
|
||||
default:
|
||||
vs[j] = (byte) id;
|
||||
NibbleArray dataArray = datas[i];
|
||||
if (dataArray == null) {
|
||||
datas[i] = dataArray = new NibbleArray(4096, 4);
|
||||
}
|
||||
dataArray.set(x, y & 15, z, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, BaseBiome biome) {
|
||||
if (this.biomes == null) {
|
||||
this.biomes = new byte[16][];
|
||||
}
|
||||
byte[] index = this.biomes[x];
|
||||
if (index == null) {
|
||||
index = this.biomes[x] = new byte[16];
|
||||
}
|
||||
index[z] = (byte) biome.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk clone() {
|
||||
ForgeChunk_All toReturn = new ForgeChunk_All(getParent(), getX(), getZ());
|
||||
toReturn.air = this.air.clone();
|
||||
toReturn.count = this.count.clone();
|
||||
toReturn.relight = this.relight.clone();
|
||||
toReturn.ids = new byte[this.ids.length][];
|
||||
for (int i = 0; i < this.ids.length; i++) {
|
||||
byte[] matrix = this.ids[i];
|
||||
if (matrix != null) {
|
||||
toReturn.ids[i] = new byte[matrix.length];
|
||||
System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length);
|
||||
}
|
||||
}
|
||||
toReturn.datas = new NibbleArray[16];
|
||||
for (int i = 0; i < this.datas.length; i++) {
|
||||
if (datas[i] != null) {
|
||||
toReturn.datas[i] = datas[i];
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
}
|
@ -0,0 +1,597 @@
|
||||
package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.NetHandlerPlayServer;
|
||||
import net.minecraft.network.play.server.S21PacketChunkData;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ChunkCoordinates;
|
||||
import net.minecraft.util.LongHashMap;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
import net.minecraft.world.ChunkPosition;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.NibbleArray;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
|
||||
public class ForgeQueue_All extends FaweQueue {
|
||||
|
||||
private World forgeWorld;
|
||||
|
||||
private ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> chunks = new LinkedBlockingDeque<>();
|
||||
|
||||
public ForgeQueue_All(final String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int x, int z) {
|
||||
return getWorld().getChunkProvider().chunkExists(x, z);
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
if (forgeWorld != null) {
|
||||
return forgeWorld;
|
||||
}
|
||||
WorldServer[] worlds = MinecraftServer.getServer().worldServers;
|
||||
for (WorldServer ws : worlds) {
|
||||
if (ws.provider.getDimensionName().equals(world)) {
|
||||
return forgeWorld = ws;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(int x, int z) {
|
||||
try {
|
||||
IChunkProvider provider = getWorld().getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
|
||||
Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
Field u;
|
||||
try {
|
||||
u = ChunkProviderServer.class.getDeclaredField("field_73248_b"); // chunksToUnload
|
||||
} catch(NoSuchFieldException e) {
|
||||
u = ChunkProviderServer.class.getDeclaredField("chunksToUnload");
|
||||
}
|
||||
u.setAccessible(true);
|
||||
Set<?> unloadQueue = (Set<?>) u.get(chunkServer);
|
||||
Field m;
|
||||
try {
|
||||
m = ChunkProviderServer.class.getDeclaredField("field_73244_f"); // loadedChunkHashMap
|
||||
} catch(NoSuchFieldException e) {
|
||||
m = ChunkProviderServer.class.getDeclaredField("loadedChunkHashMap");
|
||||
}
|
||||
m.setAccessible(true);
|
||||
LongHashMap loadedMap = (LongHashMap) m.get(chunkServer);
|
||||
Field lc;
|
||||
try {
|
||||
lc = ChunkProviderServer.class.getDeclaredField("field_73245_g"); // loadedChunkHashMap
|
||||
} catch(NoSuchFieldException e) {
|
||||
lc = ChunkProviderServer.class.getDeclaredField("loadedChunks");
|
||||
}
|
||||
lc.setAccessible(true);
|
||||
@SuppressWarnings("unchecked") List<Chunk> loaded = (List<Chunk>) lc.get(chunkServer);
|
||||
Field p;
|
||||
try {
|
||||
p = ChunkProviderServer.class.getDeclaredField("field_73246_d"); // currentChunkProvider
|
||||
} catch(NoSuchFieldException e) {
|
||||
p = ChunkProviderServer.class.getDeclaredField("currentChunkProvider");
|
||||
}
|
||||
p.setAccessible(true);
|
||||
IChunkProvider chunkProvider = (IChunkProvider) p.get(chunkServer);
|
||||
long pos = ChunkCoordIntPair.chunkXZ2Int(x, z);
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
unloadQueue.remove(pos);
|
||||
loadedMap.remove(pos);
|
||||
mcChunk = chunkProvider.provideChunk(x, z);
|
||||
loadedMap.add(pos, mcChunk);
|
||||
loaded.add(mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkProvider, chunkProvider, x, z);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTask(int x, int z, Runnable runnable) {
|
||||
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x, z);
|
||||
result.addTask(runnable);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous == null) {
|
||||
chunks.add(result);
|
||||
return;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
}
|
||||
result.addTask(runnable);
|
||||
}
|
||||
|
||||
private int lcx = Integer.MIN_VALUE;
|
||||
private int lcz = Integer.MIN_VALUE;
|
||||
private int lcy = Integer.MIN_VALUE;
|
||||
private net.minecraft.world.chunk.Chunk lc;
|
||||
private ExtendedBlockStorage ls;
|
||||
|
||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair loc) {
|
||||
Chunk chunk = getWorld().getChunkProvider().provideChunk(loc.x, loc.z);
|
||||
if (chunk != null && !chunk.isChunkLoaded) {
|
||||
chunk.onChunkLoad();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
if (y < 0 || y > 255) {
|
||||
return 0;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
int cy = y >> 4;
|
||||
if (cx != lcx || cz != lcz) {
|
||||
World world = getWorld();
|
||||
lcx = cx;
|
||||
lcz = cz;
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
Chunk chunk;
|
||||
if (!provider.chunkExists(cx, cz)) {
|
||||
boolean sync = Thread.currentThread() == Fawe.get().getMainThread();
|
||||
if (sync) {
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
} else if (Settings.CHUNK_WAIT > 0) {
|
||||
loadChunk.value = new IntegerPair(cx, cz);
|
||||
TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT);
|
||||
if (!provider.chunkExists(cx, cz)) {
|
||||
throw new FaweException.FaweChunkLoadException();
|
||||
}
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
}
|
||||
lc = chunk;
|
||||
ls = lc.getBlockStorageArray()[cy];
|
||||
} else if (cy != lcy) {
|
||||
if (lc == null) {
|
||||
return 0;
|
||||
}
|
||||
ls = lc.getBlockStorageArray()[cy];
|
||||
}
|
||||
if (ls == null) {
|
||||
ls = null;
|
||||
return 0;
|
||||
}
|
||||
byte[] ids = ls.getBlockLSBArray();
|
||||
NibbleArray datasNibble = ls.getBlockMSBArray();
|
||||
int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15];
|
||||
int combined = (ids[i] << 4) + (datasNibble == null ? 0 : datasNibble.get(x & 15, y & 15, z & 15));
|
||||
return combined;
|
||||
}
|
||||
|
||||
private FaweChunk lastChunk;
|
||||
private int lastX = Integer.MIN_VALUE;
|
||||
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;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastChunk = this.blocks.get(pair);
|
||||
if (lastChunk == null) {
|
||||
lastChunk = this.getChunk(x >> 4, z >> 4);
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, lastChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastChunk);
|
||||
return true;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastChunk = previous;
|
||||
}
|
||||
}
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int z, BaseBiome biome) {
|
||||
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x >> 4, z >> 4);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous != null) {
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
} else {
|
||||
chunks.add(result);
|
||||
}
|
||||
}
|
||||
result.setBiome(x & 15, z & 15, biome);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> next() {
|
||||
lastX = Integer.MIN_VALUE;
|
||||
lastZ = Integer.MIN_VALUE;
|
||||
try {
|
||||
if (this.blocks.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
synchronized (blocks) {
|
||||
FaweChunk<Chunk> chunk = chunks.poll();
|
||||
if (chunk != null) {
|
||||
blocks.remove(chunk.longHash());
|
||||
this.execute(chunk);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return chunks.size();
|
||||
}
|
||||
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> toUpdate = new LinkedBlockingDeque<>();
|
||||
|
||||
public boolean execute(FaweChunk<Chunk> fc) {
|
||||
if (fc == null) {
|
||||
return false;
|
||||
}
|
||||
// Load chunk
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isChunkLoaded) {
|
||||
chunk.onChunkLoad();
|
||||
}
|
||||
// Set blocks / entities / biome
|
||||
if (!this.setComponents(fc)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.blocks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(FaweChunk<?> chunk) {
|
||||
FaweChunk<Chunk> previous = this.blocks.put(chunk.longHash(), (FaweChunk<Chunk>) chunk);
|
||||
if (previous != null) {
|
||||
chunks.remove(previous);
|
||||
}
|
||||
chunks.add((FaweChunk<Chunk>) chunk);
|
||||
}
|
||||
|
||||
public void sendChunk(final FaweChunk<Chunk> fc) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isChunkLoaded) {
|
||||
return;
|
||||
}
|
||||
World world = chunk.worldObj;
|
||||
ChunkCoordIntPair pos = chunk.getChunkCoordIntPair();
|
||||
int cx = pos.chunkXPos;
|
||||
int cz = pos.chunkZPos;
|
||||
for (FawePlayer fp : Fawe.get().getCachedPlayers()) {
|
||||
ForgePlayer forgePlayer = (ForgePlayer) fp;
|
||||
EntityPlayerMP player = forgePlayer.parent;
|
||||
if (!player.worldObj.equals(world)) {
|
||||
continue;
|
||||
}
|
||||
int view = MinecraftServer.getServer().getConfigurationManager().getViewDistance();
|
||||
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||
ChunkCoordinates loc = player.getPlayerCoordinates();
|
||||
int px = loc.posX >> 4;
|
||||
int pz = loc.posZ >> 4;
|
||||
int dx = Math.abs(cx - (loc.posX >> 4));
|
||||
int dz = Math.abs(cz - (loc.posZ >> 4));
|
||||
if ((dx > view) || (dz > view)) {
|
||||
continue;
|
||||
}
|
||||
NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler;
|
||||
con.sendPacket(new S21PacketChunkData(chunk, false, 65535));
|
||||
// Try sending true, 0 first
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
}
|
||||
|
||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||
Chunk forgeChunk = fc.getChunk();
|
||||
net.minecraft.world.World nmsWorld = forgeChunk.worldObj;
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.hasNoSky;
|
||||
// Sections
|
||||
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray();
|
||||
Map<ChunkPosition, TileEntity> tiles = forgeChunk.chunkTileEntityMap;
|
||||
List[] entities = forgeChunk.entityLists;
|
||||
// Trim tiles
|
||||
Set<Map.Entry<ChunkPosition, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<ChunkPosition, TileEntity>> iterator = entryset.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<ChunkPosition, TileEntity> tile = iterator.next();
|
||||
ChunkPosition pos = tile.getKey();
|
||||
int lx = pos.chunkPosX & 15;
|
||||
int ly = pos.chunkPosY;
|
||||
int lz = pos.chunkPosZ & 15;
|
||||
int j = FaweCache.CACHE_I[ly][lx][lz];
|
||||
int k = FaweCache.CACHE_J[ly][lx][lz];
|
||||
byte[] array = fs.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
if (array[k] != 0) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
if (fs.getCount(j) == 0) {
|
||||
continue;
|
||||
}
|
||||
byte[] newIdArray = fs.getIdArray(j);
|
||||
if (newIdArray == null) {
|
||||
continue;
|
||||
}
|
||||
NibbleArray newDataArray = fs.getDataArray(j);
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
||||
sections[j] = section = new ExtendedBlockStorage(j << 4, !getWorld().provider.hasNoSky);
|
||||
section.setBlockLSBArray(newIdArray);
|
||||
section.setBlockMetadataArray(newDataArray);
|
||||
continue;
|
||||
}
|
||||
// id + data << 8
|
||||
|
||||
byte[] currentIdArray = section.getBlockLSBArray();
|
||||
NibbleArray currentDataArray = section.getMetadataArray();
|
||||
boolean data = currentDataArray != null;
|
||||
if (!data) {
|
||||
section.setBlockMetadataArray(newDataArray);
|
||||
}
|
||||
boolean fill = true;
|
||||
for (int k = 0; k < newIdArray.length; k++) {
|
||||
byte n = newIdArray[k];
|
||||
switch (n) {
|
||||
case 0:
|
||||
fill = false;
|
||||
continue;
|
||||
case -1:
|
||||
fill = false;
|
||||
currentIdArray[k] = 0;
|
||||
continue;
|
||||
default:
|
||||
currentIdArray[k] = n;
|
||||
if (data) {
|
||||
int x = FaweCache.CACHE_X[j][k];
|
||||
int y = FaweCache.CACHE_Y[j][k];
|
||||
int z = FaweCache.CACHE_Z[j][k];
|
||||
int newData = newDataArray == null ? 0 : newDataArray.get(x, y, z);
|
||||
int currentData = currentDataArray == null ? 0 : currentDataArray.get(x, y, z);
|
||||
if (newData != currentData) {
|
||||
currentDataArray.set(x, y, z, newData);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (fill) {
|
||||
fs.setCount(j, Short.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
// // Clear
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
byte[][] biomes = fs.biomes;
|
||||
if (biomes != null) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
byte[] array = biomes[x];
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
for (int z = 0; z < 16; z++) {
|
||||
byte biome = array[z];
|
||||
if (biome == 0) {
|
||||
continue;
|
||||
}
|
||||
forgeChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
sendChunk(fs);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk<?> chunk, boolean fixAll) {
|
||||
try {
|
||||
ForgeChunk_All fc = (ForgeChunk_All) chunk;
|
||||
Chunk forgeChunk = fc.getChunk();
|
||||
if (!forgeChunk.isChunkLoaded) {
|
||||
forgeChunk.onChunkLoad();
|
||||
}
|
||||
forgeChunk.generateSkylightMap();
|
||||
if (fc.getTotalRelight() == 0 && !fixAll) {
|
||||
return true;
|
||||
}
|
||||
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray();
|
||||
net.minecraft.world.World nmsWorld = forgeChunk.worldObj;
|
||||
|
||||
int X = fc.getX() << 4;
|
||||
int Z = fc.getZ() << 4;
|
||||
|
||||
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if (section == null) {
|
||||
continue;
|
||||
}
|
||||
if ((fc.getRelight(j) == 0 && !fixAll) || fc.getCount(j) == 0 || (fc.getCount(j) >= 4096 && fc.getAir(j) == 0)) {
|
||||
continue;
|
||||
}
|
||||
byte[] array = section.getBlockLSBArray();
|
||||
int l = PseudoRandom.random.random(2);
|
||||
for (int k = 0; k < array.length; k++) {
|
||||
int i = array[k];
|
||||
if (i < 16) {
|
||||
continue;
|
||||
}
|
||||
short id = (short) (i);
|
||||
switch (id) { // Lighting
|
||||
default:
|
||||
if (!fixAll) {
|
||||
continue;
|
||||
}
|
||||
if ((k & 1) == l) {
|
||||
l = 1 - l;
|
||||
continue;
|
||||
}
|
||||
case 10:
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 50:
|
||||
case 51:
|
||||
case 62:
|
||||
case 74:
|
||||
case 76:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 130:
|
||||
case 138:
|
||||
case 169:
|
||||
int x = FaweCache.CACHE_X[j][k];
|
||||
int y = FaweCache.CACHE_Y[j][k];
|
||||
int z = FaweCache.CACHE_Z[j][k];
|
||||
if (isSurrounded(sections, x, y, z)) {
|
||||
continue;
|
||||
}
|
||||
nmsWorld.func_147451_t(X + x, y, Z + z);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
if (Thread.currentThread() == Fawe.get().getMainThread()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) {
|
||||
return isSolid(getId(sections, x, y + 1, z))
|
||||
&& isSolid(getId(sections, x + 1, y - 1, z))
|
||||
&& isSolid(getId(sections, x - 1, y, z))
|
||||
&& isSolid(getId(sections, x, y, z + 1))
|
||||
&& isSolid(getId(sections, x, y, z - 1));
|
||||
}
|
||||
|
||||
public boolean isSolid(int i) {
|
||||
return i != 0 && Block.getBlockById(i).isOpaqueCube();
|
||||
}
|
||||
|
||||
public int getId(ExtendedBlockStorage[] sections, int x, int y, int z) {
|
||||
if (x < 0 || x > 15 || z < 0 || z > 15) {
|
||||
return 1;
|
||||
}
|
||||
if (y < 0 || y > 255) {
|
||||
return 1;
|
||||
}
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
byte[] array = section.getBlockLSBArray();
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
return array[j];
|
||||
}
|
||||
}
|
10
forge1710/src/main/resources/mcmod.info
Normal file
10
forge1710/src/main/resources/mcmod.info
Normal file
@ -0,0 +1,10 @@
|
||||
[{
|
||||
"modid": "com.boydti.fawe",
|
||||
"name": "FastAsyncWorldEdit",
|
||||
"description": "Extreme WorldEdit optimizations, no lag, low memory usage, area + tile + entity limits, block logging + rollback",
|
||||
"version": "3.4.0",
|
||||
"mcVersion": "1.7.10",
|
||||
"dependencies": [
|
||||
"WorldEdit"
|
||||
]
|
||||
}]
|
@ -5,15 +5,14 @@ buildscript {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {url = "http://repo.minecrell.net/snapshots"}
|
||||
maven {url = "https://oss.sonatype.org/content/repositories/snapshots/"}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecrell:VanillaGradle:2.0.3-SNAPSHOT'
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecrell.vanilla.server.library'
|
||||
apply plugin: 'net.minecraftforge.gradle.forge'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
dependencies {
|
||||
@ -41,7 +40,7 @@ repositories {
|
||||
}
|
||||
}
|
||||
minecraft {
|
||||
version = "1.8.9"
|
||||
version = "1855"
|
||||
mappings = "stable_22"
|
||||
runDir = 'run'
|
||||
}
|
||||
@ -52,15 +51,16 @@ 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.mcstats.sponge:metrics:R8-SNAPSHOT'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
}
|
||||
relocate 'org.mcstats', 'com.boydti.fawe.stats'
|
||||
archiveName = "${parent.name}-${project.name}.jar"
|
||||
destinationDir = file '../target'
|
||||
}
|
||||
@ -69,6 +69,7 @@ shadowJar.doLast {
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
|
||||
reobf {
|
||||
shadowJar {
|
||||
mappingType = 'SEARGE'
|
||||
@ -80,4 +81,8 @@ task deobfJar(type: Jar) {
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar)
|
166
forge189/src/main/java/com/boydti/fawe/forge/FaweForge.java
Normal file
166
forge189/src/main/java/com/boydti/fawe/forge/FaweForge.java
Normal file
@ -0,0 +1,166 @@
|
||||
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.EditSessionWrapper;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.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.UUID;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import net.minecraft.command.ServerCommandManager;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FaweForge implements IFawe {
|
||||
|
||||
private final ForgeMain parent;
|
||||
private final File directory;
|
||||
private final Logger logger;
|
||||
|
||||
public FaweForge(ForgeMain plugin, Logger logger, File directory) {
|
||||
this.parent = plugin;
|
||||
this.logger = logger;
|
||||
this.directory = directory;
|
||||
try {
|
||||
Fawe.set(this);
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String s) {
|
||||
logger.debug(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupCommand(String label, FaweCommand cmd) {
|
||||
if (TaskManager.IMP != null) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ServerCommandManager scm = (ServerCommandManager) MinecraftServer.getServer().getCommandManager();
|
||||
scm.registerCommand(new ForgeCommand(label, cmd));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
EntityPlayerMP player = null;
|
||||
if (obj instanceof String) {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
player = server.getConfigurationManager().getPlayerByUsername((String) obj);
|
||||
} else if (obj instanceof UUID) {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
player = server.getConfigurationManager().getPlayerByUUID((UUID) obj);
|
||||
} else if (obj instanceof EntityPlayerMP) {
|
||||
player = (EntityPlayerMP) obj;
|
||||
}
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getName());
|
||||
return existing != null ? existing : new ForgePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupWEListener() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVault() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new com.boydti.fawe.forge.ForgeTaskMan(512);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getVersion() {
|
||||
String[] version = MinecraftServer.getServer().getMinecraftVersion().split("\\.");
|
||||
return new int[] {Integer.parseInt(version[0]), Integer.parseInt(version[1]), Integer.parseInt(version[2])};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
if (world instanceof WorldWrapper) {
|
||||
world = ((WorldWrapper) world).getParent();
|
||||
}
|
||||
return ((ForgeWorld) world).getWorld().provider.getDimensionName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditSessionWrapper getEditSessionWrapper(EditSession session) {
|
||||
return new EditSessionWrapper(session);
|
||||
}
|
||||
|
||||
@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.4.0");
|
||||
metrics.start();
|
||||
debug("[FAWE] &6Metrics enabled.");
|
||||
} catch (Throwable e) {
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatform() {
|
||||
return "forge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try {
|
||||
GameProfile profile = MinecraftServer.getServer().getPlayerProfileCache().getGameProfileForUsername(name);
|
||||
return profile.getId();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
try {
|
||||
GameProfile profile = MinecraftServer.getServer().getPlayerProfileCache().getProfileByUUID(uuid);
|
||||
return profile.getName();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
|
||||
public class ForgeCommand extends CommandBase {
|
||||
|
||||
private final String name;
|
||||
private final FaweCommand cmd;
|
||||
|
||||
public ForgeCommand(String name, FaweCommand cmd) {
|
||||
this.name = name;
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender iCommandSender) {
|
||||
return "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
|
||||
if ((sender instanceof EntityPlayerMP)) {
|
||||
EntityPlayerMP player = (EntityPlayerMP) sender;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
cmd.executeSafe(fp, args);
|
||||
}
|
||||
}
|
||||
}
|
76
forge189/src/main/java/com/boydti/fawe/forge/ForgeMain.java
Normal file
76
forge189/src/main/java/com/boydti/fawe/forge/ForgeMain.java
Normal file
@ -0,0 +1,76 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.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.4.0", 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 com.boydti.fawe.forge.FaweForge(this, event.getModLog(), directory);
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerQuit(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (event.player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
handleQuit((EntityPlayerMP) event.player);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverStopping(FMLServerStoppingEvent event) {
|
||||
for (EntityPlayerMP player : (List<EntityPlayerMP>)MinecraftServer.getServer().getConfigurationManager().playerEntityList) {
|
||||
handleQuit(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleQuit(EntityPlayerMP player) {
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
fp.unregister();
|
||||
Fawe.get().unregister(player.getName());
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerChangedWorld(EntityJoinWorldEvent event) {
|
||||
Entity entity = event.entity;
|
||||
if (!(entity instanceof EntityPlayerMP)) {
|
||||
return;
|
||||
}
|
||||
EntityPlayerMP player = (EntityPlayerMP) entity;
|
||||
if (player.worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
if (fp.getMeta("lastWorld") != event.world) {
|
||||
fp.setMeta("lastWorld", event.world);
|
||||
if (Settings.STORE_HISTORY_ON_DISK) {
|
||||
fp.getSession().clearHistory();
|
||||
fp.loadSessionsFromDisk(fp.getWorld());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
479
forge189/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java
Normal file
479
forge189/src/main/java/com/boydti/fawe/forge/ForgeMetrics.java
Normal file
@ -0,0 +1,479 @@
|
||||
/*
|
||||
* 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 java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class ForgeMetrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 7;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://report.mcstats.org";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/plugin/%s";
|
||||
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 15;
|
||||
|
||||
/**
|
||||
* The mod this metrics submits for
|
||||
*/
|
||||
private final String modName;
|
||||
|
||||
private final String modVersion;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final Configuration configuration;
|
||||
|
||||
/**
|
||||
* The metrics configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
|
||||
private Thread thread = null;
|
||||
private boolean firstPost = true;
|
||||
int tickCount;
|
||||
|
||||
public ForgeMetrics(final String modName, final String modVersion) throws IOException {
|
||||
if (modName == null || modVersion == null) {
|
||||
throw new IllegalArgumentException("modName and modVersion cannot be null");
|
||||
}
|
||||
|
||||
this.modName = modName;
|
||||
this.modVersion = modVersion;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = new Configuration(configurationFile);
|
||||
|
||||
// Get values, and add some defaults, if needed
|
||||
configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false, "Set to true to disable all reporting");
|
||||
guid = configuration.get(Configuration.CATEGORY_GENERAL, "guid", UUID.randomUUID().toString(), "Server unique ID").getString();
|
||||
debug = configuration.get(Configuration.CATEGORY_GENERAL, "debug", false, "Set to true for verbose debug").getBoolean(false);
|
||||
configuration.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async
|
||||
* repeating task as the plugin and send the initial data to the metrics
|
||||
* backend, and then after that it will post in increments of PING_INTERVAL
|
||||
* * 1200 ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void tick(TickEvent.ServerTickEvent tick) {
|
||||
if (tick.phase != TickEvent.Phase.END) return;
|
||||
|
||||
if (tickCount++ % (PING_INTERVAL * 1200) != 0) return;
|
||||
|
||||
if (thread == null) {
|
||||
thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Disable Task, if it is running and the server owner decided
|
||||
// to opt-out
|
||||
if (isOptOut()) {
|
||||
FMLCommonHandler.instance().bus().unregister(ForgeMetrics.this);
|
||||
return;
|
||||
}
|
||||
// We use the inverse of firstPost because if it
|
||||
// is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to
|
||||
// FALSE
|
||||
// Each time thereafter it will evaluate to
|
||||
// TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
// After the first post we set firstPost to
|
||||
// false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
FMLLog.info("[Metrics] Exception - %s", e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
*/
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
// Reload the metrics file
|
||||
configuration.load();
|
||||
return configuration.get(Configuration.CATEGORY_GENERAL, "opt-out", false).getBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the
|
||||
* config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("false");
|
||||
configuration.save();
|
||||
}
|
||||
// Enable Task, if it is not running
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the
|
||||
* config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.getCategory(Configuration.CATEGORY_GENERAL).get("opt-out").set("true");
|
||||
configuration.save();
|
||||
}
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data
|
||||
* such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
return new File(Loader.instance().getConfigDir(), "PluginMetrics.cfg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
String pluginName = modName;
|
||||
boolean onlineMode = MinecraftServer.getServer().isServerInOnlineMode();
|
||||
String pluginVersion = modVersion;
|
||||
String serverVersion;
|
||||
if (MinecraftServer.getServer().isDedicatedServer()) {
|
||||
serverVersion = "MinecraftForge (MC: " + MinecraftServer.getServer().getMinecraftVersion() + ")";
|
||||
} else {
|
||||
serverVersion = "MinecraftForgeSSP (MC: " + MinecraftServer.getServer().getMinecraftVersion() + ")";
|
||||
}
|
||||
int playersOnline = MinecraftServer.getServer().getCurrentPlayerCount();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
StringBuilder json = new StringBuilder(1024);
|
||||
json.append('{');
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
appendJSONPair(json, "guid", guid);
|
||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
||||
appendJSONPair(json, "server_version", serverVersion);
|
||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
appendJSONPair(json, "osname", osname);
|
||||
appendJSONPair(json, "osarch", osarch);
|
||||
appendJSONPair(json, "osversion", osversion);
|
||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
||||
appendJSONPair(json, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
appendJSONPair(json, "ping", "1");
|
||||
}
|
||||
|
||||
// close json
|
||||
json.append('}');
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
|
||||
byte[] uncompressed = json.toString().getBytes();
|
||||
byte[] compressed = gzip(json.toString());
|
||||
|
||||
// Headers
|
||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
||||
connection.addRequestProperty("Content-Type", "application/json");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(compressed);
|
||||
os.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
os.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
||||
if (response == null) {
|
||||
response = "null";
|
||||
} else if (response.startsWith("7")) {
|
||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
||||
}
|
||||
|
||||
throw new IOException(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GZip compress a string of bytes
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static byte[] gzip(String input) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gzos = null;
|
||||
|
||||
try {
|
||||
gzos = new GZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} 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");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
|
||||
public ForgePlayer(EntityPlayerMP parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return parent.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
Object meta = getMeta(perm);
|
||||
return meta instanceof Boolean ? (boolean) meta : ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(parent, perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(String perm, boolean flag) {
|
||||
setMeta(perm, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
part = EnumChatFormatting.getTextWithoutFormattingCodes(msg);
|
||||
ChatComponentText component = new ChatComponentText(part);
|
||||
component.getChatStyle().setColor(EnumChatFormatting.LIGHT_PURPLE);
|
||||
this.parent.addChatMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(String substring) {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweLocation getLocation() {
|
||||
World world = parent.worldObj;
|
||||
BlockPos pos = parent.getPosition();
|
||||
return new FaweLocation(world.provider.getDimensionName(), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return ForgeWorldEdit.inst.wrap(this.parent);
|
||||
}
|
||||
}
|
165
forge189/src/main/java/com/boydti/fawe/forge/ForgeTaskMan.java
Normal file
165
forge189/src/main/java/com/boydti/fawe/forge/ForgeTaskMan.java
Normal file
@ -0,0 +1,165 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
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<>();
|
||||
|
||||
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
later(this, interval);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
task(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int task) {
|
||||
taskIdMap.remove(task);
|
||||
}
|
||||
}
|
@ -0,0 +1,235 @@
|
||||
package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
public class ForgeChunk_All extends FaweChunk<Chunk> {
|
||||
|
||||
public char[][] ids;
|
||||
public short[] count;
|
||||
public short[] air;
|
||||
public short[] relight;
|
||||
public byte[][] biomes;
|
||||
public Chunk chunk;
|
||||
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
this.ids = new char[16][];
|
||||
this.count = new short[16];
|
||||
this.air = new short[16];
|
||||
this.relight = new short[16];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Chunk getChunk() {
|
||||
if (this.chunk == null) {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
this.chunk = world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
return this.chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
||||
super.setLoc(parent, x, z);
|
||||
this.chunk = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getCount(int i) {
|
||||
return this.count[i];
|
||||
}
|
||||
|
||||
public int getAir(int i) {
|
||||
return this.air[i];
|
||||
}
|
||||
|
||||
public void setCount(int i, short value) {
|
||||
this.count[i] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getRelight(int i) {
|
||||
return this.relight[i];
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.count[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public int getTotalRelight() {
|
||||
if (getTotalCount() == 0) {
|
||||
Arrays.fill(this.count, (short) 1);
|
||||
Arrays.fill(this.relight, Short.MAX_VALUE);
|
||||
return Short.MAX_VALUE;
|
||||
}
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.relight[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw data for a section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public char[] getIdArray(int i) {
|
||||
return this.ids[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, int id, byte data) {
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
char[] vs = this.ids[i];
|
||||
if (vs == null) {
|
||||
vs = this.ids[i] = new char[4096];
|
||||
this.count[i]++;
|
||||
} else if (vs[j] == 0) {
|
||||
this.count[i]++;
|
||||
}
|
||||
switch (id) {
|
||||
case 0:
|
||||
this.air[i]++;
|
||||
vs[j] = (char) 1;
|
||||
return;
|
||||
case 10:
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 51:
|
||||
case 74:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 138:
|
||||
case 169:
|
||||
this.relight[i]++;
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 55:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 73:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 121:
|
||||
case 129:
|
||||
case 133:
|
||||
case 165:
|
||||
case 166:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
vs[j] = (char) (id << 4);
|
||||
return;
|
||||
case 130:
|
||||
case 76:
|
||||
case 62:
|
||||
this.relight[i]++;
|
||||
case 54:
|
||||
case 146:
|
||||
case 61:
|
||||
case 65:
|
||||
case 68:
|
||||
case 50:
|
||||
if (data < 2) {
|
||||
data = 2;
|
||||
}
|
||||
default:
|
||||
vs[j] = (char) ((id << 4) + data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, BaseBiome biome) {
|
||||
if (this.biomes == null) {
|
||||
this.biomes = new byte[16][];
|
||||
}
|
||||
byte[] index = this.biomes[x];
|
||||
if (index == null) {
|
||||
index = this.biomes[x] = new byte[16];
|
||||
}
|
||||
index[z] = (byte) biome.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk clone() {
|
||||
ForgeChunk_All toReturn = new ForgeChunk_All(getParent(), getX(), getZ());
|
||||
toReturn.air = this.air.clone();
|
||||
toReturn.count = this.count.clone();
|
||||
toReturn.relight = this.relight.clone();
|
||||
toReturn.ids = new char[this.ids.length][];
|
||||
for (int i = 0; i < this.ids.length; i++) {
|
||||
char[] matrix = this.ids[i];
|
||||
if (matrix != null) {
|
||||
toReturn.ids[i] = new char[matrix.length];
|
||||
System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length);
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
}
|
@ -0,0 +1,541 @@
|
||||
package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.NetHandlerPlayServer;
|
||||
import net.minecraft.network.play.server.S21PacketChunkData;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
|
||||
public class ForgeQueue_All extends FaweQueue {
|
||||
|
||||
private World forgeWorld;
|
||||
|
||||
private ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> chunks = new LinkedBlockingDeque<>();
|
||||
|
||||
public ForgeQueue_All(final String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int x, int z) {
|
||||
return getWorld().getChunkProvider().chunkExists(x, z);
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
if (forgeWorld != null) {
|
||||
return forgeWorld;
|
||||
}
|
||||
WorldServer[] worlds = MinecraftServer.getServer().worldServers;
|
||||
for (WorldServer ws : worlds) {
|
||||
if (ws.provider.getDimensionName().equals(world)) {
|
||||
return forgeWorld = ws;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(int x, int z) {
|
||||
IChunkProvider provider = getWorld().getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
IChunkProvider chunkProvider = chunkServer.serverChunkGenerator;
|
||||
|
||||
long pos = ChunkCoordIntPair.chunkXZ2Int(x, z);
|
||||
Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
try {
|
||||
Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b");
|
||||
droppedChunksSetField.setAccessible(true);
|
||||
Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer);
|
||||
droppedChunksSet.remove(pos);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
chunkServer.id2ChunkMap.remove(pos);
|
||||
mcChunk = chunkProvider.provideChunk(x, z);
|
||||
chunkServer.id2ChunkMap.add(pos, mcChunk);
|
||||
chunkServer.loadedChunks.add(mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkProvider, chunkProvider, x, z);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTask(int x, int z, Runnable runnable) {
|
||||
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x, z);
|
||||
result.addTask(runnable);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous == null) {
|
||||
chunks.add(result);
|
||||
return;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
}
|
||||
result.addTask(runnable);
|
||||
}
|
||||
|
||||
private int lcx = Integer.MIN_VALUE;
|
||||
private int lcz = Integer.MIN_VALUE;
|
||||
private int lcy = Integer.MIN_VALUE;
|
||||
private net.minecraft.world.chunk.Chunk lc;
|
||||
private char[] ls;
|
||||
|
||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair loc) {
|
||||
getWorld().getChunkProvider().provideChunk(loc.x, loc.z);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
if (y < 0 || y > 255) {
|
||||
return 0;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
int cy = y >> 4;
|
||||
if (cx != lcx || cz != lcz) {
|
||||
World world = getWorld();
|
||||
lcx = cx;
|
||||
lcz = cz;
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
Chunk chunk;
|
||||
if (!provider.chunkExists(lcx, lcz)) {
|
||||
boolean sync = Thread.currentThread() == Fawe.get().getMainThread();
|
||||
if (sync) {
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
} else if (Settings.CHUNK_WAIT > 0) {
|
||||
loadChunk.value = new IntegerPair(cx, cz);
|
||||
TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT);
|
||||
if (!provider.chunkExists(cx, cz)) {
|
||||
throw new FaweException.FaweChunkLoadException();
|
||||
}
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
}
|
||||
lc = chunk;
|
||||
} else if (cy == lcy) {
|
||||
return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0;
|
||||
}
|
||||
ExtendedBlockStorage storage = lc.getBlockStorageArray()[cy];
|
||||
if (storage == null) {
|
||||
ls = null;
|
||||
return 0;
|
||||
}
|
||||
ls = storage.getData();
|
||||
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
|
||||
}
|
||||
|
||||
private FaweChunk lastChunk;
|
||||
private int lastX = Integer.MIN_VALUE;
|
||||
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;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastChunk = this.blocks.get(pair);
|
||||
if (lastChunk == null) {
|
||||
lastChunk = this.getChunk(x >> 4, z >> 4);
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, lastChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastChunk);
|
||||
return true;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastChunk = previous;
|
||||
}
|
||||
}
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int z, BaseBiome biome) {
|
||||
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x >> 4, z >> 4);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous != null) {
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
} else {
|
||||
chunks.add(result);
|
||||
}
|
||||
}
|
||||
result.setBiome(x & 15, z & 15, biome);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> next() {
|
||||
lastX = Integer.MIN_VALUE;
|
||||
lastZ = Integer.MIN_VALUE;
|
||||
try {
|
||||
if (this.blocks.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
synchronized (blocks) {
|
||||
FaweChunk<Chunk> chunk = chunks.poll();
|
||||
if (chunk != null) {
|
||||
blocks.remove(chunk.longHash());
|
||||
this.execute(chunk);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return chunks.size();
|
||||
}
|
||||
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> toUpdate = new LinkedBlockingDeque<>();
|
||||
|
||||
public boolean execute(FaweChunk<Chunk> fc) {
|
||||
if (fc == null) {
|
||||
return false;
|
||||
}
|
||||
// Load chunk
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
chunk.onChunkLoad();
|
||||
}
|
||||
// Set blocks / entities / biome
|
||||
if (!this.setComponents(fc)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.blocks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(FaweChunk<?> chunk) {
|
||||
FaweChunk<Chunk> previous = this.blocks.put(chunk.longHash(), (FaweChunk<Chunk>) chunk);
|
||||
if (previous != null) {
|
||||
chunks.remove(previous);
|
||||
}
|
||||
chunks.add((FaweChunk<Chunk>) chunk);
|
||||
}
|
||||
|
||||
public void sendChunk(FaweChunk<Chunk> fc) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
World world = chunk.getWorld();
|
||||
ChunkCoordIntPair pos = chunk.getChunkCoordIntPair();
|
||||
int cx = pos.chunkXPos;
|
||||
int cz = pos.chunkZPos;
|
||||
for (FawePlayer fp : Fawe.get().getCachedPlayers()) {
|
||||
ForgePlayer forgePlayer = (ForgePlayer) fp;
|
||||
EntityPlayerMP player = forgePlayer.parent;
|
||||
if (!player.worldObj.equals(world)) {
|
||||
continue;
|
||||
}
|
||||
int view = MinecraftServer.getServer().getConfigurationManager().getViewDistance();
|
||||
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||
BlockPos loc = player.getPosition();
|
||||
int px = loc.getX() >> 4;
|
||||
int pz = loc.getZ() >> 4;
|
||||
int dx = Math.abs(cx - (loc.getX() >> 4));
|
||||
int dz = Math.abs(cz - (loc.getZ() >> 4));
|
||||
if ((dx > view) || (dz > view)) {
|
||||
continue;
|
||||
}
|
||||
NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler;
|
||||
con.sendPacket(new S21PacketChunkData(chunk, false, 65535));
|
||||
// Try sending true, 0 first
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
}
|
||||
|
||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||
Chunk forgeChunk = fc.getChunk();
|
||||
net.minecraft.world.World nmsWorld = forgeChunk.getWorld();
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||
// Sections
|
||||
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray();
|
||||
Map<BlockPos, TileEntity> tiles = forgeChunk.getTileEntityMap();
|
||||
ClassInheritanceMultiMap<Entity>[] entities = forgeChunk.getEntityLists();
|
||||
// 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][lx][lz];
|
||||
int k = FaweCache.CACHE_J[ly][lx][lz];
|
||||
char[] array = fs.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
if (array[k] != 0) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
// Trim entities
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) {
|
||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
if (fs.getCount(j) == 0) {
|
||||
continue;
|
||||
}
|
||||
char[] newArray = fs.getIdArray(j);
|
||||
if (newArray == null) {
|
||||
continue;
|
||||
}
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
||||
section = new ExtendedBlockStorage(j << 4, flag);
|
||||
section.setData(newArray);
|
||||
sections[j] = section;
|
||||
continue;
|
||||
}
|
||||
char[] currentArray = section.getData();
|
||||
boolean fill = true;
|
||||
for (int k = 0; k < newArray.length; k++) {
|
||||
char n = newArray[k];
|
||||
switch (n) {
|
||||
case 0:
|
||||
fill = false;
|
||||
continue;
|
||||
case 1:
|
||||
fill = false;
|
||||
currentArray[k] = 0;
|
||||
continue;
|
||||
default:
|
||||
currentArray[k] = n;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (fill) {
|
||||
fs.setCount(j, Short.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
// // Clear
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
byte[][] biomes = fs.biomes;
|
||||
if (biomes != null) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
byte[] array = biomes[x];
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
for (int z = 0; z < 16; z++) {
|
||||
byte biome = array[z];
|
||||
if (biome == 0) {
|
||||
continue;
|
||||
}
|
||||
forgeChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
sendChunk(fs);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk<?> chunk, boolean fixAll) {
|
||||
try {
|
||||
ForgeChunk_All fc = (ForgeChunk_All) chunk;
|
||||
Chunk forgeChunk = fc.getChunk();
|
||||
if (!forgeChunk.isLoaded()) {
|
||||
forgeChunk.onChunkLoad();
|
||||
}
|
||||
forgeChunk.generateSkylightMap();
|
||||
if (fc.getTotalRelight() == 0 && !fixAll) {
|
||||
return true;
|
||||
}
|
||||
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray();
|
||||
net.minecraft.world.World nmsWorld = forgeChunk.getWorld();
|
||||
|
||||
int X = fc.getX() << 4;
|
||||
int Z = fc.getZ() << 4;
|
||||
|
||||
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if (section == null) {
|
||||
continue;
|
||||
}
|
||||
if ((fc.getRelight(j) == 0 && !fixAll) || fc.getCount(j) == 0 || (fc.getCount(j) >= 4096 && fc.getAir(j) == 0)) {
|
||||
continue;
|
||||
}
|
||||
char[] array = section.getData();
|
||||
int l = PseudoRandom.random.random(2);
|
||||
for (int k = 0; k < array.length; k++) {
|
||||
int i = array[k];
|
||||
if (i < 16) {
|
||||
continue;
|
||||
}
|
||||
short id = (short) (i >> 4);
|
||||
switch (id) { // Lighting
|
||||
default:
|
||||
if (!fixAll) {
|
||||
continue;
|
||||
}
|
||||
if ((k & 1) == l) {
|
||||
l = 1 - l;
|
||||
continue;
|
||||
}
|
||||
case 10:
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 50:
|
||||
case 51:
|
||||
case 62:
|
||||
case 74:
|
||||
case 76:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 130:
|
||||
case 138:
|
||||
case 169:
|
||||
int x = FaweCache.CACHE_X[j][k];
|
||||
int y = FaweCache.CACHE_Y[j][k];
|
||||
int z = FaweCache.CACHE_Z[j][k];
|
||||
if (isSurrounded(sections, x, y, z)) {
|
||||
continue;
|
||||
}
|
||||
BlockPos pos = new BlockPos(X + x, y, Z + z);
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
if (Thread.currentThread() == Fawe.get().getMainThread()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) {
|
||||
return isSolid(getId(sections, x, y + 1, z))
|
||||
&& isSolid(getId(sections, x + 1, y - 1, z))
|
||||
&& isSolid(getId(sections, x - 1, y, z))
|
||||
&& isSolid(getId(sections, x, y, z + 1))
|
||||
&& isSolid(getId(sections, x, y, z - 1));
|
||||
}
|
||||
|
||||
public boolean isSolid(int i) {
|
||||
return i != 0 && Block.getBlockById(i).isOpaqueCube();
|
||||
}
|
||||
|
||||
public int getId(ExtendedBlockStorage[] sections, int x, int y, int z) {
|
||||
if (x < 0 || x > 15 || z < 0 || z > 15) {
|
||||
return 1;
|
||||
}
|
||||
if (y < 0 || y > 255) {
|
||||
return 1;
|
||||
}
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
char[] array = section.getData();
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
return array[j] >> 4;
|
||||
}
|
||||
}
|
0
forge189/src/main/resources/config.yml
Normal file
0
forge189/src/main/resources/config.yml
Normal file
@ -1,3 +1,5 @@
|
||||
#org.gradle.java.home=C:/PROGRA~2/Java/jdk1.7.0_79
|
||||
#org.gradle.java.home=C:/PROGRA~1/Java/jdk1.8.0_51
|
||||
org.gradle.daemon=true
|
||||
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
org.gradle.configureondemand=true
|
||||
|
2
pom.xml
2
pom.xml
@ -8,7 +8,7 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<artifactId>FastAsyncWorldEdit</artifactId>
|
||||
<version>3.3.21</version>
|
||||
<version>3.4.0</version>
|
||||
<name>FastAsyncWorldEdit</name>
|
||||
<packaging>jar</packaging>
|
||||
<build>
|
||||
|
@ -1,3 +1,3 @@
|
||||
rootProject.name = 'FastAsyncWorldEdit'
|
||||
|
||||
include 'core', 'bukkit', 'forge'
|
||||
include 'core', 'bukkit', 'forge189', 'forge1710', 'sponge'
|
||||
|
94
sponge/build.gradle
Normal file
94
sponge/build.gradle
Normal file
@ -0,0 +1,94 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {
|
||||
name = 'minecrell'
|
||||
url = 'http://repo.minecrell.net/releases'
|
||||
}
|
||||
maven {url = "https://oss.sonatype.org/content/repositories/snapshots/"}
|
||||
maven {url = "http://repo.minecrell.net/snapshots"}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecrell:VanillaGradle:2.0.3_1'
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecrell.vanilla.server.library'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'org.spongepowered:spongeapi:4.+'
|
||||
compile 'org.mcstats.sponge:metrics:R8-SNAPSHOT'
|
||||
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = 'forge'
|
||||
url = 'http://files.minecraftforge.net/maven'
|
||||
}
|
||||
maven {
|
||||
name = "Sponge"
|
||||
url = "https://repo.spongepowered.org/maven"
|
||||
}
|
||||
maven {
|
||||
name = "Sponge Metrics"
|
||||
url = "http://repo.mcstats.org/content/repositories/releases/"
|
||||
}
|
||||
}
|
||||
minecraft {
|
||||
version = "1.8.9"
|
||||
mappings = "stable_22"
|
||||
runDir = 'run'
|
||||
}
|
||||
|
||||
project.archivesBaseName = "${project.archivesBaseName}-mc${minecraft.version}"
|
||||
|
||||
processResources {
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
expand 'version': project.version,
|
||||
'mcVersion': project.minecraft.version
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
|
||||
dependencies {
|
||||
include(dependency(':core'))
|
||||
include(dependency('org.yaml:snakeyaml:1.16'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}.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)
|
@ -1,4 +1,4 @@
|
||||
package com.boydti.fawe.forge;
|
||||
package com.boydti.fawe;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
@ -1,10 +1,10 @@
|
||||
package com.boydti.fawe.forge;
|
||||
package com.boydti.fawe.sponge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.forge.v0.SpongeEditSessionWrapper_0;
|
||||
import com.boydti.fawe.forge.v1_8.SpongeQueue_1_8;
|
||||
import com.boydti.fawe.SpongeCommand;
|
||||
import com.boydti.fawe.v1_8.SpongeQueue_1_8;
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
@ -13,12 +13,10 @@ import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
@ -118,9 +116,14 @@ public class FaweSponge implements IFawe {
|
||||
return new SpongeQueue_1_8(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
return world.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditSessionWrapper getEditSessionWrapper(EditSession session) {
|
||||
return new SpongeEditSessionWrapper_0(session);
|
||||
return new EditSessionWrapper(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -134,20 +137,11 @@ public class FaweSponge implements IFawe {
|
||||
SpongeMetrics metrics = new SpongeMetrics(Sponge.getGame(), Sponge.getPluginManager().fromInstance(plugin).get());
|
||||
metrics.start();
|
||||
debug("[FAWE] &6Metrics enabled.");
|
||||
} catch (IOException e) {
|
||||
} catch (Throwable e) {
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FawePlayer> getPlayers() {
|
||||
HashSet<FawePlayer> players = new HashSet<>();
|
||||
for (Player player : Sponge.getServer().getOnlinePlayers()) {
|
||||
players.add(wrap(player));
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatform() {
|
||||
return "sponge";
|
@ -1,10 +1,10 @@
|
||||
package com.boydti.fawe.forge;
|
||||
package com.boydti.fawe.sponge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.google.inject.Inject;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.api.Game;
|
||||
import org.spongepowered.api.Server;
|
||||
@ -18,7 +18,7 @@ import org.spongepowered.api.plugin.PluginContainer;
|
||||
import org.spongepowered.api.profile.GameProfileManager;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
@Plugin(id = "com.boydti.fawe", name = "FastAsyncWorldEdit", description = "Lagless WorldEdit, Area restrictions, Memory mangement, Block logging", url = "https://github.com/boy0001/FastAsyncWorldedit", version = "3.3.21")
|
||||
@Plugin(id = "com.boydti.fawe", name = "FastAsyncWorldEdit", description = "Lagless WorldEdit, Area restrictions, Memory mangement, Block logging", url = "https://github.com/boy0001/FastAsyncWorldedit", version = "3.4.0", authors = "Empire92")
|
||||
public class SpongeMain {
|
||||
public PluginContainer plugin;
|
||||
|
||||
@ -70,13 +70,10 @@ public class SpongeMain {
|
||||
if (!from.equals(to)) {
|
||||
Player player = event.getTargetEntity();
|
||||
FawePlayer fp = FawePlayer.wrap(player);
|
||||
for (com.sk89q.worldedit.world.World world : WorldEdit.getInstance().getServer().getWorlds()) {
|
||||
if (world.getName().equals(to.getName())) {
|
||||
fp.getSession().clearHistory();
|
||||
fp.loadSessionFromDisk(world);
|
||||
return;
|
||||
}
|
||||
}
|
||||
com.sk89q.worldedit.world.World world = FaweAPI.getWorld(to.getName());
|
||||
fp.getSession().clearHistory();
|
||||
fp.loadSessionsFromDisk(world);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.boydti.fawe.forge;
|
||||
package com.boydti.fawe.sponge;
|
||||
|
||||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
@ -1,4 +1,4 @@
|
||||
package com.boydti.fawe.forge;
|
||||
package com.boydti.fawe.sponge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
@ -58,9 +58,4 @@ public class SpongePlayer extends FawePlayer<Player> {
|
||||
public com.sk89q.worldedit.entity.Player getPlayer() {
|
||||
return (com.sk89q.worldedit.entity.Player) Fawe.<FaweSponge> imp().getWorldEditPlugin().wrap((EntityPlayerMP) this.parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasWorldEditBypass() {
|
||||
return hasPermission("fawe.bypass") || getMeta("fawe.bypass") == Boolean.TRUE;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.boydti.fawe.forge;
|
||||
package com.boydti.fawe.sponge;
|
||||
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import java.util.HashMap;
|
@ -1,4 +1,4 @@
|
||||
package com.boydti.fawe.forge;
|
||||
package com.boydti.fawe.sponge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.sk89q.worldedit.world.biome.BiomeData;
|
@ -1,4 +1,4 @@
|
||||
package com.boydti.fawe.forge.v0;
|
||||
package com.boydti.fawe.v0;
|
||||
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
@ -10,9 +10,6 @@ import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
/**
|
||||
* Created by Jesse on 4/2/2016.
|
||||
*/
|
||||
public abstract class SpongeQueue_0 extends FaweQueue {
|
||||
|
||||
/**
|
@ -1,4 +1,4 @@
|
||||
package com.boydti.fawe.forge.v1_8;
|
||||
package com.boydti.fawe.v1_8;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
@ -1,13 +1,14 @@
|
||||
package com.boydti.fawe.forge.v1_8;
|
||||
package com.boydti.fawe.v1_8;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.forge.SpongeUtil;
|
||||
import com.boydti.fawe.forge.v0.SpongeQueue_0;
|
||||
import com.boydti.fawe.sponge.SpongeUtil;
|
||||
import com.boydti.fawe.v0.SpongeQueue_0;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
@ -18,7 +19,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
@ -44,24 +44,20 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
|
||||
public SpongeQueue_1_8(String world) {
|
||||
super(world);
|
||||
TaskManager.IMP.repeat(() -> {
|
||||
synchronized (loadQueue) {
|
||||
while (loadQueue.size() > 0) {
|
||||
IntegerPair loc = loadQueue.poll();
|
||||
if (spongeWorld == null) {
|
||||
spongeWorld = Sponge.getServer().getWorld(world).get();
|
||||
}
|
||||
Chunk chunk = spongeWorld.getChunk(loc.x, 0, loc.z).orElse(null);
|
||||
if (chunk == null || !chunk.isLoaded()) {
|
||||
spongeWorld.loadChunk(loc.x, 0, loc.z, true);
|
||||
}
|
||||
}
|
||||
loadQueue.notifyAll();
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
|
||||
private LinkedBlockingDeque<IntegerPair> loadQueue = new LinkedBlockingDeque<>();
|
||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair loc) {
|
||||
if (spongeWorld == null) {
|
||||
spongeWorld = Sponge.getServer().getWorld(world).get();
|
||||
}
|
||||
Chunk chunk = spongeWorld.getChunk(loc.x, 0, loc.z).orElse(null);
|
||||
if (chunk == null || !chunk.isLoaded()) {
|
||||
spongeWorld.loadChunk(loc.x, 0, loc.z, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
@ -83,14 +79,8 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
if (sync) {
|
||||
chunk = spongeWorld.loadChunk(cx, 0, cz, true).orElse(null);
|
||||
} else if (Settings.CHUNK_WAIT > 0) {
|
||||
synchronized (loadQueue) {
|
||||
loadQueue.add(new IntegerPair(cx, cz));
|
||||
try {
|
||||
loadQueue.wait(Settings.CHUNK_WAIT);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
loadChunk.value = new IntegerPair(cx, cz);
|
||||
TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT);
|
||||
chunk = spongeWorld.getChunk(cx, 0, cz).orElse(null);
|
||||
if (chunk == null || !chunk.isLoaded()) {
|
||||
throw new FaweException.FaweChunkLoadException();
|
||||
@ -125,35 +115,48 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
}
|
||||
|
||||
public void sendChunk(FaweChunk<Chunk> fc) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
World world = chunk.getWorld();
|
||||
Vector3i pos = chunk.getBlockMin();
|
||||
int cx = pos.getX() >> 4;
|
||||
int cz = pos.getZ() >> 4;
|
||||
for (Player player : Sponge.getServer().getOnlinePlayers()) {
|
||||
if (!player.getWorld().equals(world)) {
|
||||
continue;
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
World world = chunk.getWorld();
|
||||
Vector3i pos = chunk.getBlockMin();
|
||||
int cx = pos.getX() >> 4;
|
||||
int cz = pos.getZ() >> 4;
|
||||
for (Player player : Sponge.getServer().getOnlinePlayers()) {
|
||||
if (!player.getWorld().equals(world)) {
|
||||
continue;
|
||||
}
|
||||
int view = player.getViewDistance();
|
||||
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||
Location<World> loc = player.getLocation();
|
||||
int px = loc.getBlockX() >> 4;
|
||||
int pz = loc.getBlockZ() >> 4;
|
||||
int dx = Math.abs(cx - (loc.getBlockX() >> 4));
|
||||
int dz = Math.abs(cz - (loc.getBlockZ() >> 4));
|
||||
if ((dx > view) || (dz > view)) {
|
||||
continue;
|
||||
}
|
||||
NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler;
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) chunk;
|
||||
con.sendPacket(new S21PacketChunkData(nmsChunk, false, 65535));
|
||||
// Try sending true, 0 first
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
int view = player.getViewDistance();
|
||||
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||
Location<World> loc = player.getLocation();
|
||||
int px = loc.getBlockX() >> 4;
|
||||
int pz = loc.getBlockZ() >> 4;
|
||||
int dx = Math.abs(cx - (loc.getBlockX() >> 4));
|
||||
int dz = Math.abs(cz - (loc.getBlockZ() >> 4));
|
||||
if ((dx > view) || (dz > view)) {
|
||||
continue;
|
||||
}
|
||||
NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler;
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) chunk;
|
||||
con.sendPacket(new S21PacketChunkData(nmsChunk, false, 65535));
|
||||
// Try sending true, 0 first
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
}
|
||||
|
||||
private int lcx = Integer.MIN_VALUE;
|
||||
@ -256,12 +259,7 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
}
|
||||
}
|
||||
}
|
||||
TaskManager.IMP.later(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendChunk(fs);
|
||||
}
|
||||
}, 1);
|
||||
sendChunk(fs);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -350,7 +348,9 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
if (Thread.currentThread() == Fawe.get().getMainThread()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
0
sponge/src/main/resources/config.yml
Normal file
0
sponge/src/main/resources/config.yml
Normal file
Loading…
Reference in New Issue
Block a user