turn fakeplayer from a command into a clickgui module
FakePlayer now lives under Misc: enabling spawns the dummy at your position with your equipment, disabling removes it, and it respawns itself after a world change. Settings replace the old subcommands - Name for its name, Swim for the swim pose (live-toggled), PopOnSpawn for the totem event. Drops the .fakeplayer/.fp command.
This commit is contained in:
@@ -1,142 +0,0 @@
|
||||
package cc.fros.features.commands.impl;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import cc.fros.features.commands.Command;
|
||||
import cc.fros.manager.CommandManager;
|
||||
import net.minecraft.client.player.RemotePlayer;
|
||||
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.Pose;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FakePlayerCommand extends Command {
|
||||
|
||||
private static final byte TOTEM_POP_EVENT_ID = 35;
|
||||
|
||||
private static final EquipmentSlot[] COPIED_SLOTS = {
|
||||
EquipmentSlot.MAINHAND, EquipmentSlot.OFFHAND,
|
||||
EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET
|
||||
};
|
||||
|
||||
private final List<RemotePlayer> spawned = new ArrayList<>();
|
||||
private int nextId = -13337;
|
||||
|
||||
public FakePlayerCommand() {
|
||||
super("fakeplayer", "fp");
|
||||
setDescription("Spawns a client-side fake player to test on");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createArgumentBuilder(LiteralArgumentBuilder<CommandManager> builder) {
|
||||
builder.executes(ctx -> spawn("FakePlayer"))
|
||||
.then(literal("remove")
|
||||
.executes(ctx -> removeAll()))
|
||||
.then(literal("pop")
|
||||
.executes(ctx -> popAll()))
|
||||
.then(literal("swim")
|
||||
.executes(ctx -> toggleSwim()))
|
||||
.then(argument("name", StringArgumentType.word())
|
||||
.executes(ctx -> spawn(StringArgumentType.getString(ctx, "name"))));
|
||||
}
|
||||
|
||||
private int popAll() {
|
||||
if (nullCheck() || mc.getConnection() == null) {
|
||||
return fail("You need to be in a world to do that.");
|
||||
}
|
||||
|
||||
int popped = 0;
|
||||
for (RemotePlayer fake : spawned) {
|
||||
if (fake.level() != mc.level) continue;
|
||||
mc.getConnection().handleEntityEvent(new ClientboundEntityEventPacket(fake, TOTEM_POP_EVENT_ID));
|
||||
popped++;
|
||||
}
|
||||
|
||||
if (popped == 0) {
|
||||
return fail("No fake players to pop. Spawn one first.");
|
||||
}
|
||||
return success("Popped %s fake player(s)", popped);
|
||||
}
|
||||
|
||||
private int toggleSwim() {
|
||||
if (nullCheck()) {
|
||||
return fail("You need to be in a world to do that.");
|
||||
}
|
||||
|
||||
boolean anyStanding = false;
|
||||
int found = 0;
|
||||
for (RemotePlayer fake : spawned) {
|
||||
if (fake.level() != mc.level) continue;
|
||||
found++;
|
||||
if (fake.getPose() != Pose.SWIMMING) anyStanding = true;
|
||||
}
|
||||
if (found == 0) {
|
||||
return fail("No fake players. Spawn one first.");
|
||||
}
|
||||
|
||||
Pose pose = anyStanding ? Pose.SWIMMING : Pose.STANDING;
|
||||
for (RemotePlayer fake : spawned) {
|
||||
if (fake.level() != mc.level) continue;
|
||||
fake.setPose(pose);
|
||||
fake.refreshDimensions();
|
||||
}
|
||||
return success(pose == Pose.SWIMMING
|
||||
? "Fake player(s) now in swim pose."
|
||||
: "Fake player(s) now standing.");
|
||||
}
|
||||
|
||||
private int spawn(String name) {
|
||||
if (nullCheck()) {
|
||||
return fail("You need to be in a world to do that.");
|
||||
}
|
||||
|
||||
int despawned = despawnAll();
|
||||
|
||||
GameProfile profile = new GameProfile(UUID.randomUUID(), name);
|
||||
RemotePlayer fake = new RemotePlayer(mc.level, profile);
|
||||
fake.setId(nextId--);
|
||||
fake.copyPosition(mc.player);
|
||||
fake.setYHeadRot(mc.player.getYHeadRot());
|
||||
fake.setHealth(20f);
|
||||
for (EquipmentSlot slot : COPIED_SLOTS) {
|
||||
fake.setItemSlot(slot, mc.player.getItemBySlot(slot).copy());
|
||||
}
|
||||
mc.level.addEntity(fake);
|
||||
spawned.add(fake);
|
||||
if (despawned > 0) {
|
||||
return success("Replaced fake player with {green} %s", name);
|
||||
}
|
||||
return success("Spawned fake player {green} %s", name);
|
||||
}
|
||||
|
||||
private int removeAll() {
|
||||
if (nullCheck()) {
|
||||
spawned.clear();
|
||||
return fail("You need to be in a world to do that.");
|
||||
}
|
||||
int removed = despawnAll();
|
||||
if (removed == 0) {
|
||||
return success("No fake players to remove.");
|
||||
}
|
||||
return success("Removed %s fake player(s)", removed);
|
||||
}
|
||||
|
||||
private int despawnAll() {
|
||||
int removed = 0;
|
||||
Iterator<RemotePlayer> it = spawned.iterator();
|
||||
while (it.hasNext()) {
|
||||
RemotePlayer fake = it.next();
|
||||
it.remove();
|
||||
if (fake.level() != mc.level) continue;
|
||||
mc.level.removeEntity(fake.getId(), Entity.RemovalReason.DISCARDED);
|
||||
removed++;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package cc.fros.features.modules.misc;
|
||||
|
||||
import cc.fros.features.modules.Module;
|
||||
import cc.fros.features.settings.Setting;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.client.player.RemotePlayer;
|
||||
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.Pose;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class FakePlayerModule extends Module {
|
||||
|
||||
private static final byte TOTEM_POP_EVENT_ID = 35;
|
||||
|
||||
private static final EquipmentSlot[] COPIED_SLOTS = {
|
||||
EquipmentSlot.MAINHAND, EquipmentSlot.OFFHAND,
|
||||
EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET
|
||||
};
|
||||
|
||||
private final Setting<String> name = str("Name", "FakePlayer");
|
||||
private final Setting<Boolean> swim = bool("Swim", false);
|
||||
private final Setting<Boolean> popOnSpawn = bool("PopOnSpawn", false);
|
||||
|
||||
private RemotePlayer fake;
|
||||
private int nextId = -13337;
|
||||
|
||||
public FakePlayerModule() {
|
||||
super("FakePlayer", "Spawns a client-side fake player to test on", Category.MISC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
spawn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
despawn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick() {
|
||||
if (nullCheck()) return;
|
||||
|
||||
// respawn after a world change or if anything removed it
|
||||
if (fake == null || fake.level() != mc.level || fake.isRemoved()) {
|
||||
spawn();
|
||||
return;
|
||||
}
|
||||
|
||||
// keep the pose in sync with the setting
|
||||
Pose desired = swim.getValue() ? Pose.SWIMMING : Pose.STANDING;
|
||||
if (fake.getPose() != desired) {
|
||||
fake.setPose(desired);
|
||||
fake.refreshDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
private void spawn() {
|
||||
if (nullCheck()) return;
|
||||
|
||||
despawn();
|
||||
|
||||
GameProfile profile = new GameProfile(UUID.randomUUID(), name.getValue());
|
||||
fake = new RemotePlayer(mc.level, profile);
|
||||
fake.setId(nextId--);
|
||||
fake.copyPosition(mc.player);
|
||||
fake.setYHeadRot(mc.player.getYHeadRot());
|
||||
fake.setHealth(20f);
|
||||
for (EquipmentSlot slot : COPIED_SLOTS) {
|
||||
fake.setItemSlot(slot, mc.player.getItemBySlot(slot).copy());
|
||||
}
|
||||
if (swim.getValue()) {
|
||||
fake.setPose(Pose.SWIMMING);
|
||||
fake.refreshDimensions();
|
||||
}
|
||||
mc.level.addEntity(fake);
|
||||
|
||||
if (popOnSpawn.getValue() && mc.getConnection() != null) {
|
||||
mc.getConnection().handleEntityEvent(new ClientboundEntityEventPacket(fake, TOTEM_POP_EVENT_ID));
|
||||
}
|
||||
}
|
||||
|
||||
private void despawn() {
|
||||
if (fake == null) return;
|
||||
if (mc.level != null && fake.level() == mc.level) {
|
||||
mc.level.removeEntity(fake.getId(), Entity.RemovalReason.DISCARDED);
|
||||
}
|
||||
fake = null;
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,6 @@ public class CommandManager extends Feature implements Jsonable {
|
||||
public void init() {
|
||||
register(new BindCommand());
|
||||
register(new DrawnCommand());
|
||||
register(new FakePlayerCommand());
|
||||
register(new FriendCommand());
|
||||
register(new HelpCommand());
|
||||
register(new PrefixCommand());
|
||||
|
||||
@@ -29,6 +29,7 @@ import cc.fros.features.modules.hud.RadarHudModule;
|
||||
import cc.fros.features.modules.hud.TimeHudModule;
|
||||
import cc.fros.features.modules.hud.WelcomerHudModule;
|
||||
import cc.fros.features.modules.hud.WatermarkHudModule;
|
||||
import cc.fros.features.modules.misc.FakePlayerModule;
|
||||
import cc.fros.features.modules.misc.MCFModule;
|
||||
import cc.fros.features.modules.movement.FastAccelModule;
|
||||
import cc.fros.features.modules.movement.ReverseStepModule;
|
||||
@@ -70,6 +71,7 @@ public class ModuleManager implements Jsonable, Util {
|
||||
register(new NotificationsModule());
|
||||
register(new CriticalsModule());
|
||||
register(new MCFModule());
|
||||
register(new FakePlayerModule());
|
||||
register(new StepModule());
|
||||
register(new ReverseStepModule());
|
||||
register(new FastPlaceModule());
|
||||
|
||||
Reference in New Issue
Block a user