Compare commits
26 Commits
e6c49ba3ef
...
2.2.2_1.21
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f98cc0267 | |||
| d7c9759d27 | |||
| 67f979a051 | |||
| 3a26248296 | |||
| a317773d85 | |||
| 828cf88518 | |||
| 279042b987 | |||
| 2d1c320792 | |||
| a9d3fa0bbb | |||
| 743ec5d565 | |||
| e5df33c19a | |||
| 28856d8bd5 | |||
| 126ac736ae | |||
| b74cb2e053 | |||
| d10dd665f5 | |||
| 2cbf095826 | |||
| 118b258244 | |||
| 36151e3a46 | |||
| a6e2fa7fc5 | |||
| fe037aa766 | |||
| ec973e3104 | |||
| 06b46966b8 | |||
| 702865eba1 | |||
| 22939d42e0 | |||
| 909bce4092 | |||
| cf06c30b54 |
28
build.gradle
28
build.gradle
@ -1,22 +1,21 @@
|
||||
plugins {
|
||||
id 'fabric-loom' version '1.0-SNAPSHOT'
|
||||
id 'fabric-loom' version '1.10.1'
|
||||
id 'maven-publish'
|
||||
}
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
archivesBaseName = project.archives_base_name
|
||||
version = project.mod_version
|
||||
group = project.maven_group
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
}
|
||||
|
||||
loom {
|
||||
@ -31,8 +30,27 @@ processResources {
|
||||
}
|
||||
}
|
||||
|
||||
def targetJavaVersion = 21
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
it.options.release = 17
|
||||
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
||||
// this fixes some edge cases with special characters not displaying correctly
|
||||
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
|
||||
// If Javadoc is generated, this must be specified in that task too.
|
||||
it.options.encoding = "UTF-8"
|
||||
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
|
||||
it.options.release.set(targetJavaVersion)
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
|
||||
if (JavaVersion.current() < javaVersion) {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
|
||||
}
|
||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
||||
// if it is present.
|
||||
// If you remove this line, sources will not be generated.
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
jar {
|
||||
|
||||
@ -3,12 +3,17 @@ org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.parallel=true
|
||||
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.19.3
|
||||
yarn_mappings=1.19.3+build.1
|
||||
loader_version=0.14.11
|
||||
# check these on https://fabricmc.net/develop
|
||||
|
||||
minecraft_version=1.21.5
|
||||
yarn_mappings=1.21.5+build.1
|
||||
loader_version=0.16.14
|
||||
loom_version=1.10-SNAPSHOT
|
||||
|
||||
# Fabric API
|
||||
fabric_version=0.119.3+1.21.5
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 1.0.0
|
||||
maven_group = de.zonlykroks
|
||||
archives_base_name = AdvancedScripts
|
||||
mod_version = 2.2.2
|
||||
maven_group = de.steamwar
|
||||
archives_base_name = AdvancedScripts
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@ -4,7 +4,6 @@ pluginManagement {
|
||||
name = 'Fabric'
|
||||
url = 'https://maven.fabricmc.net/'
|
||||
}
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.advancedscripts;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
|
||||
|
||||
public class AdvancedScripts implements ClientModInitializer {
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
PayloadTypeRegistry.playC2S().register(KeyAction.ID, KeyAction.CODEC);
|
||||
}
|
||||
}
|
||||
19
src/main/java/de/steamwar/advancedscripts/KeyAction.java
Normal file
19
src/main/java/de/steamwar/advancedscripts/KeyAction.java
Normal file
@ -0,0 +1,19 @@
|
||||
package de.steamwar.advancedscripts;
|
||||
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.codec.PacketCodecs;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public record KeyAction(int key, byte action, int modifiers) implements CustomPayload {
|
||||
private static final Identifier channel = Identifier.of("sw:hotkeys");
|
||||
|
||||
public static final CustomPayload.Id<KeyAction> ID = new CustomPayload.Id<>(channel);
|
||||
public static final PacketCodec<RegistryByteBuf, KeyAction> CODEC = PacketCodec.tuple(PacketCodecs.INTEGER, KeyAction::key, PacketCodecs.BYTE, KeyAction::action, PacketCodecs.INTEGER, KeyAction::modifiers, KeyAction::new);
|
||||
|
||||
@Override
|
||||
public Id<? extends CustomPayload> getId() {
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.advancedscripts.lexer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ScriptColorizer {
|
||||
|
||||
private static final Set<String> KEYWORDS = Set.of(
|
||||
"and", "break", "do", "else", "elseif", "end", "for", "function", "goto", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "until", "while"
|
||||
);
|
||||
|
||||
private ScriptColorizer() {
|
||||
throw new IllegalStateException("Utility class██");
|
||||
}
|
||||
|
||||
public static List<Token> colorize(String line) {
|
||||
List<Token> tokens = colorizeComment(line);
|
||||
if (tokens != null) return tokens;
|
||||
return colorizeLine(line);
|
||||
}
|
||||
|
||||
private static List<Token> colorizeComment(String line) {
|
||||
if (!line.startsWith("--")) return null;
|
||||
return List.of(new Token(line, TokenTypeColors.COMMENT));
|
||||
}
|
||||
|
||||
private static List<Token> colorizeLine(String line) {
|
||||
List<Token> tokens = new ArrayList<>();
|
||||
|
||||
StringBuilder currentToken = new StringBuilder();
|
||||
|
||||
boolean inString = false;
|
||||
boolean doubleQuoteString = false;
|
||||
|
||||
for (char c : line.toCharArray()) {
|
||||
switch (c) {
|
||||
case '"' -> {
|
||||
if (inString) {
|
||||
currentToken.append(c);
|
||||
if (doubleQuoteString) {
|
||||
tokens.add(new Token(currentToken.toString(), TokenTypeColors.STRING));
|
||||
currentToken = new StringBuilder();
|
||||
inString = false;
|
||||
doubleQuoteString = false;
|
||||
}
|
||||
} else {
|
||||
inString = true;
|
||||
doubleQuoteString = true;
|
||||
if (currentToken.length() > 0) {
|
||||
tokens.add(toToken(currentToken.toString()));
|
||||
currentToken = new StringBuilder();
|
||||
}
|
||||
currentToken.append(c);
|
||||
}
|
||||
}
|
||||
case '\'' -> {
|
||||
if (inString) {
|
||||
currentToken.append(c);
|
||||
if (!doubleQuoteString) {
|
||||
tokens.add(new Token(currentToken.toString(), TokenTypeColors.STRING));
|
||||
currentToken = new StringBuilder();
|
||||
inString = false;
|
||||
}
|
||||
} else {
|
||||
inString = true;
|
||||
doubleQuoteString = false;
|
||||
if (currentToken.length() > 0) {
|
||||
tokens.add(toToken(currentToken.toString()));
|
||||
currentToken = new StringBuilder();
|
||||
}
|
||||
currentToken.append(c);
|
||||
}
|
||||
}
|
||||
case '-', ';', '(', ')', ',', ' ', '{', '\t' -> {
|
||||
if (inString) {
|
||||
currentToken.append(c);
|
||||
} else {
|
||||
if(currentToken.length() > 0) {
|
||||
tokens.add(toToken(currentToken.toString()));
|
||||
}
|
||||
tokens.add(new Token(String.valueOf(c), TokenTypeColors.OTHER));
|
||||
currentToken = new StringBuilder();
|
||||
}
|
||||
}
|
||||
default -> currentToken.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentToken.length() > 0) {
|
||||
tokens.add(toToken(currentToken.toString()));
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private static Token toToken(String text) {
|
||||
if (text.length() > 0) {
|
||||
if (KEYWORDS.contains(text)) {
|
||||
return new Token(text, TokenTypeColors.CONSTANT);
|
||||
} else if ("true".contentEquals(text) || "false".contentEquals(text)) {
|
||||
return new Token(text, TokenTypeColors.BOOLEAN);
|
||||
} else if (text.matches("[0-9]+")) {
|
||||
return new Token(text, TokenTypeColors.NUMBER);
|
||||
} else {
|
||||
return new Token(text, TokenTypeColors.OTHER);
|
||||
}
|
||||
} else {
|
||||
return Token.SPACE;
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/main/java/de/steamwar/advancedscripts/lexer/Token.java
Normal file
40
src/main/java/de/steamwar/advancedscripts/lexer/Token.java
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Token{" +
|
||||
"text='" + text + '\'' +
|
||||
", color=" + color +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.advancedscripts.lexer;
|
||||
|
||||
public class TokenTypeColors {
|
||||
|
||||
private TokenTypeColors() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static final int BACKGROUND = 0xFF1E1F22;
|
||||
public static final int SELECTION = 0xFF23437F;
|
||||
public static final int OTHER = 0xFFFFFFFF;
|
||||
|
||||
public static final int ERROR = 0xFFAA0000;
|
||||
|
||||
public static final int VARIABLE = 0xFFFFFFFF;
|
||||
public static final int COMMENT = 0xFF656565;
|
||||
public static final int CONSTANT = 0x3F6EC6;
|
||||
|
||||
public static final int NUMBER = 0xFF61839F;
|
||||
public static final int BOOLEAN = 0xFF925F35;
|
||||
public static final int STRING = 0x6a8759;
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.advancedscripts.mixin;
|
||||
|
||||
import de.steamwar.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,40 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.advancedscripts.mixin;
|
||||
|
||||
import de.steamwar.advancedscripts.KeyAction;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.minecraft.client.Keyboard;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
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(Keyboard.class)
|
||||
public class KeyboardMixin {
|
||||
@Inject(method = "onKey", at = @At("HEAD"))
|
||||
public void sendKeyPress(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) {
|
||||
MinecraftClient client = ((Keyboard) (Object)this).client;
|
||||
if(client.currentScreen == null && action != 2) {
|
||||
ClientPlayNetworking.send(new KeyAction(key, (byte) action, modifiers));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,650 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.advancedscripts.screen;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import de.steamwar.advancedscripts.lexer.ScriptColorizer;
|
||||
import de.steamwar.advancedscripts.lexer.Token;
|
||||
import de.steamwar.advancedscripts.lexer.TokenTypeColors;
|
||||
import net.minecraft.client.font.TextHandler;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.BookEditScreen;
|
||||
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
||||
import net.minecraft.client.gui.widget.PressableWidget;
|
||||
import net.minecraft.client.util.NarratorManager;
|
||||
import net.minecraft.client.util.SelectionManager;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.WritableBookContentComponent;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.packet.c2s.play.BookUpdateC2SPacket;
|
||||
import net.minecraft.text.RawFilteredPair;
|
||||
import net.minecraft.text.Style;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Hand;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
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<>();
|
||||
private int scroll = 0;
|
||||
private int cursorY = 0;
|
||||
private int cursorX = 0;
|
||||
|
||||
private int savedCursorY = -1;
|
||||
private int savedCursorX = -1;
|
||||
|
||||
private int tickCounter;
|
||||
|
||||
private int keyCode = -1;
|
||||
private long time;
|
||||
|
||||
public ScriptEditScreen(PlayerEntity player, ItemStack itemStack, Hand hand) {
|
||||
super(NarratorManager.EMPTY);
|
||||
this.player = player;
|
||||
this.itemStack = itemStack;
|
||||
this.hand = hand;
|
||||
|
||||
List<RawFilteredPair<String>> pages = itemStack.get(DataComponentTypes.WRITABLE_BOOK_CONTENT).pages();
|
||||
pages.forEach(stringRawFilteredPair -> {
|
||||
for (String s : stringRawFilteredPair.raw().split("\n")) {
|
||||
if (s.isEmpty()) {
|
||||
lines.add("");
|
||||
} else {
|
||||
lines.add(s);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (lines.isEmpty()) {
|
||||
lines.add("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
this.addDrawableChild(
|
||||
new Button(CANCEL, this.width / 2 - 100, height - 55, () -> this.client.setScreen(null))
|
||||
);
|
||||
this.addDrawableChild(
|
||||
new Button(DONE, this.width / 2 + 2, height - 55, () -> {
|
||||
this.client.setScreen(null);
|
||||
finalizeBook();
|
||||
})
|
||||
);
|
||||
this.addDrawableChild(
|
||||
new Button(BOOK, this.width - 98 - 5, height - 20 - 5, () -> {
|
||||
finalizeBook();
|
||||
this.client.setScreen(new BookEditScreen(player, itemStack, hand, toContent(toPages())));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public static final Text DONE = Text.translatable("gui.done");
|
||||
public static final Text CANCEL = Text.translatable("gui.cancel");
|
||||
public static final Text BOOK = Text.translatable("item.minecraft.book");
|
||||
|
||||
private static class Button extends PressableWidget {
|
||||
private Runnable onPress;
|
||||
|
||||
public Button(Text text, int x, int y, Runnable onPress) {
|
||||
super(x, y, 98, 20, text);
|
||||
visible = true;
|
||||
this.onPress = onPress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPress() {
|
||||
onPress.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendClickableNarrations(NarrationMessageBuilder builder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNarratable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void setClipboard(String clipboard) {
|
||||
if (this.client != null) {
|
||||
SelectionManager.setClipboard(this.client, clipboard);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String getClipboard() {
|
||||
return this.client != null ? SelectionManager.getClipboard(this.client) : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
++this.tickCounter;
|
||||
if (keyCode != -1 && System.currentTimeMillis() - time > 500) {
|
||||
key(keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyBlur() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
setFocused(null);
|
||||
this.renderBackground(context, mouseX, mouseY, delta);
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
context.fill(23, 23, this.width - 23, this.height - 63, TokenTypeColors.BACKGROUND);
|
||||
|
||||
int lineNumberLength = textRenderer.getWidth(lines.size() + "");
|
||||
|
||||
boolean hasSelection = savedCursorY != -1 && savedCursorX != -1;
|
||||
int minSelectionY = Math.min(cursorY, savedCursorY);
|
||||
int maxSelectionY = Math.max(cursorY, savedCursorY);
|
||||
int minSelectionX = (minSelectionY == maxSelectionY ? Math.min(cursorX, savedCursorX) : (minSelectionY == cursorY ? cursorX : savedCursorX));
|
||||
int maxSelectionX = (minSelectionY == maxSelectionY ? Math.max(cursorX, savedCursorX) : (maxSelectionY == cursorY ? cursorX : savedCursorX));
|
||||
|
||||
int lineNumberText = scroll + 1;
|
||||
MutableInt lineNumber = new MutableInt();
|
||||
TextHandler textHandler = this.textRenderer.getTextHandler();
|
||||
for (int i = scroll; i < lines.size(); i++) {
|
||||
String s = lines.get(i);
|
||||
|
||||
if (lineNumber.getValue() * 9 + 25 > this.height - 66) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (s.isEmpty() && i == cursorY) {
|
||||
drawCursor(context, 25 + lineNumberLength + 5, lineNumber.getValue() * 9 + 25, true);
|
||||
}
|
||||
|
||||
// Line number
|
||||
int height = this.textRenderer.getWrappedLinesHeight(s, this.width - 50 - lineNumberLength - 5);
|
||||
if (lineTooLong(s)) {
|
||||
context.fill(25 + lineNumberLength + 2, 25 + lineNumber.getValue() * 9, 25 + lineNumberLength + 3, 25 + lineNumber.getValue() * 9 + height, TokenTypeColors.ERROR);
|
||||
}
|
||||
context.drawText(textRenderer, String.valueOf(lineNumberText), (int) (25f + lineNumberLength - textRenderer.getWidth(String.valueOf(lineNumberText))), (int) (25f + lineNumber.getValue() * 9f), 0xFFFFFF, false);
|
||||
lineNumberText++;
|
||||
|
||||
// Line text
|
||||
List<Token> tokens = ScriptColorizer.colorize(s);
|
||||
AtomicInteger x = new AtomicInteger(25 + lineNumberLength + 5);
|
||||
AtomicInteger currentXIndex = new AtomicInteger(0);
|
||||
for (Token token : tokens) {
|
||||
int finalI = i;
|
||||
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 - 66) {
|
||||
return;
|
||||
}
|
||||
|
||||
String line = token.text.substring(start, end);
|
||||
int previousXIndex = currentXIndex.get();
|
||||
currentXIndex.addAndGet(line.length());
|
||||
|
||||
if (hasSelection) {
|
||||
int x1 = x.get();
|
||||
int x2 = x.get() + textRenderer.getWidth(line);
|
||||
|
||||
if (finalI == minSelectionY) {
|
||||
if (minSelectionX > currentXIndex.get()) {
|
||||
x2 = 0;
|
||||
} else if (minSelectionX <= currentXIndex.get() && minSelectionX >= previousXIndex) {
|
||||
int startInLine = minSelectionX - previousXIndex;
|
||||
x1 += textRenderer.getWidth(line.substring(0, startInLine));
|
||||
}
|
||||
}
|
||||
if (finalI == maxSelectionY) {
|
||||
if (maxSelectionX < previousXIndex) {
|
||||
x2 = 0;
|
||||
} else if (maxSelectionX <= currentXIndex.get()) {
|
||||
int endInLine = maxSelectionX - previousXIndex;
|
||||
x2 = x.get() + textRenderer.getWidth(line.substring(0, endInLine));
|
||||
}
|
||||
}
|
||||
|
||||
if (finalI >= minSelectionY && finalI <= maxSelectionY && x2 > x1) {
|
||||
context.fill(x1, y + 25, x2, y + 25 + 9, TokenTypeColors.SELECTION);
|
||||
}
|
||||
}
|
||||
|
||||
if (finalI == cursorY && currentXIndex.get() >= cursorX && previousXIndex <= cursorX) {
|
||||
drawCursor(context, x.get() + textRenderer.getWidth(line.substring(0, cursorX - previousXIndex)) - 1, 25 + y, isAtEndOfLine());
|
||||
}
|
||||
|
||||
context.drawText(this.textRenderer, line, x.get(), 25 + y, token.color, false);
|
||||
x.addAndGet(textRenderer.getWidth(line));
|
||||
if (x.get() > this.width - 50 - lineNumberLength - 5) {
|
||||
x.set(25 + lineNumberLength + 5);
|
||||
lineNumber.increment();
|
||||
}
|
||||
});
|
||||
}
|
||||
lineNumber.increment();
|
||||
}
|
||||
|
||||
super.render(context, mouseX, mouseY, delta);
|
||||
}
|
||||
|
||||
private boolean lineTooLong(String s) {
|
||||
if (s.length() >= 1024) {
|
||||
return true;
|
||||
}
|
||||
return textRenderer.getWrappedLinesHeight(s, 114) > 128;
|
||||
}
|
||||
|
||||
private void drawCursor(DrawContext context, int x, int y, boolean atEnd) {
|
||||
if (this.tickCounter / 6 % 2 == 0) {
|
||||
if (!atEnd) {
|
||||
Objects.requireNonNull(this.textRenderer);
|
||||
context.fill(x, y - 1, x + 1, y + 9, 0xFFFFFFFF);
|
||||
} else {
|
||||
context.drawText(this.textRenderer, "_", x, y, 0xFFFFFFFF, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void key(int keyCode) {
|
||||
setFocused(null);
|
||||
if (Screen.isSelectAll(keyCode)) {
|
||||
this.cursorX = 0;
|
||||
this.cursorY = 0;
|
||||
this.savedCursorX = lines.get(lines.size() - 1).length();
|
||||
this.savedCursorY = lines.size() - 1;
|
||||
return;
|
||||
} else if (Screen.isCopy(keyCode)) {
|
||||
String copied = selection(false);
|
||||
if (copied != null) {
|
||||
setClipboard(copied);
|
||||
}
|
||||
return;
|
||||
} else if (Screen.isPaste(keyCode)) {
|
||||
String copied = getClipboard();
|
||||
if (copied != null) {
|
||||
insert(copied);
|
||||
}
|
||||
return;
|
||||
} else if (Screen.isCut(keyCode)) {
|
||||
String copied = selection(true);
|
||||
if (copied != null) {
|
||||
setClipboard(copied);
|
||||
}
|
||||
return;
|
||||
}
|
||||
SelectionManager.SelectionType selectionType = Screen.hasControlDown() ? SelectionManager.SelectionType.WORD : SelectionManager.SelectionType.CHARACTER;
|
||||
boolean valid = true;
|
||||
int previousCursorX = cursorX;
|
||||
int previousCursorY = cursorY;
|
||||
switch (keyCode) {
|
||||
case 258 -> {
|
||||
insert(" ");
|
||||
return;
|
||||
}
|
||||
case 257, 335 -> {
|
||||
selection(true);
|
||||
newLine();
|
||||
valid = false;
|
||||
}
|
||||
case 259 -> {
|
||||
if (selection(true) == null) backspace(selectionType);
|
||||
valid = false;
|
||||
}
|
||||
case 261 -> {
|
||||
if (selection(true) == null) delete(selectionType);
|
||||
valid = false;
|
||||
}
|
||||
case 262 -> {
|
||||
moveCursor(1, selectionType);
|
||||
valid = Screen.hasShiftDown();
|
||||
}
|
||||
case 263 -> {
|
||||
moveCursor(-1, selectionType);
|
||||
valid = Screen.hasShiftDown();
|
||||
}
|
||||
case 264 -> {
|
||||
moveDown();
|
||||
valid = Screen.hasShiftDown();
|
||||
}
|
||||
case 265 -> {
|
||||
moveUp();
|
||||
valid = Screen.hasShiftDown();
|
||||
}
|
||||
case 268 -> {
|
||||
cursorX = 0;
|
||||
valid = Screen.hasShiftDown();
|
||||
}
|
||||
case 269 -> {
|
||||
cursorX = lines.get(cursorY).length();
|
||||
valid = Screen.hasShiftDown();
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
if (Screen.hasShiftDown() && savedCursorX == -1 && savedCursorY == -1) {
|
||||
savedCursorX = previousCursorX;
|
||||
savedCursorY = previousCursorY;
|
||||
}
|
||||
} else {
|
||||
savedCursorY = -1;
|
||||
savedCursorX = -1;
|
||||
}
|
||||
autoScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
setFocused(null);
|
||||
if (super.keyPressed(keyCode, scanCode, modifiers)) {
|
||||
return true;
|
||||
}
|
||||
key(keyCode);
|
||||
this.keyCode = keyCode;
|
||||
this.time = System.currentTimeMillis();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
|
||||
setFocused(null);
|
||||
this.keyCode = -1;
|
||||
return super.keyReleased(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped(char chr, int modifiers) {
|
||||
setFocused(null);
|
||||
if (super.charTyped(chr, modifiers)) {
|
||||
return true;
|
||||
}
|
||||
selection(true);
|
||||
boolean valid = insert(String.valueOf(chr));
|
||||
savedCursorY = -1;
|
||||
savedCursorX = -1;
|
||||
autoScroll();
|
||||
return valid;
|
||||
}
|
||||
|
||||
private String selection(boolean remove) {
|
||||
if (savedCursorX == -1 || savedCursorY == -1) {
|
||||
return null;
|
||||
}
|
||||
int minSelectionY = Math.min(savedCursorY, cursorY);
|
||||
int maxSelectionY = Math.max(savedCursorY, cursorY);
|
||||
int minSelectionX = (minSelectionY == maxSelectionY ? Math.min(cursorX, savedCursorX) : (minSelectionY == cursorY ? cursorX : savedCursorX));
|
||||
int maxSelectionX = (minSelectionY == maxSelectionY ? Math.max(cursorX, savedCursorX) : (maxSelectionY == cursorY ? cursorX : savedCursorX));
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = minSelectionY; i <= maxSelectionY; i++) {
|
||||
String line = lines.get(i);
|
||||
if (i == minSelectionY && i == maxSelectionY) {
|
||||
builder.append(line, minSelectionX, maxSelectionX);
|
||||
} else if (i == minSelectionY) {
|
||||
builder.append(line, minSelectionX, line.length());
|
||||
} else if (i == maxSelectionY) {
|
||||
builder.append(line, 0, Math.min(maxSelectionX, line.length()));
|
||||
} else {
|
||||
builder.append(line);
|
||||
}
|
||||
if (i != maxSelectionY) {
|
||||
builder.append("\n");
|
||||
}
|
||||
}
|
||||
if (remove) {
|
||||
for (int i = maxSelectionY; i >= minSelectionY; i--) {
|
||||
String line = lines.get(i);
|
||||
if (i == minSelectionY && i == maxSelectionY) {
|
||||
lines.set(i, line.substring(0, minSelectionX) + line.substring(maxSelectionX));
|
||||
} else if (i == minSelectionY) {
|
||||
lines.set(i, line.substring(0, minSelectionX));
|
||||
} else if (i == maxSelectionY) {
|
||||
lines.set(i, line.substring(Math.min(maxSelectionX, line.length())));
|
||||
} else {
|
||||
lines.remove(i);
|
||||
}
|
||||
}
|
||||
if (minSelectionY != maxSelectionY) {
|
||||
lines.set(minSelectionY, lines.get(minSelectionY) + lines.get(minSelectionY + 1));
|
||||
lines.remove(minSelectionY + 1);
|
||||
}
|
||||
cursorX = minSelectionX;
|
||||
cursorY = minSelectionY;
|
||||
savedCursorX = -1;
|
||||
savedCursorY = -1;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private boolean insert(String s) {
|
||||
String[] split = s.split("\n");
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
String line = lines.get(cursorY);
|
||||
if (cursorX == line.length()) {
|
||||
line += split[i];
|
||||
} else {
|
||||
line = line.substring(0, cursorX) + split[i] + line.substring(cursorX);
|
||||
}
|
||||
lines.set(cursorY, line);
|
||||
cursorX += split[i].length();
|
||||
if (i != split.length - 1) {
|
||||
newLine();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean newLine() {
|
||||
String line = lines.get(cursorY);
|
||||
String newLine = line.substring(cursorX);
|
||||
line = line.substring(0, cursorX);
|
||||
lines.set(cursorY, line);
|
||||
lines.add(cursorY + 1, newLine);
|
||||
cursorY++;
|
||||
cursorX = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean backspace(SelectionManager.SelectionType selectionType) {
|
||||
if (cursorX == 0) {
|
||||
if (cursorY == 0) {
|
||||
return true;
|
||||
}
|
||||
String previousLine = lines.get(cursorY - 1);
|
||||
lines.set(cursorY - 1, lines.get(cursorY - 1) + lines.remove(cursorY));
|
||||
cursorY--;
|
||||
cursorX = previousLine.length();
|
||||
} else {
|
||||
String line = lines.get(cursorY);
|
||||
int remove = selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, -1);
|
||||
line = line.substring(0, cursorX - remove) + line.substring(cursorX);
|
||||
lines.set(cursorY, line);
|
||||
cursorX -= remove;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean delete(SelectionManager.SelectionType selectionType) {
|
||||
if (cursorX == lines.get(cursorY).length()) {
|
||||
if (cursorY == lines.size() - 1) {
|
||||
return true;
|
||||
}
|
||||
String nextLine = lines.get(cursorY + 1);
|
||||
lines.remove(cursorY);
|
||||
lines.set(cursorY, lines.get(cursorY) + nextLine);
|
||||
} else {
|
||||
String line = lines.get(cursorY);
|
||||
int remove = selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, 1);
|
||||
line = line.substring(0, cursorX) + line.substring(cursorX + remove);
|
||||
lines.set(cursorY, line);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getWordLength(String line, int cursorX, int direction) {
|
||||
int i = cursorX;
|
||||
while (i >= 0 && i < line.length()) {
|
||||
char c = line.charAt(i);
|
||||
if (Character.isLetterOrDigit(c)) {
|
||||
i += direction;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Math.abs(i - cursorX);
|
||||
}
|
||||
|
||||
private boolean moveCursor(int offset, SelectionManager.SelectionType selectionType) {
|
||||
if (offset == 0) {
|
||||
return true;
|
||||
}
|
||||
String line = lines.get(cursorY);
|
||||
if (offset > 0) {
|
||||
if (cursorX == line.length()) {
|
||||
if (cursorY == lines.size() - 1) {
|
||||
return true;
|
||||
}
|
||||
cursorY++;
|
||||
cursorX = 0;
|
||||
} else {
|
||||
cursorX += selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, 1);
|
||||
}
|
||||
} else {
|
||||
if (cursorX == 0) {
|
||||
if (cursorY == 0) {
|
||||
return true;
|
||||
}
|
||||
cursorY--;
|
||||
cursorX = lines.get(cursorY).length();
|
||||
} else {
|
||||
cursorX -= selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, -1);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean moveDown() {
|
||||
if (cursorY == lines.size() - 1) {
|
||||
cursorX = lines.get(cursorY).length();
|
||||
return true;
|
||||
}
|
||||
cursorY++;
|
||||
cursorX = Math.min(cursorX, lines.get(cursorY).length());
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean moveUp() {
|
||||
if (cursorY == 0) {
|
||||
cursorX = 0;
|
||||
return true;
|
||||
}
|
||||
cursorY--;
|
||||
cursorX = Math.min(cursorX, lines.get(cursorY).length());
|
||||
return true;
|
||||
}
|
||||
|
||||
private void autoScroll() {
|
||||
if (cursorY < scroll) {
|
||||
scroll = cursorY;
|
||||
} else if (cursorY >= scroll + ((this.height - 25 - 66) / 9)) {
|
||||
scroll = cursorY - ((this.height - 25 - 66) / 9);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAtEndOfLine() {
|
||||
return cursorX == lines.get(cursorY).length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
|
||||
scroll -= (int) Math.signum(verticalAmount);
|
||||
if (scroll > lines.size() - 1) {
|
||||
scroll = lines.size() - 1;
|
||||
}
|
||||
if (scroll < 0) {
|
||||
scroll = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
return super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
private List<String> toPages() {
|
||||
List<String> pages = new ArrayList<>();
|
||||
StringBuilder page = new StringBuilder();
|
||||
for (String line : lines) {
|
||||
if (!page.isEmpty()) {
|
||||
page.append("\n");
|
||||
}
|
||||
if (page.length() + line.length() > 1024) {
|
||||
pages.add(page.toString());
|
||||
page = new StringBuilder();
|
||||
}
|
||||
String temp = page + line;
|
||||
if (textRenderer.getWrappedLinesHeight(temp, 114) > 128) {
|
||||
pages.add(page.toString());
|
||||
page = new StringBuilder();
|
||||
}
|
||||
if (line.isEmpty()) {
|
||||
page.append(" ");
|
||||
} else {
|
||||
page.append(line);
|
||||
}
|
||||
}
|
||||
if (!page.isEmpty()) {
|
||||
pages.add(page.toString());
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
|
||||
private void finalizeBook() {
|
||||
List<String> pages = toPages();
|
||||
this.writeNbtData(pages);
|
||||
int i = this.hand == Hand.MAIN_HAND ? this.player.getInventory().getSelectedSlot() : 40;
|
||||
this.client.getNetworkHandler().sendPacket(new BookUpdateC2SPacket(i, pages, Optional.empty()));
|
||||
}
|
||||
|
||||
private WritableBookContentComponent toContent(List<String> pages) {
|
||||
return new WritableBookContentComponent(pages.stream().map(string -> new RawFilteredPair<String>(string, Optional.empty())).toList());
|
||||
}
|
||||
|
||||
private void writeNbtData(List<String> pages) {
|
||||
if (!pages.isEmpty()) {
|
||||
this.itemStack.set(DataComponentTypes.WRITABLE_BOOK_CONTENT, toContent(pages));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
/*
|
||||
This file is a part of the SteamWar software.
|
||||
|
||||
Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.zonlykroks.advancedscripts;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
|
||||
public class AdvancedScripts implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
/*
|
||||
This file is a part of the SteamWar software.
|
||||
|
||||
Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.zonlykroks.advancedscripts.mixin;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.client.Keyboard;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
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 {
|
||||
|
||||
@Unique
|
||||
private static final Identifier channel = new Identifier("sw:hotkeys");
|
||||
|
||||
@Inject(method = "onKey", at = @At("HEAD"))
|
||||
public void sendKeyPress(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) {
|
||||
MinecraftClient client = ((Keyboard) (Object)this).client;
|
||||
if(client.currentScreen == null && action != 2) {
|
||||
PacketByteBuf byteBuf = new PacketByteBuf(Unpooled.buffer());
|
||||
byteBuf.writeInt(key);
|
||||
byteBuf.writeByte(action);
|
||||
byteBuf.writeInt(modifiers);
|
||||
CustomPayloadC2SPacket customPayloadC2SPacket = new CustomPayloadC2SPacket(channel,byteBuf);
|
||||
client.getNetworkHandler().sendPacket(customPayloadC2SPacket);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
BIN
src/main/resources/advanced-scripts-icon.png
Normal file
BIN
src/main/resources/advanced-scripts-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
@ -1,4 +1,3 @@
|
||||
accessWidener v1 named
|
||||
|
||||
accessible field net/minecraft/client/network/ClientPlayNetworkHandler serverInfo Lnet/minecraft/client/network/ServerInfo;
|
||||
accessible field net/minecraft/client/Keyboard client Lnet/minecraft/client/MinecraftClient;
|
||||
@ -1,12 +1,13 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "de.zonlykroks.advancedscripts.mixin",
|
||||
"package": "de.steamwar.advancedscripts.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
],
|
||||
"client": [
|
||||
"KeyboardMixin"
|
||||
"KeyboardMixin",
|
||||
"ClientPlayerEntityMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
||||
@ -6,13 +6,15 @@
|
||||
"name": "Advanced Scripts",
|
||||
"description": "An addition to the Steamwar script system!",
|
||||
"authors": [
|
||||
"zOnlyKroks"
|
||||
"zOnlyKroks",
|
||||
"Chaoscaot"
|
||||
],
|
||||
"icon": "advanced-scripts-icon.png",
|
||||
"license": "AGPL-3.0",
|
||||
"environment": "client",
|
||||
"entrypoints": {
|
||||
"client": [
|
||||
"de.zonlykroks.advancedscripts.AdvancedScripts"
|
||||
"de.steamwar.advancedscripts.AdvancedScripts"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
@ -20,8 +22,9 @@
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.14.11",
|
||||
"minecraft": ">=1.19.2",
|
||||
"java": ">=17"
|
||||
"minecraft": ">=1.20.6",
|
||||
"java": ">=21",
|
||||
"fabric-api": "*"
|
||||
},
|
||||
"accessWidener" : "advancedscripts.accesswidener"
|
||||
}
|
||||
|
||||
@ -2,4 +2,4 @@ build:
|
||||
- "./gradlew remapJar"
|
||||
|
||||
artifacts:
|
||||
"/binarys/AdvancedScripts.jar": "build/libs/AdvancedScripts-1.0.0.jar"
|
||||
"/binarys/AdvancedScripts.jar": "build/libs/AdvancedScripts-2.0.0.jar"
|
||||
Reference in New Issue
Block a user