megabroke
This commit is contained in:
1 parent
ec66779474
commit
a28f7be625
20 files changed
+2242
-3
No files matched your search
@@ -7,10 +7,10 @@ import carpet.commands.CameraModeCommand;
|
||||
import carpet.commands.DrawCommand;
|
||||
//import carpet.commands.ScriptCommand;
|
||||
//import carpet.commands.InfoCommand;
|
||||
//import carpet.commands.LogCommand;
|
||||
//import carpet.commands.PerimeterInfoCommand;
|
||||
//import carpet.commands.PlayerCommand;
|
||||
//import carpet.commands.SpawnCommand;
|
||||
import carpet.commands.LogCommand;
|
||||
import carpet.commands.TestCommand;
|
||||
//import carpet.commands.TickCommand;
|
||||
//import carpet.logging.LoggerRegistry;
|
||||
@@ -53,7 +53,7 @@ public class CarpetServer // static for now - easier to handle all around the co
|
||||
//CarpetCommand.register(dispatcher);
|
||||
//TickCommand.register(dispatcher);
|
||||
//CounterCommand.register(dispatcher);
|
||||
//LogCommand.register(dispatcher);
|
||||
LogCommand.register(dispatcher);
|
||||
//SpawnCommand.register(dispatcher);
|
||||
//PlayerCommand.register(dispatcher);
|
||||
CameraModeCommand.register(dispatcher);
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
package carpet.commands;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.logging.Logger;
|
||||
import carpet.logging.LoggerRegistry;
|
||||
import carpet.utils.Messenger;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import static net.minecraft.server.command.CommandSource.suggestMatching;
|
||||
|
||||
public class LogCommand
|
||||
{
|
||||
public static void register(CommandDispatcher<ServerCommandSource> dispatcher)
|
||||
{
|
||||
LiteralArgumentBuilder<ServerCommandSource> literalargumentbuilder = CommandManager.literal("log").
|
||||
requires((player) -> CarpetSettings.getBool("commandLog")).
|
||||
executes((context) -> listLogs(context.getSource())).
|
||||
then(CommandManager.literal("clear").
|
||||
executes( (c) -> unsubFromAll(c.getSource(), c.getSource().getName())).
|
||||
then(CommandManager.argument("player", StringArgumentType.word()).
|
||||
suggests( (c, b)-> suggestMatching(c.getSource().getPlayerNames(),b)).
|
||||
executes( (c) -> unsubFromAll(c.getSource(), getString(c, "player")))));
|
||||
|
||||
literalargumentbuilder.then(CommandManager.argument("log name",StringArgumentType.word()).
|
||||
suggests( (c, b)-> suggestMatching(LoggerRegistry.getLoggerNames(),b)).
|
||||
executes( (c)-> toggleSubscription(c.getSource(), c.getSource().getName(), getString(c, "log name"))).
|
||||
then(CommandManager.literal("clear").
|
||||
executes( (c) -> unsubFromLogger(
|
||||
c.getSource(),
|
||||
c.getSource().getName(),
|
||||
getString(c, "log name")))).
|
||||
then(CommandManager.argument("option", StringArgumentType.word()).
|
||||
suggests( (c, b) -> suggestMatching(
|
||||
(LoggerRegistry.getLogger(getString(c, "log name"))==null
|
||||
?new String[]{}
|
||||
:LoggerRegistry.getLogger(getString(c, "log name")).getOptions()),
|
||||
b)).
|
||||
executes( (c) -> subscribePlayer(
|
||||
c.getSource(),
|
||||
c.getSource().getName(),
|
||||
getString(c, "log name"),
|
||||
getString(c, "option"))).
|
||||
then(CommandManager.argument("player", StringArgumentType.word()).
|
||||
suggests( (c, b) -> suggestMatching(c.getSource().getPlayerNames(),b)).
|
||||
executes( (c) -> subscribePlayer(
|
||||
c.getSource(),
|
||||
getString(c, "player"),
|
||||
getString(c, "log name"),
|
||||
getString(c, "option"))))));
|
||||
|
||||
dispatcher.register(literalargumentbuilder);
|
||||
}
|
||||
private static int listLogs(ServerCommandSource source)
|
||||
{
|
||||
PlayerEntity player;
|
||||
try
|
||||
{
|
||||
player = source.getPlayer();
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
Messenger.m(source, "For players only");
|
||||
return 0;
|
||||
}
|
||||
Map<String,String> subs = LoggerRegistry.getPlayerSubscriptions(source.getName());
|
||||
if (subs == null)
|
||||
{
|
||||
subs = new HashMap<>();
|
||||
}
|
||||
List<String> all_logs = new ArrayList<>(LoggerRegistry.getLoggerNames());
|
||||
Collections.sort(all_logs);
|
||||
Messenger.m(player, "w _____________________");
|
||||
Messenger.m(player, "w Available logging options:");
|
||||
for (String lname: all_logs)
|
||||
{
|
||||
List<Object> comp = new ArrayList<>();
|
||||
String color = subs.containsKey(lname)?"w":"g";
|
||||
comp.add("w - "+lname+": ");
|
||||
Logger logger = LoggerRegistry.getLogger(lname);
|
||||
String [] options = logger.getOptions();
|
||||
if (options.length == 0)
|
||||
{
|
||||
if (subs.containsKey(lname))
|
||||
{
|
||||
comp.add("l Subscribed ");
|
||||
}
|
||||
else
|
||||
{
|
||||
comp.add(color + " [Subscribe] ");
|
||||
comp.add("^w subscribe to " + lname);
|
||||
comp.add("!/log " + lname);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (String option : logger.getOptions())
|
||||
{
|
||||
if (subs.containsKey(lname) && subs.get(lname).equalsIgnoreCase(option))
|
||||
{
|
||||
comp.add("l [" + option + "] ");
|
||||
} else
|
||||
{
|
||||
comp.add(color + " [" + option + "] ");
|
||||
comp.add("^w subscribe to " + lname + " " + option);
|
||||
comp.add("!/log " + lname + " " + option);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (subs.containsKey(lname))
|
||||
{
|
||||
comp.add("nb [X]");
|
||||
comp.add("^w Click to unsubscribe");
|
||||
comp.add("!/log "+lname);
|
||||
}
|
||||
Messenger.m(player,comp.toArray(new Object[0]));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
private static int unsubFromAll(ServerCommandSource source, String player_name)
|
||||
{
|
||||
PlayerEntity player = source.getMinecraftServer().getPlayerManager().getPlayer(player_name);
|
||||
if (player == null)
|
||||
{
|
||||
Messenger.m(source, "r No player specified");
|
||||
return 0;
|
||||
}
|
||||
for (String logname : LoggerRegistry.getLoggerNames())
|
||||
{
|
||||
LoggerRegistry.unsubscribePlayer(player_name, logname);
|
||||
}
|
||||
Messenger.m(source, "gi Unsubscribed from all logs");
|
||||
return 1;
|
||||
}
|
||||
private static int unsubFromLogger(ServerCommandSource source, String player_name, String logname)
|
||||
{
|
||||
PlayerEntity player = source.getMinecraftServer().getPlayerManager().getPlayer(player_name);
|
||||
if (player == null)
|
||||
{
|
||||
Messenger.m(source, "r No player specified");
|
||||
return 0;
|
||||
}
|
||||
if (LoggerRegistry.getLogger(logname) == null)
|
||||
{
|
||||
Messenger.m(source, "r Unknown logger: ","rb "+logname);
|
||||
return 0;
|
||||
}
|
||||
LoggerRegistry.unsubscribePlayer(player_name, logname);
|
||||
Messenger.m(source, "gi Unsubscribed from "+logname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int toggleSubscription(ServerCommandSource source, String player_name, String logName)
|
||||
{
|
||||
PlayerEntity player = source.getMinecraftServer().getPlayerManager().getPlayer(player_name);
|
||||
if (player == null)
|
||||
{
|
||||
Messenger.m(source, "r No player specified");
|
||||
return 0;
|
||||
}
|
||||
if (LoggerRegistry.getLogger(logName) == null)
|
||||
{
|
||||
Messenger.m(source, "r Unknown logger: ","rb "+logName);
|
||||
return 0;
|
||||
}
|
||||
boolean subscribed = LoggerRegistry.togglePlayerSubscription(player_name, logName);
|
||||
if (subscribed)
|
||||
{
|
||||
Messenger.m(source, "gi "+player_name+" subscribed to " + logName + ".");
|
||||
}
|
||||
else
|
||||
{
|
||||
Messenger.m(source, "gi "+player_name+" unsubscribed from " + logName + ".");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
private static int subscribePlayer(ServerCommandSource source, String player_name, String logname, String option)
|
||||
{
|
||||
PlayerEntity player = source.getMinecraftServer().getPlayerManager().getPlayer(player_name);
|
||||
if (player == null)
|
||||
{
|
||||
Messenger.m(source, "r No player specified");
|
||||
return 0;
|
||||
}
|
||||
if (LoggerRegistry.getLogger(logname) == null)
|
||||
{
|
||||
Messenger.m(source, "r Unknown logger: ","rb "+logname);
|
||||
return 0;
|
||||
}
|
||||
LoggerRegistry.subscribePlayer(player_name, logname, option);
|
||||
if (option!=null)
|
||||
{
|
||||
Messenger.m(source, "gi Subscribed to " + logname + "(" + option + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
Messenger.m(source, "gi Subscribed to " + logname);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package carpet.helpers;
|
||||
|
||||
import carpet.utils.Messenger;
|
||||
import com.google.common.collect.Maps;
|
||||
import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2LongMap;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class HopperCounter
|
||||
{
|
||||
public static final Map<DyeColor, HopperCounter> COUNTERS;
|
||||
|
||||
static
|
||||
{
|
||||
EnumMap<DyeColor, HopperCounter> counterMap = new EnumMap<>(DyeColor.class);
|
||||
for (DyeColor color : DyeColor.values())
|
||||
{
|
||||
counterMap.put(color, new HopperCounter(color));
|
||||
}
|
||||
COUNTERS = Maps.immutableEnumMap(counterMap);
|
||||
}
|
||||
|
||||
public final DyeColor color;
|
||||
private final Object2LongMap<Item> counter = new Object2LongLinkedOpenHashMap<>();
|
||||
private long startTick;
|
||||
private long startMillis;
|
||||
// private PubSubInfoProvider<Long> pubSubProvider;
|
||||
|
||||
private HopperCounter(DyeColor color)
|
||||
{
|
||||
this.color = color;
|
||||
// pubSubProvider = new PubSubInfoProvider<>(QuickCarpet.PUBSUB, "carpet.counter." + color.getName(), 0, this::getTotalItems);
|
||||
}
|
||||
|
||||
public void add(MinecraftServer server, ItemStack stack)
|
||||
{
|
||||
if (startTick == 0)
|
||||
{
|
||||
startTick = server.getTicks();
|
||||
startMillis = System.currentTimeMillis();
|
||||
}
|
||||
Item item = stack.getItem();
|
||||
counter.put(item, counter.getLong(item) + stack.getAmount());
|
||||
// pubSubProvider.publish();
|
||||
}
|
||||
|
||||
public void reset(MinecraftServer server)
|
||||
{
|
||||
counter.clear();
|
||||
startTick = server.getTicks();
|
||||
startMillis = System.currentTimeMillis();
|
||||
// pubSubProvider.publish();
|
||||
}
|
||||
|
||||
public static void resetAll(MinecraftServer server)
|
||||
{
|
||||
for (HopperCounter counter : COUNTERS.values())
|
||||
{
|
||||
counter.reset(server);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<BaseComponent> formatAll(MinecraftServer server, boolean realtime)
|
||||
{
|
||||
List<BaseComponent> text = new ArrayList<>();
|
||||
|
||||
for (HopperCounter counter : COUNTERS.values())
|
||||
{
|
||||
List<BaseComponent> temp = counter.format(server, realtime, false);
|
||||
if (temp.size() > 1)
|
||||
{
|
||||
if (!text.isEmpty()) text.add(Messenger.s(""));
|
||||
text.addAll(temp);
|
||||
}
|
||||
}
|
||||
if (text.isEmpty())
|
||||
{
|
||||
text.add(Messenger.s("No items have been counted yet."));
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public List<BaseComponent> format(MinecraftServer server, boolean realTime, boolean brief)
|
||||
{
|
||||
if (counter.isEmpty())
|
||||
{
|
||||
if (brief)
|
||||
{
|
||||
return Collections.singletonList(Messenger.c("g "+color+": -, -/h, - min "));
|
||||
}
|
||||
return Collections.singletonList(Messenger.s(String.format("No items for %s yet", color.getName())));
|
||||
}
|
||||
long total = getTotalItems();
|
||||
long ticks = Math.max(realTime ? (System.currentTimeMillis() - startMillis) / 50 : server.getTicks() - startTick, 1);
|
||||
if (total == 0)
|
||||
{
|
||||
if (brief)
|
||||
{
|
||||
return Collections.singletonList(Messenger.c(String.format("c %s: 0, 0/h, %.1f min ", color, ticks / (20.0 * 60.0))));
|
||||
}
|
||||
return Collections.singletonList(Messenger.c(String.format("w No items for %s yet (%.2f min.%s)",
|
||||
color.getName(), ticks / (20.0 * 60.0), (realTime ? " - real time" : "")),
|
||||
"nb [X]", "^g reset", "!/counter " + color.getName() +" reset"));
|
||||
}
|
||||
if (brief)
|
||||
{
|
||||
return Collections.singletonList(Messenger.c(String.format("c %s: %d, %d/h, %.1f min ",
|
||||
color.getName(), total, total * (20 * 60 * 60) / ticks, ticks / (20.0 * 60.0))));
|
||||
}
|
||||
List<BaseComponent> items = new ArrayList<>();
|
||||
items.add(Messenger.c(String.format("w Items for %s (%.2f min.%s), total: %d, (%.1f/h):",
|
||||
color, ticks*1.0/(20*60), (realTime?" - real time":""), total, total*1.0*(20*60*60)/ticks),
|
||||
"nb [X]", "^g reset", "!/counter "+color+" reset"
|
||||
));
|
||||
items.addAll(counter.object2LongEntrySet().stream().map(e ->
|
||||
{
|
||||
BaseComponent itemName = new TranslatableComponent(e.getKey().getTranslationKey());
|
||||
long count = e.getLongValue();
|
||||
return Messenger.c("w - ", itemName, String.format("w : %d, %.1f/h",
|
||||
count,
|
||||
count * (20.0 * 60.0 * 60.0) / ticks));
|
||||
}).collect(Collectors.toList()));
|
||||
return items;
|
||||
}
|
||||
|
||||
public static HopperCounter getCounter(String color)
|
||||
{
|
||||
try
|
||||
{
|
||||
DyeColor colorEnum = DyeColor.valueOf(color.toUpperCase(Locale.ROOT));
|
||||
return COUNTERS.get(colorEnum);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public long getTotalItems()
|
||||
{
|
||||
return counter.values().stream().mapToLong(Long::longValue).sum();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package carpet.helpers;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.utils.Messenger;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
|
||||
public class TickSpeed
|
||||
{
|
||||
public static final int PLAYER_GRACE = 2;
|
||||
public static float tickrate = 20.0f;
|
||||
public static long mspt = 50l;
|
||||
public static long time_bias = 0;
|
||||
public static long time_warp_start_time = 0;
|
||||
public static long time_warp_scheduled_ticks = 0;
|
||||
public static PlayerEntity time_advancerer = null;
|
||||
public static String tick_warp_callback = null;
|
||||
public static ServerCommandSource tick_warp_sender = null;
|
||||
public static int player_active_timeout = 0;
|
||||
public static boolean process_entities = true;
|
||||
public static boolean is_paused = false;
|
||||
public static boolean is_superHot = false;
|
||||
|
||||
public static void reset_player_active_timeout()
|
||||
{
|
||||
if (player_active_timeout < PLAYER_GRACE)
|
||||
{
|
||||
player_active_timeout = PLAYER_GRACE;
|
||||
}
|
||||
}
|
||||
|
||||
public static void add_ticks_to_run_in_pause(int ticks)
|
||||
{
|
||||
player_active_timeout = PLAYER_GRACE+ticks;
|
||||
}
|
||||
|
||||
public static void tickrate(float rate)
|
||||
{
|
||||
tickrate = rate;
|
||||
mspt = (long)(1000.0/tickrate);
|
||||
if (mspt <=0)
|
||||
{
|
||||
mspt = 1l;
|
||||
tickrate = 1000.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static BaseComponent tickrate_advance(PlayerEntity player, int advance, String callback, ServerCommandSource source)
|
||||
{
|
||||
if (0 == advance)
|
||||
{
|
||||
tick_warp_callback = null;
|
||||
tick_warp_sender = null;
|
||||
finish_time_warp();
|
||||
return Messenger.c("gi Warp interrupted");
|
||||
}
|
||||
if (time_bias > 0)
|
||||
{
|
||||
return Messenger.c("l Another player is already advancing time at the moment. Try later or talk to them");
|
||||
}
|
||||
time_advancerer = player;
|
||||
time_warp_start_time = System.nanoTime();
|
||||
time_warp_scheduled_ticks = advance;
|
||||
time_bias = advance;
|
||||
tick_warp_callback = callback;
|
||||
tick_warp_sender = source;
|
||||
return Messenger.c("gi Warp speed ....");
|
||||
}
|
||||
|
||||
public static void finish_time_warp()
|
||||
{
|
||||
|
||||
long completed_ticks = time_warp_scheduled_ticks - time_bias;
|
||||
double milis_to_complete = System.nanoTime()-time_warp_start_time;
|
||||
if (milis_to_complete == 0.0)
|
||||
{
|
||||
milis_to_complete = 1.0;
|
||||
}
|
||||
milis_to_complete /= 1000000.0;
|
||||
int tps = (int) (1000.0D*completed_ticks/milis_to_complete);
|
||||
double mspt = (1.0*milis_to_complete)/completed_ticks;
|
||||
time_warp_scheduled_ticks = 0;
|
||||
time_warp_start_time = 0;
|
||||
if (tick_warp_callback != null)
|
||||
{
|
||||
CommandManager icommandmanager = tick_warp_sender.getMinecraftServer().getCommandManager();
|
||||
try
|
||||
{
|
||||
int j = icommandmanager.execute(tick_warp_sender, tick_warp_callback);
|
||||
|
||||
if (j < 1)
|
||||
{
|
||||
if (time_advancerer != null)
|
||||
{
|
||||
Messenger.m(time_advancerer, "r Command Callback failed: ", "rb /"+tick_warp_callback,"/"+tick_warp_callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable var23)
|
||||
{
|
||||
if (time_advancerer != null)
|
||||
{
|
||||
Messenger.m(time_advancerer, "r Command Callback failed - unknown error: ", "rb /"+tick_warp_callback,"/"+tick_warp_callback);
|
||||
}
|
||||
}
|
||||
tick_warp_callback = null;
|
||||
tick_warp_sender = null;
|
||||
}
|
||||
if (time_advancerer != null)
|
||||
{
|
||||
Messenger.m(time_advancerer, String.format("gi ... Time warp completed with %d tps, or %.2f mspt",tps, mspt ));
|
||||
time_advancerer = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Messenger.print_server_message(CarpetServer.minecraft_server, String.format("... Time warp completed with %d tps, or %.2f mspt",tps, mspt ));
|
||||
}
|
||||
time_bias = 0;
|
||||
|
||||
}
|
||||
|
||||
public static boolean continueWarp()
|
||||
{
|
||||
if (time_bias > 0)
|
||||
{
|
||||
if (time_bias == time_warp_scheduled_ticks) //first call after previous tick, adjust start time
|
||||
{
|
||||
time_warp_start_time = System.nanoTime();
|
||||
}
|
||||
time_bias -= 1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
finish_time_warp();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void tick(MinecraftServer server)
|
||||
{
|
||||
process_entities = true;
|
||||
if (player_active_timeout > 0)
|
||||
{
|
||||
player_active_timeout--;
|
||||
}
|
||||
if (is_paused)
|
||||
{
|
||||
if (player_active_timeout < PLAYER_GRACE)
|
||||
{
|
||||
process_entities = false;
|
||||
}
|
||||
}
|
||||
else if (is_superHot)
|
||||
{
|
||||
if (player_active_timeout <= 0)
|
||||
{
|
||||
process_entities = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package carpet.logging;
|
||||
|
||||
import carpet.utils.HUDController;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
|
||||
public class HUDLogger extends Logger
|
||||
{
|
||||
public HUDLogger(String logName, String def, String[] options)
|
||||
{
|
||||
super(logName, def, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlayer(String playerName)
|
||||
{
|
||||
PlayerEntity player = playerFromName(playerName);
|
||||
if (player != null) HUDController.clear_player(player);
|
||||
super.removePlayer(playerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPlayerMessage(PlayerEntity player, BaseComponent... messages)
|
||||
{
|
||||
for (BaseComponent m:messages) HUDController.addMessage(player, m);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package carpet.logging;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Logger
|
||||
{
|
||||
// The set of subscribed and online players.
|
||||
private Map<String, String> subscribedOnlinePlayers;
|
||||
|
||||
// The set of subscribed and offline players.
|
||||
private Map<String,String> subscribedOfflinePlayers;
|
||||
|
||||
// The logName of this log. Gets prepended to logged messages.
|
||||
private String logName;
|
||||
|
||||
private String default_option;
|
||||
|
||||
private String[] options;
|
||||
|
||||
public Logger(String logName, String def, String [] options)
|
||||
{
|
||||
subscribedOnlinePlayers = new HashMap<>();
|
||||
subscribedOfflinePlayers = new HashMap<>();
|
||||
this.logName = logName;
|
||||
this.default_option = def;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public String getDefault()
|
||||
{
|
||||
return default_option;
|
||||
}
|
||||
public String [] getOptions()
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
return new String[0];
|
||||
}
|
||||
return options;
|
||||
}
|
||||
public String getLogName()
|
||||
{
|
||||
return logName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes the player with the given logName to the logger.
|
||||
*/
|
||||
public void addPlayer(String playerName, String option)
|
||||
{
|
||||
if (playerFromName(playerName) != null)
|
||||
{
|
||||
subscribedOnlinePlayers.put(playerName, option);
|
||||
}
|
||||
else
|
||||
{
|
||||
subscribedOfflinePlayers.put(playerName, option);
|
||||
}
|
||||
LoggerRegistry.setAccess(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes the player with the given logName from the logger.
|
||||
*/
|
||||
public void removePlayer(String playerName)
|
||||
{
|
||||
subscribedOnlinePlayers.remove(playerName);
|
||||
subscribedOfflinePlayers.remove(playerName);
|
||||
LoggerRegistry.setAccess(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are any online subscribers for this log.
|
||||
*/
|
||||
public boolean hasOnlineSubscribers()
|
||||
{
|
||||
return subscribedOnlinePlayers.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* serves messages to players fetching them from the promise
|
||||
* will repeat invocation for players that share the same option
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface lMessage { BaseComponent [] get(String playerOption, PlayerEntity player);}
|
||||
public void log(lMessage messagePromise)
|
||||
{
|
||||
for (Map.Entry<String,String> en : subscribedOnlinePlayers.entrySet())
|
||||
{
|
||||
PlayerEntity player = playerFromName(en.getKey());
|
||||
if (player != null)
|
||||
{
|
||||
BaseComponent [] messages = messagePromise.get(en.getValue(),player);
|
||||
if (messages != null)
|
||||
sendPlayerMessage(player, messages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* guarantees that each message for each option will be evaluated once from the promise
|
||||
* and served the same way to all other players subscribed to the same option
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface lMessageIgnorePlayer { BaseComponent [] get(String playerOption);}
|
||||
public void log(lMessageIgnorePlayer messagePromise)
|
||||
{
|
||||
Map<String, BaseComponent[]> cannedMessages = new HashMap<>();
|
||||
for (Map.Entry<String,String> en : subscribedOnlinePlayers.entrySet())
|
||||
{
|
||||
PlayerEntity player = playerFromName(en.getKey());
|
||||
if (player != null)
|
||||
{
|
||||
String option = en.getValue();
|
||||
if (!cannedMessages.containsKey(option))
|
||||
{
|
||||
cannedMessages.put(option,messagePromise.get(option));
|
||||
}
|
||||
BaseComponent [] messages = cannedMessages.get(option);
|
||||
if (messages != null)
|
||||
sendPlayerMessage(player, messages);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* guarantees that message is evaluated once, so independent from the player and chosen option
|
||||
*/
|
||||
public void log(Supplier<BaseComponent[]> messagePromise)
|
||||
{
|
||||
BaseComponent [] cannedMessages = null;
|
||||
for (Map.Entry<String,String> en : subscribedOnlinePlayers.entrySet())
|
||||
{
|
||||
PlayerEntity player = playerFromName(en.getKey());
|
||||
if (player != null)
|
||||
{
|
||||
if (cannedMessages == null) cannedMessages = messagePromise.get();
|
||||
sendPlayerMessage(player, cannedMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendPlayerMessage(PlayerEntity player, BaseComponent ... messages)
|
||||
{
|
||||
Arrays.stream(messages).forEach(player::sendMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@code PlayerEntity} instance for a player given their UUID. Returns null if they are offline.
|
||||
*/
|
||||
protected PlayerEntity playerFromName(String name)
|
||||
{
|
||||
return CarpetServer.minecraft_server.getPlayerManager().getPlayer(name);
|
||||
}
|
||||
|
||||
// ----- Event Handlers ----- //
|
||||
|
||||
public void onPlayerConnect(PlayerEntity player)
|
||||
{
|
||||
// If the player was subscribed to the log and offline, move them to the set of online subscribers.
|
||||
String playerName = player.getName().getString();
|
||||
if (subscribedOfflinePlayers.containsKey(playerName))
|
||||
{
|
||||
subscribedOnlinePlayers.put(playerName, subscribedOfflinePlayers.get(playerName));
|
||||
subscribedOfflinePlayers.remove(playerName);
|
||||
}
|
||||
LoggerRegistry.setAccess(this);
|
||||
}
|
||||
|
||||
public void onPlayerDisconnect(PlayerEntity player)
|
||||
{
|
||||
// If the player was subscribed to the log, move them to the set of offline subscribers.
|
||||
String playerName = player.getName().getString();
|
||||
if (subscribedOnlinePlayers.containsKey(playerName))
|
||||
{
|
||||
subscribedOfflinePlayers.put(playerName, subscribedOnlinePlayers.get(playerName));
|
||||
subscribedOnlinePlayers.remove(playerName);
|
||||
}
|
||||
LoggerRegistry.setAccess(this);
|
||||
}
|
||||
|
||||
public String getAcceptedOption(String arg)
|
||||
{
|
||||
if (options != null && Arrays.asList(options).contains(arg)) return arg;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package carpet.logging;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.EnumDyeColor;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class LoggerRegistry
|
||||
{
|
||||
// Map from logger names to loggers.
|
||||
private static Map<String, Logger> loggerRegistry = new HashMap<>();
|
||||
// Map from player names to the set of names of the logs that player is subscribed to.
|
||||
private static Map<String, Map<String, String>> playerSubscriptions = new HashMap<>();
|
||||
//statics to quickly asses if its worth even to call each one
|
||||
public static boolean __tnt;
|
||||
public static boolean __projectiles;
|
||||
public static boolean __fallingBlocks;
|
||||
public static boolean __kills;
|
||||
public static boolean __tps;
|
||||
public static boolean __counter;
|
||||
public static boolean __mobcaps;
|
||||
public static boolean __damage;
|
||||
public static boolean __packets;
|
||||
public static boolean __weather;
|
||||
|
||||
public static void initLoggers()
|
||||
{
|
||||
registerLogger("tnt", new Logger("tnt", "brief", new String[]{"brief", "full"}));
|
||||
registerLogger("projectiles", new Logger("projectiles", "brief", new String[]{"brief", "full"}));
|
||||
registerLogger("fallingBlocks",new Logger("fallingBlocks", "brief", new String[]{"brief", "full"}));
|
||||
registerLogger("kills", new Logger("kills", null, null));
|
||||
registerLogger("damage", new Logger("damage", "all", new String[]{"all","players","me"}));
|
||||
registerLogger("weather", new Logger("weather", null, null));
|
||||
|
||||
registerLogger("tps", new HUDLogger("tps", null, null));
|
||||
registerLogger("packets", new HUDLogger("packets", null, null));
|
||||
registerLogger("counter",new HUDLogger("counter","white", Arrays.stream(EnumDyeColor.values()).map(Object::toString).toArray(String[]::new)));
|
||||
registerLogger("mobcaps", new HUDLogger("mobcaps", "dynamic",new String[]{"dynamic", "overworld", "nether","end"}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the logger with the given name. Returns null if no such logger exists.
|
||||
*/
|
||||
public static Logger getLogger(String name) { return loggerRegistry.get(name); }
|
||||
|
||||
/**
|
||||
* Gets the set of logger names.
|
||||
*/
|
||||
public static Set<String> getLoggerNames() { return loggerRegistry.keySet(); }
|
||||
|
||||
/**
|
||||
* Subscribes the player with name playerName to the log with name logName.
|
||||
*/
|
||||
public static void subscribePlayer(String playerName, String logName, String option)
|
||||
{
|
||||
if (!playerSubscriptions.containsKey(playerName)) playerSubscriptions.put(playerName, new HashMap<>());
|
||||
Logger log = loggerRegistry.get(logName);
|
||||
if (option == null) option = log.getDefault();
|
||||
playerSubscriptions.get(playerName).put(logName,option);
|
||||
log.addPlayer(playerName, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes the player with name playerName from the log with name logName.
|
||||
*/
|
||||
public static void unsubscribePlayer(String playerName, String logName)
|
||||
{
|
||||
if (playerSubscriptions.containsKey(playerName))
|
||||
{
|
||||
Map<String,String> subscriptions = playerSubscriptions.get(playerName);
|
||||
subscriptions.remove(logName);
|
||||
loggerRegistry.get(logName).removePlayer(playerName);
|
||||
if (subscriptions.size() == 0) playerSubscriptions.remove(playerName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the player is not subscribed to the log, then subscribe them. Otherwise, unsubscribe them.
|
||||
*/
|
||||
public static boolean togglePlayerSubscription(String playerName, String logName)
|
||||
{
|
||||
if (playerSubscriptions.containsKey(playerName) && playerSubscriptions.get(playerName).containsKey(logName))
|
||||
{
|
||||
unsubscribePlayer(playerName, logName);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
subscribePlayer(playerName, logName, null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of logs the current player is subscribed to.
|
||||
*/
|
||||
public static Map<String,String> getPlayerSubscriptions(String playerName)
|
||||
{
|
||||
if (playerSubscriptions.containsKey(playerName))
|
||||
{
|
||||
return playerSubscriptions.get(playerName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static void setAccess(Logger logger)
|
||||
{
|
||||
String name = logger.getLogName();
|
||||
boolean value = logger.hasOnlineSubscribers();
|
||||
try
|
||||
{
|
||||
Field f = LoggerRegistry.class.getDeclaredField("__"+name);
|
||||
f.setBoolean(null, value);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
CarpetSettings.LOG.error("Cannot change logger quick access field");
|
||||
}
|
||||
catch (NoSuchFieldException e)
|
||||
{
|
||||
CarpetSettings.LOG.error("Wrong logger name");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called when the server starts. Creates the logs used by Carpet mod.
|
||||
*/
|
||||
private static void registerLogger(String name, Logger logger)
|
||||
{
|
||||
loggerRegistry.put(name, logger);
|
||||
setAccess(logger);
|
||||
}
|
||||
|
||||
public static void playerConnected(EntityPlayer player)
|
||||
{
|
||||
for(Logger log: loggerRegistry.values() )
|
||||
{
|
||||
log.onPlayerConnect(player);
|
||||
}
|
||||
|
||||
}
|
||||
public static void playerDisconnected(EntityPlayer player)
|
||||
{
|
||||
for(Logger log: loggerRegistry.values() )
|
||||
{
|
||||
log.onPlayerDisconnect(player);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package carpet.logging.logHelpers;
|
||||
|
||||
import carpet.logging.LoggerRegistry;
|
||||
import carpet.utils.Messenger;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class DamageReporter
|
||||
{
|
||||
private static ITextComponent[] verifyAndProduceMessage(String option, EntityPlayer player, Entity from, Entity to, Supplier<ITextComponent> messageFuture)
|
||||
{
|
||||
if ("all".equalsIgnoreCase(option)
|
||||
|| ("players".equalsIgnoreCase(option) && (from instanceof EntityPlayer || to instanceof EntityPlayer))
|
||||
|| ("me".equalsIgnoreCase(option) && ( (from == player) || ( to == player) ) ))
|
||||
{
|
||||
return new ITextComponent[]{messageFuture.get()};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean register_damage_attacker(Entity target, EntityLivingBase source, float amount)
|
||||
{
|
||||
if (!LoggerRegistry.__damage) return true;
|
||||
LoggerRegistry.getLogger("damage").log( (option, player)->
|
||||
verifyAndProduceMessage(option, player, source, target, () ->
|
||||
Messenger.c(source.getDisplayName(),
|
||||
"g attacking ", target.getDisplayName(),"g for ",
|
||||
String.format("r %.2f",amount), "g points of damage")
|
||||
)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void register_damage(EntityLivingBase target, DamageSource source, float amount)
|
||||
{
|
||||
if (!LoggerRegistry.__damage) return;
|
||||
if (source.isFireDamage() && (target.isImmuneToFire() ||
|
||||
target.isPotionActive(MobEffects.FIRE_RESISTANCE)))
|
||||
return;
|
||||
LoggerRegistry.getLogger("damage").log( (option, player)->
|
||||
verifyAndProduceMessage(option, player, source.getTrueSource(), target, () ->
|
||||
Messenger.c(target.getDisplayName(),
|
||||
"g receiving ",
|
||||
String.format("r %.2f", amount),
|
||||
String.format("g points of damage from %s", source.getDamageType()))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static void register_final_damage(EntityLivingBase target, DamageSource source, float amount)
|
||||
{
|
||||
if (!LoggerRegistry.__damage) return;
|
||||
LoggerRegistry.getLogger("damage").log( (option, player)->
|
||||
verifyAndProduceMessage(option, player, source.getTrueSource(), target, () ->
|
||||
Messenger.c("g - total received ",
|
||||
String.format("r %.2f", amount),
|
||||
"g points of damage")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static void modify_damage(EntityLivingBase target, DamageSource source, float previous_amount, float final_amount, String component)
|
||||
{
|
||||
if (!LoggerRegistry.__damage)
|
||||
return;
|
||||
if (previous_amount == final_amount)
|
||||
return;
|
||||
if (source.isFireDamage() && (target.isImmuneToFire() ||
|
||||
target.isPotionActive(MobEffects.FIRE_RESISTANCE)))
|
||||
return;
|
||||
LoggerRegistry.getLogger("damage").log( (option, player)->
|
||||
verifyAndProduceMessage(option, player, source.getTrueSource(), target, () ->
|
||||
{
|
||||
if (final_amount == 0.0f)
|
||||
{
|
||||
return Messenger.c("g - reduced to ","r 0.0","g due to: "+component);
|
||||
}
|
||||
else if (previous_amount > final_amount)
|
||||
{
|
||||
float reduction = previous_amount-final_amount;
|
||||
return Messenger.c("g - reduced to ",
|
||||
String.format("l %.2f",final_amount),
|
||||
String.format("g by %.2f (%.1f%% less) due to: %s",reduction,100.0*reduction/previous_amount, component));
|
||||
}
|
||||
else
|
||||
{
|
||||
float increase = final_amount-previous_amount;
|
||||
return Messenger.c("g - increased to ",
|
||||
String.format("r %.2f",final_amount),
|
||||
String.format("g by %.2f (%.1f%% more) due to: %s",increase,100.0*increase/previous_amount, component));
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package carpet.logging.logHelpers;
|
||||
|
||||
import carpet.logging.LoggerRegistry;
|
||||
import carpet.utils.Messenger;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
public class KillLogHelper {
|
||||
|
||||
public static void onSweep(String name, int count)
|
||||
{
|
||||
LoggerRegistry.getLogger("kills").log( () -> new ITextComponent[]{
|
||||
Messenger.c("g "+name+" smacked ","r "+count,"g entities with sweeping")});
|
||||
}
|
||||
|
||||
public static void onNonSweepAttack(String name)
|
||||
{
|
||||
LoggerRegistry.getLogger("kills").log( () -> new ITextComponent[]{
|
||||
Messenger.c("g "+name+" smacked ","r 1","g (no sweeping)")});
|
||||
}
|
||||
|
||||
public static void onDudHit(String name)
|
||||
{
|
||||
LoggerRegistry.getLogger("kills").log( () -> new ITextComponent[]{
|
||||
Messenger.c("g "+name+" dud hot = no one affected")});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package carpet.logging.logHelpers;
|
||||
|
||||
public class PacketCounter
|
||||
{
|
||||
public static long totalOut=0;
|
||||
public static long totalIn=0;
|
||||
public static void reset() {totalIn = 0l; totalOut = 0L; }
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package carpet.logging.logHelpers;
|
||||
|
||||
import carpet.logging.LoggerRegistry;
|
||||
import carpet.utils.Messenger;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
public class TNTLogHelper
|
||||
{
|
||||
private double primedX, primedY, primedZ, primedAngle;
|
||||
/**
|
||||
* Runs when the TNT is primed. Expects the position and motion angle of the TNT.
|
||||
*/
|
||||
public void onPrimed(double x, double y, double z, float angle)
|
||||
{
|
||||
primedX = x;
|
||||
primedY = y;
|
||||
primedZ = z;
|
||||
primedAngle = angle;
|
||||
}
|
||||
/**
|
||||
* Runs when the TNT explodes. Expects the position of the TNT.
|
||||
*/
|
||||
public void onExploded(double x, double y, double z)
|
||||
{
|
||||
LoggerRegistry.getLogger("tnt").log( (option) -> {
|
||||
switch (option)
|
||||
{
|
||||
case "brief":
|
||||
return new ITextComponent[]{Messenger.c(
|
||||
"l P ",Messenger.dblt("l",primedX,primedY,primedZ,primedAngle),
|
||||
"r E ",Messenger.dblt("r",x, y, z))};
|
||||
case "full":
|
||||
return new ITextComponent[]{Messenger.c(
|
||||
"l P ",Messenger.dblf("l",primedX,primedY,primedZ,primedAngle),
|
||||
"r E ",Messenger.dblf("r",x, y, z))};
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package carpet.logging.logHelpers;
|
||||
|
||||
import carpet.logging.Logger;
|
||||
import carpet.logging.LoggerRegistry;
|
||||
import carpet.utils.Messenger;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A generic log helper for logging the trajectory of things like blocks and throwables.
|
||||
*/
|
||||
public class TrajectoryLogHelper
|
||||
{
|
||||
private static final int MAX_TICKS_PER_LINE = 20;
|
||||
|
||||
private boolean doLog;
|
||||
private Logger logger;
|
||||
|
||||
private ArrayList<Vec3d> positions = new ArrayList<>();
|
||||
private ArrayList<Vec3d> motions = new ArrayList<>();
|
||||
|
||||
public TrajectoryLogHelper(String logName)
|
||||
{
|
||||
this.logger = LoggerRegistry.getLogger(logName);
|
||||
this.doLog = this.logger.hasOnlineSubscribers();
|
||||
}
|
||||
|
||||
public void onTick(double x, double y, double z, double motionX, double motionY, double motionZ)
|
||||
{
|
||||
if (!doLog) return;
|
||||
positions.add(new Vec3d(x, y, z));
|
||||
motions.add(new Vec3d(motionX, motionY, motionZ));
|
||||
}
|
||||
|
||||
public void onFinish()
|
||||
{
|
||||
if (!doLog) return;
|
||||
logger.log( (option) -> {
|
||||
List<ITextComponent> comp = new ArrayList<>();
|
||||
switch (option)
|
||||
{
|
||||
case "brief":
|
||||
comp.add(Messenger.s(""));
|
||||
List<String> line = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < positions.size(); i++)
|
||||
{
|
||||
Vec3d pos = positions.get(i);
|
||||
Vec3d mot = motions.get(i);
|
||||
line.add("w x");
|
||||
line.add(String.format("^w Tick: %d\nx: %f\ny: %f\nz: %f\n------------\nmx: %f\nmy: %f\nmz: %f",
|
||||
i, pos.x, pos.y, pos.z, mot.x, mot.y, mot.z));
|
||||
if ((((i+1) % MAX_TICKS_PER_LINE)==0) || i == positions.size()-1)
|
||||
{
|
||||
comp.add(Messenger.c(line.toArray(new Object[0])));
|
||||
line.clear();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "full":
|
||||
comp.add(Messenger.c("w ---------"));
|
||||
for (int i = 0; i < positions.size(); i++)
|
||||
{
|
||||
Vec3d pos = positions.get(i);
|
||||
Vec3d mot = motions.get(i);
|
||||
comp.add(Messenger.c(
|
||||
String.format("w tick: %3d pos",i),Messenger.dblt("w",pos.x, pos.y, pos.z),
|
||||
"w mot",Messenger.dblt("w",mot.x, mot.y, mot.z)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return comp.toArray(new ITextComponent[0]);
|
||||
});
|
||||
doLog = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package carpet.mixins.logging;
|
||||
|
||||
import net.minecraft.client.network.packet.PlayerListHeaderS2CPacket;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(PlayerListHeaderS2CPacket.class)
|
||||
public interface PlayerListHeaderS2CPacketMixin {
|
||||
@Accessor("header")
|
||||
void setHeader(Component header);
|
||||
|
||||
@Accessor("footer")
|
||||
void setFooter(Component footer);
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
package carpet.utils;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.mob.MobEntityWithAi;
|
||||
import net.minecraft.entity.ai.goal.WanderAroundGoal;
|
||||
import net.minecraft.entity.ai.PathfindingUtil;
|
||||
import net.minecraft.entity.mob.ZombiePigmanEntity;
|
||||
import net.minecraft.block.BlockPlacementEnvironment;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class BlockInfo
|
||||
{
|
||||
public static Map<BlockSoundGroup, String> soundName = new HashMap<BlockSoundGroup, String>() {{
|
||||
put(BlockSoundGroup.WOOD, "wood" );
|
||||
put(BlockSoundGroup.GROUND, "gravel");
|
||||
put(BlockSoundGroup.PLANT, "grass" );
|
||||
put(BlockSoundGroup.STONE, "stone" );
|
||||
put(BlockSoundGroup.METAL, "metal" );
|
||||
put(BlockSoundGroup.GLASS , "glass" );
|
||||
put(BlockSoundGroup.CLOTH , "wool" );
|
||||
put(BlockSoundGroup.SAND , "sand" );
|
||||
put(BlockSoundGroup.SNOW , "snow" );
|
||||
put(BlockSoundGroup.LADDER, "ladder");
|
||||
put(BlockSoundGroup.ANVIL , "anvil" );
|
||||
put(BlockSoundGroup.SLIME , "slime" );
|
||||
put(BlockSoundGroup.WET_GRASS , "sea_grass" );
|
||||
put(BlockSoundGroup.CORAL , "coral" );
|
||||
}};
|
||||
|
||||
public static Map<MaterialColor, String> mapColourName = new HashMap<MaterialColor, String>() {{
|
||||
put(MaterialColor.AIR , "air" );
|
||||
put(MaterialColor.GRASS , "grass" );
|
||||
put(MaterialColor.SAND , "sand" );
|
||||
put(MaterialColor.WOOL , "wool" );
|
||||
put(MaterialColor.TNT , "tnt" );
|
||||
put(MaterialColor.ICE , "ice" );
|
||||
put(MaterialColor.IRON , "iron" );
|
||||
put(MaterialColor.FOLIAGE , "foliage" );
|
||||
put(MaterialColor.SNOW , "snow" );
|
||||
put(MaterialColor.CLAY , "clay" );
|
||||
put(MaterialColor.DIRT , "dirt" );
|
||||
put(MaterialColor.STONE , "stone" );
|
||||
put(MaterialColor.WATER , "water" );
|
||||
put(MaterialColor.WOOD , "wood" );
|
||||
put(MaterialColor.QUARTZ , "quartz" );
|
||||
put(MaterialColor.ADOBE , "adobe" );
|
||||
put(MaterialColor.MAGENTA , "magenta" );
|
||||
put(MaterialColor.LIGHT_BLUE, "light_blue");
|
||||
put(MaterialColor.YELLOW , "yellow" );
|
||||
put(MaterialColor.LIME , "lime" );
|
||||
put(MaterialColor.PINK , "pink" );
|
||||
put(MaterialColor.GRAY , "gray" );
|
||||
put(MaterialColor.LIGHT_GRAY, "light_gray");
|
||||
put(MaterialColor.CYAN , "cyan" );
|
||||
put(MaterialColor.PURPLE , "purple" );
|
||||
put(MaterialColor.BLUE , "blue" );
|
||||
put(MaterialColor.BROWN , "brown" );
|
||||
put(MaterialColor.GREEN , "green" );
|
||||
put(MaterialColor.RED , "red" );
|
||||
put(MaterialColor.BLACK , "black" );
|
||||
put(MaterialColor.GOLD , "gold" );
|
||||
put(MaterialColor.DIAMOND , "diamond" );
|
||||
put(MaterialColor.LAPIS , "lapis" );
|
||||
put(MaterialColor.EMERALD , "emerald" );
|
||||
put(MaterialColor.OBSIDIAN , "obsidian" );
|
||||
put(MaterialColor.NETHERRACK, "netherrack");
|
||||
put(MaterialColor.WHITE_TERRACOTTA , "white_terracotta" );
|
||||
put(MaterialColor.ORANGE_TERRACOTTA , "orange_terracotta" );
|
||||
put(MaterialColor.MAGENTA_TERRACOTTA , "magenta_terracotta" );
|
||||
put(MaterialColor.LIGHT_BLUE_TERRACOTTA, "light_blue_terracotta" );
|
||||
put(MaterialColor.YELLOW_TERRACOTTA , "yellow_terracotta" );
|
||||
put(MaterialColor.LIME_TERRACOTTA , "lime_terracotta" );
|
||||
put(MaterialColor.PINK_TERRACOTTA , "pink_terracotta" );
|
||||
put(MaterialColor.GRAY_TERRACOTTA , "gray_terracotta" );
|
||||
put(MaterialColor.LIGHT_GRAY_TERRACOTTA, "light_gray_terracotta" );
|
||||
put(MaterialColor.CYAN_TERRACOTTA , "cyan_terracotta" );
|
||||
put(MaterialColor.PURPLE_TERRACOTTA , "purple_terracotta" );
|
||||
put(MaterialColor.BLUE_TERRACOTTA , "blue_terracotta" );
|
||||
put(MaterialColor.BROWN_TERRACOTTA , "brown_terracotta" );
|
||||
put(MaterialColor.GREEN_TERRACOTTA , "green_terracotta" );
|
||||
put(MaterialColor.RED_TERRACOTTA , "red_terracotta" );
|
||||
put(MaterialColor.BLACK_TERRACOTTA , "black_terracotta" );
|
||||
}};
|
||||
|
||||
public static Map<Material, String> materialName = new HashMap<Material, String>() {{
|
||||
put(Material.AIR , "air" );
|
||||
put(Material.STRUCTURE_VOID , "void" );
|
||||
put(Material.PORTAL , "portal" );
|
||||
put(Material.CARPET , "carpet" );
|
||||
put(Material.PLANTS , "plant" );
|
||||
put(Material.OCEAN_PLANT , "water_plant" );
|
||||
put(Material.VINE , "vine" );
|
||||
put(Material.SEA_GRASS , "sea_grass" );
|
||||
put(Material.WATER , "water" );
|
||||
put(Material.BUBBLE_COLUMN , "bubble_column");
|
||||
put(Material.LAVA , "lava" );
|
||||
put(Material.SNOW , "snow_layer" );
|
||||
put(Material.FIRE , "fire" );
|
||||
put(Material.CIRCUITS , "redstone_bits");
|
||||
put(Material.WEB , "cobweb" );
|
||||
put(Material.REDSTONE_LIGHT , "redstone_lamp");
|
||||
put(Material.CLAY , "clay" );
|
||||
put(Material.GROUND , "dirt" );
|
||||
put(Material.GRASS , "grass" );
|
||||
put(Material.PACKED_ICE , "packed_ice" );
|
||||
put(Material.SAND , "sand" );
|
||||
put(Material.SPONGE , "sponge" );
|
||||
put(Material.WOOD , "wood" );
|
||||
put(Material.CLOTH , "wool" );
|
||||
put(Material.TNT , "tnt" );
|
||||
put(Material.LEAVES , "leaves" );
|
||||
put(Material.GLASS , "glass" );
|
||||
put(Material.ICE , "ice" );
|
||||
put(Material.CACTUS , "cactus" );
|
||||
put(Material.ROCK , "stone" );
|
||||
put(Material.IRON , "iron" );
|
||||
put(Material.CRAFTED_SNOW , "snow" );
|
||||
put(Material.ANVIL , "anvil" );
|
||||
put(Material.BARRIER , "barrier" );
|
||||
put(Material.PISTON , "piston" );
|
||||
put(Material.CORAL , "coral" );
|
||||
put(Material.GOURD , "gourd" );
|
||||
put(Material.DRAGON_EGG , "dragon_egg" );
|
||||
put(Material.CAKE , "cake" );
|
||||
}};
|
||||
|
||||
public static List<BaseComponent> blockInfo(BlockPos pos, World world)
|
||||
{
|
||||
BlockState state = world.getBlockState(pos);
|
||||
Material material = state.getMaterial();
|
||||
Block block = state.getBlock();
|
||||
String metastring = "";
|
||||
for (net.minecraft.state.IProperty<?> iproperty : state.getProperties())
|
||||
{
|
||||
metastring += ", "+iproperty.getName() + '='+state.get(iproperty);
|
||||
}
|
||||
List<BaseComponent> lst = new ArrayList<>();
|
||||
lst.add(Messenger.s(""));
|
||||
lst.add(Messenger.s("====================================="));
|
||||
lst.add(Messenger.s(String.format("Block info for %s%s (id %d%s):",Registry.BLOCK.getKey(block),metastring, Registry.BLOCK.getId(block), metastring )));
|
||||
lst.add(Messenger.s(String.format(" - Material: %s", materialName.get(material))));
|
||||
lst.add(Messenger.s(String.format(" - Map colour: %s", mapColourName.get(state.getMaterialColor(world, pos)))));
|
||||
lst.add(Messenger.s(String.format(" - Sound type: %s", soundName.get(block.getBlockSoundGroup()))));
|
||||
lst.add(Messenger.s(""));
|
||||
lst.add(Messenger.s(String.format(" - Full block: %s", state.isFullCube() )));
|
||||
lst.add(Messenger.s(String.format(" - Normal cube: %s", state.isNormalCube())));
|
||||
lst.add(Messenger.s(String.format(" - Is liquid: %s", material.isLiquid())));
|
||||
lst.add(Messenger.s(String.format(" - Is solid: %s", material.isSolid())));
|
||||
lst.add(Messenger.s(""));
|
||||
lst.add(Messenger.s(String.format(" - Light in: %d, above: %d", world.getLight(pos), world.getLight(pos.up()))));
|
||||
lst.add(Messenger.s(String.format(" - Brightness in: %.2f, above: %.2f", world.getBrightness(pos), world.getBrightness(pos.up()))));
|
||||
lst.add(Messenger.s(String.format(" - Is opaque: %s", material.isOpaque() )));
|
||||
lst.add(Messenger.s(String.format(" - Light opacity: %d", state.getOpacity(world,pos))));
|
||||
lst.add(Messenger.s(String.format(" - Blocks light: %s", state.propagatesSkylightDown(world, pos))));
|
||||
lst.add(Messenger.s(String.format(" - Emitted light: %d", state.getLightValue())));
|
||||
lst.add(Messenger.s(String.format(" - Picks neighbour light value: %s", state.useNeighborBrightness(world, pos))));
|
||||
lst.add(Messenger.s(""));
|
||||
lst.add(Messenger.s(String.format(" - Causes suffocation: %s", state.causesSuffocation())));
|
||||
lst.add(Messenger.s(String.format(" - Blocks movement on land: %s", !state.canPlaceAtSide(world,pos, BlockPlacementEnvironment.LAND))));
|
||||
lst.add(Messenger.s(String.format(" - Blocks movement in air: %s", !state.canPlaceAtSide(world,pos, BlockPlacementEnvironment.AIR))));
|
||||
lst.add(Messenger.s(String.format(" - Blocks movement in liquids: %s", !state.canPlaceAtSide(world,pos, BlockPlacementEnvironment.WATER))));
|
||||
lst.add(Messenger.s(String.format(" - Can burn: %s", material.isFlammable())));
|
||||
lst.add(Messenger.s(String.format(" - Requires a tool: %s", !material.isToolNotRequired())));
|
||||
lst.add(Messenger.s(String.format(" - Hardness: %.2f", state.getBlockHardness(world, pos))));
|
||||
lst.add(Messenger.s(String.format(" - Blast resistance: %.2f", block.getExplosionResistance())));
|
||||
lst.add(Messenger.s(String.format(" - Ticks randomly: %s", block.ticksRandomly(state))));
|
||||
lst.add(Messenger.s(""));
|
||||
lst.add(Messenger.s(String.format(" - Can provide power: %s", state.canProvidePower())));
|
||||
lst.add(Messenger.s(String.format(" - Strong power level: %d", world.getStrongPower(pos))));
|
||||
lst.add(Messenger.s(String.format(" - Redstone power level: %d", world.getRedstonePowerFromNeighbors(pos))));
|
||||
lst.add(Messenger.s(""));
|
||||
lst.add(wander_chances(pos.up(), world));
|
||||
|
||||
return lst;
|
||||
}
|
||||
|
||||
private static BaseComponent wander_chances(BlockPos pos, World worldIn)
|
||||
{
|
||||
MobEntityWithAi creature = new ZombiePigmanEntity(worldIn);
|
||||
creature.onInitialSpawn(worldIn.getDifficultyForLocation(pos), null, null);
|
||||
creature.setLocationAndAngles(pos.getX()+0.5F, pos.getY(), pos.getZ()+0.5F, 0.0F, 0.0F);
|
||||
WanderAroundGoal wander = new WanderAroundGoal(creature, 0.8D);
|
||||
int success = 0;
|
||||
for (int i=0; i<1000; i++)
|
||||
{
|
||||
|
||||
Vec3d vec = PathfindingUtil.findRandomTarget(creature, 10, 7);
|
||||
if (vec == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
success++;
|
||||
}
|
||||
long total_ticks = 0;
|
||||
for (int trie=0; trie<1000; trie++)
|
||||
{
|
||||
int i;
|
||||
for (i=1;i<30*20*60; i++) //*60 used to be 5 hours, limited to 30 mins
|
||||
{
|
||||
if (wander.shouldExecute())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
total_ticks += 3*i;
|
||||
}
|
||||
creature.remove();
|
||||
long total_time = (total_ticks)/1000/20;
|
||||
return Messenger.s(String.format(" - Wander chance above: %.1f%%%%\n - Average standby above: %s",
|
||||
(100.0F*success)/1000,
|
||||
((total_time>5000)?"INFINITY":(Long.toString(total_time)+" s"))
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package carpet.utils;
|
||||
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class DistanceCalculator
|
||||
{
|
||||
public static final HashMap<String, Vec3d> START_POINT_STORAGE = new HashMap<>();
|
||||
|
||||
public static boolean hasStartingPoint(ServerCommandSource source)
|
||||
{
|
||||
return START_POINT_STORAGE.containsKey(source.getName());
|
||||
}
|
||||
|
||||
public static List<BaseComponent> findDistanceBetweenTwoPoints(Vec3d pos1, Vec3d pos2)
|
||||
{
|
||||
double dx = MathHelper.abs((float)pos1.x-(float)pos2.x);
|
||||
double dy = MathHelper.abs((float)pos1.y-(float)pos2.y);
|
||||
double dz = MathHelper.abs((float)pos1.z-(float)pos2.z);
|
||||
double manhattan = dx+dy+dz;
|
||||
double spherical = MathHelper.sqrt(dx*dx + dy*dy + dz*dz);
|
||||
double cylindrical = MathHelper.sqrt(dx*dx + dz*dz);
|
||||
List<BaseComponent> res = new ArrayList<>();
|
||||
res.add(Messenger.c("w Distance between ",
|
||||
Messenger.tp("c",pos1),"w and ",
|
||||
Messenger.tp("c",pos2),"w :"));
|
||||
res.add(Messenger.c("w - Manhattan: ", String.format("wb %.1f", manhattan)));
|
||||
res.add(Messenger.c("w - Spherical: ", String.format("wb %.2f", spherical)));
|
||||
res.add(Messenger.c("w - Cylindrical: ", String.format("wb %.2f", cylindrical)));
|
||||
return res;
|
||||
}
|
||||
|
||||
public static int distance(ServerCommandSource source, Vec3d pos1, Vec3d pos2)
|
||||
{
|
||||
Messenger.send(source, findDistanceBetweenTwoPoints(pos1, pos2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int setStart(ServerCommandSource source, Vec3d pos)
|
||||
{
|
||||
START_POINT_STORAGE.put(source.getName(), pos);
|
||||
Messenger.m(source,"gi Initial point set to: ", Messenger.tp("g",pos));
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int setEnd(ServerCommandSource source, Vec3d pos)
|
||||
{
|
||||
if ( !hasStartingPoint(source) )
|
||||
{
|
||||
START_POINT_STORAGE.put(source.getName(), pos);
|
||||
Messenger.m(source,"gi There was no initial point for "+source.getName());
|
||||
Messenger.m(source,"gi Initial point set to: ", Messenger.tp("g",pos));
|
||||
return 0;
|
||||
}
|
||||
Messenger.send(source, findDistanceBetweenTwoPoints( START_POINT_STORAGE.get(source.getName()), pos));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package carpet.utils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EvictingQueue<K,V> extends LinkedHashMap<K,V>
|
||||
{
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest)
|
||||
{
|
||||
return this.size() > 10;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package carpet.utils;
|
||||
|
||||
import carpet.helpers.HopperCounter;
|
||||
import carpet.helpers.TickSpeed;
|
||||
import carpet.logging.LoggerRegistry;
|
||||
import carpet.logging.logHelpers.PacketCounter;
|
||||
import carpet.mixins.logging.PlayerListHeaderS2CPacketMixin;
|
||||
import net.minecraft.entity.EntityCategory;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.client.network.packet.PlayerListHeaderS2CPacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.Pair;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class HUDController
|
||||
{
|
||||
public static Map<PlayerEntity, List<BaseComponent>> player_huds = new HashMap<>();
|
||||
|
||||
public static void addMessage(PlayerEntity player, BaseComponent hudMessage)
|
||||
{
|
||||
if (!player_huds.containsKey(player))
|
||||
{
|
||||
player_huds.put(player, new ArrayList<>());
|
||||
}
|
||||
else
|
||||
{
|
||||
player_huds.get(player).add(new TextComponent("\n"));
|
||||
}
|
||||
player_huds.get(player).add(hudMessage);
|
||||
}
|
||||
public static void clear_player(PlayerEntity player)
|
||||
{
|
||||
PlayerListHeaderS2CPacket packet = new PlayerListHeaderS2CPacket();
|
||||
((PlayerListHeaderS2CPacketMixin)packet).setHeader(new TextComponent(""));
|
||||
((PlayerListHeaderS2CPacketMixin)packet).setFooter(new TextComponent(""));
|
||||
((ServerPlayerEntity)player).networkHandler.sendPacket(packet);
|
||||
}
|
||||
|
||||
|
||||
public static void update_hud(MinecraftServer server)
|
||||
{
|
||||
if(server.getTicks() % 20 != 0)
|
||||
return;
|
||||
|
||||
player_huds.clear();
|
||||
|
||||
if (LoggerRegistry.__tps)
|
||||
LoggerRegistry.getLogger("tps").log(()-> send_tps_display(server));
|
||||
|
||||
if (LoggerRegistry.__mobcaps)
|
||||
LoggerRegistry.getLogger("mobcaps").log((option, player) -> {
|
||||
int dim = player.dimension.getRawId();
|
||||
switch (option)
|
||||
{
|
||||
case "overworld":
|
||||
dim = 0;
|
||||
break;
|
||||
case "nether":
|
||||
dim = -1;
|
||||
break;
|
||||
case "end":
|
||||
dim = 1;
|
||||
break;
|
||||
}
|
||||
return send_mobcap_display(dim);
|
||||
});
|
||||
|
||||
if(LoggerRegistry.__counter)
|
||||
LoggerRegistry.getLogger("counter").log((option)->send_counter_info(server, option));
|
||||
|
||||
if (LoggerRegistry.__packets)
|
||||
LoggerRegistry.getLogger("packets").log(()-> packetCounter());
|
||||
|
||||
for (PlayerEntity player: player_huds.keySet())
|
||||
{
|
||||
PlayerListHeaderS2CPacket packet = new PlayerListHeaderS2CPacket();
|
||||
((PlayerListHeaderS2CPacketMixin)packet).setHeader(new TextComponent(""));
|
||||
((PlayerListHeaderS2CPacketMixin)packet).setFooter(Messenger.c(player_huds.get(player).toArray(new Object[0])));
|
||||
((ServerPlayerEntity)player).networkHandler.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
private static BaseComponent [] send_tps_display(MinecraftServer server)
|
||||
{
|
||||
double MSPT = MathHelper.average(server.lastTickLengths) * 1.0E-6D;
|
||||
double TPS = 1000.0D / Math.max((TickSpeed.time_warp_start_time != 0)?0.0:TickSpeed.mspt, MSPT);
|
||||
String color = Messenger.heatmap_color(MSPT,TickSpeed.mspt);
|
||||
return new BaseComponent[]{Messenger.c(
|
||||
"g TPS: ", String.format(Locale.US, "%s %.1f",color, TPS),
|
||||
"g MSPT: ", String.format(Locale.US,"%s %.1f", color, MSPT))};
|
||||
}
|
||||
|
||||
private static BaseComponent [] send_mobcap_display(int dim)
|
||||
{
|
||||
List<BaseComponent> components = new ArrayList<>();
|
||||
for (EntityCategory type:EntityCategory.values())
|
||||
{
|
||||
Pair<Integer,Integer> counts = SpawnReporter.mobcaps.get(dim).getOrDefault(type, new Pair<>(0, 0));
|
||||
int actual = counts.getLeft(); int limit = counts.getRight();
|
||||
components.add(Messenger.c(
|
||||
(actual+limit == 0)?"g -":Messenger.heatmap_color(actual,limit)+" "+actual,
|
||||
Messenger.creatureTypeColor(type)+" /"+((actual+limit == 0)?"-":limit)
|
||||
));
|
||||
components.add(Messenger.c("w "));
|
||||
}
|
||||
components.remove(components.size()-1);
|
||||
return new BaseComponent[]{Messenger.c(components.toArray(new Object[0]))};
|
||||
}
|
||||
|
||||
private static BaseComponent [] send_counter_info(MinecraftServer server, String color)
|
||||
{
|
||||
HopperCounter counter = HopperCounter.getCounter(color);
|
||||
List <BaseComponent> res = counter == null ? Collections.emptyList() : counter.format(server, false, true);
|
||||
return new BaseComponent[]{ Messenger.c(res.toArray(new Object[0]))};
|
||||
}
|
||||
private static BaseComponent [] packetCounter()
|
||||
{
|
||||
BaseComponent [] ret = new BaseComponent[]{
|
||||
Messenger.c("w I/" + PacketCounter.totalIn + " O/" + PacketCounter.totalOut),
|
||||
};
|
||||
PacketCounter.reset();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,510 @@
|
||||
|
||||
package carpet.utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.util.Pair;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import net.minecraft.util.DyeColor;
|
||||
|
||||
import net.minecraft.entity.EntityCategory;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import net.minecraft.world.SpawnHelper;
|
||||
import net.minecraft.entity.SpawnRestriction;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.Entity;
|
||||
|
||||
import net.minecraft.entity.passive.OcelotEntity;
|
||||
import net.minecraft.world.Heightmap;
|
||||
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||
|
||||
import java.lang.Math;
|
||||
|
||||
public class SpawnReporter
|
||||
{
|
||||
public static String [] mob_groups = {"hostile","passive","water","ambient"};
|
||||
public static boolean mock_spawns = false;
|
||||
|
||||
public static Long track_spawns = 0L;
|
||||
public static final HashMap<Integer, HashMap<EntityCategory, Pair<Integer,Integer>>> mobcaps = new HashMap<>();
|
||||
public static final HashMap<String, HashMap<String,Long>> spawn_stats = new HashMap<String, HashMap<String,Long>>();
|
||||
public static double mobcap_exponent = 0.0D;
|
||||
|
||||
public static final HashMap<String, Long> spawn_attempts = new HashMap<String, Long>();
|
||||
public static final HashMap<String, Long> overall_spawn_ticks = new HashMap<String, Long>();
|
||||
public static final HashMap<String, Long> spawn_ticks_full = new HashMap<String, Long>();
|
||||
public static final HashMap<String, Long> spawn_ticks_fail = new HashMap<String, Long>();
|
||||
public static final HashMap<String, Long> spawn_ticks_succ = new HashMap<String, Long>();
|
||||
public static final HashMap<String, Long> spawn_ticks_spawns = new HashMap<String, Long>();
|
||||
public static final HashMap<String, Long> spawn_cap_count = new HashMap<String, Long>();
|
||||
public static class SpawnPos
|
||||
{
|
||||
public String mob;
|
||||
public BlockPos pos;
|
||||
public SpawnPos(String mob, BlockPos pos)
|
||||
{
|
||||
this.mob = mob;
|
||||
this.pos = pos;
|
||||
}
|
||||
}
|
||||
public static final HashMap<String, EvictingQueue<SpawnPos, Integer>> spawned_mobs = new HashMap<>();
|
||||
public static final HashMap<String, Integer> spawn_tries = new HashMap<>();
|
||||
public static BlockPos lower_spawning_limit = null;
|
||||
public static BlockPos upper_spawning_limit = null;
|
||||
|
||||
static {
|
||||
reset_spawn_stats(true);
|
||||
}
|
||||
|
||||
public static void registerSpawn(LivingEntity el, String type, String mob, BlockPos pos) { registerSpawn(el, type, mob, pos, 1L);}
|
||||
public static void registerSpawn(LivingEntity el, String type, String mob, BlockPos pos, long value)
|
||||
{
|
||||
if (lower_spawning_limit != null)
|
||||
{
|
||||
if (!( (lower_spawning_limit.getX() <= pos.getX() && pos.getX() <= upper_spawning_limit.getX()) &&
|
||||
(lower_spawning_limit.getY() <= pos.getY() && pos.getY() <= upper_spawning_limit.getY()) &&
|
||||
(lower_spawning_limit.getZ() <= pos.getZ() && pos.getZ() <= upper_spawning_limit.getZ())
|
||||
))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
long count = spawn_stats.get(type).getOrDefault(mob, 0L);
|
||||
spawn_stats.get(type).put(mob, count + value);
|
||||
spawned_mobs.get(type).put(new SpawnPos(mob, new BlockPos(el)), 1);
|
||||
}
|
||||
|
||||
|
||||
public static List<BaseComponent> printMobcapsForDimension(int dim)
|
||||
{
|
||||
String name = DimensionType.byRawId(dim).toString();
|
||||
List<BaseComponent> lst = new ArrayList<>();
|
||||
lst.add(Messenger.s(String.format("Mobcaps for %s:",name)));
|
||||
for (EntityCategory enumcreaturetype : EntityCategory.values())
|
||||
{
|
||||
String type_code = String.format("%s", enumcreaturetype);
|
||||
Pair<Integer, Integer> stat = mobcaps.get(dim).getOrDefault(enumcreaturetype, new Pair<>(0,0));
|
||||
int cur = stat.getLeft();
|
||||
int max = stat.getRight();
|
||||
int rounds = spawn_tries.get(type_code);
|
||||
lst.add( Messenger.c(String.format("w %s: ",type_code),
|
||||
(cur+max==0)?"g -/-":String.format("%s %d/%d", (cur >= max)?"r":((cur >= 8*max/10)?"y":"l") ,cur, max),
|
||||
(rounds == 1)?"w ":String.format("fi (%d rounds/tick)",spawn_tries.get(type_code))
|
||||
));
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
public static List<BaseComponent> recent_spawns(World world, String creature_type_code)
|
||||
{
|
||||
|
||||
EntityCategory creature_type = get_creature_type_from_code(creature_type_code);
|
||||
List<BaseComponent> lst = new ArrayList<>();
|
||||
if ((track_spawns == 0L))
|
||||
{
|
||||
lst.add(Messenger.s("Spawn tracking not started"));
|
||||
return lst;
|
||||
}
|
||||
if (creature_type == null)
|
||||
{
|
||||
lst.add(Messenger.s(String.format("Incorrect creature type: %s",creature_type_code)));
|
||||
return lst;
|
||||
}
|
||||
|
||||
String type_code = get_type_string(creature_type);
|
||||
|
||||
lst.add(Messenger.s(String.format("Recent %s spawns:",type_code)));
|
||||
for (SpawnPos entry: spawned_mobs.get(type_code).keySet())
|
||||
{
|
||||
lst.add( Messenger.c(String.format("w - %s ",entry.mob), Messenger.tp("wb",entry.pos)));
|
||||
}
|
||||
|
||||
if (lst.size()==1)
|
||||
{
|
||||
lst.add(Messenger.s(" - Nothing spawned yet, sorry."));
|
||||
}
|
||||
return lst;
|
||||
|
||||
}
|
||||
|
||||
public static List<BaseComponent> show_mobcaps(BlockPos pos, World worldIn)
|
||||
{
|
||||
DyeColor under = WoolTool.getWoolColorAtPosition(worldIn, pos.down());
|
||||
if (under == null)
|
||||
{
|
||||
if (track_spawns > 0L)
|
||||
{
|
||||
return tracking_report(worldIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
//return print_general_mobcaps(worldIn);
|
||||
}
|
||||
}
|
||||
String creature_type = get_type_code_from_wool_code(under);
|
||||
if (creature_type != null)
|
||||
{
|
||||
if (track_spawns > 0L)
|
||||
{
|
||||
return recent_spawns(worldIn, creature_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
return printEntitiesByType(creature_type, worldIn);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if (track_spawns > 0L)
|
||||
{
|
||||
return tracking_report(worldIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tracking_report(worldIn);
|
||||
//// TODO
|
||||
//return print_general_mobcaps(worldIn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String get_type_code_from_wool_code(DyeColor color)
|
||||
{
|
||||
switch (color)
|
||||
{
|
||||
case RED:
|
||||
return "hostile";
|
||||
case GREEN:
|
||||
return "passive";
|
||||
case BLUE:
|
||||
return "water";
|
||||
case BROWN:
|
||||
return "ambient";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static EntityCategory get_creature_type_from_code(String type_code)
|
||||
{
|
||||
if ("hostile".equalsIgnoreCase(type_code))
|
||||
{
|
||||
return EntityCategory.MONSTER;
|
||||
}
|
||||
else if ("passive".equalsIgnoreCase(type_code))
|
||||
{
|
||||
return EntityCategory.CREATURE;
|
||||
}
|
||||
else if ("water".equalsIgnoreCase(type_code))
|
||||
{
|
||||
return EntityCategory.WATER_CREATURE;
|
||||
}
|
||||
else if ("ambient".equalsIgnoreCase(type_code))
|
||||
{
|
||||
return EntityCategory.AMBIENT;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static String get_type_string(EntityCategory type)
|
||||
{
|
||||
return String.format("%s", type);
|
||||
}
|
||||
|
||||
public static String get_creature_code_from_string(String str)
|
||||
{
|
||||
return get_type_string(get_creature_type_from_code(str));
|
||||
}
|
||||
|
||||
public static List<BaseComponent> printEntitiesByType(String creature_type_code, World worldIn) //Class<?> entityType)
|
||||
{
|
||||
EntityCategory typ = get_creature_type_from_code(creature_type_code);
|
||||
List<BaseComponent> lst = new ArrayList<>();
|
||||
if (typ == null)
|
||||
{
|
||||
lst.add(Messenger.c(String.format("r Incorrect creature type: %s",creature_type_code)));
|
||||
return lst;
|
||||
}
|
||||
Class<?> cls = typ.getBaseClass();// getCreatureClass();
|
||||
lst.add( Messenger.s(String.format("Loaded entities for %s class:", get_type_string(typ))));
|
||||
for (Entity entity : worldIn.loadedEntityList)
|
||||
{
|
||||
if ((!(entity instanceof LivingEntity) || !((LivingEntity)entity).isNoDespawnRequired()) && cls.isAssignableFrom(entity.getClass()))
|
||||
{
|
||||
lst.add(Messenger.c("w - ",
|
||||
Messenger.tp("w", entity.posX, entity.posY, entity.posZ),"w : "+EntityType.getId(entity.getType())));
|
||||
}
|
||||
}
|
||||
if (lst.size()==1)
|
||||
{
|
||||
lst.add(Messenger.s(" - Empty."));
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
public static void initialize_mocking()
|
||||
{
|
||||
reset_spawn_stats(false);
|
||||
mock_spawns = true;
|
||||
|
||||
}
|
||||
public static void stop_mocking()
|
||||
{
|
||||
reset_spawn_stats(false);
|
||||
mock_spawns = false;
|
||||
|
||||
}
|
||||
public static void reset_spawn_stats(boolean full)
|
||||
{
|
||||
spawn_stats.clear();
|
||||
spawned_mobs.clear();
|
||||
for (EntityCategory enumcreaturetype : EntityCategory.values())
|
||||
{
|
||||
String type_code = String.format("%s", enumcreaturetype);
|
||||
if (full)
|
||||
{
|
||||
spawn_tries.put(type_code, 1);
|
||||
}
|
||||
for (String suffix: new String[] {""," (N)"," (E)"})
|
||||
{
|
||||
String code = type_code+suffix;
|
||||
overall_spawn_ticks.put(code, 0L);
|
||||
spawn_attempts.put(code, 0L);
|
||||
spawn_ticks_full.put(code, 0L);
|
||||
spawn_ticks_fail.put(code, 0L);
|
||||
spawn_ticks_succ.put(code, 0L);
|
||||
spawn_ticks_spawns.put(code, 0L);
|
||||
spawn_cap_count.put(code, 0L);
|
||||
}
|
||||
|
||||
spawn_stats.put(type_code, new HashMap<>());
|
||||
spawned_mobs.put(type_code, new EvictingQueue<>());
|
||||
}
|
||||
mobcaps.put(-1,new HashMap<>());
|
||||
mobcaps.put(0,new HashMap<>());
|
||||
mobcaps.put(1,new HashMap<>());
|
||||
track_spawns = 0L;
|
||||
}
|
||||
|
||||
public static List<BaseComponent> tracking_report(World worldIn)
|
||||
{
|
||||
List<BaseComponent> report = new ArrayList<>();
|
||||
if (track_spawns == 0L)
|
||||
{
|
||||
report.add(Messenger.c(
|
||||
"w Spawn tracking disabled, type '",
|
||||
"wi /spawn tracking start","/spawn tracking start",
|
||||
"w ' to enable"));
|
||||
return report;
|
||||
}
|
||||
Long duration = (long) worldIn.getServer().getTickCounter() - track_spawns;
|
||||
report.add(Messenger.c("bw --------------------"));
|
||||
String simulated = mock_spawns?"[SIMULATED] ":"";
|
||||
String location = (lower_spawning_limit != null)?String.format("[in (%d, %d, %d)x(%d, %d, %d)]",
|
||||
lower_spawning_limit.getX(),lower_spawning_limit.getY(),lower_spawning_limit.getZ(),
|
||||
upper_spawning_limit.getX(),upper_spawning_limit.getY(),upper_spawning_limit.getZ() ):"";
|
||||
report.add(Messenger.s(String.format("%sSpawn statistics %s: for %.1f min", simulated, location, (duration/72000.0)*60)));
|
||||
for (EntityCategory enumcreaturetype : EntityCategory.values())
|
||||
{
|
||||
String type_code = String.format("%s", enumcreaturetype);
|
||||
boolean there_are_mobs_to_list = false;
|
||||
for (String world_code: new String[] {"", " (N)", " (E)"})
|
||||
{
|
||||
String code = type_code+world_code;
|
||||
if (spawn_ticks_spawns.get(code) > 0L)
|
||||
{
|
||||
there_are_mobs_to_list = true;
|
||||
double hours = overall_spawn_ticks.get(code)/72000.0;
|
||||
report.add(Messenger.s(String.format(" > %s (%.1f min), %.1f m/t, {%.1f%%F / %.1f%%- / %.1f%%+}; %.2f s/att",
|
||||
code,
|
||||
60*hours,
|
||||
(1.0D*spawn_cap_count.get(code))/ spawn_attempts.get(code),
|
||||
(100.0D*spawn_ticks_full.get(code))/ spawn_attempts.get(code),
|
||||
(100.0D*spawn_ticks_fail.get(code))/ spawn_attempts.get(code),
|
||||
(100.0D*spawn_ticks_succ.get(code))/ spawn_attempts.get(code),
|
||||
(1.0D*spawn_ticks_spawns.get(code))/(spawn_ticks_fail.get(code)+spawn_ticks_succ.get(code))
|
||||
)));
|
||||
}
|
||||
}
|
||||
if (there_are_mobs_to_list)
|
||||
{
|
||||
for (String creature_name : spawn_stats.get(type_code).keySet())
|
||||
{
|
||||
report.add(Messenger.s(String.format(" - %s: %d spawns, %d per hour",
|
||||
creature_name,
|
||||
spawn_stats.get(type_code).get(creature_name),
|
||||
(72000 * spawn_stats.get(type_code).get(creature_name)/duration ))));
|
||||
}
|
||||
}
|
||||
}
|
||||
return report;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void killEntity(LivingEntity entity)
|
||||
{
|
||||
if (entity.isPassenger())
|
||||
{
|
||||
entity.getRidingEntity().remove();
|
||||
}
|
||||
if (entity.isBeingRidden())
|
||||
{
|
||||
for (Entity e: entity.getPassengers())
|
||||
{
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
if (entity instanceof OcelotEntity)
|
||||
{
|
||||
for (Entity e: entity.getEntityWorld().getEntitiesWithinAABB(OcelotEntity.class, entity.getBoundingBox()))
|
||||
{
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
entity.remove();
|
||||
}
|
||||
|
||||
public static List<BaseComponent> report(BlockPos pos, World worldIn)
|
||||
{
|
||||
List<BaseComponent> rep = new ArrayList<>();
|
||||
int x = pos.getX(); int y = pos.getY(); int z = pos.getZ();
|
||||
Chunk chunk = worldIn.getChunk(pos);
|
||||
int lc = chunk.getTopBlockY(Heightmap.Type.LIGHT_BLOCKING, x, z) + 1;
|
||||
String where = String.format((y >= lc) ? "%d blocks above it." : "%d blocks below it.", MathHelper.abs(y-lc));
|
||||
if (y == lc) where = "right at it.";
|
||||
rep.add(Messenger.s(String.format("Maximum spawn Y value for (%+d, %+d) is %d. You are "+where, x, z, lc )));
|
||||
rep.add(Messenger.s("Spawns:"));
|
||||
for (EntityCategory enumcreaturetype : EntityCategory.values())
|
||||
{
|
||||
String type_code = String.format("%s", enumcreaturetype).substring(0, 3);
|
||||
List<Biome.SpawnEntry> lst = ((ChunkGenerator)worldIn.getChunkManager().getChunkGenerator()).getEntitySpawnList(enumcreaturetype, pos);
|
||||
if (lst != null && !lst.isEmpty())
|
||||
{
|
||||
for (Biome.SpawnEntry SpawnListEntry animal : lst)
|
||||
{
|
||||
boolean canspawn = SpawnHelper.canCreatureTypeSpawnAtLocation(SpawnRestriction.getPlacementType(animal.entityType), worldIn, pos, animal.entityType);
|
||||
int will_spawn = -1;
|
||||
boolean fits = false;
|
||||
boolean fits1 = false;
|
||||
|
||||
LivingEntity entityliving;
|
||||
try
|
||||
{
|
||||
entityliving = animal.entityType.create(worldIn);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
return rep;
|
||||
}
|
||||
|
||||
boolean fits_true = false;
|
||||
boolean fits_false = false;
|
||||
|
||||
if (canspawn)
|
||||
{
|
||||
will_spawn = 0;
|
||||
for (int attempt = 0; attempt < 50; ++attempt)
|
||||
{
|
||||
float f = (float)x + 0.5F;
|
||||
float f1 = (float)z + 0.5F;
|
||||
entityliving.setLocationAndAngles((double)f, (double)y, (double)f1, worldIn.rand.nextFloat() * 360.0F, 0.0F);
|
||||
fits1 = entityliving.isNotColliding();
|
||||
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
if (entityliving.canSpawn(worldIn, false))
|
||||
{
|
||||
will_spawn += 1;
|
||||
}
|
||||
}
|
||||
entityliving.onInitialSpawn(worldIn.getDifficultyForLocation(new BlockPos(entityliving)), null, null);
|
||||
// the code invokes onInitialSpawn after getCanSpawHere
|
||||
fits = fits1 && entityliving.isNotColliding();
|
||||
if (fits)
|
||||
{
|
||||
fits_true = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fits_false = true;
|
||||
}
|
||||
|
||||
killEntity(entityliving);
|
||||
|
||||
try
|
||||
{
|
||||
entityliving = animal.entityType.create(worldIn);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
return rep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String creature_name = Registry.ENTITY_TYPE.getKey(entityliving.getType()).toString().replaceFirst("minecraft:","");
|
||||
String pack_size = String.format("%d", entityliving.getMaxSpawnedInChunk());//String.format("%d-%d", animal.minGroupCount, animal.maxGroupCount);
|
||||
int weight = animal.getItemWeight();
|
||||
if (canspawn)
|
||||
{
|
||||
String c = (fits_true && will_spawn>0)?"e":"gi";
|
||||
rep.add(Messenger.c(
|
||||
String.format("%s %s: %s (%d:%d-%d/%d), can: ",c,type_code,creature_name,weight,animal.minGroupCount, animal.maxGroupCount, entityliving.getMaxSpawnedInChunk()),
|
||||
"l YES",
|
||||
c+" , fit: ",
|
||||
((fits_true && fits_false)?"y YES and NO":(fits_true?"l YES":"r NO")),
|
||||
c+" , will: ",
|
||||
((will_spawn>0)?"l ":"r ")+Math.round((double)will_spawn)/10+"%"
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
rep.add(Messenger.c(String.format("gi %s: %s (%d:%d-%d/%d), can: ",type_code,creature_name,weight,animal.minGroupCount, animal.maxGroupCount, entityliving.getMaxSpawnedInChunk()), "n NO"));
|
||||
}
|
||||
killEntity(entityliving);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
||||
public static boolean check_player_within_spawning_range(World worldServerIn, float x, float y, float z)
|
||||
{
|
||||
|
||||
for (int i = 0; i < worldServerIn.playerEntities.size(); ++i)
|
||||
{
|
||||
PlayerEntity entityplayer = worldServerIn.playerEntities.get(i);
|
||||
|
||||
if (EntityPredicates.NOT_SPECTATING.test(entityplayer))
|
||||
{
|
||||
double d0 = entityplayer.getDistanceSq(x, y, z);
|
||||
|
||||
if ( d0 > 24.0*24.0 && d0 < 128.0*128.0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package carpet.utils;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.helpers.HopperCounter;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class WoolTool
|
||||
{
|
||||
private static final HashMap<MaterialColor,DyeColor> Material2Dye = new HashMap<>();
|
||||
static
|
||||
{
|
||||
for (DyeColor color: DyeColor.values())
|
||||
{
|
||||
Material2Dye.put(color.getMaterialColor(),color);
|
||||
}
|
||||
}
|
||||
|
||||
public static void carpetPlacedAction(DyeColor color, PlayerEntity placer, BlockPos pos, World worldIn)
|
||||
{
|
||||
if (!CarpetSettings.getBool("carpets"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (color)
|
||||
{
|
||||
case PINK:
|
||||
if (CarpetSettings.getBool("commandSpawn"))
|
||||
Messenger.send(placer, SpawnReporter.report(pos, worldIn));
|
||||
|
||||
break;
|
||||
case BLACK:
|
||||
if (CarpetSettings.getBool("commandSpawn"))
|
||||
Messenger.send(placer, SpawnReporter.show_mobcaps(pos, worldIn));
|
||||
break;
|
||||
case BROWN:
|
||||
if (CarpetSettings.getBool("commandDistance"))
|
||||
{
|
||||
ServerCommandSource source = placer.getCommandSource();
|
||||
if (!DistanceCalculator.hasStartingPoint(source) || placer.isSneaking()) {
|
||||
DistanceCalculator.setStart(source, new Vec3d(pos));
|
||||
}
|
||||
else {
|
||||
DistanceCalculator.setEnd(source, new Vec3d(pos));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRAY:
|
||||
if (CarpetSettings.getBool("commandInfo"))
|
||||
Messenger.send(placer, BlockInfo.blockInfo(pos.down(), worldIn));
|
||||
break;
|
||||
case YELLOW:
|
||||
if (CarpetSettings.getBool("commandInfo"))
|
||||
EntityInfo.issue_entity_info(placer);
|
||||
break;
|
||||
case GREEN:
|
||||
if (CarpetSettings.getBool("hopperCounters"))
|
||||
{
|
||||
DyeColor under = getWoolColorAtPosition(worldIn, pos.down());
|
||||
if (under == null) return;
|
||||
HopperCounter counter = HopperCounter.getCounter(under.toString());
|
||||
if (counter != null)
|
||||
Messenger.send(placer, counter.format(worldIn.getServer(), false, false));
|
||||
}
|
||||
break;
|
||||
case RED:
|
||||
if (CarpetSettings.getBool("hopperCounters"))
|
||||
{
|
||||
DyeColor under = getWoolColorAtPosition(worldIn, pos.down());
|
||||
if (under == null) return;
|
||||
HopperCounter counter = HopperCounter.getCounter(under.toString());
|
||||
if (counter == null) return;
|
||||
counter.reset(placer.getServer());
|
||||
List<BaseComponent> res = new ArrayList<>();
|
||||
res.add(Messenger.s(String.format("%s counter reset",under.toString())));
|
||||
Messenger.send(placer, res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static DyeColor getWoolColorAtPosition(World worldIn, BlockPos pos)
|
||||
{
|
||||
BlockState state = worldIn.getBlockState(pos);
|
||||
if (state.getMaterial() != Material.CLOTH || !state.isFullCube())
|
||||
return null;
|
||||
return Material2Dye.get(state.getMaterialColor(worldIn, pos));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user