Add basic Script visualization and colorization
This commit is contained in:
@ -0,0 +1,13 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Command {
|
||||||
|
public final boolean repeatable;
|
||||||
|
public final List<List<TokenType>> arguments;
|
||||||
|
|
||||||
|
public Command(boolean repeatable, List<List<TokenType>> arguments) {
|
||||||
|
this.repeatable = repeatable;
|
||||||
|
this.arguments = arguments;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Commands {
|
||||||
|
|
||||||
|
private Commands() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Command> COMMANDS = new HashMap<>();
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class Headers {
|
||||||
|
|
||||||
|
private Headers() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Set<String> HEADERS = new HashSet<>();
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class Operators {
|
||||||
|
|
||||||
|
private Operators() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Set<String> OPERATORS = new HashSet<>();
|
||||||
|
}
|
||||||
@ -0,0 +1,239 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ScriptColorizer {
|
||||||
|
|
||||||
|
private ScriptColorizer() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Token> colorize(int lineNumber, String line) {
|
||||||
|
if (lineNumber == 0) {
|
||||||
|
List<Token> tokens = colorizeHeader(line);
|
||||||
|
if (tokens != null) return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Token> tokens;
|
||||||
|
tokens = colorizeComment(line);
|
||||||
|
if (tokens != null) return tokens;
|
||||||
|
tokens = colorizeJumpPoint(line);
|
||||||
|
if (tokens != null) return tokens;
|
||||||
|
return colorizeLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> colorizeHeader(String line) {
|
||||||
|
if (!line.startsWith("#!")) return null;
|
||||||
|
List<Token> tokens = new ArrayList<>();
|
||||||
|
tokens.add(new Token("#!", TokenTypeColors.COMMENT));
|
||||||
|
String s = line.substring(2);
|
||||||
|
|
||||||
|
for (String pattern : Headers.HEADERS) {
|
||||||
|
if (s.matches(pattern)) {
|
||||||
|
tokens.add(new Token(s, TokenTypeColors.OTHER));
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tokens.add(new Token(s, TokenTypeColors.ERROR));
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> colorizeComment(String line) {
|
||||||
|
if (!line.startsWith("#")) return null;
|
||||||
|
return List.of(new Token(line, TokenTypeColors.COMMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> colorizeJumpPoint(String line) {
|
||||||
|
if (!line.startsWith(".")) return null;
|
||||||
|
return List.of(new Token(line, TokenTypeColors.JUMP_POINT));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> colorizeLine(String line) {
|
||||||
|
List<Token> tokens = new ArrayList<>();
|
||||||
|
|
||||||
|
String command = line;
|
||||||
|
if (line.indexOf(' ') != -1) {
|
||||||
|
command = line.substring(0, line.indexOf(' '));
|
||||||
|
}
|
||||||
|
boolean repeatable = false;
|
||||||
|
List<List<TokenType>> argumentTypes = null;
|
||||||
|
if (Commands.COMMANDS.containsKey(command)) {
|
||||||
|
Command c = Commands.COMMANDS.get(command);
|
||||||
|
repeatable = c.repeatable;
|
||||||
|
argumentTypes = c.arguments;
|
||||||
|
tokens.add(new Token(command, TokenTypeColors.LITERAL));
|
||||||
|
} else {
|
||||||
|
repeatable = true;
|
||||||
|
argumentTypes = new ArrayList<>();
|
||||||
|
argumentTypes.add(List.of(TokenType.any));
|
||||||
|
tokens.add(new Token(command, TokenTypeColors.OTHER));
|
||||||
|
}
|
||||||
|
if (command.equals(line)) return tokens;
|
||||||
|
tokens.add(Token.SPACE);
|
||||||
|
|
||||||
|
String args = line.substring(command.length() + 1).trim();
|
||||||
|
tokens.addAll(colorizeArgs(args, repeatable, argumentTypes));
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> colorizeArgs(String args, boolean repeatable, List<List<TokenType>> argumentTypes) {
|
||||||
|
List<Token> tokens = new ArrayList<>();
|
||||||
|
|
||||||
|
for (List<TokenType> tokenTypes : argumentTypes) {
|
||||||
|
List<Token> temp = new ArrayList<>();
|
||||||
|
int index = 0;
|
||||||
|
int argIndex = 0;
|
||||||
|
try {
|
||||||
|
while (argIndex < args.length()) {
|
||||||
|
if (args.charAt(argIndex) == ' ') {
|
||||||
|
argIndex++;
|
||||||
|
temp.add(Token.SPACE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<Token> current = parse(tokenTypes.get(index), args.substring(argIndex));
|
||||||
|
if (current.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
temp.addAll(current);
|
||||||
|
argIndex += current.stream().mapToInt(t -> t.text.length()).sum();
|
||||||
|
index++;
|
||||||
|
if (repeatable && index == tokenTypes.size()) {
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
if (index == tokenTypes.size()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (argIndex != args.length()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (index != tokenTypes.size() - (repeatable ? 1 : 0)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!temp.isEmpty()) {
|
||||||
|
tokens.addAll(temp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokens.isEmpty()) {
|
||||||
|
tokens.add(new Token(args, TokenTypeColors.OTHER));
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> parse(TokenType type, String current) {
|
||||||
|
return switch (type) {
|
||||||
|
case any -> parseAny(current);
|
||||||
|
case expression -> parseExpression(current);
|
||||||
|
case jump_point -> parseJumpPoint(current);
|
||||||
|
case variable -> parseVariable(current);
|
||||||
|
case text_type -> parseText(current);
|
||||||
|
case number_type -> parseNumber(current);
|
||||||
|
case floating_number_type -> parseFloatingNumber(current);
|
||||||
|
case boolean_type -> parseBoolean(current);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> parseAny(String current) {
|
||||||
|
List<Token> tokens = parseExpression(current);
|
||||||
|
if (!tokens.isEmpty()) return tokens;
|
||||||
|
tokens = parseFloatingNumber(current);
|
||||||
|
if (!tokens.isEmpty()) return tokens;
|
||||||
|
tokens = parseNumber(current);
|
||||||
|
if (!tokens.isEmpty()) return tokens;
|
||||||
|
tokens = parseBoolean(current);
|
||||||
|
if (!tokens.isEmpty()) return tokens;
|
||||||
|
return parseText(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> parseExpression(String current) {
|
||||||
|
if (!current.startsWith("{")) return new ArrayList<>();
|
||||||
|
int depth = 0;
|
||||||
|
int index = 0;
|
||||||
|
do {
|
||||||
|
if (current.charAt(index) == '{') {
|
||||||
|
depth++;
|
||||||
|
} else if (current.charAt(index) == '}') {
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
} while (depth != 0 && index <= current.length());
|
||||||
|
if (depth != 0) return List.of(new Token(current, TokenTypeColors.ERROR));
|
||||||
|
String expression = current.substring(0, index); // TODO: colorize expression
|
||||||
|
return List.of(new Token(expression, TokenTypeColors.OTHER));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> parseJumpPoint(String current) {
|
||||||
|
int index = current.indexOf(' ');
|
||||||
|
if (index == -1) {
|
||||||
|
return List.of(new Token(current, TokenTypeColors.JUMP_POINT));
|
||||||
|
} else {
|
||||||
|
return List.of(new Token(current.substring(0, index), TokenTypeColors.JUMP_POINT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> parseVariable(String current) {
|
||||||
|
int index = current.indexOf(' ');
|
||||||
|
if (index == -1) {
|
||||||
|
return List.of(new Token(current, TokenTypeColors.VARIABLE));
|
||||||
|
} else {
|
||||||
|
return List.of(new Token(current.substring(0, index), TokenTypeColors.VARIABLE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> parseText(String current) {
|
||||||
|
int index = current.indexOf(' ');
|
||||||
|
if (index == -1) {
|
||||||
|
return List.of(new Token(current, TokenTypeColors.TEXT));
|
||||||
|
} else {
|
||||||
|
return List.of(new Token(current.substring(0, index), TokenTypeColors.TEXT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> parseNumber(String current) {
|
||||||
|
int index = current.indexOf(' ');
|
||||||
|
String number = current;
|
||||||
|
if (index != -1) {
|
||||||
|
number = current.substring(0, index);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Long.parseLong(number);
|
||||||
|
return List.of(new Token(number, TokenTypeColors.NUMBER));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> parseFloatingNumber(String current) {
|
||||||
|
int index = current.indexOf(' ');
|
||||||
|
String number = current;
|
||||||
|
if (index != -1) {
|
||||||
|
number = current.substring(0, index);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Double.parseDouble(number);
|
||||||
|
return List.of(new Token(number, TokenTypeColors.NUMBER));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Token> parseBoolean(String current) {
|
||||||
|
int index = current.indexOf(' ');
|
||||||
|
String bool = current;
|
||||||
|
if (index != -1) {
|
||||||
|
bool = current.substring(0, index);
|
||||||
|
}
|
||||||
|
if ("true".equalsIgnoreCase(bool) || "false".equalsIgnoreCase(bool)) {
|
||||||
|
return List.of(new Token(bool, TokenTypeColors.BOOLEAN));
|
||||||
|
} else {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class ScriptSyntaxPacketParser {
|
||||||
|
|
||||||
|
private ScriptSyntaxPacketParser() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final TokenType[] TOKEN_TYPES = TokenType.values();
|
||||||
|
|
||||||
|
private static void reset() {
|
||||||
|
Operators.OPERATORS.clear();
|
||||||
|
Headers.HEADERS.clear();
|
||||||
|
VariablePrefixes.RPEFIXES.clear();
|
||||||
|
VariableSuffixes.SUFFIXES.clear();
|
||||||
|
Commands.COMMANDS.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized void parse(String scriptSyntax) {
|
||||||
|
reset();
|
||||||
|
|
||||||
|
JsonObject jsonObject = JsonParser.parseString(scriptSyntax).getAsJsonObject();
|
||||||
|
for (String key : jsonObject.keySet()) {
|
||||||
|
JsonArray jsonElements = jsonObject.get(key).getAsJsonArray();
|
||||||
|
if (key.startsWith("@")) {
|
||||||
|
parseSpecial(key, jsonElements);
|
||||||
|
} else {
|
||||||
|
parseCommand(key, jsonElements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void parseCommand(String key, JsonArray value) {
|
||||||
|
boolean repeating = value.get(0).getAsBoolean();
|
||||||
|
List<List<TokenType>> validArgumentTypes = new ArrayList<>();
|
||||||
|
for (int i = 1; i < value.size(); i++) {
|
||||||
|
JsonArray parameters = value.get(i).getAsJsonArray();
|
||||||
|
List<TokenType> parameterTypes = new ArrayList<>();
|
||||||
|
for (JsonElement parameter : parameters) {
|
||||||
|
parameterTypes.add(TOKEN_TYPES[parameter.getAsInt()]);
|
||||||
|
}
|
||||||
|
validArgumentTypes.add(parameterTypes);
|
||||||
|
}
|
||||||
|
Commands.COMMANDS.put(key, new Command(repeating, validArgumentTypes));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void parseSpecial(String key, JsonArray value) {
|
||||||
|
Set<String> set;
|
||||||
|
switch (key) {
|
||||||
|
case "@operators":
|
||||||
|
set = Operators.OPERATORS;
|
||||||
|
break;
|
||||||
|
case "@headers":
|
||||||
|
set = Headers.HEADERS;
|
||||||
|
break;
|
||||||
|
case "@prefixes":
|
||||||
|
set = VariablePrefixes.RPEFIXES;
|
||||||
|
break;
|
||||||
|
case "@suffixes":
|
||||||
|
set = VariableSuffixes.SUFFIXES;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (JsonElement element : value) {
|
||||||
|
set.add(element.getAsString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/main/java/de/zonlykroks/advancedscripts/lexer/Token.java
Normal file
13
src/main/java/de/zonlykroks/advancedscripts/lexer/Token.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
public class Token {
|
||||||
|
public static final Token SPACE = new Token(" ", 0xFFFFFFFF);
|
||||||
|
|
||||||
|
public final String text;
|
||||||
|
public final int color;
|
||||||
|
|
||||||
|
public Token(String text, int color) {
|
||||||
|
this.text = text;
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
public enum TokenType { // This is copied from the BauSystem2.0 sources.
|
||||||
|
any, // This does not include jump_point and variable
|
||||||
|
expression,
|
||||||
|
jump_point,
|
||||||
|
variable,
|
||||||
|
|
||||||
|
text_type,
|
||||||
|
number_type,
|
||||||
|
floating_number_type,
|
||||||
|
boolean_type,
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
public class TokenTypeColors {
|
||||||
|
|
||||||
|
private TokenTypeColors() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int BACKGROUND = 0xFF1E1F22;
|
||||||
|
public static final int OTHER = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
public static final int ERROR = 0xFFAA0000;
|
||||||
|
|
||||||
|
public static final int VARIABLE = 0xFFFFFFFF;
|
||||||
|
public static final int LITERAL = 0xFF925F35;
|
||||||
|
public static final int COMMENT = 0xFF656565;
|
||||||
|
public static final int JUMP_POINT = 0xFFFFa500;
|
||||||
|
|
||||||
|
public static final int NUMBER = 0xFF61839F;
|
||||||
|
public static final int BOOLEAN = 0xFF925F35;
|
||||||
|
public static final int TEXT = 0xFF6F855D;
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class VariablePrefixes {
|
||||||
|
|
||||||
|
private VariablePrefixes() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Set<String> RPEFIXES = new HashSet<>();
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.lexer;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class VariableSuffixes {
|
||||||
|
|
||||||
|
private VariableSuffixes() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Set<String> SUFFIXES = new HashSet<>();
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.mixin;
|
||||||
|
|
||||||
|
import de.zonlykroks.advancedscripts.lexer.ScriptSyntaxPacketParser;
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ClientPlayNetworkHandler.class)
|
||||||
|
public class ClientPlayNetworkHandlerMixin {
|
||||||
|
|
||||||
|
private static final Identifier CHANNEL = new Identifier("sw:script_syntax");
|
||||||
|
|
||||||
|
@Inject(method = "onCustomPayload", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/CustomPayloadS2CPacket;getData()Lnet/minecraft/network/PacketByteBuf;"), cancellable = true)
|
||||||
|
public void onCustomPayload(CustomPayloadS2CPacket packet, CallbackInfo ci) {
|
||||||
|
if (CHANNEL.equals(packet.getChannel())) {
|
||||||
|
PacketByteBuf buf = packet.getData();
|
||||||
|
int readableBytes = buf.readableBytes();
|
||||||
|
StringBuilder st = new StringBuilder();
|
||||||
|
for (int i = 0; i < readableBytes; i++) {
|
||||||
|
st.append((char) buf.readByte());
|
||||||
|
}
|
||||||
|
ScriptSyntaxPacketParser.parse(st.toString());
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.mixin;
|
||||||
|
|
||||||
|
import de.zonlykroks.advancedscripts.screen.ScriptEditScreen;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ClientPlayerEntity.class)
|
||||||
|
public class ClientPlayerEntityMixin {
|
||||||
|
|
||||||
|
@Shadow @Final protected MinecraftClient client;
|
||||||
|
|
||||||
|
@Inject(method = "useBook", at = @At("HEAD"), cancellable = true)
|
||||||
|
public void useBookMixin(ItemStack book, Hand hand, CallbackInfo ci) {
|
||||||
|
if (book.isOf(Items.WRITABLE_BOOK)) {
|
||||||
|
this.client.setScreen(new ScriptEditScreen(((ClientPlayerEntity)(Object)this), book, hand));
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,111 @@
|
|||||||
|
package de.zonlykroks.advancedscripts.screen;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import de.zonlykroks.advancedscripts.lexer.ScriptColorizer;
|
||||||
|
import de.zonlykroks.advancedscripts.lexer.Token;
|
||||||
|
import de.zonlykroks.advancedscripts.lexer.TokenTypeColors;
|
||||||
|
import net.minecraft.client.font.TextHandler;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.BookScreen;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
|
import net.minecraft.client.util.NarratorManager;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.text.Style;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class ScriptEditScreen extends Screen {
|
||||||
|
|
||||||
|
private PlayerEntity player;
|
||||||
|
private ItemStack itemStack;
|
||||||
|
private Hand hand;
|
||||||
|
|
||||||
|
private List<String> lines = new ArrayList<>();
|
||||||
|
|
||||||
|
public ScriptEditScreen(PlayerEntity player, ItemStack itemStack, Hand hand) {
|
||||||
|
super(NarratorManager.EMPTY);
|
||||||
|
this.player = player;
|
||||||
|
this.itemStack = itemStack;
|
||||||
|
this.hand = hand;
|
||||||
|
|
||||||
|
NbtCompound nbtCompound = itemStack.getNbt();
|
||||||
|
if (nbtCompound != null) {
|
||||||
|
BookScreen.filterPages(nbtCompound, s -> {
|
||||||
|
lines.addAll(Arrays.asList(s.split("\n")));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (lines.isEmpty()) {
|
||||||
|
lines.add("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||||
|
this.renderBackground(matrices);
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionTexProgram);
|
||||||
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
fill(matrices, 23, 23, this.width - 23, this.height - 72, TokenTypeColors.BACKGROUND);
|
||||||
|
|
||||||
|
int lineNumberLength = textRenderer.getWidth(lines.size() + "");
|
||||||
|
|
||||||
|
// TODO: Implement text rendering
|
||||||
|
int lineNumberText = 1;
|
||||||
|
MutableInt lineNumber = new MutableInt();
|
||||||
|
TextHandler textHandler = this.textRenderer.getTextHandler();
|
||||||
|
for (String s : lines) {
|
||||||
|
if (lineNumber.getValue() * 9 + 25 > this.height - 75) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Line number
|
||||||
|
this.textRenderer.draw(matrices, lineNumberText + "", 25 + lineNumberLength - textRenderer.getWidth(lineNumberText + ""), 25 + lineNumber.getValue() * 9, 0xFFFFFF);
|
||||||
|
lineNumberText++;
|
||||||
|
|
||||||
|
// Line text
|
||||||
|
List<Token> tokens = ScriptColorizer.colorize(lineNumber.getValue(), s);
|
||||||
|
AtomicInteger x = new AtomicInteger(25 + lineNumberLength + 5);
|
||||||
|
for (Token token : tokens) {
|
||||||
|
textHandler.wrapLines(token.text, this.width - x.get() - 25, Style.EMPTY, true, (style, start, end) -> {
|
||||||
|
int y = lineNumber.getValue() * 9;
|
||||||
|
if (y + 25 > this.height - 75) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String line = token.text.substring(start, end);
|
||||||
|
this.textRenderer.draw(matrices, line, x.get(), 25 + y, token.color);
|
||||||
|
x.addAndGet(textRenderer.getWidth(line));
|
||||||
|
if (x.get() > this.width - 50 - lineNumberLength - 5) {
|
||||||
|
x.set(25 + lineNumberLength + 5);
|
||||||
|
lineNumber.increment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
lineNumber.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.render(matrices, mouseX, mouseY, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
|
||||||
|
return super.keyReleased(keyCode, scanCode, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean charTyped(char chr, int modifiers) {
|
||||||
|
return super.charTyped(chr, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||||
|
return super.mouseClicked(mouseX, mouseY, button);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,7 +7,9 @@
|
|||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"ClientLoginNetworkHandlerMixin",
|
"ClientLoginNetworkHandlerMixin",
|
||||||
"KeyboardMixin"
|
"KeyboardMixin",
|
||||||
|
"ClientPlayerEntityMixin",
|
||||||
|
"ClientPlayNetworkHandlerMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|||||||
Reference in New Issue
Block a user