File size: 6,619 Bytes
d46f4a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package net.minecraft.server.commands;

import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.logging.LogUtils;
import java.io.IOException;
import javax.annotation.Nullable;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.chase.ChaseClient;
import net.minecraft.server.chase.ChaseServer;
import net.minecraft.world.level.Level;
import org.slf4j.Logger;

public class ChaseCommand {
    private static final Logger LOGGER = LogUtils.getLogger();
    private static final String DEFAULT_CONNECT_HOST = "localhost";
    private static final String DEFAULT_BIND_ADDRESS = "0.0.0.0";
    private static final int DEFAULT_PORT = 10000;
    private static final int BROADCAST_INTERVAL_MS = 100;
    public static BiMap<String, ResourceKey<Level>> DIMENSION_NAMES = ImmutableBiMap.of("o", Level.OVERWORLD, "n", Level.NETHER, "e", Level.END);
    @Nullable
    private static ChaseServer chaseServer;
    @Nullable
    private static ChaseClient chaseClient;

    public static void register(CommandDispatcher<CommandSourceStack> p_196078_) {
        p_196078_.register(
            Commands.literal("chase")
                .then(
                    Commands.literal("follow")
                        .then(
                            Commands.argument("host", StringArgumentType.string())
                                .executes(p_196104_ -> follow(p_196104_.getSource(), StringArgumentType.getString(p_196104_, "host"), 10000))
                                .then(
                                    Commands.argument("port", IntegerArgumentType.integer(1, 65535))
                                        .executes(
                                            p_196102_ -> follow(
                                                    p_196102_.getSource(),
                                                    StringArgumentType.getString(p_196102_, "host"),
                                                    IntegerArgumentType.getInteger(p_196102_, "port")
                                                )
                                        )
                                )
                        )
                        .executes(p_196100_ -> follow(p_196100_.getSource(), "localhost", 10000))
                )
                .then(
                    Commands.literal("lead")
                        .then(
                            Commands.argument("bind_address", StringArgumentType.string())
                                .executes(p_196098_ -> lead(p_196098_.getSource(), StringArgumentType.getString(p_196098_, "bind_address"), 10000))
                                .then(
                                    Commands.argument("port", IntegerArgumentType.integer(1024, 65535))
                                        .executes(
                                            p_196096_ -> lead(
                                                    p_196096_.getSource(),
                                                    StringArgumentType.getString(p_196096_, "bind_address"),
                                                    IntegerArgumentType.getInteger(p_196096_, "port")
                                                )
                                        )
                                )
                        )
                        .executes(p_196088_ -> lead(p_196088_.getSource(), "0.0.0.0", 10000))
                )
                .then(Commands.literal("stop").executes(p_196080_ -> stop(p_196080_.getSource())))
        );
    }

    private static int stop(CommandSourceStack p_196082_) {
        if (chaseClient != null) {
            chaseClient.stop();
            p_196082_.sendSuccess(() -> Component.literal("You have now stopped chasing"), false);
            chaseClient = null;
        }

        if (chaseServer != null) {
            chaseServer.stop();
            p_196082_.sendSuccess(() -> Component.literal("You are no longer being chased"), false);
            chaseServer = null;
        }

        return 0;
    }

    private static boolean alreadyRunning(CommandSourceStack p_196090_) {
        if (chaseServer != null) {
            p_196090_.sendFailure(Component.literal("Chase server is already running. Stop it using /chase stop"));
            return true;
        } else if (chaseClient != null) {
            p_196090_.sendFailure(Component.literal("You are already chasing someone. Stop it using /chase stop"));
            return true;
        } else {
            return false;
        }
    }

    private static int lead(CommandSourceStack p_196084_, String p_196085_, int p_196086_) {
        if (alreadyRunning(p_196084_)) {
            return 0;
        } else {
            chaseServer = new ChaseServer(p_196085_, p_196086_, p_196084_.getServer().getPlayerList(), 100);

            try {
                chaseServer.start();
                p_196084_.sendSuccess(
                    () -> Component.literal("Chase server is now running on port " + p_196086_ + ". Clients can follow you using /chase follow <ip> <port>"),
                    false
                );
            } catch (IOException ioexception) {
                LOGGER.error("Failed to start chase server", (Throwable)ioexception);
                p_196084_.sendFailure(Component.literal("Failed to start chase server on port " + p_196086_));
                chaseServer = null;
            }

            return 0;
        }
    }

    private static int follow(CommandSourceStack p_196092_, String p_196093_, int p_196094_) {
        if (alreadyRunning(p_196092_)) {
            return 0;
        } else {
            chaseClient = new ChaseClient(p_196093_, p_196094_, p_196092_.getServer());
            chaseClient.start();
            p_196092_.sendSuccess(
                () -> Component.literal(
                        "You are now chasing "
                            + p_196093_
                            + ":"
                            + p_196094_
                            + ". If that server does '/chase lead' then you will automatically go to the same position. Use '/chase stop' to stop chasing."
                    ),
                false
            );
            return 0;
        }
    }
}