mirror of
https://github.com/Miasmusa/Shadow.git
synced 2025-04-09 02:34:22 -04:00
5000 kromer
This commit is contained in:
parent
3102b0a1be
commit
6b57aecbd4
31 changed files with 1874 additions and 380 deletions
build.gradle
src/main
java/me/x150/sipprivate
SipoverPrivate.java
command
feature
command
gui
module
helper
keybinding
mixin
ClientPlayerEntityMixin.javaIMinecraftClientAccessor.javaIRenderTickCounterAccessor.javaKeyboardMixin.javaMinecraftClientMixin.java
module
util
resources
17
build.gradle
17
build.gradle
|
@ -12,7 +12,9 @@ group = project.maven_group
|
|||
|
||||
minecraft {
|
||||
}
|
||||
|
||||
configurations {
|
||||
impl
|
||||
}
|
||||
dependencies {
|
||||
//to change the versions see the gradle.properties file
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
|
@ -20,6 +22,19 @@ dependencies {
|
|||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
|
||||
|
||||
impl('io.github.spair:imgui-java-binding:1.82.2')
|
||||
impl('io.github.spair:imgui-java-lwjgl3:1.82.2') {
|
||||
exclude group: "org.lwjgl"
|
||||
}
|
||||
["linux", "linux-x86", "macos", "windows", "windows-x86"].each {
|
||||
impl("io.github.spair:imgui-java-natives-$it:1.82.2")
|
||||
}
|
||||
|
||||
configurations.impl.dependencies.each {
|
||||
implementation(group: it.group, name: it.name, version: it.version)
|
||||
include(group: it.group, name: it.name, version: it.version)
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
|
|
@ -12,10 +12,10 @@ import java.io.File;
|
|||
|
||||
public class SipoverPrivate implements ModInitializer {
|
||||
|
||||
public static final String MOD_ID = "sipoverprivate";
|
||||
public static final String MOD_NAME = "SipoverPrivate";
|
||||
public static Logger LOGGER = LogManager.getLogger();
|
||||
public static MinecraftClient client = MinecraftClient.getInstance();
|
||||
public static final String MOD_ID = "sipoverprivate";
|
||||
public static final String MOD_NAME = "SipoverPrivate";
|
||||
public static Logger LOGGER = LogManager.getLogger();
|
||||
public static MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
public static File BASE = new File(MinecraftClient.getInstance().runDirectory, "sip");
|
||||
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
package me.x150.sipprivate.command;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
||||
/**
|
||||
* A class representing a command
|
||||
*/
|
||||
public abstract class Command {
|
||||
|
||||
/**
|
||||
* The minecraft instance
|
||||
*/
|
||||
public final MinecraftClient mc;
|
||||
/**
|
||||
* The main command name
|
||||
*/
|
||||
private final String command;
|
||||
/**
|
||||
* The command's aliases
|
||||
*/
|
||||
private final String[] alias;
|
||||
|
||||
/**
|
||||
* Constructs a new command instance
|
||||
*
|
||||
* @param command The name of the command
|
||||
* @param aliases Triggers for the command
|
||||
*/
|
||||
public Command(String command, String... aliases) {
|
||||
this.command = command;
|
||||
this.alias = aliases;
|
||||
this.mc = MinecraftClient.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command's name
|
||||
*
|
||||
* @return The command name
|
||||
*/
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command's aliases
|
||||
*
|
||||
* @return The command's aliases
|
||||
*/
|
||||
public String[] getAliases() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the command is executed
|
||||
*
|
||||
* @param args The arguments (excluding prefix and command name) specified
|
||||
*/
|
||||
public abstract void runCommand(String[] args);
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package me.x150.sipprivate.command;
|
||||
|
||||
import me.x150.sipprivate.command.commands.BindCommand;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CommandManager {
|
||||
|
||||
/**
|
||||
* A list of all registered commands
|
||||
*/
|
||||
private final List<Command> commands = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs a new command manager
|
||||
*/
|
||||
public CommandManager() {
|
||||
addCommands();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the commands
|
||||
*/
|
||||
public void addCommands() {
|
||||
addCommand(new BindCommand());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a command to the list of registered commands, registering it
|
||||
*
|
||||
* @param command The command instance
|
||||
*/
|
||||
private void addCommand(Command command) {
|
||||
commands.add(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all registered commands
|
||||
*
|
||||
* @return The list of registered commands
|
||||
*/
|
||||
@NotNull public List<Command> getCommands() {
|
||||
return Collections.unmodifiableList(commands);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package me.x150.sipprivate.command.commands;
|
||||
|
||||
import me.x150.sipprivate.command.Command;
|
||||
import me.x150.sipprivate.keybinding.KeybindingManager;
|
||||
import me.x150.sipprivate.module.Module;
|
||||
import me.x150.sipprivate.module.ModuleManager;
|
||||
import me.x150.sipprivate.util.ChatUtil;
|
||||
|
||||
public class BindCommand extends Command {
|
||||
|
||||
public BindCommand() {
|
||||
super("BindCommand", "bind");
|
||||
}
|
||||
|
||||
@Override public void runCommand(String[] args) {
|
||||
if (args.length < 2) {
|
||||
ChatUtil.send("I need the module and key to bind");
|
||||
return;
|
||||
}
|
||||
String mod = args[0];
|
||||
String key = args[1];
|
||||
if (key.length() != 1) {
|
||||
ChatUtil.send("One character as key allowed only");
|
||||
return;
|
||||
}
|
||||
|
||||
int kc = key.toUpperCase().charAt(0);
|
||||
Module m = ModuleManager.instance().getModuleByName(mod);
|
||||
if (m == null) {
|
||||
ChatUtil.send("Cant find that module");
|
||||
return;
|
||||
}
|
||||
ChatUtil.send("BIND " + m.getName() + " -> " + kc + " (" + ((char) kc) + ")");
|
||||
//m.config.get("Keybind").setValue(kc);
|
||||
m.keybind.setValue(kc);
|
||||
KeybindingManager.reload();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* This file is part of the atomic client distribution.
|
||||
* Copyright (c) 2021-2021 0x150.
|
||||
*/
|
||||
|
||||
package me.x150.sipprivate.feature.command;
|
||||
|
||||
public abstract class Command {
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final String[] aliases;
|
||||
|
||||
public Command(String n, String d, String... a) {
|
||||
this.name = n;
|
||||
this.description = d;
|
||||
this.aliases = a;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String[] getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
public abstract void onExecute(String[] args);
|
||||
|
||||
public String[] getSuggestions(String fullCommand, String[] args) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* This file is part of the atomic client distribution.
|
||||
* Copyright (c) 2021-2021 0x150.
|
||||
*/
|
||||
|
||||
package me.x150.sipprivate.feature.command;
|
||||
|
||||
import me.x150.sipprivate.feature.gui.AtomicConsoleScreen;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class CommandRegistry {
|
||||
|
||||
private static final List<Command> commands = new ArrayList<>();
|
||||
|
||||
static {
|
||||
// TODO: 18.12.21 add commands
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
|
||||
}
|
||||
|
||||
public static List<Command> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
public static void execute(String command) {
|
||||
String[] spl = command.split(" +");
|
||||
String cmd = spl[0].toLowerCase();
|
||||
String[] args = Arrays.copyOfRange(spl, 1, spl.length);
|
||||
Command c = CommandRegistry.getByAlias(cmd);
|
||||
if (c == null) {
|
||||
AtomicConsoleScreen.instance().log("Command \"" + cmd + "\" not found", AtomicConsoleScreen.ERROR);
|
||||
} else {
|
||||
AtomicConsoleScreen.instance().log("> " + command, AtomicConsoleScreen.CLIENT);
|
||||
try {
|
||||
c.onExecute(args);
|
||||
} catch (Exception e) {
|
||||
AtomicConsoleScreen.instance().log("Error while running command " + command, AtomicConsoleScreen.ERROR);
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
for (String s : sw.toString().split("\n")) {
|
||||
AtomicConsoleScreen.instance().log(s, AtomicConsoleScreen.BACKGROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Command getByAlias(String n) {
|
||||
for (Command command : getCommands()) {
|
||||
for (String alias : command.getAliases()) {
|
||||
if (alias.equalsIgnoreCase(n)) {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
package me.x150.sipprivate.feature.gui;
|
||||
|
||||
import imgui.ImVec2;
|
||||
import imgui.flag.ImGuiCol;
|
||||
import imgui.flag.ImGuiKey;
|
||||
import imgui.flag.ImGuiStyleVar;
|
||||
import imgui.flag.ImGuiWindowFlags;
|
||||
import imgui.internal.ImGui;
|
||||
import imgui.type.ImString;
|
||||
import me.x150.sipprivate.feature.command.Command;
|
||||
import me.x150.sipprivate.feature.command.CommandRegistry;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class AtomicConsoleScreen extends ImGuiProxyScreen {
|
||||
public static final Color ERROR = new Color(214, 93, 62);
|
||||
public static final Color SUCCESS = new Color(65, 217, 101);
|
||||
public static final Color DEFAULT = Color.WHITE;
|
||||
public static final Color CLIENT = new Color(61, 173, 217);
|
||||
public static final Color BACKGROUND = new Color(80, 99, 107);
|
||||
static AtomicConsoleScreen inst = null;
|
||||
final List<LogEntry> logs = new ArrayList<>();
|
||||
ImString current = new ImString();
|
||||
boolean focusBefore = false;
|
||||
|
||||
private AtomicConsoleScreen() {
|
||||
|
||||
}
|
||||
|
||||
public static AtomicConsoleScreen instance() {
|
||||
if (inst == null) {
|
||||
inst = new AtomicConsoleScreen();
|
||||
}
|
||||
return inst;
|
||||
}
|
||||
|
||||
public void log(String t, Color c) {
|
||||
logs.add(new LogEntry(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, t));
|
||||
}
|
||||
|
||||
@Override protected void renderInternal() {
|
||||
current.inputData.isResizable = true;
|
||||
ImGui.setNextWindowSizeConstraints(300, 200, 800, 500);
|
||||
ImGui.begin("Console");
|
||||
ImGui.pushItemWidth(-1);
|
||||
|
||||
if (ImGui.beginChild("ScrollRegion##", 0, -(ImGui.getStyle().getItemSpacingY() + ImGui.getFrameHeightWithSpacing()), false)) {
|
||||
ImGui.pushTextWrapPos();
|
||||
ImGui.pushStyleVar(ImGuiStyleVar.ItemSpacing, 4, 0);
|
||||
for (LogEntry log : logs) {
|
||||
ImGui.pushStyleColor(ImGuiCol.Text, log.r, log.g, log.b, 1f);
|
||||
ImGui.textUnformatted(" " + log.text);
|
||||
ImGui.popStyleColor();
|
||||
}
|
||||
ImGui.popStyleVar();
|
||||
ImGui.popTextWrapPos();
|
||||
if (ImGui.getScrollY() >= ImGui.getScrollMaxY()) {
|
||||
ImGui.setScrollHereY(1f);
|
||||
}
|
||||
ImGui.endChild();
|
||||
}
|
||||
boolean reclaimFocus = false;
|
||||
ImGui.inputText("", current);
|
||||
if (focusBefore && !ImGui.isItemActive() && ImGui.isKeyPressed(ImGui.getIO().getKeyMap(ImGuiKey.Enter))) {
|
||||
String command = current.get();
|
||||
if (!command.isEmpty()) {
|
||||
CommandRegistry.execute(command);
|
||||
}
|
||||
current.set("");
|
||||
reclaimFocus = true;
|
||||
}
|
||||
focusBefore = ImGui.isItemActive();
|
||||
|
||||
ImGui.popItemWidth();
|
||||
if (reclaimFocus) {
|
||||
ImGui.setKeyboardFocusHere(-1);
|
||||
}
|
||||
String cmd = current.get();
|
||||
if (!cmd.isEmpty() && !getSuggestions(cmd).isEmpty()) {
|
||||
List<String> s = getSuggestions(cmd);
|
||||
ImVec2 c = ImGui.getWindowPos();
|
||||
c.y += ImGui.getWindowHeight() + ImGui.getStyle().getWindowPaddingY();
|
||||
ImGui.setNextWindowSizeConstraints(0, 0, 200, 170);
|
||||
ImGui.begin("cmdSuggestions", ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoFocusOnAppearing);
|
||||
|
||||
ImGui.setWindowPos(c.x, c.y);
|
||||
for (String suggestion : s) {
|
||||
ImGui.text(suggestion);
|
||||
}
|
||||
ImGui.end();
|
||||
}
|
||||
ImGui.end();
|
||||
|
||||
}
|
||||
|
||||
List<String> getSuggestions(String command) {
|
||||
List<String> a = new ArrayList<>();
|
||||
String[] args = command.split(" +");
|
||||
String cmd = args[0].toLowerCase();
|
||||
args = Arrays.copyOfRange(args, 1, args.length);
|
||||
if (command.endsWith(" ")) { // append empty arg when we end with a space
|
||||
String[] args1 = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, args1, 0, args.length);
|
||||
args1[args1.length - 1] = "";
|
||||
args = args1;
|
||||
}
|
||||
if (args.length > 0) {
|
||||
Command c = CommandRegistry.getByAlias(cmd);
|
||||
if (c != null) {
|
||||
a = List.of(c.getSuggestions(command, args));
|
||||
} else {
|
||||
return new ArrayList<>(); // we have no command to ask -> we have no suggestions
|
||||
}
|
||||
} else {
|
||||
for (Command command1 : CommandRegistry.getCommands()) {
|
||||
for (String alias : command1.getAliases()) {
|
||||
if (alias.toLowerCase().startsWith(cmd.toLowerCase())) {
|
||||
a.add(alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String[] finalArgs = args;
|
||||
return finalArgs.length > 0 ? a.stream().filter(s -> s.toLowerCase().startsWith(finalArgs[finalArgs.length - 1].toLowerCase())).collect(Collectors.toList()) : a;
|
||||
}
|
||||
|
||||
|
||||
@Override public boolean isPauseScreen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
record LogEntry(float r, float g, float b, String text) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package me.x150.sipprivate.feature.gui;
|
||||
|
||||
import imgui.ImGui;
|
||||
import me.x150.sipprivate.SipoverPrivate;
|
||||
import me.x150.sipprivate.helper.ImGuiManager;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
|
||||
public abstract class ImGuiProxyScreen extends Screen {
|
||||
public static boolean imguiDebugWindow = false;
|
||||
boolean closed = false;
|
||||
boolean closedAck = false;
|
||||
|
||||
public ImGuiProxyScreen() {
|
||||
super(Text.of(""));
|
||||
ImGuiManager.init();
|
||||
}
|
||||
|
||||
protected abstract void renderInternal();
|
||||
|
||||
@Override protected void init() {
|
||||
closed = closedAck = false;
|
||||
}
|
||||
|
||||
@Override public void onClose() {
|
||||
closed = true;
|
||||
// super.onClose();
|
||||
}
|
||||
|
||||
@Override public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
if (closed && closedAck) {
|
||||
super.onClose();
|
||||
return;
|
||||
}
|
||||
// sets the size of the window in case it got resized
|
||||
ImGui.getIO().setDisplaySize(SipoverPrivate.client.getWindow().getWidth(), SipoverPrivate.client.getWindow().getHeight());
|
||||
// new frame
|
||||
ImGuiManager.getImplGlfw().newFrame();
|
||||
ImGui.newFrame();
|
||||
|
||||
if (!closed) { // render empty frame when closed
|
||||
if (imguiDebugWindow) {
|
||||
ImGui.showMetricsWindow(); // show debug window on all imgui screens if we wish to
|
||||
}
|
||||
|
||||
renderInternal(); // pass it to homeboy
|
||||
} else {
|
||||
closedAck = true;
|
||||
}
|
||||
|
||||
// end the frame
|
||||
ImGui.endFrame();
|
||||
// draw
|
||||
ImGui.render();
|
||||
ImGuiManager.getImplGl3().renderDrawData(ImGui.getDrawData());
|
||||
}
|
||||
}
|
84
src/main/java/me/x150/sipprivate/feature/module/Module.java
Normal file
84
src/main/java/me/x150/sipprivate/feature/module/Module.java
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* This file is part of the atomic client distribution.
|
||||
* Copyright (c) 2021-2021 0x150.
|
||||
*/
|
||||
|
||||
package me.x150.sipprivate.feature.module;
|
||||
|
||||
import me.x150.sipprivate.config.BooleanSetting;
|
||||
import me.x150.sipprivate.config.IntSetting;
|
||||
import me.x150.sipprivate.config.ModuleConfig;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
public abstract class Module {
|
||||
|
||||
public final ModuleConfig config;
|
||||
public final IntSetting keybind;
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final ModuleType moduleType;
|
||||
private final BooleanSetting toasts;
|
||||
private boolean enabled = false;
|
||||
|
||||
public Module(String n, String d, ModuleType type) {
|
||||
this.name = n;
|
||||
this.description = d;
|
||||
this.moduleType = type;
|
||||
this.config = new ModuleConfig();
|
||||
this.keybind = this.config.create(new IntSetting.Builder(-1).name("Keybind").description("The keybind to toggle the module with").min(-1).get());
|
||||
this.toasts = this.config.create(new BooleanSetting.Builder(true).name("Toasts").description("Whether to show enabled / disabled toasts").get());
|
||||
}
|
||||
|
||||
public ModuleType getModuleType() {
|
||||
return moduleType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public abstract void tick();
|
||||
|
||||
public abstract void enable();
|
||||
|
||||
public abstract void disable();
|
||||
|
||||
public abstract String getContext();
|
||||
|
||||
public abstract void onWorldRender(MatrixStack matrices);
|
||||
|
||||
public abstract void onHudRender();
|
||||
|
||||
public void onFastTick() {
|
||||
|
||||
}
|
||||
|
||||
public void onFastTick_NWC() {
|
||||
|
||||
}
|
||||
|
||||
public void toggle() {
|
||||
setEnabled(!enabled);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
if (toasts.getValue()) {
|
||||
// Notification.create(1000, "Module toggle", (this.enabled ? "§aEn" : "§cDis") + "abled §r" + this.getName());
|
||||
}
|
||||
if (this.enabled) {
|
||||
this.enable();
|
||||
} else {
|
||||
this.disable();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* This file is part of the atomic client distribution.
|
||||
* Copyright (c) 2021-2021 0x150.
|
||||
*/
|
||||
|
||||
package me.x150.sipprivate.feature.module;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ModuleRegistry {
|
||||
static final List<Module> modules = new ArrayList<>();
|
||||
static boolean initialized = false;
|
||||
|
||||
public static void init() {
|
||||
initialized = true;
|
||||
|
||||
// TODO: 18.12.21 add modules
|
||||
}
|
||||
|
||||
public static List<Module> getModules() {
|
||||
if (!initialized) {
|
||||
init();
|
||||
}
|
||||
return modules;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") public static <T extends Module> T getByClass(Class<T> clazz) {
|
||||
if (!initialized) {
|
||||
init();
|
||||
}
|
||||
for (Module module : getModules()) {
|
||||
if (module.getClass() == clazz) {
|
||||
return (T) module;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Unregistered module: " + clazz.getName());
|
||||
}
|
||||
|
||||
public static Module getByName(String n) {
|
||||
if (!initialized) {
|
||||
init();
|
||||
}
|
||||
for (Module module : getModules()) {
|
||||
if (module.getName().equalsIgnoreCase(n)) {
|
||||
return module;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* This file is part of the atomic client distribution.
|
||||
* Copyright (c) 2021-2021 0x150.
|
||||
*/
|
||||
|
||||
package me.x150.sipprivate.feature.module;
|
||||
|
||||
public enum ModuleType {
|
||||
RENDER("Render"), MOVEMENT("Movement"), MISC("Miscellaneous"), CLIENT("Client"), COMBAT("Combat"), WORLD("World"), EXPLOIT("Exploit"), HIDDEN(""), FUN("Fun");
|
||||
|
||||
|
||||
final String name;
|
||||
|
||||
ModuleType(String n) {
|
||||
this.name = n;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
139
src/main/java/me/x150/sipprivate/helper/ImGuiManager.java
Normal file
139
src/main/java/me/x150/sipprivate/helper/ImGuiManager.java
Normal file
|
@ -0,0 +1,139 @@
|
|||
package me.x150.sipprivate.helper;
|
||||
|
||||
import imgui.ImGui;
|
||||
import imgui.flag.ImGuiCol;
|
||||
import imgui.gl3.ImGuiImplGl3;
|
||||
import imgui.glfw.ImGuiImplGlfw;
|
||||
import me.x150.sipprivate.SipoverPrivate;
|
||||
import me.x150.sipprivate.feature.gui.ImGuiProxyScreen;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class ImGuiManager {
|
||||
protected static final ImGuiImplGlfw implGlfw = new ImGuiImplGlfw();
|
||||
protected static final ImGuiImplGl3 implGl3 = new ImGuiImplGl3();
|
||||
private static boolean init = false;
|
||||
|
||||
public static boolean isInitialized() {
|
||||
return init;
|
||||
}
|
||||
|
||||
public static ImGuiImplGl3 getImplGl3() {
|
||||
return implGl3;
|
||||
}
|
||||
|
||||
public static ImGuiImplGlfw getImplGlfw() {
|
||||
return implGlfw;
|
||||
}
|
||||
|
||||
private static byte[] getMainFont() {
|
||||
try {
|
||||
return Files.readAllBytes(Paths.get(ImGuiProxyScreen.class.getClassLoader().getResource("Font.ttf").toURI()));
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void style() {
|
||||
// ImGui.getStyle().setWindowRounding(6f);
|
||||
ImGui.getStyle().setWindowPadding(8, 8);
|
||||
ImGui.getStyle().setFramePadding(4, 4);
|
||||
ImGui.getStyle().setCellPadding(4, 2);
|
||||
ImGui.getStyle().setItemSpacing(8, 4);
|
||||
ImGui.getStyle().setItemInnerSpacing(4, 4);
|
||||
ImGui.getStyle().setTouchExtraPadding(0, 0);
|
||||
ImGui.getStyle().setIndentSpacing(21);
|
||||
ImGui.getStyle().setScrollbarSize(10);
|
||||
ImGui.getStyle().setGrabMinSize(4);
|
||||
|
||||
ImGui.getStyle().setWindowRounding(6);
|
||||
ImGui.getStyle().setChildRounding(6);
|
||||
ImGui.getStyle().setFrameRounding(6);
|
||||
ImGui.getStyle().setPopupRounding(6);
|
||||
ImGui.getStyle().setScrollbarRounding(6);
|
||||
ImGui.getStyle().setGrabRounding(6);
|
||||
ImGui.getStyle().setLogSliderDeadzone(4);
|
||||
ImGui.getStyle().setTabRounding(4);
|
||||
|
||||
ImGui.getStyle().setColor(ImGuiCol.Text, 1.00f, 1.00f, 1.00f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TextDisabled, 0.50f, 0.50f, 0.50f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.WindowBg, 0.07f, 0.10f, 0.10f, 0.94f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ChildBg, 0.09f, 0.11f, 0.12f, 0.94f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.PopupBg, 0.05f, 0.07f, 0.08f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.Border, 0.20f, 0.50f, 0.35f, 0.50f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.BorderShadow, 0.00f, 0.00f, 0.00f, 0.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.FrameBg, 0.09f, 0.13f, 0.15f, 0.94f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.FrameBgHovered, 0.12f, 0.18f, 0.20f, 0.94f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.FrameBgActive, 0.17f, 0.23f, 0.26f, 0.94f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TitleBg, 0.06f, 0.10f, 0.12f, 0.94f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TitleBgActive, 0.09f, 0.15f, 0.16f, 0.94f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TitleBgCollapsed, 0.03f, 0.05f, 0.06f, 0.94f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.MenuBarBg, 0.14f, 0.14f, 0.14f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ScrollbarBg, 0.07f, 0.12f, 0.13f, 0.94f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ScrollbarGrab, 0.20f, 0.50f, 0.35f, 0.50f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ScrollbarGrabHovered, 0.28f, 0.54f, 0.41f, 0.50f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ScrollbarGrabActive, 0.20f, 0.50f, 0.28f, 0.50f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.CheckMark, 0.26f, 0.59f, 0.98f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.SliderGrab, 0.24f, 0.52f, 0.88f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.SliderGrabActive, 0.26f, 0.59f, 0.98f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.Button, 0.10f, 0.23f, 0.24f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ButtonHovered, 0.12f, 0.30f, 0.31f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ButtonActive, 0.13f, 0.27f, 0.24f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.Header, 0.15f, 0.22f, 0.31f, 0.31f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.HeaderHovered, 0.16f, 0.28f, 0.41f, 0.31f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.HeaderActive, 0.25f, 0.35f, 0.47f, 0.31f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.Separator, 0.43f, 0.43f, 0.50f, 0.50f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.SeparatorHovered, 0.10f, 0.40f, 0.75f, 0.78f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.SeparatorActive, 0.10f, 0.40f, 0.75f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ResizeGrip, 0.16f, 0.32f, 0.35f, 0.20f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ResizeGripHovered, 0.13f, 0.34f, 0.39f, 0.20f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ResizeGripActive, 0.16f, 0.35f, 0.33f, 0.20f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.Tab, 0.10f, 0.19f, 0.20f, 0.86f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TabHovered, 0.12f, 0.25f, 0.26f, 0.86f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TabActive, 0.12f, 0.26f, 0.24f, 0.86f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TabUnfocused, 0.07f, 0.10f, 0.15f, 0.97f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TabUnfocusedActive, 0.14f, 0.26f, 0.42f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.DockingPreview, 0.26f, 0.59f, 0.98f, 0.70f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.DockingEmptyBg, 0.15f, 0.18f, 0.19f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.PlotLines, 0.61f, 0.85f, 0.80f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.PlotLinesHovered, 1.00f, 0.43f, 0.35f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.PlotHistogram, 0.90f, 0.70f, 0.00f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.PlotHistogramHovered, 1.00f, 0.60f, 0.00f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TableHeaderBg, 0.19f, 0.19f, 0.20f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TableBorderStrong, 0.31f, 0.31f, 0.35f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TableBorderLight, 0.23f, 0.23f, 0.25f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TableRowBg, 0.00f, 0.00f, 0.00f, 0.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TableRowBgAlt, 1.00f, 1.00f, 1.00f, 0.06f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.TextSelectedBg, 0.26f, 0.98f, 0.61f, 0.35f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.DragDropTarget, 1.00f, 1.00f, 0.00f, 0.90f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.NavHighlight, 0.26f, 0.59f, 0.98f, 1.00f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.NavWindowingHighlight, 1.00f, 1.00f, 1.00f, 0.70f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.NavWindowingDimBg, 0.80f, 0.80f, 0.80f, 0.20f);
|
||||
ImGui.getStyle().setColor(ImGuiCol.ModalWindowDimBg, 0.80f, 0.80f, 0.80f, 0.35f);
|
||||
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
if (init) {
|
||||
return;
|
||||
}
|
||||
|
||||
init = true;
|
||||
long win = SipoverPrivate.client.getWindow().getHandle();
|
||||
ImGui.createContext();
|
||||
initFonts();
|
||||
style();
|
||||
implGlfw.init(win, true);
|
||||
implGl3.init();
|
||||
ImGui.getIO().setConfigWindowsMoveFromTitleBarOnly(true);
|
||||
// ImGui.getIO().addConfigFlags(ImGuiConfigFlags.ViewportsEnable);
|
||||
ImGui.getStyle().setWindowMenuButtonPosition(-1);
|
||||
}
|
||||
|
||||
public static void initFonts() {
|
||||
ImGui.getIO().getFonts().addFontFromMemoryTTF(getMainFont(), 18);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package me.x150.sipprivate.helper.font;
|
||||
|
||||
import me.x150.sipprivate.helper.font.adapter.FontAdapter;
|
||||
import me.x150.sipprivate.helper.font.adapter.impl.ClientFontRenderer;
|
||||
import me.x150.sipprivate.helper.font.render.GlyphPageFontRenderer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FontRenderers {
|
||||
private static final List<ClientFontRenderer> fontRenderers = new ArrayList<>();
|
||||
private static FontAdapter normal, title, mono, vanilla;
|
||||
|
||||
public static FontAdapter getNormal() {
|
||||
return normal;
|
||||
}
|
||||
|
||||
public static void setNormal(FontAdapter normal) {
|
||||
FontRenderers.normal = normal;
|
||||
}
|
||||
|
||||
public static ClientFontRenderer getCustomNormal(int size) {
|
||||
for (ClientFontRenderer fontRenderer : fontRenderers) {
|
||||
if (fontRenderer.getSize() == size) {
|
||||
return fontRenderer;
|
||||
}
|
||||
}
|
||||
ClientFontRenderer cfr = new ClientFontRenderer(GlyphPageFontRenderer.createFromID("Font.ttf", size, false, false, false));
|
||||
fontRenderers.add(cfr);
|
||||
return cfr;
|
||||
}
|
||||
|
||||
public static FontAdapter getMono() {
|
||||
return mono;
|
||||
}
|
||||
|
||||
public static void setMono(FontAdapter mono) {
|
||||
FontRenderers.mono = mono;
|
||||
}
|
||||
|
||||
public static FontAdapter getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public static void setTitle(FontAdapter title) {
|
||||
FontRenderers.title = title;
|
||||
}
|
||||
|
||||
public static FontAdapter getVanilla() {
|
||||
return vanilla;
|
||||
}
|
||||
|
||||
public static void setVanilla(FontAdapter vanilla) {
|
||||
FontRenderers.vanilla = vanilla;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package me.x150.sipprivate.helper.font.adapter;
|
||||
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
public interface FontAdapter {
|
||||
int drawString(MatrixStack matrices, String text, float x, float y, int color);
|
||||
|
||||
int drawString(MatrixStack matrices, String text, double x, double y, int color);
|
||||
|
||||
int drawCenteredString(MatrixStack matrices, String text, double x, double y, int color);
|
||||
|
||||
float getStringWidth(String text);
|
||||
|
||||
float getFontHeight();
|
||||
|
||||
float getMarginHeight();
|
||||
|
||||
void drawString(MatrixStack matrices, String s, float x, float y, int color, boolean dropShadow);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package me.x150.sipprivate.helper.font.adapter.impl;
|
||||
|
||||
import me.x150.sipprivate.helper.font.adapter.FontAdapter;
|
||||
import me.x150.sipprivate.helper.font.render.GlyphPageFontRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
public class ClientFontRenderer implements FontAdapter {
|
||||
final GlyphPageFontRenderer renderer;
|
||||
|
||||
public ClientFontRenderer(GlyphPageFontRenderer gpfr) {
|
||||
this.renderer = gpfr;
|
||||
}
|
||||
|
||||
@Override public int drawString(MatrixStack matrices, String text, float x, float y, int color) {
|
||||
return renderer.drawString(matrices, text, x, y, color);
|
||||
}
|
||||
|
||||
@Override public int drawString(MatrixStack matrices, String text, double x, double y, int color) {
|
||||
return renderer.drawString(matrices, text, x, y, color);
|
||||
}
|
||||
|
||||
@Override public int drawCenteredString(MatrixStack matrices, String text, double x, double y, int color) {
|
||||
return renderer.drawCenteredString(matrices, text, x, y, color);
|
||||
}
|
||||
|
||||
@Override public float getStringWidth(String text) {
|
||||
return renderer.getStringWidth(text);
|
||||
}
|
||||
|
||||
@Override public float getFontHeight() {
|
||||
return renderer.getFontHeight();
|
||||
}
|
||||
|
||||
@Override public float getMarginHeight() {
|
||||
return getFontHeight();
|
||||
}
|
||||
|
||||
@Override public void drawString(MatrixStack matrices, String s, float x, float y, int color, boolean dropShadow) {
|
||||
renderer.drawString(matrices, s, x, y, color, dropShadow);
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return renderer.size;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package me.x150.sipprivate.helper.font.adapter.impl;
|
||||
|
||||
import me.x150.sipprivate.SipoverPrivate;
|
||||
import me.x150.sipprivate.helper.font.adapter.FontAdapter;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
public class VanillaFontRenderer implements FontAdapter {
|
||||
@Override public int drawString(MatrixStack matrices, String text, float x, float y, int color) {
|
||||
return SipoverPrivate.client.textRenderer.draw(matrices, text, x, y, color);
|
||||
}
|
||||
|
||||
@Override public int drawString(MatrixStack matrices, String text, double x, double y, int color) {
|
||||
return SipoverPrivate.client.textRenderer.draw(matrices, text, (float) x, (float) y, color);
|
||||
}
|
||||
|
||||
@Override public int drawCenteredString(MatrixStack matrices, String text, double x, double y, int color) {
|
||||
return drawString(matrices, text, x - getStringWidth(text) / 2d, y, color);
|
||||
}
|
||||
|
||||
@Override public float getStringWidth(String text) {
|
||||
return SipoverPrivate.client.textRenderer.getWidth(text);
|
||||
}
|
||||
|
||||
@Override public float getFontHeight() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override public float getMarginHeight() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
@Override public void drawString(MatrixStack matrices, String s, float x, float y, int color, boolean dropShadow) {
|
||||
drawString(matrices, s, x, y, color);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
package me.x150.sipprivate.helper.font.render;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.BufferRenderer;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import net.minecraft.client.render.Tessellator;
|
||||
import net.minecraft.client.render.VertexFormat;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.texture.AbstractTexture;
|
||||
import net.minecraft.client.texture.NativeImage;
|
||||
import net.minecraft.client.texture.NativeImageBackedTexture;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import org.lwjgl.BufferUtils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class GlyphPage {
|
||||
|
||||
private final Font font;
|
||||
private final boolean antiAliasing;
|
||||
private final boolean fractionalMetrics;
|
||||
private final HashMap<Character, Glyph> glyphCharacterMap = new HashMap<>();
|
||||
private int imgSize;
|
||||
private int maxFontHeight = -1;
|
||||
private BufferedImage bufferedImage;
|
||||
private AbstractTexture loadedTexture;
|
||||
|
||||
public GlyphPage(Font font, boolean antiAliasing, boolean fractionalMetrics) {
|
||||
this.font = font;
|
||||
this.antiAliasing = antiAliasing;
|
||||
this.fractionalMetrics = fractionalMetrics;
|
||||
}
|
||||
|
||||
public void generateGlyphPage(char[] chars) {
|
||||
// Calculate glyphPageSize
|
||||
double maxWidth = -1;
|
||||
double maxHeight = -1;
|
||||
|
||||
AffineTransform affineTransform = new AffineTransform();
|
||||
FontRenderContext fontRenderContext = new FontRenderContext(affineTransform, antiAliasing, fractionalMetrics);
|
||||
|
||||
for (char ch : chars) {
|
||||
Rectangle2D bounds = font.getStringBounds(Character.toString(ch), fontRenderContext);
|
||||
|
||||
if (maxWidth < bounds.getWidth()) {
|
||||
maxWidth = bounds.getWidth();
|
||||
}
|
||||
if (maxHeight < bounds.getHeight()) {
|
||||
maxHeight = bounds.getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
// Leave some additional space
|
||||
|
||||
maxWidth += 2;
|
||||
maxHeight += 2;
|
||||
|
||||
imgSize = (int) Math.ceil(Math.max(Math.ceil(Math.sqrt(maxWidth * maxWidth * chars.length) / maxWidth), Math.ceil(Math.sqrt(maxHeight * maxHeight * chars.length) / maxHeight)) * Math.max(maxWidth, maxHeight)) + 1;
|
||||
|
||||
bufferedImage = new BufferedImage(imgSize, imgSize, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D g = bufferedImage.createGraphics();
|
||||
|
||||
g.setFont(font);
|
||||
// Set Color to Transparent
|
||||
g.setColor(new Color(255, 255, 255, 0));
|
||||
// Set the image background to transparent
|
||||
g.fillRect(0, 0, imgSize, imgSize);
|
||||
|
||||
g.setColor(Color.white);
|
||||
|
||||
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, fractionalMetrics ? RenderingHints.VALUE_FRACTIONALMETRICS_ON : RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAliasing ? RenderingHints.VALUE_ANTIALIAS_OFF : RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, antiAliasing ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
|
||||
|
||||
FontMetrics fontMetrics = g.getFontMetrics();
|
||||
|
||||
int currentCharHeight = 0;
|
||||
int posX = 0;
|
||||
int posY = 1;
|
||||
|
||||
for (char ch : chars) {
|
||||
Glyph glyph = new Glyph();
|
||||
|
||||
Rectangle2D bounds = fontMetrics.getStringBounds(Character.toString(ch), g);
|
||||
|
||||
glyph.width = bounds.getBounds().width + 8; // Leave some additional space
|
||||
glyph.height = bounds.getBounds().height;
|
||||
|
||||
if (posX + glyph.width >= imgSize) {
|
||||
posX = 0;
|
||||
posY += currentCharHeight;
|
||||
currentCharHeight = 0;
|
||||
}
|
||||
|
||||
glyph.x = posX;
|
||||
glyph.y = posY;
|
||||
|
||||
if (glyph.height > maxFontHeight) {
|
||||
maxFontHeight = glyph.height;
|
||||
}
|
||||
|
||||
if (glyph.height > currentCharHeight) {
|
||||
currentCharHeight = glyph.height;
|
||||
}
|
||||
|
||||
g.drawString(Character.toString(ch), posX + 2, posY + fontMetrics.getAscent());
|
||||
|
||||
posX += glyph.width;
|
||||
|
||||
glyphCharacterMap.put(ch, glyph);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void setupTexture() {
|
||||
try {
|
||||
// Converting to ByteBuffer
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(bufferedImage, "png", baos);
|
||||
byte[] bytes = baos.toByteArray();
|
||||
|
||||
ByteBuffer data = BufferUtils.createByteBuffer(bytes.length).put(bytes);
|
||||
data.flip();
|
||||
loadedTexture = new NativeImageBackedTexture(NativeImage.read(data));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void bindTexture() {
|
||||
RenderSystem.setShaderTexture(0, loadedTexture.getGlId());
|
||||
}
|
||||
|
||||
public void unbindTexture() {
|
||||
RenderSystem.setShaderTexture(0, 0);
|
||||
}
|
||||
|
||||
public float drawChar(MatrixStack stack, char ch, float x, float y, float red, float blue, float green, float alpha) {
|
||||
Glyph glyph = glyphCharacterMap.get(ch);
|
||||
|
||||
if (glyph == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float pageX = glyph.x / (float) imgSize;
|
||||
float pageY = glyph.y / (float) imgSize;
|
||||
|
||||
float pageWidth = glyph.width / (float) imgSize;
|
||||
float pageHeight = glyph.height / (float) imgSize;
|
||||
|
||||
float width = glyph.width;
|
||||
float height = glyph.height;
|
||||
|
||||
BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
|
||||
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorTexShader);
|
||||
bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE);
|
||||
|
||||
bufferBuilder.vertex(stack.peek().getPositionMatrix(), x, y + height, 0).color(red, green, blue, alpha).texture(pageX, pageY + pageHeight).next();
|
||||
bufferBuilder.vertex(stack.peek().getPositionMatrix(), x + width, y + height, 0).color(red, green, blue, alpha).texture(pageX + pageWidth, pageY + pageHeight).next();
|
||||
bufferBuilder.vertex(stack.peek().getPositionMatrix(), x + width, y, 0).color(red, green, blue, alpha).texture(pageX + pageWidth, pageY).next();
|
||||
bufferBuilder.vertex(stack.peek().getPositionMatrix(), x, y, 0).color(red, green, blue, alpha).texture(pageX, pageY).next();
|
||||
bufferBuilder.end();
|
||||
|
||||
BufferRenderer.draw(bufferBuilder);
|
||||
|
||||
return width - 8;
|
||||
}
|
||||
|
||||
public float getWidth(char ch) {
|
||||
Glyph g = glyphCharacterMap.get(ch);
|
||||
return g == null ? 0 : g.width;
|
||||
}
|
||||
|
||||
public int getMaxFontHeight() {
|
||||
return maxFontHeight;
|
||||
}
|
||||
|
||||
public boolean isAntiAliasingEnabled() {
|
||||
return antiAliasing;
|
||||
}
|
||||
|
||||
public boolean isFractionalMetricsEnabled() {
|
||||
return fractionalMetrics;
|
||||
}
|
||||
|
||||
static class Glyph {
|
||||
|
||||
private int x;
|
||||
private int y;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
Glyph() {
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,528 @@
|
|||
package me.x150.sipprivate.helper.font.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.BufferRenderer;
|
||||
import net.minecraft.client.render.Tessellator;
|
||||
import net.minecraft.client.render.VertexFormat;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_LINEAR;
|
||||
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
|
||||
import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
|
||||
|
||||
public class GlyphPageFontRenderer {
|
||||
|
||||
/**
|
||||
* Array of RGB triplets defining the 16 standard chat colors followed by 16 darker version of the same colors for drop shadows.
|
||||
*/
|
||||
private final int[] colorCode = new int[32];
|
||||
private final GlyphPage regularGlyphPage;
|
||||
private final GlyphPage boldGlyphPage;
|
||||
private final GlyphPage italicGlyphPage;
|
||||
private final GlyphPage boldItalicGlyphPage;
|
||||
public int size = -1;
|
||||
/**
|
||||
* Current X coordinate at which to draw the next character.
|
||||
*/
|
||||
private float posX;
|
||||
/**
|
||||
* Current Y coordinate at which to draw the next character.
|
||||
*/
|
||||
private float posY;
|
||||
/**
|
||||
* Set if the "l" style (bold) is active in currently rendering string
|
||||
*/
|
||||
private boolean boldStyle;
|
||||
/**
|
||||
* Set if the "o" style (italic) is active in currently rendering string
|
||||
*/
|
||||
private boolean italicStyle;
|
||||
/**
|
||||
* Set if the "n" style (underlined) is active in currently rendering string
|
||||
*/
|
||||
private boolean underlineStyle;
|
||||
/**
|
||||
* Set if the "m" style (strikethrough) is active in currently rendering string
|
||||
*/
|
||||
private boolean strikethroughStyle;
|
||||
|
||||
public GlyphPageFontRenderer(GlyphPage regularGlyphPage, GlyphPage boldGlyphPage, GlyphPage italicGlyphPage, GlyphPage boldItalicGlyphPage) {
|
||||
this.regularGlyphPage = regularGlyphPage;
|
||||
this.boldGlyphPage = boldGlyphPage;
|
||||
this.italicGlyphPage = italicGlyphPage;
|
||||
this.boldItalicGlyphPage = boldItalicGlyphPage;
|
||||
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
int j = (i >> 3 & 1) * 85;
|
||||
int k = (i >> 2 & 1) * 170 + j;
|
||||
int l = (i >> 1 & 1) * 170 + j;
|
||||
int i1 = (i & 1) * 170 + j;
|
||||
|
||||
if (i == 6) {
|
||||
k += 85;
|
||||
}
|
||||
|
||||
if (i >= 16) {
|
||||
k /= 4;
|
||||
l /= 4;
|
||||
i1 /= 4;
|
||||
}
|
||||
|
||||
this.colorCode[i] = (k & 255) << 16 | (l & 255) << 8 | i1 & 255;
|
||||
}
|
||||
}
|
||||
|
||||
public static GlyphPageFontRenderer create(String fontName, int size, boolean bold, boolean italic, boolean boldItalic) {
|
||||
char[] chars = new char[256];
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
chars[i] = (char) i;
|
||||
}
|
||||
|
||||
GlyphPage regularPage;
|
||||
|
||||
regularPage = new GlyphPage(new Font(fontName, Font.PLAIN, size), true, true);
|
||||
|
||||
regularPage.generateGlyphPage(chars);
|
||||
regularPage.setupTexture();
|
||||
|
||||
GlyphPage boldPage = regularPage;
|
||||
GlyphPage italicPage = regularPage;
|
||||
GlyphPage boldItalicPage = regularPage;
|
||||
|
||||
if (bold) {
|
||||
boldPage = new GlyphPage(new Font(fontName, Font.BOLD, size), true, true);
|
||||
|
||||
boldPage.generateGlyphPage(chars);
|
||||
boldPage.setupTexture();
|
||||
}
|
||||
|
||||
if (italic) {
|
||||
italicPage = new GlyphPage(new Font(fontName, Font.ITALIC, size), true, true);
|
||||
|
||||
italicPage.generateGlyphPage(chars);
|
||||
italicPage.setupTexture();
|
||||
}
|
||||
|
||||
if (boldItalic) {
|
||||
boldItalicPage = new GlyphPage(new Font(fontName, Font.BOLD | Font.ITALIC, size), true, true);
|
||||
|
||||
boldItalicPage.generateGlyphPage(chars);
|
||||
boldItalicPage.setupTexture();
|
||||
}
|
||||
|
||||
GlyphPageFontRenderer gpfr = new GlyphPageFontRenderer(regularPage, boldPage, italicPage, boldItalicPage);
|
||||
gpfr.size = size;
|
||||
return gpfr;
|
||||
}
|
||||
|
||||
public static GlyphPageFontRenderer createFromStream(InputStream inp, int size, boolean bold, boolean italic, boolean boldItalic) {
|
||||
char[] chars = new char[256];
|
||||
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
chars[i] = (char) i;
|
||||
}
|
||||
|
||||
Font font = null;
|
||||
|
||||
try {
|
||||
font = Font.createFont(Font.TRUETYPE_FONT, inp).deriveFont(Font.PLAIN, size);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
GlyphPage regularPage;
|
||||
|
||||
regularPage = new GlyphPage(font, true, true);
|
||||
regularPage.generateGlyphPage(chars);
|
||||
regularPage.setupTexture();
|
||||
|
||||
GlyphPage boldPage = regularPage;
|
||||
GlyphPage italicPage = regularPage;
|
||||
GlyphPage boldItalicPage = regularPage;
|
||||
|
||||
try {
|
||||
if (bold) {
|
||||
boldPage = new GlyphPage(Font.createFont(Font.TRUETYPE_FONT, inp).deriveFont(Font.BOLD, size), true, true);
|
||||
|
||||
boldPage.generateGlyphPage(chars);
|
||||
boldPage.setupTexture();
|
||||
}
|
||||
|
||||
if (italic) {
|
||||
italicPage = new GlyphPage(Font.createFont(Font.TRUETYPE_FONT, inp).deriveFont(Font.ITALIC, size), true, true);
|
||||
|
||||
italicPage.generateGlyphPage(chars);
|
||||
italicPage.setupTexture();
|
||||
}
|
||||
|
||||
if (boldItalic) {
|
||||
boldItalicPage = new GlyphPage(Font.createFont(Font.TRUETYPE_FONT, inp).deriveFont(Font.BOLD | Font.ITALIC, size), true, true);
|
||||
|
||||
boldItalicPage.generateGlyphPage(chars);
|
||||
boldItalicPage.setupTexture();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new GlyphPageFontRenderer(regularPage, boldPage, italicPage, boldItalicPage);
|
||||
}
|
||||
|
||||
public static GlyphPageFontRenderer createFromID(String id, int size, boolean bold, boolean italic, boolean boldItalic) {
|
||||
char[] chars = new char[256];
|
||||
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
chars[i] = (char) i;
|
||||
}
|
||||
|
||||
Font font = null;
|
||||
|
||||
try {
|
||||
font = Font.createFont(Font.TRUETYPE_FONT, Objects.requireNonNull(GlyphPageFontRenderer.class.getClassLoader().getResourceAsStream(id))).deriveFont(Font.PLAIN, size);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
GlyphPage regularPage;
|
||||
|
||||
regularPage = new GlyphPage(font, true, true);
|
||||
regularPage.generateGlyphPage(chars);
|
||||
regularPage.setupTexture();
|
||||
|
||||
GlyphPage boldPage = regularPage;
|
||||
GlyphPage italicPage = regularPage;
|
||||
GlyphPage boldItalicPage = regularPage;
|
||||
|
||||
try {
|
||||
if (bold) {
|
||||
boldPage = new GlyphPage(Font.createFont(Font.TRUETYPE_FONT, Objects.requireNonNull(GlyphPageFontRenderer.class.getClassLoader().getResourceAsStream(id)))
|
||||
.deriveFont(Font.BOLD, size), true, true);
|
||||
|
||||
boldPage.generateGlyphPage(chars);
|
||||
boldPage.setupTexture();
|
||||
}
|
||||
|
||||
if (italic) {
|
||||
italicPage = new GlyphPage(Font.createFont(Font.TRUETYPE_FONT, Objects.requireNonNull(GlyphPageFontRenderer.class.getClassLoader().getResourceAsStream(id)))
|
||||
.deriveFont(Font.ITALIC, size), true, true);
|
||||
|
||||
italicPage.generateGlyphPage(chars);
|
||||
italicPage.setupTexture();
|
||||
}
|
||||
|
||||
if (boldItalic) {
|
||||
boldItalicPage = new GlyphPage(Font.createFont(Font.TRUETYPE_FONT, Objects.requireNonNull(GlyphPageFontRenderer.class.getClassLoader().getResourceAsStream(id)))
|
||||
.deriveFont(Font.BOLD | Font.ITALIC, size), true, true);
|
||||
|
||||
boldItalicPage.generateGlyphPage(chars);
|
||||
boldItalicPage.setupTexture();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
GlyphPageFontRenderer gp = new GlyphPageFontRenderer(regularPage, boldPage, italicPage, boldItalicPage);
|
||||
gp.size = size;
|
||||
return gp;
|
||||
}
|
||||
|
||||
public int drawString(MatrixStack matrices, String text, float x, float y, int color) {
|
||||
return drawString(matrices, text, x, y, color, true);
|
||||
}
|
||||
|
||||
public int drawString(MatrixStack matrices, String text, double x, double y, int color) {
|
||||
return drawString(matrices, text, (float) x, (float) y, color, true);
|
||||
}
|
||||
|
||||
public int drawCenteredString(MatrixStack matrices, String text, double x, double y, int color) {
|
||||
return drawString(matrices, text, (float) x - getStringWidth(text) / 2f, (float) y, color, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the specified string.
|
||||
*/
|
||||
public int drawString(MatrixStack matrices, String text, float x, float y, int color, boolean dropShadow) {
|
||||
this.resetStyles();
|
||||
int i;
|
||||
|
||||
if (dropShadow) {
|
||||
i = this.renderString(matrices, text, x + .5F, y + .5F, color, true);
|
||||
i = Math.max(i, this.renderString(matrices, text, x, y, color, false));
|
||||
} else {
|
||||
i = this.renderString(matrices, text, x, y, color, false);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render single line string by setting GL color, current (posX,posY), and calling renderStringAtPos()
|
||||
*/
|
||||
private int renderString(MatrixStack matrices, String text, float x, float y, int color, boolean dropShadow) {
|
||||
if (text == null) {
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
if ((color & 0xfc000000) == 0) {
|
||||
color |= 0xff000000;
|
||||
}
|
||||
|
||||
if (dropShadow) {
|
||||
color = 0xFF323232;
|
||||
}
|
||||
this.posX = x * 2.0f;
|
||||
this.posY = y * 2.0f;
|
||||
this.renderStringAtPos(matrices, text, dropShadow, color);
|
||||
return (int) (this.posX / 4.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a single line string at the current (posX,posY) and update posX
|
||||
*/
|
||||
private void renderStringAtPos(MatrixStack matrices, String text, boolean shadow, int color) {
|
||||
GlyphPage glyphPage = getCurrentGlyphPage();
|
||||
float alpha = (float) (color >> 24 & 255) / 255.0F;
|
||||
float r = (float) (color >> 16 & 255) / 255.0F;
|
||||
float g = (float) (color >> 8 & 255) / 255.0F;
|
||||
float b = (float) (color & 255) / 255.0F;
|
||||
|
||||
matrices.push();
|
||||
|
||||
matrices.scale(0.5F, 0.5F, 0.5F);
|
||||
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
RenderSystem.enableTexture();
|
||||
|
||||
glyphPage.bindTexture();
|
||||
|
||||
GlStateManager._texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
for (int i = 0; i < text.length(); ++i) {
|
||||
char c0 = text.charAt(i);
|
||||
|
||||
if (c0 == '§' && i + 1 < text.length()) {
|
||||
int i1 = "0123456789abcdefklmnor".indexOf(text.toLowerCase().charAt(i + 1));
|
||||
|
||||
if (i1 < 16) {
|
||||
resetStyles();
|
||||
|
||||
if (i1 < 0) {
|
||||
i1 = 15;
|
||||
}
|
||||
|
||||
if (shadow) {
|
||||
i1 += 16;
|
||||
}
|
||||
|
||||
int j1 = this.colorCode[i1];
|
||||
|
||||
r = (float) (j1 >> 16 & 255) / 255.0F;
|
||||
g = (float) (j1 >> 8 & 255) / 255.0F;
|
||||
b = (float) (j1 & 255) / 255.0F;
|
||||
} else if (i1 == 17) {
|
||||
this.boldStyle = true;
|
||||
} else if (i1 == 18) {
|
||||
this.strikethroughStyle = true;
|
||||
} else if (i1 == 19) {
|
||||
this.underlineStyle = true;
|
||||
} else if (i1 == 20) {
|
||||
this.italicStyle = true;
|
||||
} else if (i1 == 21) {
|
||||
resetStyles();
|
||||
alpha = (float) (color >> 24 & 255) / 255.0F;
|
||||
r = (float) (color >> 16 & 255) / 255.0F;
|
||||
g = (float) (color >> 8 & 255) / 255.0F;
|
||||
b = (float) (color & 255) / 255.0F;
|
||||
}
|
||||
|
||||
++i;
|
||||
} else {
|
||||
float f = glyphPage.drawChar(matrices, c0, posX, posY, r, b, g, alpha);
|
||||
|
||||
doDraw(f, glyphPage);
|
||||
}
|
||||
}
|
||||
|
||||
//glyphPage.unbindTexture();
|
||||
matrices.pop();
|
||||
|
||||
}
|
||||
|
||||
private void doDraw(float f, GlyphPage glyphPage) {
|
||||
BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
|
||||
GlStateManager._disableTexture();
|
||||
if (this.strikethroughStyle) {
|
||||
bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION);
|
||||
bufferBuilder.vertex(this.posX, this.posY + (float) (glyphPage.getMaxFontHeight() / 2), 0.0D).next();
|
||||
bufferBuilder.vertex(this.posX + f, this.posY + (float) (glyphPage.getMaxFontHeight() / 2), 0.0D).next();
|
||||
bufferBuilder.vertex(this.posX + f, this.posY + (float) (glyphPage.getMaxFontHeight() / 2) - 1.0F, 0.0D).next();
|
||||
bufferBuilder.vertex(this.posX, this.posY + (float) (glyphPage.getMaxFontHeight() / 2) - 1.0F, 0.0D).next();
|
||||
bufferBuilder.end();
|
||||
BufferRenderer.draw(bufferBuilder);
|
||||
GlStateManager._enableTexture();
|
||||
}
|
||||
|
||||
if (this.underlineStyle) {
|
||||
bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION);
|
||||
int l = this.underlineStyle ? -1 : 0;
|
||||
bufferBuilder.vertex(this.posX + (float) l, this.posY + (float) glyphPage.getMaxFontHeight(), 0.0D).next();
|
||||
bufferBuilder.vertex(this.posX + f, this.posY + (float) glyphPage.getMaxFontHeight(), 0.0D).next();
|
||||
bufferBuilder.vertex(this.posX + f, this.posY + (float) glyphPage.getMaxFontHeight() - 1.0F, 0.0D).next();
|
||||
bufferBuilder.vertex(this.posX + (float) l, this.posY + (float) glyphPage.getMaxFontHeight() - 1.0F, 0.0D).next();
|
||||
bufferBuilder.end();
|
||||
BufferRenderer.draw(bufferBuilder);
|
||||
GlStateManager._enableTexture();
|
||||
}
|
||||
|
||||
this.posX += f;
|
||||
}
|
||||
|
||||
private GlyphPage getCurrentGlyphPage() {
|
||||
if (boldStyle && italicStyle) {
|
||||
return boldItalicGlyphPage;
|
||||
} else if (boldStyle) {
|
||||
return boldGlyphPage;
|
||||
} else if (italicStyle) {
|
||||
return italicGlyphPage;
|
||||
} else {
|
||||
return regularGlyphPage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all style flag fields in the class to false; called at the start of string rendering
|
||||
*/
|
||||
private void resetStyles() {
|
||||
this.boldStyle = false;
|
||||
this.italicStyle = false;
|
||||
this.underlineStyle = false;
|
||||
this.strikethroughStyle = false;
|
||||
}
|
||||
|
||||
public int getFontHeight() {
|
||||
return regularGlyphPage.getMaxFontHeight() / 2;
|
||||
}
|
||||
|
||||
public int getStringWidth(String text) {
|
||||
if (text == null) {
|
||||
return 0;
|
||||
}
|
||||
int width = 0;
|
||||
|
||||
GlyphPage currentPage;
|
||||
|
||||
int size = text.length();
|
||||
|
||||
boolean on = false;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
char character = text.charAt(i);
|
||||
|
||||
if (character == '§') {
|
||||
on = true;
|
||||
} else if (on && character >= '0' && character <= 'r') {
|
||||
int colorIndex = "0123456789abcdefklmnor".indexOf(character);
|
||||
if (colorIndex < 16) {
|
||||
boldStyle = false;
|
||||
italicStyle = false;
|
||||
} else if (colorIndex == 17) {
|
||||
boldStyle = true;
|
||||
} else if (colorIndex == 20) {
|
||||
italicStyle = true;
|
||||
} else if (colorIndex == 21) {
|
||||
boldStyle = false;
|
||||
italicStyle = false;
|
||||
}
|
||||
on = false;
|
||||
} else {
|
||||
on = false;
|
||||
character = text.charAt(i);
|
||||
|
||||
currentPage = getCurrentGlyphPage();
|
||||
|
||||
width += currentPage.getWidth(character) - 8;
|
||||
//i++;
|
||||
}
|
||||
}
|
||||
|
||||
return width / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims a string to fit a specified Width.
|
||||
*/
|
||||
public String trimStringToWidth(String text, int width) {
|
||||
return this.trimStringToWidth(text, width, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims a string to a specified width, and will reverse it if par3 is set.
|
||||
*/
|
||||
public String trimStringToWidth(String text, int maxWidth, boolean reverse) {
|
||||
StringBuilder stringbuilder = new StringBuilder();
|
||||
|
||||
boolean on = false;
|
||||
|
||||
int j = reverse ? text.length() - 1 : 0;
|
||||
int k = reverse ? -1 : 1;
|
||||
int width = 0;
|
||||
|
||||
GlyphPage currentPage;
|
||||
|
||||
for (int i = j; i >= 0 && i < text.length() && i < maxWidth; i += k) {
|
||||
char character = text.charAt(i);
|
||||
|
||||
if (character == '§') {
|
||||
on = true;
|
||||
} else if (on && character >= '0' && character <= 'r') {
|
||||
int colorIndex = "0123456789abcdefklmnor".indexOf(character);
|
||||
if (colorIndex < 16) {
|
||||
boldStyle = false;
|
||||
italicStyle = false;
|
||||
} else if (colorIndex == 17) {
|
||||
boldStyle = true;
|
||||
} else if (colorIndex == 20) {
|
||||
italicStyle = true;
|
||||
} else if (colorIndex == 21) {
|
||||
boldStyle = false;
|
||||
italicStyle = false;
|
||||
}
|
||||
on = false;
|
||||
} else {
|
||||
if (on) {
|
||||
i--; // include the §, because color code is invalid
|
||||
}
|
||||
character = text.charAt(i);
|
||||
|
||||
currentPage = getCurrentGlyphPage();
|
||||
|
||||
width += (currentPage.getWidth(character) - 8) / 2;
|
||||
}
|
||||
|
||||
if (i > width) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (reverse) {
|
||||
stringbuilder.insert(0, character);
|
||||
} else {
|
||||
stringbuilder.append(character);
|
||||
}
|
||||
}
|
||||
|
||||
return stringbuilder.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package me.x150.sipprivate.keybinding;
|
||||
|
||||
import me.x150.sipprivate.module.Module;
|
||||
import me.x150.sipprivate.module.ModuleManager;
|
||||
import me.x150.sipprivate.feature.module.Module;
|
||||
import me.x150.sipprivate.feature.module.ModuleRegistry;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -20,7 +20,7 @@ public class KeybindingManager {
|
|||
* Init the keybinding manager
|
||||
*/
|
||||
public static void init() {
|
||||
for (Module module : ModuleManager.instance().getModules()) {
|
||||
for (Module module : ModuleRegistry.getModules()) {
|
||||
keybindMap.put(module, new Keybind(module.keybind.getValue()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ClientPlayerEntity.class)
|
||||
public class ClientPlayerEntityMixin {
|
||||
@Mixin(ClientPlayerEntity.class) public class ClientPlayerEntityMixin {
|
||||
@Inject(method = "tick", at = @At("HEAD")) void tick(CallbackInfo ci) {
|
||||
if (!ConfigManager.enabled) {
|
||||
ConfigManager.enableModules();
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package me.x150.sipprivate.mixin;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
import net.minecraft.client.util.Session;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(MinecraftClient.class) public interface IMinecraftClientAccessor {
|
||||
|
||||
@Mutable @Accessor("session") void setSession(Session newSession);
|
||||
|
||||
@Accessor("renderTickCounter") RenderTickCounter getRenderTickCounter();
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package me.x150.sipprivate.mixin;
|
||||
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(RenderTickCounter.class) public interface IRenderTickCounterAccessor {
|
||||
|
||||
@Mutable @Accessor("tickTime") void setTickTime(float v);
|
||||
}
|
|
@ -8,8 +8,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Keyboard.class)
|
||||
public class KeyboardMixin {
|
||||
@Mixin(Keyboard.class) public class KeyboardMixin {
|
||||
@Inject(method = "onKey", at = @At("RETURN")) void atomic_postKeyPressed(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) {
|
||||
if (window == MinecraftClient.getInstance().getWindow()
|
||||
.getHandle() && MinecraftClient.getInstance().currentScreen == null) { // make sure we are in game and the screen has been there for at least 10 ms
|
||||
|
|
|
@ -7,8 +7,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
public class MinecraftClientMixin {
|
||||
@Mixin(MinecraftClient.class) public class MinecraftClientMixin {
|
||||
@Inject(method = "stop", at = @At("HEAD")) void real(CallbackInfo ci) {
|
||||
ConfigManager.saveState();
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package me.x150.sipprivate.module;
|
||||
|
||||
/**
|
||||
* Enum containing each category of module
|
||||
*/
|
||||
public enum Category {
|
||||
|
||||
COMBAT("Combat"), MOVEMENT("Movement"), RENDER("Render"), EXPLOIT("Exploit"), PLAYER("Player"), MISC("Miscellaneous");
|
||||
String name;
|
||||
|
||||
Category(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
package me.x150.sipprivate.module;
|
||||
|
||||
import me.x150.sipprivate.config.IntSetting;
|
||||
import me.x150.sipprivate.config.ModuleConfig;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
||||
/**
|
||||
* A container describing a module
|
||||
*/
|
||||
public abstract class Module {
|
||||
|
||||
/**
|
||||
* The minecraft instance
|
||||
*/
|
||||
protected static final MinecraftClient mc = MinecraftClient.getInstance();
|
||||
/**
|
||||
* The configuration of this module
|
||||
*/
|
||||
public final ModuleConfig config;
|
||||
/**
|
||||
* The name of this module
|
||||
*/
|
||||
private final String name;
|
||||
/**
|
||||
* The description of this module
|
||||
*/
|
||||
private final String description;
|
||||
/**
|
||||
* The category this module belongs in
|
||||
*/
|
||||
private final Category category;
|
||||
/**
|
||||
* The keybind of this module
|
||||
*/
|
||||
public IntSetting keybind;
|
||||
/**
|
||||
* Whether this module is currently enabled
|
||||
*/
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Constructs a new module
|
||||
*
|
||||
* @param name The name of the module
|
||||
* @param description The description of this module
|
||||
* @param category Which category this module belongs in
|
||||
*/
|
||||
public Module(String name, String description, Category category) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
this.config = new ModuleConfig();
|
||||
keybind = config.create(new IntSetting.Builder(-1).min(-1).name("Keybind").description("The keybind to toggle the module with").get());
|
||||
// this.config.create("Keybind", -1).description("The keybind to toggle the module with");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this module
|
||||
*
|
||||
* @return This module's name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of this module
|
||||
*
|
||||
* @return This module's description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the category of this module
|
||||
*
|
||||
* @return This module's category
|
||||
*/
|
||||
public Category getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this module is enabled or not
|
||||
*
|
||||
* @return true if the module is enabled, false if otherwise
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this module's enabled state
|
||||
*
|
||||
* @param enabled The new enabled state
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
if (this.enabled) {
|
||||
onEnable();
|
||||
} else {
|
||||
onDisable();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns this module on if it's off, off when otherwise
|
||||
*/
|
||||
public void toggle() {
|
||||
setEnabled(!isEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets called when the module switches from disabled to enabled, not implemented in base class
|
||||
*/
|
||||
protected abstract void onEnable();
|
||||
|
||||
/**
|
||||
* Gets called when the module switches from enabled to disabled, not implemented in base class
|
||||
*/
|
||||
protected abstract void onDisable();
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package me.x150.sipprivate.module;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The module manager
|
||||
*/
|
||||
public class ModuleManager {
|
||||
|
||||
private static final ModuleManager instance = new ModuleManager();
|
||||
/**
|
||||
* A list of all registered modules
|
||||
*/
|
||||
private final List<Module> modules = new ArrayList<>();
|
||||
|
||||
private ModuleManager() {
|
||||
addModules();
|
||||
}
|
||||
|
||||
public static ModuleManager instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all modules we want to register
|
||||
*/
|
||||
public void addModules() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a module
|
||||
*
|
||||
* @param module The module to register
|
||||
*/
|
||||
private void addModule(Module module) {
|
||||
modules.add(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all modules
|
||||
*
|
||||
* @return The modules
|
||||
*/
|
||||
@NotNull public List<Module> getModules() {
|
||||
return Collections.unmodifiableList(modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first module which has the name we specified, null if no module matches
|
||||
*
|
||||
* @param name The name we want to find
|
||||
* @return The module found, null otherwise
|
||||
*/
|
||||
@Nullable public Module getModuleByName(String name) {
|
||||
for (Module m : modules) {
|
||||
if (m.getName().equalsIgnoreCase(name)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -6,9 +6,9 @@ import com.google.gson.JsonObject;
|
|||
import com.google.gson.JsonParser;
|
||||
import me.x150.sipprivate.SipoverPrivate;
|
||||
import me.x150.sipprivate.config.SettingBase;
|
||||
import me.x150.sipprivate.feature.module.Module;
|
||||
import me.x150.sipprivate.feature.module.ModuleRegistry;
|
||||
import me.x150.sipprivate.keybinding.KeybindingManager;
|
||||
import me.x150.sipprivate.module.Module;
|
||||
import me.x150.sipprivate.module.ModuleManager;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
@ -116,7 +116,7 @@ public class ConfigManager {
|
|||
JsonObject base = new JsonObject();
|
||||
JsonArray enabled = new JsonArray();
|
||||
JsonArray config = new JsonArray();
|
||||
for (Module module : ModuleManager.instance().getModules()) {
|
||||
for (Module module : ModuleRegistry.getModules()) {
|
||||
if (module.isEnabled()) {
|
||||
enabled.add(module.getName());
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ public class ConfigManager {
|
|||
if (jsonElement.isJsonObject()) {
|
||||
JsonObject jobj = jsonElement.getAsJsonObject();
|
||||
String name = jobj.get("name").getAsString();
|
||||
Module j = ModuleManager.instance().getModuleByName(name);
|
||||
Module j = ModuleRegistry.getByName(name);
|
||||
if (j == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ public class ConfigManager {
|
|||
if (config.has("enabled") && config.get("enabled").isJsonArray()) {
|
||||
for (JsonElement enabled : config.get("enabled").getAsJsonArray()) {
|
||||
String name = enabled.getAsString();
|
||||
Module m = ModuleManager.instance().getModuleByName(name);
|
||||
Module m = ModuleRegistry.getByName(name);
|
||||
if (m != null) {
|
||||
toBeEnabled.add(m);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,322 @@
|
|||
/*
|
||||
* This file is part of the atomic client distribution.
|
||||
* Copyright (c) 2021-2021 0x150.
|
||||
*/
|
||||
|
||||
package me.x150.sipprivate.util;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import me.x150.sipprivate.SipoverPrivate;
|
||||
import me.x150.sipprivate.feature.gui.AtomicConsoleScreen;
|
||||
import me.x150.sipprivate.helper.font.adapter.FontAdapter;
|
||||
import me.x150.sipprivate.mixin.IMinecraftClientAccessor;
|
||||
import me.x150.sipprivate.mixin.IRenderTickCounterAccessor;
|
||||
import net.minecraft.client.network.ServerInfo;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtDouble;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
import net.minecraft.nbt.StringNbtReader;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.RaycastContext;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Utils {
|
||||
|
||||
/**
|
||||
* Returns an RGB color based on time
|
||||
*
|
||||
* @return The color
|
||||
*/
|
||||
public static ServerInfo latestServerInfo;
|
||||
|
||||
public static void sleep(long ms) {
|
||||
try {
|
||||
Thread.sleep(ms);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setClientTps(float tps) {
|
||||
IRenderTickCounterAccessor accessor = ((IRenderTickCounterAccessor) ((IMinecraftClientAccessor) SipoverPrivate.client).getRenderTickCounter());
|
||||
accessor.setTickTime(1000f / tps);
|
||||
}
|
||||
|
||||
public static Color getCurrentRGB() {
|
||||
return new Color(Color.HSBtoRGB((System.currentTimeMillis() % 4750) / 4750f, 0.5f, 1));
|
||||
}
|
||||
|
||||
public static String[] splitLinesToWidth(String input, double maxWidth, FontAdapter rendererUsed) {
|
||||
List<String> dSplit = List.of(input.split("\n"));
|
||||
List<String> splits = new ArrayList<>();
|
||||
for (String s : dSplit) {
|
||||
List<String> splitContent = new ArrayList<>();
|
||||
StringBuilder line = new StringBuilder();
|
||||
for (String c : s.split(" ")) {
|
||||
if (rendererUsed.getStringWidth(line + c) >= maxWidth - 10) {
|
||||
splitContent.add(line.toString().trim());
|
||||
line = new StringBuilder();
|
||||
}
|
||||
line.append(c).append(" ");
|
||||
}
|
||||
splitContent.add(line.toString().trim());
|
||||
splits.addAll(splitContent);
|
||||
}
|
||||
return splits.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue") public static NbtCompound putPos(Vec3d pos, NbtCompound comp) {
|
||||
NbtList list = new NbtList();
|
||||
list.add(NbtDouble.of(pos.x));
|
||||
list.add(NbtDouble.of(pos.y));
|
||||
list.add(NbtDouble.of(pos.z));
|
||||
comp.put("Pos", list);
|
||||
return comp;
|
||||
}
|
||||
|
||||
public static ItemStack generateItemStackWithMeta(String nbt, Item item) {
|
||||
try {
|
||||
ItemStack stack = new ItemStack(item);
|
||||
stack.setNbt(StringNbtReader.parse(nbt));
|
||||
return stack;
|
||||
} catch (Exception ignored) {
|
||||
return new ItemStack(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Inventory {
|
||||
|
||||
public static int slotIndexToId(int index) {
|
||||
int translatedSlotId;
|
||||
if (index >= 0 && index < 9) {
|
||||
translatedSlotId = 36 + index;
|
||||
} else {
|
||||
translatedSlotId = index;
|
||||
}
|
||||
return translatedSlotId;
|
||||
}
|
||||
|
||||
public static void drop(int index) {
|
||||
int translatedSlotId = slotIndexToId(index);
|
||||
Objects.requireNonNull(SipoverPrivate.client.interactionManager)
|
||||
.clickSlot(Objects.requireNonNull(SipoverPrivate.client.player).currentScreenHandler.syncId, translatedSlotId, 1, SlotActionType.THROW, SipoverPrivate.client.player);
|
||||
}
|
||||
|
||||
public static void moveStackToOther(int slotIdFrom, int slotIdTo) {
|
||||
Objects.requireNonNull(SipoverPrivate.client.interactionManager).clickSlot(0, slotIdFrom, 0, SlotActionType.PICKUP, SipoverPrivate.client.player); // pick up item from stack
|
||||
SipoverPrivate.client.interactionManager.clickSlot(0, slotIdTo, 0, SlotActionType.PICKUP, SipoverPrivate.client.player); // put item to target
|
||||
SipoverPrivate.client.interactionManager.clickSlot(0, slotIdFrom, 0, SlotActionType.PICKUP, SipoverPrivate.client.player); // (in case target slot had item) put item from target back to from
|
||||
}
|
||||
}
|
||||
|
||||
public static class Math {
|
||||
|
||||
public static boolean isNumber(String in) {
|
||||
try {
|
||||
Integer.parseInt(in);
|
||||
return true;
|
||||
} catch (Exception ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static double roundToDecimal(double n, int point) {
|
||||
if (point == 0) {
|
||||
return java.lang.Math.floor(n);
|
||||
}
|
||||
double factor = java.lang.Math.pow(10, point);
|
||||
return java.lang.Math.round(n * factor) / factor;
|
||||
}
|
||||
|
||||
public static int tryParseInt(String input, int defaultValue) {
|
||||
try {
|
||||
return Integer.parseInt(input);
|
||||
} catch (Exception ignored) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vec3d getRotationVector(float pitch, float yaw) {
|
||||
float f = pitch * 0.017453292F;
|
||||
float g = -yaw * 0.017453292F;
|
||||
float h = MathHelper.cos(g);
|
||||
float i = MathHelper.sin(g);
|
||||
float j = MathHelper.cos(f);
|
||||
float k = MathHelper.sin(f);
|
||||
return new Vec3d(i * j, -k, h * j);
|
||||
}
|
||||
|
||||
public static boolean isABObstructed(Vec3d a, Vec3d b, World world, Entity requester) {
|
||||
RaycastContext rcc = new RaycastContext(a, b, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, requester);
|
||||
BlockHitResult bhr = world.raycast(rcc);
|
||||
return !bhr.getPos().equals(b);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Mouse {
|
||||
|
||||
public static double getMouseX() {
|
||||
return SipoverPrivate.client.mouse.getX() / SipoverPrivate.client.getWindow().getScaleFactor();
|
||||
}
|
||||
|
||||
public static double getMouseY() {
|
||||
return SipoverPrivate.client.mouse.getY() / SipoverPrivate.client.getWindow().getScaleFactor();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Players {
|
||||
|
||||
static final Map<String, UUID> UUID_CACHE = new HashMap<>();
|
||||
static final Map<UUID, String> NAME_CACHE = new HashMap<>();
|
||||
static final HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
|
||||
|
||||
public static String getNameFromUUID(UUID uuid) {
|
||||
if (NAME_CACHE.containsKey(uuid)) {
|
||||
return NAME_CACHE.get(uuid);
|
||||
}
|
||||
try {
|
||||
HttpRequest req = HttpRequest.newBuilder().GET().uri(URI.create("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid)).build();
|
||||
HttpResponse<String> response = client.send(req, HttpResponse.BodyHandlers.ofString());
|
||||
if (response.statusCode() == 204 || response.statusCode() == 400) {
|
||||
return null; // no user / invalid username
|
||||
}
|
||||
JsonObject root = JsonParser.parseString(response.body()).getAsJsonObject();
|
||||
return root.get("name").getAsString();
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static UUID getUUIDFromName(String name) {
|
||||
if (!isPlayerNameValid(name)) {
|
||||
return null;
|
||||
}
|
||||
if (UUID_CACHE.containsKey(name.toLowerCase())) {
|
||||
return UUID_CACHE.get(name.toLowerCase());
|
||||
}
|
||||
try {
|
||||
HttpRequest req = HttpRequest.newBuilder().GET().uri(URI.create("https://api.mojang.com/users/profiles/minecraft/" + name)).build();
|
||||
HttpResponse<String> response = client.send(req, HttpResponse.BodyHandlers.ofString());
|
||||
if (response.statusCode() == 204 || response.statusCode() == 400) {
|
||||
return null; // no user / invalid username
|
||||
}
|
||||
JsonObject root = JsonParser.parseString(response.body()).getAsJsonObject();
|
||||
String id = root.get("id").getAsString();
|
||||
String uuid = id.replaceAll("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5");
|
||||
UUID u = UUID.fromString(uuid);
|
||||
UUID_CACHE.put(name.toLowerCase(), u);
|
||||
return u;
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPlayerNameValid(String name) {
|
||||
if (name.length() < 3 || name.length() > 16) {
|
||||
return false;
|
||||
}
|
||||
String valid = "abcdefghijklmnopqrstuvwxyz0123456789_";
|
||||
boolean isValidEntityName = true;
|
||||
for (char c : name.toLowerCase().toCharArray()) {
|
||||
if (!valid.contains(c + "")) {
|
||||
isValidEntityName = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isValidEntityName;
|
||||
}
|
||||
|
||||
public static int[] decodeUUID(UUID uuid) {
|
||||
long sigLeast = uuid.getLeastSignificantBits();
|
||||
long sigMost = uuid.getMostSignificantBits();
|
||||
return new int[]{(int) (sigMost >> 32), (int) sigMost, (int) (sigLeast >> 32), (int) sigLeast};
|
||||
}
|
||||
}
|
||||
|
||||
public static class Logging {
|
||||
public static void warn(String n) {
|
||||
message0(n, Color.YELLOW);
|
||||
}
|
||||
|
||||
public static void success(String n) {
|
||||
message0(n, AtomicConsoleScreen.SUCCESS);
|
||||
}
|
||||
|
||||
public static void error(String n) {
|
||||
message0(n, AtomicConsoleScreen.ERROR);
|
||||
}
|
||||
|
||||
public static void message(String n) {
|
||||
message0(n, AtomicConsoleScreen.DEFAULT);
|
||||
}
|
||||
|
||||
public static void message0(String n, Color c) {
|
||||
AtomicConsoleScreen.instance().log(n, c);
|
||||
}
|
||||
|
||||
public static void messageChat(String n) {
|
||||
if (SipoverPrivate.client.player == null) {
|
||||
return;
|
||||
}
|
||||
SipoverPrivate.client.player.sendMessage(Text.of("[§9A§r] " + n), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TickManager {
|
||||
|
||||
static final List<TickEntry> entries = new ArrayList<>();
|
||||
static final List<Runnable> nextTickRunners = new ArrayList<>();
|
||||
|
||||
public static void runInNTicks(int n, Runnable toRun) {
|
||||
entries.add(new TickEntry(n, toRun));
|
||||
}
|
||||
|
||||
public static void tick() {
|
||||
for (TickEntry entry : entries.toArray(new TickEntry[0])) {
|
||||
entry.v--;
|
||||
if (entry.v <= 0) {
|
||||
entry.r.run();
|
||||
entries.remove(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void runOnNextRender(Runnable r) {
|
||||
nextTickRunners.add(r);
|
||||
}
|
||||
|
||||
public static void render() {
|
||||
for (Runnable nextTickRunner : nextTickRunners) {
|
||||
nextTickRunner.run();
|
||||
}
|
||||
nextTickRunners.clear();
|
||||
}
|
||||
|
||||
static class TickEntry {
|
||||
|
||||
final Runnable r;
|
||||
int v;
|
||||
|
||||
public TickEntry(int v, Runnable r) {
|
||||
this.v = v;
|
||||
this.r = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"ClientPlayerEntityMixin",
|
||||
"IMinecraftClientAccessor",
|
||||
"IRenderTickCounterAccessor",
|
||||
"KeyboardMixin",
|
||||
"MinecraftClientMixin"
|
||||
],
|
||||
|
|
Loading…
Add table
Reference in a new issue