Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-26 16:12:42 +01:00
More spring cleaning
Dieser Commit ist enthalten in:
Ursprung
095fe16447
Commit
5850a9852d
@ -87,7 +87,7 @@ public interface ViaVersionConfig extends Config {
|
||||
* <p>
|
||||
* This option requires {@link #isShowShieldWhenSwordInHand()} to be disabled
|
||||
*
|
||||
* @return {@code true} if non delayed shield blocking is enabled.
|
||||
* @return {@code true} if non-delayed shield blocking is enabled.
|
||||
*/
|
||||
boolean isNoDelayShieldBlocking();
|
||||
|
||||
@ -126,7 +126,7 @@ public interface ViaVersionConfig extends Config {
|
||||
* Get if the boss bars for 1.9 & 1.10 clients are being stopped from flickering
|
||||
* This will keep all boss bars on 100% (not recommended)
|
||||
*
|
||||
* @return true if boss bar anti flickering is enabled
|
||||
* @return true if boss bar anti-flickering is enabled
|
||||
*/
|
||||
boolean isBossbarAntiflicker();
|
||||
|
||||
@ -384,7 +384,7 @@ public interface ViaVersionConfig extends Config {
|
||||
boolean isTruncate1_14Books();
|
||||
|
||||
/**
|
||||
* Handles left handed info by using unused bit 7 on Client Settings packet
|
||||
* Handles left-handed info by using unused bit 7 on Client Settings packet
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
@ -443,7 +443,7 @@ public interface ViaVersionConfig extends Config {
|
||||
|
||||
/***
|
||||
* Get the world names that should be returned for each Vanilla dimension.
|
||||
* Note that this can be overriden per-user by using {@link UserConnection#put(StorableObject)} with
|
||||
* Note that this can be overridden per-user by using {@link UserConnection#put(StorableObject)} with
|
||||
* a custom instance of {@link WorldIdentifiers} for the user's {@link UserConnection}.
|
||||
*
|
||||
* @return the global map from vanilla dimensions to world name
|
||||
|
@ -66,7 +66,7 @@ public interface BossBar {
|
||||
BossColor getColor();
|
||||
|
||||
/**
|
||||
* Yay colors!
|
||||
* Yay, colors!
|
||||
*
|
||||
* @param color Whatever color you want!
|
||||
* @return The BossBar object
|
||||
|
@ -206,12 +206,13 @@ public interface ViaPlatform<T> {
|
||||
JsonObject getDump();
|
||||
|
||||
/**
|
||||
* Get if older clients are allowed to be used using ViaVersion.
|
||||
* (Only 1.9 on 1.9.2 server is supported by ViaVersion alone)
|
||||
* Get if older clients are allowed using ViaVersion.
|
||||
*
|
||||
* @return True if allowed
|
||||
*/
|
||||
boolean isOldClientsAllowed();
|
||||
default boolean isOldClientsAllowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable collection of classes to be checked as unsupported software with their software name.
|
||||
|
@ -42,9 +42,7 @@ public final class PaletteType1_18 extends Type<DataPalette> {
|
||||
|
||||
@Override
|
||||
public DataPalette read(final ByteBuf buffer) throws Exception {
|
||||
final int originalBitsPerValue = buffer.readByte();
|
||||
int bitsPerValue = originalBitsPerValue;
|
||||
|
||||
int bitsPerValue = buffer.readByte();
|
||||
final DataPaletteImpl palette;
|
||||
if (bitsPerValue == 0) {
|
||||
// Single value storage
|
||||
|
@ -27,7 +27,7 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
// Based on https://github.com/SpigotMC/BungeeCord/blob/master/chat/src/main/java/net/md_5/bungee/api/ChatColor.java
|
||||
public class ChatColorUtil {
|
||||
public final class ChatColorUtil {
|
||||
|
||||
public static final String ALL_CODES = "0123456789AaBbCcDdEeFfKkLlMmNnOoRrXx";
|
||||
public static final char COLOR_CHAR = '§';
|
||||
|
@ -27,6 +27,7 @@ import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
public class Int2IntBiHashMap implements Int2IntBiMap {
|
||||
@ -91,6 +92,13 @@ public class Int2IntBiHashMap implements Int2IntBiMap {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(@NonNull Map<? extends Integer, ? extends Integer> m) {
|
||||
for (final Map.Entry<? extends Integer, ? extends Integer> entry : m.entrySet()) {
|
||||
put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defaultReturnValue(final int rv) {
|
||||
map.defaultReturnValue(rv);
|
||||
|
@ -23,8 +23,6 @@
|
||||
package com.viaversion.viaversion.util;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* Simple wrapper class for two {@link Int2IntMap}s.
|
||||
@ -50,10 +48,4 @@ public interface Int2IntBiMap extends Int2IntMap {
|
||||
*/
|
||||
@Override
|
||||
int put(int key, int value);
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
default void putAll(@NonNull Map<? extends Integer, ? extends Integer> m) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
@ -53,9 +53,7 @@ public class DeathListener extends ViaBukkitListener {
|
||||
}
|
||||
|
||||
private void sendPacket(final Player p, final String msg) {
|
||||
Via.getPlatform().runSync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Via.getPlatform().runSync(() -> {
|
||||
// If online
|
||||
UserConnection userConnection = getUserConnection(p);
|
||||
if (userConnection != null) {
|
||||
@ -71,7 +69,6 @@ public class DeathListener extends ViaBukkitListener {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import com.google.gson.JsonObject;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.ViaAPI;
|
||||
import com.viaversion.viaversion.api.command.ViaCommandSender;
|
||||
import com.viaversion.viaversion.api.configuration.ConfigurationProvider;
|
||||
import com.viaversion.viaversion.api.platform.PlatformTask;
|
||||
import com.viaversion.viaversion.api.platform.UnsupportedSoftware;
|
||||
import com.viaversion.viaversion.api.platform.ViaPlatform;
|
||||
|
@ -74,13 +74,10 @@ public class PlayerSneakListener extends ViaBukkitListener {
|
||||
if (Via.getAPI().getServerVersion().lowestSupportedVersion() >= ProtocolVersion.v1_9.getVersion()) {
|
||||
sneaking = new WeakHashMap<>();
|
||||
useCache = true;
|
||||
plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plugin.getServer().getScheduler().runTaskTimer(plugin, () -> {
|
||||
for (Map.Entry<Player, Boolean> entry : sneaking.entrySet()) {
|
||||
setHeight(entry.getKey(), entry.getValue() ? HEIGHT_1_14 : HEIGHT_1_9);
|
||||
}
|
||||
}
|
||||
}, 1, 1);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.platform.ViaPlatformLoader;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.bukkit.compat.ProtocolSupportCompat;
|
||||
import com.viaversion.viaversion.bukkit.listeners.JoinListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.UpdateListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.multiversion.PlayerSneakListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.protocol1_15to1_14_4.EntityToggleGlideListener;
|
||||
|
@ -199,11 +199,6 @@ public class BungeePlugin extends Plugin implements ViaServerProxyPlatform<Proxi
|
||||
return platformSpecific;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOldClientsAllowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<UnsupportedSoftware> getUnsupportedSoftwareClasses() {
|
||||
final Collection<UnsupportedSoftware> list = new ArrayList<>(ViaServerProxyPlatform.super.getUnsupportedSoftwareClasses());
|
||||
|
@ -125,8 +125,8 @@ public class BungeeServerHandler implements Listener {
|
||||
int playerId;
|
||||
try {
|
||||
playerId = Via.getManager().getProviders().get(EntityIdProvider.class).getEntityId(userConnection);
|
||||
} catch (Exception ex) {
|
||||
return; // Ignored
|
||||
} catch (Exception ignored) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (EntityTracker tracker : userConnection.getEntityTrackers()) {
|
||||
@ -156,18 +156,13 @@ public class BungeeServerHandler implements Listener {
|
||||
|
||||
// Clear auto-team
|
||||
EntityTracker1_9 oldEntityTracker = user.getEntityTracker(Protocol1_9To1_8.class);
|
||||
if (oldEntityTracker != null) {
|
||||
if (oldEntityTracker.isAutoTeam() && oldEntityTracker.isTeamExists()) {
|
||||
if (oldEntityTracker != null && oldEntityTracker.isAutoTeam() && oldEntityTracker.isTeamExists()) {
|
||||
oldEntityTracker.sendTeamPacket(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
String serverName = event.getServer().getInfo().getName();
|
||||
|
||||
String serverName = server.getInfo().getName();
|
||||
storage.setCurrentServer(serverName);
|
||||
|
||||
int protocolId = Via.proxyPlatform().protocolDetectorService().serverProtocolVersion(serverName);
|
||||
|
||||
if (protocolId <= ProtocolVersion.v1_8.getVersion() && storage.getBossbar() != null) { // 1.8 doesn't have BossBar packet
|
||||
// This ensures we can encode it properly as only the 1.9 protocol is currently implemented.
|
||||
if (user.getProtocolInfo().getPipeline().contains(Protocol1_9To1_8.class)) {
|
||||
|
@ -76,7 +76,6 @@ public class BungeeViaInjector implements ViaInjector {
|
||||
Via.getPlatform().getLogger().severe("ViaVersion cannot remove itself from Bungee without a reboot!");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void injectChannel(Channel channel) throws ReflectiveOperationException {
|
||||
List<String> names = channel.pipeline().names();
|
||||
ChannelHandler bootstrapAcceptor = null;
|
||||
|
@ -24,13 +24,13 @@ import java.lang.reflect.Method;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
public class BungeeEntityIdProvider extends EntityIdProvider {
|
||||
private static Method getClientEntityId;
|
||||
private static final Method GET_CLIENT_ENTITY_ID;
|
||||
|
||||
static {
|
||||
try {
|
||||
getClientEntityId = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getClientEntityId");
|
||||
GET_CLIENT_ENTITY_ID = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getClientEntityId");
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,6 +39,6 @@ public class BungeeEntityIdProvider extends EntityIdProvider {
|
||||
BungeeStorage storage = user.get(BungeeStorage.class);
|
||||
ProxiedPlayer player = storage.getPlayer();
|
||||
|
||||
return (int) getClientEntityId.invoke(player);
|
||||
return (int) GET_CLIENT_ENTITY_ID.invoke(player);
|
||||
}
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
/*
|
||||
This solves the wrong mainhand issue when you join with BungeeCord on a 1.8 server, and switch to a 1.9 or higher.
|
||||
This solves the wrong main hand issue when you join with BungeeCord on a 1.8 server, and switch to a 1.9 or higher.
|
||||
*/
|
||||
public class BungeeMainHandProvider extends MainHandProvider {
|
||||
private static Method getSettings = null;
|
||||
private static Method setMainHand = null;
|
||||
private static Method getSettings;
|
||||
private static Method setMainHand;
|
||||
|
||||
static {
|
||||
try {
|
||||
|
@ -43,8 +43,10 @@ public class BungeeVersionProvider extends BaseVersionProvider {
|
||||
|
||||
@Override
|
||||
public int getClosestServerProtocol(UserConnection user) throws Exception {
|
||||
if (ref == null)
|
||||
if (ref == null) {
|
||||
return super.getClosestServerProtocol(user);
|
||||
}
|
||||
|
||||
// TODO Have one constant list forever until restart? (Might limit plugins if they change this)
|
||||
List<Integer> list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSION_IDS", List.class);
|
||||
List<Integer> sorted = new ArrayList<>(list);
|
||||
|
@ -120,15 +120,12 @@ public class ParticleRewriter {
|
||||
|
||||
// Randomized because the previous one was a lot of different colors at once! :)
|
||||
private static ParticleDataHandler reddustHandler() {
|
||||
return new ParticleDataHandler() {
|
||||
@Override
|
||||
public Particle handler(Particle particle, Integer[] data) {
|
||||
return (particle, data) -> {
|
||||
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, randomBool() ? 1f : 0f)); // Red 0 - 1
|
||||
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, 0f)); // Green 0 - 1
|
||||
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, randomBool() ? 1f : 0f)); // Blue 0 - 1
|
||||
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, 1f));// Scale 0.01 - 4
|
||||
return particle;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -138,38 +135,33 @@ public class ParticleRewriter {
|
||||
|
||||
// Rewrite IconCrack items to new format :)
|
||||
private static ParticleDataHandler iconcrackHandler() {
|
||||
return new ParticleDataHandler() {
|
||||
@Override
|
||||
public Particle handler(Particle particle, Integer[] data) {
|
||||
return (particle, data) -> {
|
||||
Item item;
|
||||
if (data.length == 1)
|
||||
if (data.length == 1) {
|
||||
item = new DataItem(data[0], (byte) 1, (short) 0, null);
|
||||
else if (data.length == 2)
|
||||
} else if (data.length == 2) {
|
||||
item = new DataItem(data[0], (byte) 1, data[1].shortValue(), null);
|
||||
else
|
||||
} else {
|
||||
return particle;
|
||||
}
|
||||
|
||||
// Transform to new Item
|
||||
Via.getManager().getProtocolManager().getProtocol(Protocol1_13To1_12_2.class).getItemRewriter().handleItemToClient(item);
|
||||
|
||||
particle.getArguments().add(new Particle.ParticleData(Type.FLAT_ITEM, item)); // Item Slot The item that will be used.
|
||||
return particle;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Handle (id+(data<<12)) encoded blocks
|
||||
private static ParticleDataHandler blockHandler() {
|
||||
return new ParticleDataHandler() {
|
||||
@Override
|
||||
public Particle handler(Particle particle, Integer[] data) {
|
||||
return (particle, data) -> {
|
||||
int value = data[0];
|
||||
int combined = (((value & 4095) << 4) | (value >> 12 & 15));
|
||||
int newId = WorldPackets.toNewId(combined);
|
||||
|
||||
particle.getArguments().add(new Particle.ParticleData(Type.VAR_INT, newId)); // BlockState VarInt The ID of the block state.
|
||||
return particle;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
|
@ -173,7 +173,7 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter<Clientbound
|
||||
@Override
|
||||
protected void registerRewrites() {
|
||||
filter().handler((event, meta) -> meta.setMetaType(Types1_20_2.META_TYPES.byId(meta.metaType().typeId())));
|
||||
registerMetaTypeHandler(null, Types1_20_2.META_TYPES.blockStateType, Types1_20_2.META_TYPES.optionalBlockStateType, Types1_20_2.META_TYPES.particleType);
|
||||
registerMetaTypeHandler(Types1_20_2.META_TYPES.itemType, Types1_20_2.META_TYPES.blockStateType, Types1_20_2.META_TYPES.optionalBlockStateType, Types1_20_2.META_TYPES.particleType);
|
||||
|
||||
filter().filterFamily(Entity1_19_4Types.DISPLAY).addIndex(10);
|
||||
|
||||
|
@ -245,13 +245,10 @@ public class InventoryPackets {
|
||||
boolean throwItem = (slot == 45);
|
||||
if (throwItem) {
|
||||
// Send a packet wiping the slot
|
||||
wrapper.create(ClientboundPackets1_9.SET_SLOT, new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
wrapper.write(Type.UNSIGNED_BYTE, (short) 0);
|
||||
wrapper.write(Type.SHORT, slot);
|
||||
wrapper.write(Type.ITEM, null);
|
||||
}
|
||||
wrapper.create(ClientboundPackets1_9.SET_SLOT, w -> {
|
||||
w.write(Type.UNSIGNED_BYTE, (short) 0);
|
||||
w.write(Type.SHORT, slot);
|
||||
w.write(Type.ITEM, null);
|
||||
}).send(Protocol1_9To1_8.class);
|
||||
// Finally reset to simulate throwing item
|
||||
wrapper.set(Type.SHORT, 0, (short) -999); // Set slot to -999
|
||||
@ -303,13 +300,10 @@ public class InventoryPackets {
|
||||
|
||||
if (throwItem) {
|
||||
// Send a packet wiping the slot
|
||||
wrapper.create(ClientboundPackets1_9.SET_SLOT, new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
wrapper.write(Type.UNSIGNED_BYTE, (short) windowID);
|
||||
wrapper.write(Type.SHORT, slot);
|
||||
wrapper.write(Type.ITEM, null);
|
||||
}
|
||||
wrapper.create(ClientboundPackets1_9.SET_SLOT, w -> {
|
||||
w.write(Type.UNSIGNED_BYTE, windowID);
|
||||
w.write(Type.SHORT, slot);
|
||||
w.write(Type.ITEM, null);
|
||||
}).scheduleSend(Protocol1_9To1_8.class);
|
||||
// Finally reset to simulate throwing item
|
||||
wrapper.set(Type.BYTE, 0, (byte) 0); // Set button to 0
|
||||
|
@ -33,20 +33,16 @@ public class CommandBlockProvider implements Provider {
|
||||
|
||||
public void addOrUpdateBlock(UserConnection user, Position position, CompoundTag tag) throws Exception {
|
||||
checkPermission(user);
|
||||
if (isEnabled())
|
||||
getStorage(user).addOrUpdateBlock(position, tag);
|
||||
}
|
||||
|
||||
public Optional<CompoundTag> get(UserConnection user, Position position) throws Exception {
|
||||
checkPermission(user);
|
||||
if (isEnabled())
|
||||
return getStorage(user).getCommandBlock(position);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public void unloadChunk(UserConnection user, int x, int z) throws Exception {
|
||||
checkPermission(user);
|
||||
if (isEnabled())
|
||||
getStorage(user).unloadChunk(x, z);
|
||||
}
|
||||
|
||||
@ -55,8 +51,6 @@ public class CommandBlockProvider implements Provider {
|
||||
}
|
||||
|
||||
public void sendPermission(UserConnection user) throws Exception {
|
||||
if (!isEnabled())
|
||||
return;
|
||||
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_9.ENTITY_STATUS, null, user); // Entity status
|
||||
|
||||
EntityTracker1_9 tracker = user.getEntityTracker(Protocol1_9To1_8.class);
|
||||
@ -70,20 +64,13 @@ public class CommandBlockProvider implements Provider {
|
||||
|
||||
// Fix for Bungee since the join game is not sent after the first one
|
||||
private void checkPermission(UserConnection user) throws Exception {
|
||||
if (!isEnabled())
|
||||
return;
|
||||
CommandBlockStorage storage = getStorage(user);
|
||||
if (!storage.isPermissions()) {
|
||||
sendPermission(user);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void unloadChunks(UserConnection userConnection) {
|
||||
if (isEnabled())
|
||||
getStorage(userConnection).unloadChunks();
|
||||
}
|
||||
}
|
||||
|
@ -131,11 +131,6 @@ public final class TestPlatform implements ViaPlatform {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOldClientsAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlugin(final String name) {
|
||||
return false;
|
||||
|
@ -222,11 +222,6 @@ public class SpongePlugin implements ViaPlatform<Player> {
|
||||
return platformSpecific;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOldClientsAllowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlugin(final String name) {
|
||||
return game.pluginManager().plugin(name).isPresent();
|
||||
|
@ -230,11 +230,6 @@ public class VelocityPlugin implements ViaServerProxyPlatform<Player> {
|
||||
return extra;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOldClientsAllowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlugin(final String name) {
|
||||
return proxy.getPluginManager().getPlugin(name).isPresent();
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren