SteamWar/SpigotCore
Archiviert
13
0

Merge branch 'master' into 1.19.3

Dieser Commit ist enthalten in:
Lixfel 2023-03-01 20:27:15 +01:00
Commit 3a777970d0
18 geänderte Dateien mit 302 neuen und 70 gelöschten Zeilen

@ -1 +1 @@
Subproject commit 9ea02ebcd4620e7baa6980cd88e1a4dabd59e50c Subproject commit 38457db0141d34e6f9f133e70bc3061b8a3d3e5a

Datei anzeigen

@ -22,6 +22,7 @@ package de.steamwar.core;
import com.comphenix.tinyprotocol.Reflection; import com.comphenix.tinyprotocol.Reflection;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -325,9 +326,13 @@ public class FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper
return displayName != null ? Optional.of(ChatWrapper.impl.stringToChatComponent(displayName)) : Optional.empty(); return displayName != null ? Optional.of(ChatWrapper.impl.stringToChatComponent(displayName)) : Optional.empty();
} }
private static final Reflection.FieldAccessor<?> spawnType = Reflection.getField(ProtocolWrapper.spawnPacket, Reflection.getClass("{nms.world.entity}.EntityTypes"), 0); private static final Class<?> registryBlocks = Reflection.getClass("{nms.core}.RegistryBlocks");
private static final Reflection.FieldAccessor<?> spawnLivingType = Core.getVersion() > 19 ? spawnType : Reflection.getField(ProtocolWrapper.spawnLivingPacket, int.class, 1); private static final Class<?> entityTypes = Reflection.getClass("{nms.world.entity}.EntityTypes");
private static final Reflection.MethodInvoker getEntityTypes = Reflection.getMethod("{obc}.util.CraftMagicNumbers", "getEntityTypes", EntityType.class); private static final Object entityTypesRegistry = Reflection.getField(Reflection.getClass("{nms.core}.IRegistry"), registryBlocks, 0, entityTypes).get(null);
private static final Reflection.MethodInvoker get = Reflection.getMethod(registryBlocks, null, Reflection.getClass("{nms.resources}.MinecraftKey"));
private static final Reflection.FieldAccessor<?> spawnType = Reflection.getField(ProtocolWrapper.spawnPacket, entityTypes, 0);
private static final Reflection.FieldAccessor<?> spawnLivingType = Core.getVersion() > 18 ? spawnType : Reflection.getField(ProtocolWrapper.spawnLivingPacket, int.class, 1);
private static final Reflection.MethodInvoker toMinecraft = Reflection.getMethod("{obc}.util.CraftNamespacedKey", "toMinecraft", NamespacedKey.class);
private static final Map<EntityType, Object> types = new HashMap<>(); private static final Map<EntityType, Object> types = new HashMap<>();
static { static {
types.put(EntityType.ARMOR_STAND, 1); types.put(EntityType.ARMOR_STAND, 1);
@ -335,9 +340,9 @@ public class FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper
@Override @Override
public void setSpawnPacketType(Object packet, EntityType type) { public void setSpawnPacketType(Object packet, EntityType type) {
if(type.isAlive()) { if(type.isAlive()) {
spawnLivingType.set(packet, Core.getVersion() > 18 ? getEntityTypes.invoke(null, type) : types.get(type)); spawnLivingType.set(packet, Core.getVersion() > 18 ? get.invoke(entityTypesRegistry, toMinecraft.invoke(null, type.getKey())) : types.get(type));
} else { } else {
spawnType.set(packet, getEntityTypes.invoke(null, type)); spawnType.set(packet, get.invoke(entityTypesRegistry, toMinecraft.invoke(null, type.getKey())));
} }
} }

Datei anzeigen

@ -0,0 +1,30 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerRecipeDiscoverEvent;
public class RecipeDiscoverWrapper14 implements RecipeDiscoverWrapper {
@EventHandler
public void onRecipeDiscover(PlayerRecipeDiscoverEvent e) {
e.setCancelled(true);
}
}

Datei anzeigen

@ -0,0 +1,24 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core;
public class RecipeDiscoverWrapper8 implements RecipeDiscoverWrapper {
// Event not available pre flattening
}

Datei anzeigen

@ -43,6 +43,8 @@ sourceSets {
} }
dependencies { dependencies {
compileOnly 'com.viaversion:viaversion-api:4.3.1'
compileOnly project(":SpigotCore_Main") compileOnly project(":SpigotCore_Main")
compileOnly project(":SpigotCore_8") compileOnly project(":SpigotCore_8")

Datei anzeigen

@ -20,6 +20,7 @@
package de.steamwar.core; package de.steamwar.core;
import com.comphenix.tinyprotocol.Reflection; import com.comphenix.tinyprotocol.Reflection;
import com.viaversion.viaversion.api.Via;
import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Sound; import org.bukkit.Sound;
@ -36,6 +37,9 @@ public class BountifulWrapper9 implements BountifulWrapper.IBountifulWrapper {
@Override @Override
public void sendMessage(Player player, ChatMessageType type, BaseComponent... msg) { public void sendMessage(Player player, ChatMessageType type, BaseComponent... msg) {
if(type == ChatMessageType.CHAT && Via.getAPI().getPlayerVersion(player.getUniqueId()) >= 759)
type = ChatMessageType.SYSTEM;
player.spigot().sendMessage(type, msg); player.spigot().sendMessage(type, msg);
} }

Datei anzeigen

@ -251,7 +251,7 @@ public final class Reflection {
// Search in every superclass // Search in every superclass
if (clazz.getSuperclass() != null) if (clazz.getSuperclass() != null)
return getMethod(clazz.getSuperclass(), methodName, params); return getTypedMethod(clazz.getSuperclass(), methodName, returnType, params);
throw new IllegalStateException(String.format("Unable to find method %s (%s).", methodName, Arrays.asList(params))); throw new IllegalStateException(String.format("Unable to find method %s (%s).", methodName, Arrays.asList(params)));
} }

Datei anzeigen

@ -22,10 +22,7 @@ package de.steamwar.core;
import com.comphenix.tinyprotocol.TinyProtocol; import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.command.*; import de.steamwar.command.*;
import de.steamwar.core.authlib.AuthlibInjector; import de.steamwar.core.authlib.AuthlibInjector;
import de.steamwar.core.events.ChattingEvent; import de.steamwar.core.events.*;
import de.steamwar.core.events.PartialChunkFixer;
import de.steamwar.core.events.PlayerJoinedEvent;
import de.steamwar.core.events.WorldLoadEvent;
import de.steamwar.message.Message; import de.steamwar.message.Message;
import de.steamwar.network.NetworkReceiver; import de.steamwar.network.NetworkReceiver;
import de.steamwar.network.handlers.ServerDataHandler; import de.steamwar.network.handlers.ServerDataHandler;
@ -34,6 +31,7 @@ import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.internal.Statement; import de.steamwar.sql.internal.Statement;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -84,30 +82,33 @@ public class Core extends JavaPlugin{
return tabCompleter.apply(sender, s); return tabCompleter.apply(sender, s);
} }
}); });
Bukkit.getScheduler().runTaskTimer(this, TabCompletionCache::invalidateOldEntries, 20, 20);
Bukkit.getPluginManager().registerEvents(new CaseInsensitiveCommandsListener(), this);
Bukkit.getPluginManager().registerEvents(new PlayerJoinedEvent(), this); for(Listener listener : new Listener[]{new CaseInsensitiveCommandsListener(), new PlayerJoinedEvent(), new ChattingEvent(), new WorldLoadEvent(), RecipeDiscoverWrapper.impl}) {
Bukkit.getPluginManager().registerEvents(new ChattingEvent(), this); getServer().getPluginManager().registerEvents(listener, this);
Bukkit.getPluginManager().registerEvents(new WorldLoadEvent(), this);
if(!Statement.productionDatabase()) {
Bukkit.getPluginManager().registerEvents(LocaleChangeWrapper.impl, this);
} }
if(!Statement.productionDatabase()) {
getServer().getPluginManager().registerEvents(LocaleChangeWrapper.impl, this);
}
getServer().getMessenger().registerIncomingPluginChannel(this, "sw:bridge", new NetworkReceiver()); getServer().getMessenger().registerIncomingPluginChannel(this, "sw:bridge", new NetworkReceiver());
getServer().getMessenger().registerOutgoingPluginChannel(this, "sw:bridge"); getServer().getMessenger().registerOutgoingPluginChannel(this, "sw:bridge");
if(Core.getVersion() < 19) if(Core.getVersion() < 19)
AuthlibInjector.inject(); AuthlibInjector.inject();
TinyProtocol.init(); TinyProtocol.init();
new AntiNocom();
if(Core.getVersion() < 17 && Bukkit.getPluginManager().getPlugin("ViaVersion") != null) if(Core.getVersion() < 17 && Bukkit.getPluginManager().getPlugin("ViaVersion") != null)
new PartialChunkFixer(); new PartialChunkFixer();
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), SteamwarUser::clear, 72000, 72000);
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), SchematicNode::clear, 20L * 30, 20L * 30);
if(Core.getVersion() >= 19) if(Core.getVersion() >= 19)
new ServerDataHandler(); new ServerDataHandler();
Bukkit.getScheduler().runTaskTimer(this, TabCompletionCache::invalidateOldEntries, 20, 20);
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), SteamwarUser::clear, 72000, 72000);
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), SchematicNode::clear, 20L * 30, 20L * 30);
try { try {
getLogger().log(Level.INFO, "Running on: " + new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream())).readLine()); getLogger().log(Level.INFO, "Running on: " + new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream())).readLine());
} catch (IOException e) { } catch (IOException e) {

Datei anzeigen

@ -0,0 +1,26 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core;
import org.bukkit.event.Listener;
public interface RecipeDiscoverWrapper extends Listener {
RecipeDiscoverWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
}

Datei anzeigen

@ -0,0 +1,85 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core.events;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.core.Core;
import de.steamwar.sql.SWException;
import de.steamwar.techhider.ProtocolUtils;
import de.steamwar.techhider.TechHider;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.function.Function;
public class AntiNocom {
public AntiNocom() {
TinyProtocol.instance.addFilter(blockDig, this::onDig);
if(Core.getVersion() > 8) {
registerUseItem();
}
}
private void registerUseItem() {
Class<?> useItem = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInUseItem");
Function<Object, Object> getPosition;
if(Core.getVersion() > 12) {
Class<?> movingObjectPositionBlock = Reflection.getClass("{nms.world.phys}.MovingObjectPositionBlock");
Reflection.FieldAccessor<?> useItemPosition = Reflection.getField(useItem, movingObjectPositionBlock, 0);
Reflection.FieldAccessor<?> movingBlockPosition = Reflection.getField(movingObjectPositionBlock, TechHider.blockPosition, 0);
getPosition = (packet) -> movingBlockPosition.get(useItemPosition.get(packet));
} else {
getPosition = Reflection.getField(useItem, TechHider.blockPosition, 0)::get;
}
TinyProtocol.instance.addFilter(useItem, (player, packet) -> {
Object pos = getPosition.apply(packet);
int x = TechHider.blockPositionX.get(pos);
int z = TechHider.blockPositionZ.get(pos);
if(!player.getWorld().isChunkLoaded(ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(z))) {
Bukkit.getScheduler().runTask(Core.getInstance(), () -> player.kickPlayer(null));
SWException.log(player.getName() + " kicked for using item on unloaded block (potential NoCom-DOS attack)", x + " " + z);
return null;
}
return packet;
});
}
private static final Class<?> blockDig = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInBlockDig");
private static final Reflection.FieldAccessor<?> digPosition = Reflection.getField(blockDig, TechHider.blockPosition, 0);
private Object onDig(Player player, Object packet) {
Object pos = digPosition.get(packet);
int x = TechHider.blockPositionX.get(pos);
int z = TechHider.blockPositionZ.get(pos);
if((x != 0 || z != 0) && !player.getWorld().isChunkLoaded(ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(z))) {
Bukkit.getScheduler().runTask(Core.getInstance(), () -> player.kickPlayer(null));
SWException.log(player.getName() + " kicked for digging an unloaded block (potential NoCom-DOS attack)", x + " " + z);
return null;
}
return packet;
}
}

Datei anzeigen

@ -35,10 +35,7 @@ public class PlayerJoinedEvent implements Listener{
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
private void onJoin(PlayerJoinEvent event) { private void onJoin(PlayerJoinEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
if(!Statement.productionDatabase()) { SteamwarUser user = Statement.productionDatabase() ? SteamwarUser.get(player.getUniqueId()) : SteamwarUser.getOrCreate(player.getUniqueId(), player.getName(), uuid -> {}, (oldName, newName) -> {});
SteamwarUser.createOrUpdateUsername(player.getUniqueId(), player.getName());
}
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
if(user.getUserGroup() != UserGroup.Member) { if(user.getUserGroup() != UserGroup.Member) {
UserGroup group = user.getUserGroup(); UserGroup group = user.getUserGroup();

Datei anzeigen

@ -52,8 +52,9 @@ public class RArmorStand extends REntity {
private final Size size; private final Size size;
public RArmorStand(REntityServer server, Location location, Size size) { public RArmorStand(REntityServer server, Location location, Size size) {
super(server, EntityType.ARMOR_STAND, location); super(server, EntityType.ARMOR_STAND, location, 0);
this.size = size; this.size = size;
server.addEntity(this);
} }
@Override @Override

Datei anzeigen

@ -20,7 +20,10 @@
package de.steamwar.entity; package de.steamwar.entity;
import com.comphenix.tinyprotocol.Reflection; import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.core.*; import de.steamwar.core.BountifulWrapper;
import de.steamwar.core.Core;
import de.steamwar.core.FlatteningWrapper;
import de.steamwar.core.ProtocolWrapper;
import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntList;
import lombok.Getter; import lombok.Getter;
@ -73,6 +76,7 @@ public class REntity {
public REntity(REntityServer server, EntityType entityType, Location location) { public REntity(REntityServer server, EntityType entityType, Location location) {
this(server,entityType,location,0); this(server,entityType,location,0);
server.addEntity(this);
} }
protected REntity(REntityServer server, EntityType entityType, Location location,int objectData) { protected REntity(REntityServer server, EntityType entityType, Location location,int objectData) {
@ -97,8 +101,6 @@ public class REntity {
this.isGlowing = false; this.isGlowing = false;
this.objectData = objectData; this.objectData = objectData;
server.addEntity(this);
} }
public void move(Location location) { public void move(Location location) {
@ -214,6 +216,18 @@ public class REntity {
} }
} }
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
private static int spawnPacketOffset() { private static int spawnPacketOffset() {
switch (Core.getVersion()) { switch (Core.getVersion()) {
case 8: case 8:

Datei anzeigen

@ -19,9 +19,11 @@
package de.steamwar.entity; package de.steamwar.entity;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol; import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.core.Core; import de.steamwar.core.Core;
import de.steamwar.core.FlatteningWrapper; import de.steamwar.core.FlatteningWrapper;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -31,11 +33,15 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
public class REntityServer implements Listener { public class REntityServer implements Listener {
@ -43,15 +49,58 @@ public class REntityServer implements Listener {
private static final HashSet<REntity> emptyEntities = new HashSet<>(0); private static final HashSet<REntity> emptyEntities = new HashSet<>(0);
private static final HashSet<Player> emptyPlayers = new HashSet<>(0); private static final HashSet<Player> emptyPlayers = new HashSet<>(0);
private static final Class<?> useEntity = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInUseEntity");
private static final Reflection.FieldAccessor<Integer> useEntityTarget = Reflection.getField(useEntity, int.class, 0);
private static final Class<?> useEntityEnumAction = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInUseEntity$EnumEntityUseAction");
private static final Reflection.FieldAccessor<?> useEntityAction = Reflection.getField(useEntity, useEntityEnumAction, 0);
private static final Function<Object, Integer> getEntityAction;
static {
if(Core.getVersion() > 15) {
Reflection.MethodInvoker useEntityGetAction = Reflection.getMethod(useEntityEnumAction, "a");
getEntityAction = value -> ((Enum<?>) useEntityGetAction.invoke(value)).ordinal();
} else {
getEntityAction = value -> ((Enum<?>) value).ordinal();
}
}
private final ConcurrentHashMap<Integer, REntity> entityMap = new ConcurrentHashMap<>();
private final HashMap<Long, HashSet<REntity>> entities = new HashMap<>(); private final HashMap<Long, HashSet<REntity>> entities = new HashMap<>();
private final HashMap<Long, Set<Player>> players = new HashMap<>(); private final HashMap<Long, Set<Player>> players = new HashMap<>();
private final HashMap<Player, Location> lastLocation = new HashMap<>(); private final HashMap<Player, Location> lastLocation = new HashMap<>();
private final HashMap<Player, Integer> viewDistance = new HashMap<>(); private final HashMap<Player, Integer> viewDistance = new HashMap<>();
private EntityActionListener callback = null;
private final Set<Player> playersThatClicked = Collections.synchronizedSet(new HashSet<>());
private final BiFunction<Player, Object, Object> filter = (player, packet) -> {
REntity entity = entityMap.get(useEntityTarget.get(packet));
if (entity == null)
return packet;
if (playersThatClicked.contains(player))
return null;
playersThatClicked.add(player);
EntityAction action = getEntityAction.apply(useEntityAction.get(packet)) == 1 ? EntityAction.ATTACK : EntityAction.INTERACT;
Bukkit.getScheduler().runTask(Core.getInstance(), () -> {
playersThatClicked.remove(player);
callback.onAction(player, entity, action);
});
return null;
};
public REntityServer() { public REntityServer() {
Core.getInstance().getServer().getPluginManager().registerEvents(this, Core.getInstance()); Core.getInstance().getServer().getPluginManager().registerEvents(this, Core.getInstance());
} }
public void setCallback(EntityActionListener callback) {
boolean uninitialized = this.callback == null;
this.callback = callback;
if(uninitialized)
TinyProtocol.instance.addFilter(useEntity, filter);
}
public void addPlayer(Player player) { public void addPlayer(Player player) {
Location location = player.getLocation(); Location location = player.getLocation();
lastLocation.put(player, location); lastLocation.put(player, location);
@ -65,6 +114,7 @@ public class REntityServer implements Listener {
} }
public void close() { public void close() {
TinyProtocol.instance.removeFilter(useEntity, filter);
for(Player player : lastLocation.keySet().toArray(new Player[0])) { for(Player player : lastLocation.keySet().toArray(new Player[0])) {
removePlayer(player); removePlayer(player);
} }
@ -72,6 +122,7 @@ public class REntityServer implements Listener {
} }
void addEntity(REntity entity) { void addEntity(REntity entity) {
entityMap.put(entity.entityId, entity);
addEntityToChunk(entity); addEntityToChunk(entity);
entity.spawn(packet -> updateEntity(entity, packet)); entity.spawn(packet -> updateEntity(entity, packet));
} }
@ -105,6 +156,7 @@ public class REntityServer implements Listener {
void removeEntity(REntity entity) { void removeEntity(REntity entity) {
entity.despawn(packet -> updateEntity(entity, packet)); entity.despawn(packet -> updateEntity(entity, packet));
removeEntityFromChunk(entity); removeEntityFromChunk(entity);
entityMap.remove(entity.entityId);
} }
private void addEntityToChunk(REntity entity) { private void addEntityToChunk(REntity entity) {
@ -158,7 +210,14 @@ public class REntityServer implements Listener {
if(location == null) if(location == null)
return; return;
forChunkInView(player, location, (x, z) -> players.get(chunkToId(x, z)).remove(player)); forChunkInView(player, location, (x, z) -> {
long id = chunkToId(x, z);
Set<Player> playersInChunk = players.get(id);
playersInChunk.remove(player);
if(playersInChunk.isEmpty())
players.remove(id);
});
viewDistance.remove(player);
} }
private void onMissing(Set<Player> of, Set<Player> in, Consumer<Consumer<Object>> packetProvider) { private void onMissing(Set<Player> of, Set<Player> in, Consumer<Consumer<Object>> packetProvider) {
@ -194,7 +253,12 @@ public class REntityServer implements Listener {
private void removePlayerFromChunk(Player player, int x, int z) { private void removePlayerFromChunk(Player player, int x, int z) {
long id = chunkToId(x, z); long id = chunkToId(x, z);
players.get(id).remove(player);
Set<Player> playersInChunk = players.get(id);
playersInChunk.remove(player);
if(playersInChunk.isEmpty())
players.remove(id);
for(REntity entity : entities.getOrDefault(id, emptyEntities)) { for(REntity entity : entities.getOrDefault(id, emptyEntities)) {
entity.despawn(packet -> TinyProtocol.instance.sendPacket(player, packet)); entity.despawn(packet -> TinyProtocol.instance.sendPacket(player, packet));
} }
@ -227,4 +291,13 @@ public class REntityServer implements Listener {
private long chunkToId(int x, int z) { private long chunkToId(int x, int z) {
return ((long) x << 32) + z; return ((long) x << 32) + z;
} }
public enum EntityAction {
INTERACT,
ATTACK,
}
public interface EntityActionListener {
void onAction(Player player, REntity entity, EntityAction action);
}
} }

Datei anzeigen

@ -29,5 +29,6 @@ public class RFallingBlockEntity extends REntity{
public RFallingBlockEntity(REntityServer server, Location location, Material material) { public RFallingBlockEntity(REntityServer server, Location location, Material material) {
super(server, EntityType.FALLING_BLOCK, location, BlockIds.impl.materialToId(material) >> (Core.getVersion() <= 12 ? 4 : 0)); super(server, EntityType.FALLING_BLOCK, location, BlockIds.impl.materialToId(material) >> (Core.getVersion() <= 12 ? 4 : 0));
server.addEntity(this);
} }
} }

Datei anzeigen

@ -78,6 +78,7 @@ public class RPlayer extends REntity {
super(server, EntityType.PLAYER, uuid, location,0); super(server, EntityType.PLAYER, uuid, location,0);
this.name = name; this.name = name;
//team.addEntry(name); //team.addEntry(name);
server.addEntity(this);
} }
@Override @Override

Datei anzeigen

@ -163,7 +163,7 @@ public class SchematicSelector {
} }
if(!singleDirOpen) { if(!singleDirOpen) {
if(NodeMember.getNodeMember(parent.getId(), user.getId()) != null) { if(NodeMember.getNodeMember(parent.getId(), user.getId()) != null) {
return Optional.ofNullable(SchematicNode.byIdAndUser(user, parent.getId())).flatMap(SchematicNode::getOptionalParent).map(integer -> SchematicNode.byIdAndUser(user, integer)).orElse(null); return NodeMember.getNodeMember(parent.getId(), user.getId()).getParent().map(integer -> SchematicNode.byIdAndUser(user, integer)).orElse(null);
} else { } else {
return getParent(parent).orElse(null); return getParent(parent).orElse(null);
} }

Datei anzeigen

@ -36,11 +36,6 @@ import java.util.zip.GZIPInputStream;
public class SchematicData { public class SchematicData {
static {
new SqlTypeMapper<>(PipedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("PipedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
new SqlTypeMapper<>(ByteArrayInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("ByteArrayInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
}
public static Clipboard clipboardFromStream(InputStream is, boolean schemFormat) { public static Clipboard clipboardFromStream(InputStream is, boolean schemFormat) {
try { try {
return WorldEditWrapper.impl.getClipboard(is, schemFormat); return WorldEditWrapper.impl.getClipboard(is, schemFormat);
@ -49,42 +44,20 @@ public class SchematicData {
} }
} }
private static final Statement updateDatabase = new Statement("UPDATE SchematicNode SET NodeData = ?, NodeFormat = ? WHERE NodeId = ?"); private final NodeData data;
private static final Statement selSchemData = new Statement("SELECT NodeData FROM SchematicNode WHERE NodeId = ?");
private final SchematicNode node;
public SchematicData(SchematicNode node) { public SchematicData(SchematicNode node) {
this.node = node; this.data = NodeData.get(node);
if(node.isDir()) if(node.isDir())
throw new SecurityException("Node is Directory"); throw new SecurityException("Node is Directory");
} }
public InputStream schemData() throws IOException {
try {
return selSchemData.select(rs -> {
rs.next();
Blob schemData = rs.getBlob("NodeData");
if(schemData == null) {
throw new SecurityException("SchemData is null");
}
try {
return new GZIPInputStream(schemData.getBinaryStream());
} catch (IOException e) {
throw new SecurityException("SchemData is wrong", e);
}
}, node.getId());
} catch (Exception e) {
throw new IOException(e);
}
}
public Clipboard load() throws IOException, NoClipboardException { public Clipboard load() throws IOException, NoClipboardException {
return WorldEditWrapper.impl.getClipboard(schemData(), node.getSchemFormat()); return WorldEditWrapper.impl.getClipboard(data.schemData(), data.getNodeFormat());
} }
public void loadToPlayer(Player player) throws IOException, NoClipboardException { public void loadToPlayer(Player player) throws IOException, NoClipboardException {
WorldEditWrapper.impl.setPlayerClipboard(player, schemData(), node.getSchemFormat()); WorldEditWrapper.impl.setPlayerClipboard(player, data.schemData(), data.getNodeFormat());
} }
public void saveFromPlayer(Player player) throws IOException, NoClipboardException { public void saveFromPlayer(Player player) throws IOException, NoClipboardException {
@ -92,16 +65,11 @@ public class SchematicData {
} }
public void saveFromPlayer(Player player, boolean newFormat) throws IOException, NoClipboardException { public void saveFromPlayer(Player player, boolean newFormat) throws IOException, NoClipboardException {
saveFromStream(WorldEditWrapper.impl.getPlayerClipboard(player, newFormat), newFormat); data.saveFromStream(WorldEditWrapper.impl.getPlayerClipboard(player, newFormat), newFormat);
} }
@Deprecated @Deprecated
public void saveFromBytes(byte[] bytes, boolean newFormat) { public void saveFromBytes(byte[] bytes, boolean newFormat) {
saveFromStream(new ByteArrayInputStream(bytes), newFormat); data.saveFromStream(new ByteArrayInputStream(bytes), newFormat);
}
public void saveFromStream(InputStream blob, boolean newFormat) {
updateDatabase.update(blob, newFormat, node.getId());
node.setNodeFormat(newFormat);
} }
} }