mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 01:37:37 +00:00
Update Upstream
0036e06 Alter the CUI lifecycle to be more consistent and reliable (1633)
This commit is contained in:
parent
d1af6c38e7
commit
75fbe654ee
@ -62,6 +62,7 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import org.bukkit.inventory.PlayerInventory;
|
import org.bukkit.inventory.PlayerInventory;
|
||||||
import org.bukkit.permissions.PermissionAttachment;
|
import org.bukkit.permissions.PermissionAttachment;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -283,7 +284,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
|||||||
if (params.length > 0) {
|
if (params.length > 0) {
|
||||||
send = send + "|" + StringUtil.joinString(params, "|");
|
send = send + "|" + StringUtil.joinString(params, "|");
|
||||||
}
|
}
|
||||||
player.sendPluginMessage(plugin, WorldEditPlugin.CUI_PLUGIN_CHANNEL, send.getBytes(CUIChannelListener.UTF_8_CHARSET));
|
player.sendPluginMessage(plugin, WorldEditPlugin.CUI_PLUGIN_CHANNEL, send.getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player getPlayer() {
|
public Player getPlayer() {
|
||||||
@ -343,18 +344,18 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SessionKey getSessionKey() {
|
public SessionKey getSessionKey() {
|
||||||
return new SessionKeyImpl(this.player.getUniqueId(), player.getName());
|
return new SessionKeyImpl(this.player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SessionKeyImpl implements SessionKey {
|
static class SessionKeyImpl implements SessionKey {
|
||||||
// If not static, this will leak a reference
|
// If not static, this will leak a reference
|
||||||
|
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private SessionKeyImpl(UUID uuid, String name) {
|
SessionKeyImpl(Player player) {
|
||||||
this.uuid = uuid;
|
this.uuid = player.getUniqueId();
|
||||||
this.name = name;
|
this.name = player.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,7 +31,6 @@ import java.nio.charset.StandardCharsets;
|
|||||||
*/
|
*/
|
||||||
public class CUIChannelListener implements PluginMessageListener {
|
public class CUIChannelListener implements PluginMessageListener {
|
||||||
|
|
||||||
public static final Charset UTF_8_CHARSET = StandardCharsets.UTF_8;
|
|
||||||
private final WorldEditPlugin plugin;
|
private final WorldEditPlugin plugin;
|
||||||
|
|
||||||
public CUIChannelListener(WorldEditPlugin plugin) {
|
public CUIChannelListener(WorldEditPlugin plugin) {
|
||||||
@ -41,10 +40,9 @@ public class CUIChannelListener implements PluginMessageListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
|
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
|
||||||
LocalSession session = plugin.getSession(player);
|
LocalSession session = plugin.getSession(player);
|
||||||
String text = new String(message, UTF_8_CHARSET);
|
String text = new String(message, StandardCharsets.UTF_8);
|
||||||
final BukkitPlayer actor = plugin.wrapPlayer(player);
|
final BukkitPlayer actor = plugin.wrapPlayer(player);
|
||||||
session.handleCUIInitializationMessage(text, actor);
|
session.handleCUIInitializationMessage(text, actor);
|
||||||
session.describeCUI(actor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ package com.sk89q.worldedit.bukkit;
|
|||||||
|
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
|
import com.sk89q.worldedit.event.platform.SessionIdleEvent;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
@ -35,6 +36,7 @@ import org.bukkit.event.block.Action;
|
|||||||
import org.bukkit.event.player.PlayerCommandSendEvent;
|
import org.bukkit.event.player.PlayerCommandSendEvent;
|
||||||
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
import org.bukkit.inventory.EquipmentSlot;
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
import org.enginehub.piston.CommandManager;
|
import org.enginehub.piston.CommandManager;
|
||||||
import org.enginehub.piston.inject.InjectedValueStore;
|
import org.enginehub.piston.inject.InjectedValueStore;
|
||||||
@ -142,4 +144,9 @@ public class WorldEditListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
plugin.getWorldEdit().getEventBus().post(new SessionIdleEvent(new BukkitPlayer.SessionKeyImpl(event.getPlayer())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,12 +107,17 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
*/
|
*/
|
||||||
public class LocalSession implements TextureHolder {
|
public class LocalSession implements TextureHolder {
|
||||||
|
|
||||||
|
private static final transient int CUI_VERSION_UNINITIALIZED = -1;
|
||||||
public static transient int MAX_HISTORY_SIZE = 15;
|
public static transient int MAX_HISTORY_SIZE = 15;
|
||||||
|
|
||||||
// Non-session related fields
|
// Non-session related fields
|
||||||
private transient LocalConfiguration config;
|
private transient LocalConfiguration config;
|
||||||
private final transient AtomicBoolean dirty = new AtomicBoolean();
|
private final transient AtomicBoolean dirty = new AtomicBoolean();
|
||||||
|
|
||||||
|
// Single-connection lifetime fields
|
||||||
private transient int failedCuiAttempts = 0;
|
private transient int failedCuiAttempts = 0;
|
||||||
|
private transient boolean hasCUISupport = false;
|
||||||
|
private transient int cuiVersion = CUI_VERSION_UNINITIALIZED;
|
||||||
|
|
||||||
// Session related
|
// Session related
|
||||||
private transient RegionSelector selector = new CuboidRegionSelector();
|
private transient RegionSelector selector = new CuboidRegionSelector();
|
||||||
@ -145,8 +150,6 @@ public class LocalSession implements TextureHolder {
|
|||||||
private transient boolean useInventory;
|
private transient boolean useInventory;
|
||||||
private transient com.sk89q.worldedit.world.snapshot.Snapshot snapshot;
|
private transient com.sk89q.worldedit.world.snapshot.Snapshot snapshot;
|
||||||
private transient Snapshot snapshotExperimental;
|
private transient Snapshot snapshotExperimental;
|
||||||
private transient boolean hasCUISupport = false;
|
|
||||||
private transient int cuiVersion = -1;
|
|
||||||
private transient SideEffectSet sideEffectSet = SideEffectSet.defaults();
|
private transient SideEffectSet sideEffectSet = SideEffectSet.defaults();
|
||||||
private transient Mask mask;
|
private transient Mask mask;
|
||||||
private transient Mask sourceMask;
|
private transient Mask sourceMask;
|
||||||
@ -1398,7 +1401,12 @@ public class LocalSession implements TextureHolder {
|
|||||||
*/
|
*/
|
||||||
public void handleCUIInitializationMessage(String text, Actor actor) {
|
public void handleCUIInitializationMessage(String text, Actor actor) {
|
||||||
checkNotNull(text);
|
checkNotNull(text);
|
||||||
if (this.hasCUISupport || this.failedCuiAttempts > 3) {
|
if (this.hasCUISupport) {
|
||||||
|
// WECUI is a bit aggressive about re-initializing itself
|
||||||
|
// the last attempt to touch handshakes didn't go well, so this will do... for now
|
||||||
|
dispatchCUISelection(actor);
|
||||||
|
return;
|
||||||
|
} else if (this.failedCuiAttempts > 3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1456,6 +1464,10 @@ public class LocalSession implements TextureHolder {
|
|||||||
* @param cuiVersion the CUI version
|
* @param cuiVersion the CUI version
|
||||||
*/
|
*/
|
||||||
public void setCUIVersion(int cuiVersion) {
|
public void setCUIVersion(int cuiVersion) {
|
||||||
|
if (cuiVersion < 0) {
|
||||||
|
throw new IllegalArgumentException("CUI protocol version must be non-negative, but '" + cuiVersion + "' was received.");
|
||||||
|
}
|
||||||
|
|
||||||
this.cuiVersion = cuiVersion;
|
this.cuiVersion = cuiVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1687,4 +1699,15 @@ public class LocalSession implements TextureHolder {
|
|||||||
this.transform = transform;
|
this.transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call when this session has become inactive.
|
||||||
|
*
|
||||||
|
* <p>This is for internal use only.</p>
|
||||||
|
*/
|
||||||
|
public void onIdle() {
|
||||||
|
this.cuiVersion = CUI_VERSION_UNINITIALIZED;
|
||||||
|
this.hasCUISupport = false;
|
||||||
|
this.failedCuiAttempts = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit team and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.worldedit.event.platform;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.event.Event;
|
||||||
|
import com.sk89q.worldedit.session.SessionKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event fired when a session becomes idle.
|
||||||
|
*
|
||||||
|
* <p>This can happen when a player leaves the server.</p>
|
||||||
|
*/
|
||||||
|
public final class SessionIdleEvent extends Event {
|
||||||
|
private final SessionKey key;
|
||||||
|
|
||||||
|
public SessionIdleEvent(SessionKey key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a key identifying the session that has become idle.
|
||||||
|
*
|
||||||
|
* @return the key for the session
|
||||||
|
*/
|
||||||
|
public SessionKey getKey() {
|
||||||
|
return this.key;
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,7 @@ import com.sk89q.worldedit.command.tool.InvalidToolBindException;
|
|||||||
import com.sk89q.worldedit.command.tool.Tool;
|
import com.sk89q.worldedit.command.tool.Tool;
|
||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
|
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
|
||||||
|
import com.sk89q.worldedit.event.platform.SessionIdleEvent;
|
||||||
import com.sk89q.worldedit.extension.platform.Locatable;
|
import com.sk89q.worldedit.extension.platform.Locatable;
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.session.request.Request;
|
import com.sk89q.worldedit.session.request.Request;
|
||||||
@ -132,6 +133,9 @@ public class SessionManager {
|
|||||||
checkNotNull(owner);
|
checkNotNull(owner);
|
||||||
SessionHolder stored = sessions.get(getKey(owner));
|
SessionHolder stored = sessions.get(getKey(owner));
|
||||||
if (stored != null) {
|
if (stored != null) {
|
||||||
|
if (stored.sessionIdle && stored.key.isActive()) {
|
||||||
|
stored.sessionIdle = false;
|
||||||
|
}
|
||||||
return stored.session;
|
return stored.session;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -350,6 +354,18 @@ public class SessionManager {
|
|||||||
store = new JsonFileSessionStore(dir);
|
store = new JsonFileSessionStore(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onSessionIdle(final SessionIdleEvent event) {
|
||||||
|
SessionHolder holder = this.sessions.get(getKey(event.getKey()));
|
||||||
|
if (holder != null && !holder.sessionIdle) {
|
||||||
|
holder.sessionIdle = true;
|
||||||
|
LocalSession session = holder.session;
|
||||||
|
|
||||||
|
// Perform any session cleanup for data that should not be persisted.
|
||||||
|
session.onIdle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the owner of a session, the session, and the last active time.
|
* Stores the owner of a session, the session, and the last active time.
|
||||||
*/
|
*/
|
||||||
@ -357,6 +373,7 @@ public class SessionManager {
|
|||||||
private final SessionKey key;
|
private final SessionKey key;
|
||||||
private final LocalSession session;
|
private final LocalSession session;
|
||||||
private long lastActive = System.currentTimeMillis();
|
private long lastActive = System.currentTimeMillis();
|
||||||
|
private boolean sessionIdle = false;
|
||||||
|
|
||||||
private SessionHolder(SessionKey key, LocalSession session) {
|
private SessionHolder(SessionKey key, LocalSession session) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
|
@ -1,15 +1,33 @@
|
|||||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||||
|
import net.fabricmc.loom.LoomGradleExtension
|
||||||
import net.fabricmc.loom.task.RemapJarTask
|
import net.fabricmc.loom.task.RemapJarTask
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
name = "Fabric"
|
||||||
|
url = uri("https://maven.fabricmc.net/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath("net.fabricmc:fabric-loom:${versions.loom}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
applyPlatformAndCoreConfiguration()
|
applyPlatformAndCoreConfiguration()
|
||||||
applyShadowConfiguration()
|
applyShadowConfiguration()
|
||||||
|
|
||||||
apply(plugin = "fabric-loom")
|
apply(plugin = "fabric-loom")
|
||||||
apply(plugin = "java-library")
|
apply(plugin = "java-library")
|
||||||
|
|
||||||
val minecraftVersion = "1.15.2"
|
configure<LoomGradleExtension> {
|
||||||
val yarnMappings = "1.15.2+build.14:v2"
|
accessWidener("src/main/resources/worldedit.accesswidener")
|
||||||
val loaderVersion = "0.7.8+build.189"
|
}
|
||||||
|
|
||||||
|
val minecraftVersion = "1.16.3"
|
||||||
|
val yarnMappings = "1.16.3+build.1:v2"
|
||||||
|
val loaderVersion = "0.10.8"
|
||||||
|
|
||||||
configurations.all {
|
configurations.all {
|
||||||
resolutionStrategy {
|
resolutionStrategy {
|
||||||
@ -17,32 +35,77 @@ configurations.all {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val fabricApiConfiguration: Configuration = configurations.create("fabricApi")
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "Fabric"
|
||||||
|
url = uri("https://maven.fabricmc.net/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
"api"(project(":worldedit-core"))
|
"api"(project(":worldedit-core"))
|
||||||
"implementation"(enforcedPlatform("org.apache.logging.log4j:log4j-bom:2.8.1") {
|
"implementation"("org.apache.logging.log4j:log4j-slf4j-impl:2.8.1")
|
||||||
because("Mojang provides Log4J at 2.8.1")
|
|
||||||
})
|
|
||||||
|
|
||||||
"minecraft"("com.mojang:minecraft:$minecraftVersion")
|
"minecraft"("com.mojang:minecraft:$minecraftVersion")
|
||||||
"mappings"("net.fabricmc:yarn:$yarnMappings")
|
"mappings"("net.fabricmc:yarn:$yarnMappings")
|
||||||
"modCompile"("net.fabricmc:fabric-loader:$loaderVersion")
|
"modImplementation"("net.fabricmc:fabric-loader:$loaderVersion")
|
||||||
|
|
||||||
listOf(
|
// [1] declare fabric-api dependency...
|
||||||
"net.fabricmc.fabric-api:fabric-api-base:0.1.2+28f8190f42",
|
"fabricApi"("net.fabricmc.fabric-api:fabric-api:0.29.3+1.16")
|
||||||
"net.fabricmc.fabric-api:fabric-events-interaction-v0:0.2.6+12515ed975",
|
|
||||||
"net.fabricmc.fabric-api:fabric-events-lifecycle-v0:0.1.2+b7f9825de8",
|
// [2] Load the API dependencies from the fabric mod json...
|
||||||
"net.fabricmc.fabric-api:fabric-networking-v0:0.1.7+12515ed975"
|
@Suppress("UNCHECKED_CAST")
|
||||||
).forEach {
|
val fabricModJson = file("src/main/resources/fabric.mod.json").bufferedReader().use {
|
||||||
|
groovy.json.JsonSlurper().parse(it) as Map<String, Map<String, *>>
|
||||||
|
}
|
||||||
|
val wantedDependencies = (fabricModJson["depends"] ?: error("no depends in fabric.mod.json")).keys
|
||||||
|
.filter { it == "fabric-api-base" || it.contains(Regex("v\\d$")) }
|
||||||
|
.map { "net.fabricmc.fabric-api:$it" }
|
||||||
|
logger.lifecycle("Looking for these dependencies:")
|
||||||
|
for (wantedDependency in wantedDependencies) {
|
||||||
|
logger.lifecycle(wantedDependency)
|
||||||
|
}
|
||||||
|
// [3] and now we resolve it to pick out what we want :D
|
||||||
|
val fabricApiDependencies = fabricApiConfiguration.incoming.resolutionResult.allDependencies
|
||||||
|
.onEach {
|
||||||
|
if (it is UnresolvedDependencyResult) {
|
||||||
|
throw kotlin.IllegalStateException("Failed to resolve Fabric API", it.failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.filterIsInstance<ResolvedDependencyResult>()
|
||||||
|
// pick out transitive dependencies
|
||||||
|
.flatMap {
|
||||||
|
it.selected.dependencies
|
||||||
|
}
|
||||||
|
// grab the requested versions
|
||||||
|
.map { it.requested }
|
||||||
|
.filterIsInstance<ModuleComponentSelector>()
|
||||||
|
// map to standard notation
|
||||||
|
.associateByTo(
|
||||||
|
mutableMapOf(),
|
||||||
|
keySelector = { "${it.group}:${it.module}" },
|
||||||
|
valueTransform = { "${it.group}:${it.module}:${it.version}" }
|
||||||
|
)
|
||||||
|
fabricApiDependencies.keys.retainAll(wantedDependencies)
|
||||||
|
// sanity check
|
||||||
|
for (wantedDep in wantedDependencies) {
|
||||||
|
check(wantedDep in fabricApiDependencies) { "Fabric API library $wantedDep is missing!" }
|
||||||
|
}
|
||||||
|
|
||||||
|
fabricApiDependencies.values.forEach {
|
||||||
"include"(it)
|
"include"(it)
|
||||||
"modImplementation"(it)
|
"modImplementation"(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No need for this at runtime
|
||||||
|
"modCompileOnly"("me.lucko:fabric-permissions-api:0.1-SNAPSHOT")
|
||||||
|
|
||||||
// Hook these up manually, because Fabric doesn't seem to quite do it properly.
|
// Hook these up manually, because Fabric doesn't seem to quite do it properly.
|
||||||
"compileClasspath"("net.fabricmc:sponge-mixin:${project.versions.mixin}")
|
"compileOnly"("net.fabricmc:sponge-mixin:${project.versions.mixin}")
|
||||||
"annotationProcessor"("net.fabricmc:sponge-mixin:${project.versions.mixin}")
|
"annotationProcessor"("net.fabricmc:sponge-mixin:${project.versions.mixin}")
|
||||||
"annotationProcessor"("net.fabricmc:fabric-loom:${project.versions.loom}")
|
"annotationProcessor"("net.fabricmc:fabric-loom:${project.versions.loom}")
|
||||||
|
|
||||||
"testCompile"("org.mockito:mockito-core:3.11.0")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configure<BasePluginConvention> {
|
configure<BasePluginConvention> {
|
||||||
@ -64,18 +127,17 @@ tasks.named<Copy>("processResources") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named<Jar>("jar") {
|
addJarManifest(includeClasspath = true)
|
||||||
manifest {
|
|
||||||
attributes("Class-Path" to CLASSPATH,
|
|
||||||
"WorldEdit-Version" to project.version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named<ShadowJar>("shadowJar") {
|
tasks.named<ShadowJar>("shadowJar") {
|
||||||
archiveClassifier.set("dist-dev")
|
archiveClassifier.set("dist-dev")
|
||||||
dependencies {
|
dependencies {
|
||||||
|
relocate("org.slf4j", "com.sk89q.worldedit.slf4j")
|
||||||
|
relocate("org.apache.logging.slf4j", "com.sk89q.worldedit.log4jbridge")
|
||||||
relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4")
|
relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4")
|
||||||
|
|
||||||
|
include(dependency("org.slf4j:slf4j-api"))
|
||||||
|
include(dependency("org.apache.logging.log4j:log4j-slf4j-impl"))
|
||||||
include(dependency("org.antlr:antlr4-runtime"))
|
include(dependency("org.antlr:antlr4-runtime"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,6 +157,7 @@ tasks.register<RemapJarTask>("remapShadowJar") {
|
|||||||
input.set(shadowJar.archiveFile)
|
input.set(shadowJar.archiveFile)
|
||||||
archiveFileName.set(shadowJar.archiveFileName.get().replace(Regex("-dev\\.jar$"), ".jar"))
|
archiveFileName.set(shadowJar.archiveFileName.get().replace(Regex("-dev\\.jar$"), ".jar"))
|
||||||
addNestedDependencies.set(true)
|
addNestedDependencies.set(true)
|
||||||
|
remapAccessWidener.set(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named("assemble").configure {
|
tasks.named("assemble").configure {
|
||||||
|
@ -42,11 +42,11 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
|||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
|
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
@ -58,6 +58,7 @@ import net.minecraft.util.math.BlockPos;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -126,9 +127,11 @@ public class FabricPlayer extends AbstractPlayerActor {
|
|||||||
if (params.length > 0) {
|
if (params.length > 0) {
|
||||||
send = send + "|" + StringUtil.joinString(params, "|");
|
send = send + "|" + StringUtil.joinString(params, "|");
|
||||||
}
|
}
|
||||||
PacketByteBuf buffer = new PacketByteBuf(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)));
|
ServerPlayNetworking.send(
|
||||||
CustomPayloadS2CPacket packet = new CustomPayloadS2CPacket(new Identifier(FabricWorldEdit.MOD_ID, FabricWorldEdit.CUI_PLUGIN_CHANNEL), buffer);
|
this.player,
|
||||||
this.player.networkHandler.sendPacket(packet);
|
WECUIPacketHandler.CUI_IDENTIFIER,
|
||||||
|
new PacketByteBuf(Unpooled.copiedBuffer(send, StandardCharsets.UTF_8))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -248,18 +251,18 @@ public class FabricPlayer extends AbstractPlayerActor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SessionKey getSessionKey() {
|
public SessionKey getSessionKey() {
|
||||||
return new SessionKeyImpl(player.getUuid(), player.getName().getString());
|
return new SessionKeyImpl(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SessionKeyImpl implements SessionKey {
|
static class SessionKeyImpl implements SessionKey {
|
||||||
// If not static, this will leak a reference
|
// If not static, this will leak a reference
|
||||||
|
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private SessionKeyImpl(UUID uuid, String name) {
|
SessionKeyImpl(ServerPlayerEntity player) {
|
||||||
this.uuid = uuid;
|
this.uuid = player.getUuid();
|
||||||
this.name = name;
|
this.name = player.getName().getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,16 +19,17 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.fabric;
|
package com.sk89q.worldedit.fabric;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer;
|
|
||||||
|
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
||||||
|
import com.sk89q.worldedit.event.platform.SessionIdleEvent;
|
||||||
|
import com.sk89q.worldedit.extension.platform.Capability;
|
||||||
import com.sk89q.worldedit.extension.platform.Platform;
|
import com.sk89q.worldedit.extension.platform.Platform;
|
||||||
|
import com.sk89q.worldedit.extension.platform.PlatformManager;
|
||||||
import com.sk89q.worldedit.fabric.net.handler.WECUIPacketHandler;
|
import com.sk89q.worldedit.fabric.net.handler.WECUIPacketHandler;
|
||||||
|
import com.sk89q.worldedit.internal.anvil.ChunkDeleter;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BlockCategory;
|
import com.sk89q.worldedit.world.block.BlockCategory;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
@ -36,41 +37,50 @@ import com.sk89q.worldedit.world.entity.EntityType;
|
|||||||
import com.sk89q.worldedit.world.item.ItemCategory;
|
import com.sk89q.worldedit.world.item.ItemCategory;
|
||||||
import com.sk89q.worldedit.world.item.ItemType;
|
import com.sk89q.worldedit.world.item.ItemType;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
|
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
|
||||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||||
import net.fabricmc.fabric.api.event.player.UseItemCallback;
|
import net.fabricmc.fabric.api.event.player.UseItemCallback;
|
||||||
import net.fabricmc.fabric.api.event.server.ServerStartCallback;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.fabricmc.fabric.api.event.server.ServerStopCallback;
|
|
||||||
import net.fabricmc.fabric.api.event.server.ServerTickCallback;
|
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.fabricmc.loader.api.ModContainer;
|
import net.fabricmc.loader.api.ModContainer;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.tag.BlockTags;
|
import net.minecraft.tag.BlockTags;
|
||||||
import net.minecraft.tag.ItemTags;
|
import net.minecraft.tag.ItemTags;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.TypedActionResult;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.util.registry.Registry;
|
import net.minecraft.util.registry.Registry;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer;
|
||||||
|
import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Fabric implementation of WorldEdit.
|
* The Fabric implementation of WorldEdit.
|
||||||
*/
|
*/
|
||||||
public class FabricWorldEdit implements ModInitializer {
|
public class FabricWorldEdit implements ModInitializer {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
public static final String MOD_ID = "worldedit";
|
public static final String MOD_ID = "worldedit";
|
||||||
public static final String CUI_PLUGIN_CHANNEL = "cui";
|
public static final String CUI_PLUGIN_CHANNEL = "cui";
|
||||||
|
|
||||||
@ -95,7 +105,7 @@ public class FabricWorldEdit implements ModInitializer {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Setup working directory
|
// Setup working directory
|
||||||
workingDir = new File(FabricLoader.getInstance().getConfigDirectory(), "worldedit").toPath();
|
workingDir = FabricLoader.getInstance().getConfigDir().resolve("worldedit");
|
||||||
if (!Files.exists(workingDir)) {
|
if (!Files.exists(workingDir)) {
|
||||||
try {
|
try {
|
||||||
Files.createDirectory(workingDir);
|
Files.createDirectory(workingDir);
|
||||||
@ -106,24 +116,55 @@ public class FabricWorldEdit implements ModInitializer {
|
|||||||
|
|
||||||
WECUIPacketHandler.init();
|
WECUIPacketHandler.init();
|
||||||
|
|
||||||
ServerTickCallback.EVENT.register(ThreadSafeCache.getInstance());
|
ServerTickEvents.END_SERVER_TICK.register(ThreadSafeCache.getInstance());
|
||||||
ServerStartCallback.EVENT.register(this::onStartServer);
|
CommandRegistrationCallback.EVENT.register(this::registerCommands);
|
||||||
ServerStopCallback.EVENT.register(this::onStopServer);
|
ServerLifecycleEvents.SERVER_STARTING.register(this::onStartingServer);
|
||||||
|
ServerLifecycleEvents.SERVER_STARTED.register(this::onStartServer);
|
||||||
|
ServerLifecycleEvents.SERVER_STOPPING.register(this::onStopServer);
|
||||||
|
ServerPlayConnectionEvents.DISCONNECT.register(this::onPlayerDisconnect);
|
||||||
AttackBlockCallback.EVENT.register(this::onLeftClickBlock);
|
AttackBlockCallback.EVENT.register(this::onLeftClickBlock);
|
||||||
UseBlockCallback.EVENT.register(this::onRightClickBlock);
|
UseBlockCallback.EVENT.register(this::onRightClickBlock);
|
||||||
UseItemCallback.EVENT.register(this::onRightClickAir);
|
UseItemCallback.EVENT.register(this::onRightClickAir);
|
||||||
LOGGER.info("WorldEdit for Fabric (version " + getInternalVersion() + ") is loaded");
|
LOGGER.info("WorldEdit for Fabric (version " + getInternalVersion() + ") is loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerCommands(CommandDispatcher<ServerCommandSource> dispatcher, boolean dedicated) {
|
||||||
|
PlatformManager manager = WorldEdit.getInstance().getPlatformManager();
|
||||||
|
if (manager.getPlatforms().isEmpty()) {
|
||||||
|
// We'll register as part of our platform initialization later.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a re-register (due to /reload), we must add our commands now
|
||||||
|
|
||||||
|
Platform commandsPlatform = manager.queryCapability(Capability.USER_COMMANDS);
|
||||||
|
if (commandsPlatform != platform || !platform.isHookingEvents()) {
|
||||||
|
// We're not in control of commands/events -- do not re-register.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
platform.setNativeDispatcher(dispatcher);
|
||||||
|
platform.registerCommands(manager.getPlatformCommandManager().getCommandManager());
|
||||||
|
}
|
||||||
|
|
||||||
private void setupPlatform(MinecraftServer server) {
|
private void setupPlatform(MinecraftServer server) {
|
||||||
this.platform = new FabricPlatform(this, server);
|
this.platform = new FabricPlatform(this, server);
|
||||||
|
|
||||||
WorldEdit.getInstance().getPlatformManager().register(platform);
|
WorldEdit.getInstance().getPlatformManager().register(platform);
|
||||||
|
|
||||||
this.provider = new FabricPermissionsProvider.VanillaPermissionsProvider(platform);
|
this.provider = getInitialPermissionsProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupRegistries() {
|
private FabricPermissionsProvider getInitialPermissionsProvider() {
|
||||||
|
try {
|
||||||
|
Class.forName("me.lucko.fabric.api.permissions.v0.Permissions", false, getClass().getClassLoader());
|
||||||
|
return new FabricPermissionsProvider.LuckoFabricPermissionsProvider(platform);
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
// fallback to vanilla
|
||||||
|
}
|
||||||
|
return new FabricPermissionsProvider.VanillaPermissionsProvider(platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupRegistries(MinecraftServer server) {
|
||||||
// Blocks
|
// Blocks
|
||||||
for (Identifier name : Registry.BLOCK.getIds()) {
|
for (Identifier name : Registry.BLOCK.getIds()) {
|
||||||
if (BlockType.REGISTRY.get(name.toString()) == null) {
|
if (BlockType.REGISTRY.get(name.toString()) == null) {
|
||||||
@ -144,31 +185,42 @@ public class FabricWorldEdit implements ModInitializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Biomes
|
// Biomes
|
||||||
for (Identifier name : Registry.BIOME.getIds()) {
|
for (Identifier name : server.getRegistryManager().get(Registry.BIOME_KEY).getIds()) {
|
||||||
if (BiomeType.REGISTRY.get(name.toString()) == null) {
|
if (BiomeType.REGISTRY.get(name.toString()) == null) {
|
||||||
BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
|
BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Tags
|
// Tags
|
||||||
for (Identifier name : BlockTags.getContainer().getKeys()) {
|
for (Identifier name : BlockTags.getTagGroup().getTagIds()) {
|
||||||
if (BlockCategory.REGISTRY.get(name.toString()) == null) {
|
if (BlockCategory.REGISTRY.get(name.toString()) == null) {
|
||||||
BlockCategory.REGISTRY.register(name.toString(), new BlockCategory(name.toString()));
|
BlockCategory.REGISTRY.register(name.toString(), new BlockCategory(name.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Identifier name : ItemTags.getContainer().getKeys()) {
|
for (Identifier name : ItemTags.getTagGroup().getTagIds()) {
|
||||||
if (ItemCategory.REGISTRY.get(name.toString()) == null) {
|
if (ItemCategory.REGISTRY.get(name.toString()) == null) {
|
||||||
ItemCategory.REGISTRY.register(name.toString(), new ItemCategory(name.toString()));
|
ItemCategory.REGISTRY.register(name.toString(), new ItemCategory(name.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onStartingServer(MinecraftServer minecraftServer) {
|
||||||
|
final Path delChunks = workingDir.resolve(DELCHUNKS_FILE_NAME);
|
||||||
|
if (Files.exists(delChunks)) {
|
||||||
|
ChunkDeleter.runFromFile(delChunks, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onStartServer(MinecraftServer minecraftServer) {
|
private void onStartServer(MinecraftServer minecraftServer) {
|
||||||
|
FabricAdapter.setServer(minecraftServer);
|
||||||
setupPlatform(minecraftServer);
|
setupPlatform(minecraftServer);
|
||||||
setupRegistries();
|
setupRegistries(minecraftServer);
|
||||||
|
|
||||||
config = new FabricConfiguration(this);
|
config = new FabricConfiguration(this);
|
||||||
config.load();
|
config.load();
|
||||||
WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
|
WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
|
||||||
|
minecraftServer.reloadResources(
|
||||||
|
minecraftServer.getDataPackManager().getEnabledNames()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onStopServer(MinecraftServer minecraftServer) {
|
private void onStopServer(MinecraftServer minecraftServer) {
|
||||||
@ -198,8 +250,9 @@ public class FabricWorldEdit implements ModInitializer {
|
|||||||
blockPos.getY(),
|
blockPos.getY(),
|
||||||
blockPos.getZ()
|
blockPos.getZ()
|
||||||
);
|
);
|
||||||
|
com.sk89q.worldedit.util.Direction weDirection = FabricAdapter.adaptEnumFacing(direction);
|
||||||
|
|
||||||
if (we.handleBlockLeftClick(player, pos)) {
|
if (we.handleBlockLeftClick(player, pos, weDirection)) {
|
||||||
return ActionResult.SUCCESS;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,12 +263,6 @@ public class FabricWorldEdit implements ModInitializer {
|
|||||||
return ActionResult.PASS;
|
return ActionResult.PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onLeftClickAir(PlayerEntity playerEntity, World world, Hand hand) {
|
|
||||||
WorldEdit we = WorldEdit.getInstance();
|
|
||||||
FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity);
|
|
||||||
we.handleArmSwing(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ActionResult onRightClickBlock(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult blockHitResult) {
|
private ActionResult onRightClickBlock(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult blockHitResult) {
|
||||||
if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) {
|
if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) {
|
||||||
return ActionResult.PASS;
|
return ActionResult.PASS;
|
||||||
@ -229,8 +276,9 @@ public class FabricWorldEdit implements ModInitializer {
|
|||||||
blockHitResult.getBlockPos().getY(),
|
blockHitResult.getBlockPos().getY(),
|
||||||
blockHitResult.getBlockPos().getZ()
|
blockHitResult.getBlockPos().getZ()
|
||||||
);
|
);
|
||||||
|
com.sk89q.worldedit.util.Direction direction = FabricAdapter.adaptEnumFacing(blockHitResult.getSide());
|
||||||
|
|
||||||
if (we.handleBlockRightClick(player, pos)) {
|
if (we.handleBlockRightClick(player, pos, direction)) {
|
||||||
return ActionResult.SUCCESS;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,23 +289,29 @@ public class FabricWorldEdit implements ModInitializer {
|
|||||||
return ActionResult.PASS;
|
return ActionResult.PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionResult onRightClickAir(PlayerEntity playerEntity, World world, Hand hand) {
|
private TypedActionResult<ItemStack> onRightClickAir(PlayerEntity playerEntity, World world, Hand hand) {
|
||||||
|
ItemStack stackInHand = playerEntity.getStackInHand(hand);
|
||||||
if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) {
|
if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) {
|
||||||
return ActionResult.PASS;
|
return TypedActionResult.pass(stackInHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldEdit we = WorldEdit.getInstance();
|
WorldEdit we = WorldEdit.getInstance();
|
||||||
FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity);
|
FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity);
|
||||||
|
|
||||||
if (we.handleRightClick(player)) {
|
if (we.handleRightClick(player)) {
|
||||||
return ActionResult.SUCCESS;
|
return TypedActionResult.success(stackInHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ActionResult.PASS;
|
return TypedActionResult.pass(stackInHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Pass empty left click to server
|
// TODO Pass empty left click to server
|
||||||
|
|
||||||
|
private void onPlayerDisconnect(ServerPlayNetworkHandler handler, MinecraftServer server) {
|
||||||
|
WorldEdit.getInstance().getEventBus()
|
||||||
|
.post(new SessionIdleEvent(new FabricPlayer.SessionKeyImpl(handler.player)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the configuration.
|
* Get the configuration.
|
||||||
*
|
*
|
||||||
@ -303,8 +357,8 @@ public class FabricWorldEdit implements ModInitializer {
|
|||||||
*
|
*
|
||||||
* @return the working directory
|
* @return the working directory
|
||||||
*/
|
*/
|
||||||
public File getWorkingDir() {
|
public Path getWorkingDir() {
|
||||||
return this.workingDir.toFile();
|
return this.workingDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,33 +23,23 @@ import com.sk89q.worldedit.LocalSession;
|
|||||||
import com.sk89q.worldedit.fabric.FabricAdapter;
|
import com.sk89q.worldedit.fabric.FabricAdapter;
|
||||||
import com.sk89q.worldedit.fabric.FabricPlayer;
|
import com.sk89q.worldedit.fabric.FabricPlayer;
|
||||||
import com.sk89q.worldedit.fabric.FabricWorldEdit;
|
import com.sk89q.worldedit.fabric.FabricWorldEdit;
|
||||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
public final class WECUIPacketHandler {
|
public final class WECUIPacketHandler {
|
||||||
private WECUIPacketHandler() {
|
private WECUIPacketHandler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Charset UTF_8_CHARSET = StandardCharsets.UTF_8;
|
public static final Identifier CUI_IDENTIFIER = new Identifier(FabricWorldEdit.MOD_ID, FabricWorldEdit.CUI_PLUGIN_CHANNEL);
|
||||||
private static final Identifier CUI_IDENTIFIER = new Identifier(FabricWorldEdit.MOD_ID, FabricWorldEdit.CUI_PLUGIN_CHANNEL);
|
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
ServerSidePacketRegistry.INSTANCE.register(CUI_IDENTIFIER, (packetContext, packetByteBuf) -> {
|
ServerPlayNetworking.registerGlobalReceiver(CUI_IDENTIFIER, (server, player, handler, buf, responder) -> {
|
||||||
ServerPlayerEntity player = (ServerPlayerEntity) packetContext.getPlayer();
|
|
||||||
LocalSession session = FabricWorldEdit.inst.getSession(player);
|
LocalSession session = FabricWorldEdit.inst.getSession(player);
|
||||||
|
String text = buf.toString(StandardCharsets.UTF_8);
|
||||||
if (session.hasCUISupport()) {
|
FabricPlayer actor = FabricAdapter.adaptPlayer(player);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String text = packetByteBuf.toString(UTF_8_CHARSET);
|
|
||||||
final FabricPlayer actor = FabricAdapter.adaptPlayer(player);
|
|
||||||
session.handleCUIInitializationMessage(text, actor);
|
session.handleCUIInitializationMessage(text, actor);
|
||||||
session.describeCUI(actor);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
"fabric-api-base": "*",
|
"fabric-api-base": "*",
|
||||||
"fabric-events-lifecycle-v0": "*",
|
"fabric-events-lifecycle-v0": "*",
|
||||||
"fabric-events-interaction-v0": "*",
|
"fabric-events-interaction-v0": "*",
|
||||||
"fabric-networking-v0": "*"
|
"fabric-networking-api-v1": "*"
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"worldedit.mixins.json"
|
"worldedit.mixins.json"
|
||||||
|
@ -26,7 +26,6 @@ import com.sk89q.worldedit.entity.BaseEntity;
|
|||||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||||
import com.sk89q.worldedit.forge.internal.NBTConverter;
|
import com.sk89q.worldedit.forge.internal.NBTConverter;
|
||||||
import com.sk89q.worldedit.forge.net.handler.WECUIPacketHandler;
|
|
||||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.math.Vector3;
|
import com.sk89q.worldedit.math.Vector3;
|
||||||
@ -57,6 +56,7 @@ import net.minecraft.util.text.StringTextComponent;
|
|||||||
import net.minecraft.util.text.TextFormatting;
|
import net.minecraft.util.text.TextFormatting;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ public class ForgePlayer extends AbstractPlayerActor {
|
|||||||
if (params.length > 0) {
|
if (params.length > 0) {
|
||||||
send = send + "|" + StringUtil.joinString(params, "|");
|
send = send + "|" + StringUtil.joinString(params, "|");
|
||||||
}
|
}
|
||||||
PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)));
|
PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send, StandardCharsets.UTF_8));
|
||||||
SCustomPayloadPlayPacket packet = new SCustomPayloadPlayPacket(new ResourceLocation(ForgeWorldEdit.MOD_ID, ForgeWorldEdit.CUI_PLUGIN_CHANNEL), buffer);
|
SCustomPayloadPlayPacket packet = new SCustomPayloadPlayPacket(new ResourceLocation(ForgeWorldEdit.MOD_ID, ForgeWorldEdit.CUI_PLUGIN_CHANNEL), buffer);
|
||||||
this.player.connection.sendPacket(packet);
|
this.player.connection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
@ -249,18 +249,18 @@ public class ForgePlayer extends AbstractPlayerActor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SessionKey getSessionKey() {
|
public SessionKey getSessionKey() {
|
||||||
return new SessionKeyImpl(player.getUniqueID(), player.getName().getString());
|
return new SessionKeyImpl(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SessionKeyImpl implements SessionKey {
|
static class SessionKeyImpl implements SessionKey {
|
||||||
// If not static, this will leak a reference
|
// If not static, this will leak a reference
|
||||||
|
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private SessionKeyImpl(UUID uuid, String name) {
|
SessionKeyImpl(ServerPlayerEntity player) {
|
||||||
this.uuid = uuid;
|
this.uuid = player.getUniqueID();
|
||||||
this.name = name;
|
this.name = player.getName().getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -24,6 +24,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
||||||
|
import com.sk89q.worldedit.event.platform.SessionIdleEvent;
|
||||||
import com.sk89q.worldedit.extension.platform.Platform;
|
import com.sk89q.worldedit.extension.platform.Platform;
|
||||||
import com.sk89q.worldedit.forge.net.handler.InternalPacketHandler;
|
import com.sk89q.worldedit.forge.net.handler.InternalPacketHandler;
|
||||||
import com.sk89q.worldedit.forge.net.handler.WECUIPacketHandler;
|
import com.sk89q.worldedit.forge.net.handler.WECUIPacketHandler;
|
||||||
@ -49,6 +50,7 @@ import net.minecraft.util.ResourceLocation;
|
|||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.event.CommandEvent;
|
import net.minecraftforge.event.CommandEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickEmpty;
|
import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickEmpty;
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
@ -284,6 +286,14 @@ public class ForgeWorldEdit {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onPlayerLogOut(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||||
|
if (event.getPlayer() instanceof ServerPlayerEntity) {
|
||||||
|
WorldEdit.getInstance().getEventBus()
|
||||||
|
.post(new SessionIdleEvent(new ForgePlayer.SessionKeyImpl((ServerPlayerEntity) event.getPlayer())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the configuration.
|
* Get the configuration.
|
||||||
*
|
*
|
||||||
|
@ -27,6 +27,7 @@ import net.minecraftforge.fml.network.NetworkEvent.ClientCustomPayloadEvent;
|
|||||||
import net.minecraftforge.fml.network.event.EventNetworkChannel;
|
import net.minecraftforge.fml.network.event.EventNetworkChannel;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import static com.sk89q.worldedit.forge.ForgeAdapter.adaptPlayer;
|
import static com.sk89q.worldedit.forge.ForgeAdapter.adaptPlayer;
|
||||||
|
|
||||||
@ -34,7 +35,6 @@ public final class WECUIPacketHandler {
|
|||||||
private WECUIPacketHandler() {
|
private WECUIPacketHandler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Charset UTF_8_CHARSET = Charset.forName("UTF-8");
|
|
||||||
private static final int PROTOCOL_VERSION = 1;
|
private static final int PROTOCOL_VERSION = 1;
|
||||||
private static EventNetworkChannel HANDLER = PacketHandlerUtil
|
private static EventNetworkChannel HANDLER = PacketHandlerUtil
|
||||||
.buildLenientHandler(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, PROTOCOL_VERSION)
|
.buildLenientHandler(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, PROTOCOL_VERSION)
|
||||||
@ -47,15 +47,9 @@ public final class WECUIPacketHandler {
|
|||||||
public static void onPacketData(ClientCustomPayloadEvent event) {
|
public static void onPacketData(ClientCustomPayloadEvent event) {
|
||||||
ServerPlayerEntity player = event.getSource().get().getSender();
|
ServerPlayerEntity player = event.getSource().get().getSender();
|
||||||
LocalSession session = ForgeWorldEdit.inst.getSession(player);
|
LocalSession session = ForgeWorldEdit.inst.getSession(player);
|
||||||
|
String text = event.getPayload().toString(StandardCharsets.UTF_8);
|
||||||
if (session.hasCUISupport()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String text = event.getPayload().toString(UTF_8_CHARSET);
|
|
||||||
final ForgePlayer actor = adaptPlayer(player);
|
final ForgePlayer actor = adaptPlayer(player);
|
||||||
session.handleCUIInitializationMessage(text, actor);
|
session.handleCUIInitializationMessage(text, actor);
|
||||||
session.describeCUI(actor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,14 +53,9 @@ public class CUIChannelHandler implements RawDataListener {
|
|||||||
|
|
||||||
LocalSession session = SpongeWorldEdit.inst().getSession(player);
|
LocalSession session = SpongeWorldEdit.inst().getSession(player);
|
||||||
|
|
||||||
if (session.hasCUISupport()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final SpongePlayer actor = SpongeWorldEdit.inst().wrapPlayer(player);
|
final SpongePlayer actor = SpongeWorldEdit.inst().wrapPlayer(player);
|
||||||
session.handleCUIInitializationMessage(new String(data.readBytes(data.available()), StandardCharsets.UTF_8),
|
session.handleCUIInitializationMessage(new String(data.readBytes(data.available()), StandardCharsets.UTF_8),
|
||||||
actor);
|
actor);
|
||||||
session.describeCUI(actor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,18 +239,18 @@ public class SpongePlayer extends AbstractPlayerActor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SessionKey getSessionKey() {
|
public SessionKey getSessionKey() {
|
||||||
return new SessionKeyImpl(player.getUniqueId(), player.getName());
|
return new SessionKeyImpl(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SessionKeyImpl implements SessionKey {
|
static class SessionKeyImpl implements SessionKey {
|
||||||
// If not static, this will leak a reference
|
// If not static, this will leak a reference
|
||||||
|
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private SessionKeyImpl(UUID uuid, String name) {
|
SessionKeyImpl(Player player) {
|
||||||
this.uuid = uuid;
|
this.uuid = player.getUniqueId();
|
||||||
this.name = name;
|
this.name = player.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,6 +27,7 @@ import com.sk89q.worldedit.LocalSession;
|
|||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||||
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
||||||
|
import com.sk89q.worldedit.event.platform.SessionIdleEvent;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extension.platform.Capability;
|
import com.sk89q.worldedit.extension.platform.Capability;
|
||||||
import com.sk89q.worldedit.extension.platform.Platform;
|
import com.sk89q.worldedit.extension.platform.Platform;
|
||||||
@ -54,6 +55,7 @@ import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
|
|||||||
import org.spongepowered.api.event.game.state.GameStartedServerEvent;
|
import org.spongepowered.api.event.game.state.GameStartedServerEvent;
|
||||||
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
|
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
|
||||||
import org.spongepowered.api.event.item.inventory.InteractItemEvent;
|
import org.spongepowered.api.event.item.inventory.InteractItemEvent;
|
||||||
|
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
||||||
import org.spongepowered.api.item.ItemType;
|
import org.spongepowered.api.item.ItemType;
|
||||||
import org.spongepowered.api.item.inventory.ItemStack;
|
import org.spongepowered.api.item.inventory.ItemStack;
|
||||||
import org.spongepowered.api.plugin.Plugin;
|
import org.spongepowered.api.plugin.Plugin;
|
||||||
@ -290,6 +292,12 @@ public class SpongeWorldEdit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Listener
|
||||||
|
public void onPlayerQuit(ClientConnectionEvent.Disconnect event) {
|
||||||
|
WorldEdit.getInstance().getEventBus()
|
||||||
|
.post(new SessionIdleEvent(new SpongePlayer.SessionKeyImpl(event.getTargetEntity())));
|
||||||
|
}
|
||||||
|
|
||||||
public static ItemStack toSpongeItemStack(BaseItemStack item) {
|
public static ItemStack toSpongeItemStack(BaseItemStack item) {
|
||||||
return inst().getAdapter().makeSpongeStack(item);
|
return inst().getAdapter().makeSpongeStack(item);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user