Fix missing method sendParticle, implement ServerListPingEvent
This commit is contained in:
parent
4478a24913
commit
1ed82a216c
|
@ -0,0 +1,133 @@
|
|||
package io.izzel.arclight.common.mixin.core.network.status;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.network.IPacket;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.ServerStatusResponse;
|
||||
import net.minecraft.network.status.ServerStatusNetHandler;
|
||||
import net.minecraft.network.status.server.SServerInfoPacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.SharedConstants;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v.CraftServer;
|
||||
import org.bukkit.craftbukkit.v.util.CraftIconCache;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.CachedServerIcon;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spigotmc.SpigotConfig;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
@Mixin(ServerStatusNetHandler.class)
|
||||
public class ServerStatusNetHandlerMixin {
|
||||
|
||||
@Shadow @Final private MinecraftServer server;
|
||||
|
||||
@Redirect(method = "processServerQuery", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;sendPacket(Lnet/minecraft/network/IPacket;)V"))
|
||||
private void arclight$handleServerPing(NetworkManager networkManager, IPacket<?> packetIn) {
|
||||
Object[] players = this.server.getPlayerList().players.toArray();
|
||||
class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent {
|
||||
|
||||
CraftIconCache icon;
|
||||
|
||||
ServerListPingEvent() {
|
||||
super(((InetSocketAddress) networkManager.getRemoteAddress()).getAddress(), server.getMOTD(), server.getPlayerList().getMaxPlayers());
|
||||
this.icon = ((CraftServer) Bukkit.getServer()).getServerIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServerIcon(CachedServerIcon icon) {
|
||||
if (!(icon instanceof CraftIconCache)) {
|
||||
throw new IllegalArgumentException(icon + " was not created by " + CraftServer.class);
|
||||
}
|
||||
this.icon = (CraftIconCache) icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Iterator<Player> iterator() throws UnsupportedOperationException {
|
||||
class Itr implements Iterator<Player> {
|
||||
|
||||
int i;
|
||||
int ret = Integer.MIN_VALUE;
|
||||
ServerPlayerEntity player;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (this.player != null) {
|
||||
return true;
|
||||
}
|
||||
Object[] currentPlayers = players;
|
||||
for (int length = currentPlayers.length, i = this.i; i < length; ++i) {
|
||||
ServerPlayerEntity player = (ServerPlayerEntity) currentPlayers[i];
|
||||
if (player != null) {
|
||||
this.i = i + 1;
|
||||
this.player = player;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player next() {
|
||||
if (!this.hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
ServerPlayerEntity player = this.player;
|
||||
this.player = null;
|
||||
this.ret = this.i - 1;
|
||||
return ((ServerPlayerEntityBridge) player).bridge$getBukkitEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
Object[] currentPlayers = players;
|
||||
int i = this.ret;
|
||||
if (i < 0 || currentPlayers[i] == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
currentPlayers[i] = null;
|
||||
}
|
||||
}
|
||||
return new Itr();
|
||||
}
|
||||
}
|
||||
ServerListPingEvent event = new ServerListPingEvent();
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
List<GameProfile> profiles = new ArrayList<>(players.length);
|
||||
Object[] array;
|
||||
for (int length = (array = players).length, i = 0; i < length; ++i) {
|
||||
Object player = array[i];
|
||||
if (player != null) {
|
||||
profiles.add(((ServerPlayerEntity) player).getGameProfile());
|
||||
}
|
||||
}
|
||||
ServerStatusResponse.Players playerSample = new ServerStatusResponse.Players(event.getMaxPlayers(), profiles.size());
|
||||
if (!profiles.isEmpty()) {
|
||||
Collections.shuffle(profiles);
|
||||
profiles = profiles.subList(0, Math.min(profiles.size(), SpigotConfig.playerSample));
|
||||
}
|
||||
playerSample.setPlayers(profiles.toArray(new GameProfile[0]));
|
||||
ServerStatusResponse ping = new ServerStatusResponse();
|
||||
ping.setFavicon(event.icon.value);
|
||||
ping.setServerDescription(new StringTextComponent(event.getMotd()));
|
||||
ping.setPlayers(playerSample);
|
||||
int version = SharedConstants.getVersion().getProtocolVersion();
|
||||
ping.setVersion(new ServerStatusResponse.Version(this.server.getServerModName() + " " + this.server.getMinecraftVersion(), version));
|
||||
networkManager.sendPacket(new SServerInfoPacket(ping));
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.server;
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.izzel.arclight.common.bridge.entity.EntityBridge;
|
||||
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
|
||||
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
|
||||
import io.izzel.arclight.common.bridge.world.ExplosionBridge;
|
||||
import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge;
|
||||
|
@ -16,6 +17,7 @@ import net.minecraft.entity.effect.LightningBoltEntity;
|
|||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.network.IPacket;
|
||||
import net.minecraft.network.play.server.SSpawnParticlePacket;
|
||||
import net.minecraft.particles.IParticleData;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
@ -44,6 +46,7 @@ import org.bukkit.event.server.MapInitializeEvent;
|
|||
import org.bukkit.event.weather.LightningStrikeEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Implements;
|
||||
import org.spongepowered.asm.mixin.Interface;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
@ -58,6 +61,7 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Level;
|
||||
|
@ -73,6 +77,7 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
|
|||
@Shadow public abstract <T extends IParticleData> int spawnParticle(T type, double posX, double posY, double posZ, int particleCount, double xOffset, double yOffset, double zOffset, double speed);
|
||||
@Shadow protected abstract boolean sendPacketWithinDistance(ServerPlayerEntity player, boolean longDistance, double posX, double posY, double posZ, IPacket<?> packet);
|
||||
@Shadow @Nonnull public abstract MinecraftServer shadow$getServer();
|
||||
@Shadow @Final private List<ServerPlayerEntity> players;
|
||||
// @formatter:on
|
||||
|
||||
public void arclight$constructor(MinecraftServer serverIn, Executor executor, SaveHandler saveHandler, WorldInfo worldInfo, DimensionType dimType, IProfiler profiler, IChunkStatusListener listener) {
|
||||
|
@ -86,6 +91,19 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
|
|||
bridge$getWorld();
|
||||
}
|
||||
|
||||
public <T extends IParticleData> int sendParticles(final ServerPlayerEntity sender, final T t0, final double d0, final double d1, final double d2, final int i, final double d3, final double d4, final double d5, final double d6, final boolean force) {
|
||||
SSpawnParticlePacket packet = new SSpawnParticlePacket((T) t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i);
|
||||
int j = 0;
|
||||
for (ServerPlayerEntity entity : this.players) {
|
||||
if (sender == null || ((ServerPlayerEntityBridge) entity).bridge$getBukkitEntity().canSee(((ServerPlayerEntityBridge) sender).bridge$getBukkitEntity())) {
|
||||
if (this.sendPacketWithinDistance(entity, force, d0, d1, d2, packet)) {
|
||||
++j;
|
||||
}
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
@Inject(method = "onEntityAdded", at = @At("RETURN"))
|
||||
private void arclight$validEntity(Entity entityIn, CallbackInfo ci) {
|
||||
((EntityBridge) entityIn).bridge$setValid(true);
|
||||
|
|
|
@ -298,6 +298,7 @@
|
|||
"network.play.server.SChatPacketMixin",
|
||||
"network.play.server.SWorldBorderPacketMixin",
|
||||
"network.rcon.RConConsoleSourceMixin",
|
||||
"network.status.ServerStatusNetHandlerMixin",
|
||||
"potion.EffectMixin",
|
||||
"server.CustomServerBossInfoMixin",
|
||||
"server.MinecraftServerMixin",
|
||||
|
|
Loading…
Reference in New Issue
Block a user