tcr/java/src/game/gui/GuiConsole.java

395 lines
12 KiB
Java
Raw Normal View History

2025-03-11 14:09:49 +01:00
package game.gui;
import java.util.List;
import game.collect.Lists;
2025-03-16 17:40:47 +01:00
2025-03-17 18:21:41 +01:00
import game.Game;
import game.color.TextColor;
2025-03-11 14:09:49 +01:00
import game.gui.element.ActButton;
import game.gui.element.Fill;
import game.gui.element.Textbox;
import game.gui.element.Textbox.Action;
2025-03-16 17:45:08 +01:00
import game.gui.element.TransparentBox;
2025-03-11 14:09:49 +01:00
import game.network.NetHandlerPlayServer;
import game.packet.CPacketComplete;
import game.util.ExtMath;
2025-03-17 18:21:41 +01:00
import game.vars.BoolVar;
import game.vars.CVar;
2025-03-11 14:09:49 +01:00
import game.window.Keysym;
2025-03-25 17:02:41 +01:00
import game.world.BlockPos;
import game.world.HitPosition;
2025-03-11 14:09:49 +01:00
public class GuiConsole extends Gui implements Textbox.Callback {
public static final GuiConsole INSTANCE = new GuiConsole();
private final List<String> sentMessages = Lists.<String>newArrayList();
2025-03-17 18:21:41 +01:00
private boolean full;
2025-03-11 14:09:49 +01:00
private String historyBuffer = "";
private int sentHistoryCursor = -1;
private boolean playerNamesFound;
private boolean waitingOnAutocomplete;
2025-03-17 18:21:41 +01:00
private boolean reverse;
private String prefixFirst;
2025-03-11 14:09:49 +01:00
private int autocompleteIndex;
private List<String> foundPlayerNames = Lists.<String>newArrayList();
private Textbox inputField;
private TransparentBox logBox;
2025-03-17 18:21:41 +01:00
public GuiConsole setFull(boolean full) {
this.full = full;
return this;
}
2025-03-11 14:09:49 +01:00
public void init(int width, int height) {
2025-03-17 18:21:41 +01:00
if(this.full) {
this.addSelector("con_autoclose", 0, 0, 160, 24);
this.addSelector("con_timestamps", 160, 0, 160, 24);
this.addSelector("con_loglevel", 320, 0, 160, 24);
this.add(new ActButton(480, 0, 160, 24, new ActButton.Callback() {
public void use(ActButton elem, ActButton.Mode action) {
GuiConsole.this.reset();
GuiConsole.this.setLog(GuiConsole.this.gm.getBuffer());
}
}, "Löschen"));
}
this.logBox = this.add(new TransparentBox(0, this.full ? 24 : 0, width, height - (this.full ? 48 : 24), this.gm.getBuffer()));
if(this.full)
this.add(new Fill(640, 0, width - 640, 24));
2025-03-11 14:09:49 +01:00
this.inputField = this.add(new Textbox(0, height - 24, width, 24, NetHandlerPlayServer.MAX_CMD_LENGTH, true, this, ""));
this.inputField.setSelected();
this.sentHistoryCursor = this.sentMessages.size();
}
public String getTitle() {
return "Konsole / Chat";
}
public void reset() {
this.gm.reset();
this.sentMessages.clear();
this.sentHistoryCursor = -1;
}
public void setLog(String buffer) {
if(this.logBox != null)
this.logBox.setText(buffer);
}
public void drawMainBackground() {
if(this.gm.theWorld == null)
super.drawMainBackground();
}
public void key(Keysym key, boolean ctrl, boolean shift) {
super.key(key, ctrl, shift);
// this.waitingOnAutocomplete = false;
2025-03-17 18:21:41 +01:00
if(key != Keysym.TAB && key != Keysym.LEFT_SHIFT && key != Keysym.RIGHT_SHIFT)
2025-03-11 14:09:49 +01:00
this.playerNamesFound = false;
}
public void use(Textbox elem, Action value)
{
this.waitingOnAutocomplete = false;
2025-03-17 18:21:41 +01:00
if (value == Action.FORWARD || value == Action.BACKWARD)
2025-03-11 14:09:49 +01:00
{
2025-03-17 18:21:41 +01:00
this.reverse = value == Action.BACKWARD;
2025-03-11 14:09:49 +01:00
this.autocompletePlayerNames();
}
else
{
this.playerNamesFound = false;
}
if(value == Action.PREVIOUS)
this.getSentHistory(-1);
else if (value == Action.NEXT)
this.getSentHistory(1);
if(value == Action.SEND)
{
String s = this.inputField.getText().trim();
if (s.length() > 0)
{
if(this.sentMessages.isEmpty() || !((String)this.sentMessages.get(this.sentMessages.size() - 1)).equals(s))
this.sentMessages.add(s);
2025-03-17 18:21:41 +01:00
this.sentHistoryCursor = this.sentMessages.size();
2025-03-11 14:09:49 +01:00
this.gm.exec(s);
// if(this.gm.thePlayer != null)
// this.gm.thePlayer.sendQueue.addToSendQueue(new CPacketMessage(CPacketMessage.Type.CHAT, s));
}
this.inputField.setText("");
2025-03-17 18:21:41 +01:00
if((this.gm.conAutoclose || !this.full) && this.gm.theWorld != null)
2025-03-11 14:09:49 +01:00
this.gm.displayGuiScreen(null);
}
}
protected void setText(String newChatText, boolean shouldOverwrite)
{
if (shouldOverwrite)
{
this.inputField.setText(newChatText);
}
else
{
this.inputField.insertText(newChatText);
}
}
2025-03-17 18:21:41 +01:00
private void addMessage(String msg) {
String buffer = this.gm.getBuffer();
if((buffer.length() + msg.length() + 2) > Game.LOG_BUFFER) {
int offset = (msg.length() + 2) > 1024 ? (msg.length() + 2) : 1024;
int nl = buffer.indexOf('\n', offset);
buffer = nl >= 0 ? buffer.substring(nl + 1) : "";
}
this.setLog(buffer + "\n" + TextColor.RESET + msg);
}
2025-03-11 14:09:49 +01:00
public void autocompletePlayerNames()
{
if (this.playerNamesFound)
{
this.inputField.deleteFromCursor();
if (this.autocompleteIndex >= this.foundPlayerNames.size())
{
this.autocompleteIndex = 0;
}
2025-03-17 18:21:41 +01:00
else if (this.autocompleteIndex < 0)
{
this.autocompleteIndex = this.foundPlayerNames.size() - 1;
}
2025-03-11 14:09:49 +01:00
}
else
{
int i = this.inputField.getNthCharFromPos();
this.foundPlayerNames.clear();
this.autocompleteIndex = 0;
String s = this.inputField.getText().substring(i).toLowerCase();
String s1 = this.inputField.getText().substring(0, this.inputField.getCursorPosition());
2025-03-17 18:21:41 +01:00
String[] localMatches = this.sendAutocompleteRequest(s1, s);
if(localMatches != null) {
this.onAutocompleteResponse(localMatches);
return;
}
2025-03-11 14:09:49 +01:00
if (this.foundPlayerNames.isEmpty())
{
return;
}
this.playerNamesFound = true;
this.inputField.deleteFromCursor();
}
if (this.foundPlayerNames.size() > 1)
{
StringBuilder stringbuilder = new StringBuilder();
for (String s2 : this.foundPlayerNames)
{
if (stringbuilder.length() > 0)
{
stringbuilder.append(", ");
}
stringbuilder.append(s2);
}
2025-03-17 18:21:41 +01:00
this.addMessage(stringbuilder.toString());
2025-03-11 14:09:49 +01:00
}
2025-03-17 18:21:41 +01:00
this.inputField.insertText((String)this.foundPlayerNames.get(this.autocompleteIndex));
this.autocompleteIndex += this.reverse ? -1 : 1;
2025-03-11 14:09:49 +01:00
}
2025-03-17 18:21:41 +01:00
private String[] complete(String s) {
List<String> list = Lists.<String>newArrayList();
String[] argv = s.split(" ", -1);
String pre = argv[0];
s = argv[argv.length - 1];
Iterable<String> res = pre.startsWith("#") ?
(argv.length == 1 ? this.gm.getVars() : (argv.length == 2 ? getVarCompletion(argv[0].substring(1)) : Lists.newArrayList())) :
(this.gm.thePlayer == null ? Lists.newArrayList() : this.gm.thePlayer.sendQueue.getPlayerNames());
if(argv.length == 1 && pre.startsWith("#"))
s = s.substring(1);
for(String s1 : res) {
if(s1.regionMatches(true, 0, s, 0, s.length()))
list.add((argv.length == 1 && pre.startsWith("#") ? "#" : "") + s1);
}
return list.isEmpty() ? null : list.toArray(new String[list.size()]);
}
private List<String> getVarCompletion(String var) {
CVar cv = this.gm.getVar(var);
if(cv == null)
return Lists.newArrayList();
if(cv instanceof BoolVar)
return Boolean.parseBoolean(cv.format()) ? Lists.newArrayList("false", "true") : Lists.newArrayList("true", "false");
else
return Lists.newArrayList(cv.getDefault());
// return Lists.newArrayList();
}
private String[] sendAutocompleteRequest(String currentText, String newText)
2025-03-11 14:09:49 +01:00
{
if (currentText.length() >= 1)
{
2025-03-25 17:02:41 +01:00
BlockPos blockpos = null;
int eid = -1;
if (this.gm.pointed != null && this.gm.pointed.type == HitPosition.ObjectType.BLOCK)
{
blockpos = this.gm.pointed.block;
}
else if (this.gm.pointed != null && this.gm.pointed.type == HitPosition.ObjectType.ENTITY)
{
eid = this.gm.pointed.entity.getId();
blockpos = new BlockPos(this.gm.pointed.entity);
}
2025-03-17 18:21:41 +01:00
if(currentText.startsWith("/")) {
if(this.gm.thePlayer != null) {
currentText = currentText.substring(1);
this.prefixFirst = currentText.split(" ", -1).length == 1 ? "/" : null;
2025-03-25 17:02:41 +01:00
this.gm.thePlayer.sendQueue.addToSendQueue(new CPacketComplete(currentText, eid, blockpos));
2025-03-17 18:21:41 +01:00
this.waitingOnAutocomplete = true;
}
}
else {
String[] comp = this.complete(currentText);
this.prefixFirst = null;
if(comp != null)
this.waitingOnAutocomplete = true;
return comp;
}
2025-03-11 14:09:49 +01:00
}
2025-03-17 18:21:41 +01:00
return null;
2025-03-11 14:09:49 +01:00
}
private void getSentHistory(int msgPos)
{
int i = this.sentHistoryCursor + msgPos;
int j = this.sentMessages.size();
i = ExtMath.clampi(i, 0, j);
if (i != this.sentHistoryCursor)
{
if (i == j)
{
this.sentHistoryCursor = j;
this.inputField.setText(this.historyBuffer);
}
else
{
if (this.sentHistoryCursor == j)
{
this.historyBuffer = this.inputField.getText();
}
this.inputField.setText(this.sentMessages.get(i));
this.sentHistoryCursor = i;
}
}
}
public void onAutocompleteResponse(String[] choices)
{
if (this.waitingOnAutocomplete)
{
this.playerNamesFound = false;
this.foundPlayerNames.clear();
2025-03-17 18:21:41 +01:00
for (int z = 0; z < choices.length; z++)
2025-03-11 14:09:49 +01:00
{
2025-03-17 18:21:41 +01:00
String s = choices[z];
if(this.prefixFirst != null)
choices[z] = s = this.prefixFirst + s;
2025-03-11 14:09:49 +01:00
if (s.length() > 0)
{
this.foundPlayerNames.add(s);
}
}
String s1 = this.inputField.getText().substring(this.inputField.getNthCharFromPos());
String s2 = getCommonPrefix(choices);
if (s2.length() > 0 && !s1.equalsIgnoreCase(s2))
{
this.inputField.deleteFromCursor();
this.inputField.insertText(s2);
}
else if (this.foundPlayerNames.size() > 0)
{
this.playerNamesFound = true;
this.autocompletePlayerNames();
}
}
}
private static String getCommonPrefix(String[] strs) {
if (strs != null && strs.length != 0) {
int smallestIndexOfDiff = indexOfDifference(strs);
if (smallestIndexOfDiff == -1) {
return strs[0] == null ? "" : strs[0];
} else {
return smallestIndexOfDiff == 0 ? "" : strs[0].substring(0, smallestIndexOfDiff);
}
} else {
return "";
}
}
private static int indexOfDifference(CharSequence[] css) {
if (css != null && css.length > 1) {
boolean anyStringNull = false;
boolean allStringsNull = true;
int arrayLen = css.length;
int shortestStrLen = Integer.MAX_VALUE;
int longestStrLen = 0;
int firstDiff;
for (firstDiff = 0; firstDiff < arrayLen; ++firstDiff) {
if (css[firstDiff] == null) {
anyStringNull = true;
shortestStrLen = 0;
} else {
allStringsNull = false;
shortestStrLen = Math.min(css[firstDiff].length(), shortestStrLen);
longestStrLen = Math.max(css[firstDiff].length(), longestStrLen);
}
}
if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
return -1;
} else if (shortestStrLen == 0) {
return 0;
} else {
firstDiff = -1;
for (int stringPos = 0; stringPos < shortestStrLen; ++stringPos) {
char comparisonChar = css[0].charAt(stringPos);
for (int arrayPos = 1; arrayPos < arrayLen; ++arrayPos) {
if (css[arrayPos].charAt(stringPos) != comparisonChar) {
firstDiff = stringPos;
break;
}
}
if (firstDiff != -1) {
break;
}
}
return firstDiff == -1 && shortestStrLen != longestStrLen ? shortestStrLen : firstDiff;
}
} else {
return -1;
}
}
}