Hytale Modding
Fundamentos do Java

09 — Trabalhando com strings

Domine operações de manipulação de texto e string em Java.

As strings são um dos tipos mais comumente usados em Java. São essenciais para lidar com nomes de jogadores, mensagens de chat, descrições de itens e com tudo o que você vê.

Noções básicas de string

As strings são objetos que armazenam texto:

String name = "Simon";
String message = "Bem-vindo(a) ao Hytale!";
String empty = "";
Strings são imutáveis

Uma vez criada, uma string não pode ser alterada. Métodos que parecem modificar uma string realmente criam uma nova!

String text = "Olá";
text.toUpperCase();           // Cria "OLÁ", mas não o salva
System.out.println(text);     // Ainda "Olá"

String upper = text.toUpperCase();  //Salva o resultado
System.out.println(upper);          // "OLÁ"

Métodos de string

Comprimento

String name = "Alice";
int length = name.length();
System.out.println(length);  // 5

Reverter uma string

String text = "Olá, Mundo";
String upper = text.toUpperCase();  // "OLÁ, MUNDO"
String lower = text.toLowerCase();  // "olá, mundo"

Verificando conteúdos

String message = "Bem-vindo(a) ao Hytale";

boolean hasHytale = message.contains("Hytale");  // verdadeiro
boolean hasMinecraft = message.contains("Minecraft");  // falso

boolean starts = message.startsWith("Bem-vindo(a)");  // verdadeiro
boolean ends = message.endsWith("Hytale");  // verdadeiro

Extração das partes da string

String text = "Olá Mundo";

char first = text.charAt(0);      // 'O'
char last = text.charAt(10);      // 'o'

String sub1 = text.substring(0, 5);   // "OIá"
String sub2 = text.substring(6);      // "Mundo"
Índices de substring

substring(start, end) inclue start, mas não end:

String text = "Hytale";
//             012345 (índices)

text.substring(0, 2);  // "Hy" (índices 0 e 1)
text.substring(2, 6);  // "tale" (índices 2, 3, 4, 5)
text.substring(2);     // "tale" (de 2 até o final)

Substituindo texto

String text = "Eu amo Minecraft";
String replaced = text.replace("Minecraft", "Hytale");
System.out.println(replaced);  // "Eu amo Hytale"

String noSpaces = "Olá, Mundo".replace(" ", "");
System.out.println(noSpaces);  // "Olá,Mundo" — sem o espaço entre as palavras

Retirando espaços vazios

String messy = "  Olá, Mundo  ";
String clean = messy.trim();
System.out.println(clean);  // "Olá, Mundo" (sem espaços no final)

Dividindo strings

String command = "Dar ao jogador uma espada 5";
String[] parts = command.split(" ");

System.out.println(parts[0]);  // "dar"
System.out.println(parts[1]);  // "ao"
System.out.println(parts[2]);  // "jogador"
System.out.println(parts[3]);  // "uma"

Comparação de strings

Nunca use `==` para strings

Sempre use .equals() para comparar os conteúdos das strings!

String name1 = "Steve";
String name2 = "Steve";

// Errado — Compara referências de objetos
if (name1 == name2) {
    System.out.println("Iguais");
}

// Correto — Compara o texto real
if (name1.equals(name2)) {
    System.out.println("Iguais");
}

// Ignora letras maiúsculas e minúsculas ao comparar.
if (name1.equalsIgnoreCase("steve")) {
    System.out.println("Iguais (ignorando a capitalização");
}

Comparando a ordem

String a = "Maçã";
String b = "Banana";

int result = a.compareTo(b);
// result < 0 se "a" vier antes de "b"
// result == 0 se "a" for igual a "b"
// result > 0 se "a" vier depois de "b"

if (a.compareTo(b) < 0) {
    System.out.println(a + " vem antes de " + b);
}

Concatenação de string

Usando o operador +

String first = "Olá";
String second = "Mundo";
String combined = first + " " + second;  // "Olá Mundo"

int score = 100;
String message = "Pontuação: " + score;  // "Pontuação: 100"

Usando .concat()

String result = "Olá".concat(" Mundo");  // "Olá Mundo"

Construindo strings longas

Para muitas concatenações, use o StringBuilder:

StringBuilder builder = new StringBuilder();
builder.append("Jogador: ");
builder.append("Alice");
builder.append(", Nível: ");
builder.append(10);
builder.append(", Vida: ");
builder.append(100);

String result = builder.toString();
System.out.println(result);
// "Jogador: Alice, Nível: 10, Vida: 100"
Por que StringBuilder?

A concatenação regular cria muitas strings temporárias:

// Ineficiente - Cria muitas strings temporárias
String result = "";
for (int i = 0; i < 1000; i++) {
    result = result + i;  // Cria 1000 strings temporárias!
}

// Eficiente - StringBuilder é mutável
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append(i);  // Modifica um objeto
}
String result = sb.toString();

Use StringBuilder ao montar strings em repetições!

Exemplos práticos

Parse Player Command

public class CommandParser {
    public static void parseCommand(String command) {
        // "/give Steve diamond_sword 1"
        String[] parts = command.split(" ");
        
        String action = parts[0].replace("/", "");  // "give"
        String player = parts[1];                   // "Steve"
        String item = parts[2];                     // "diamond_sword"
        int amount = Integer.parseInt(parts[3]);    // 1
        
        System.out.println("Ação: " + action);
        System.out.println("Jogador: " + player);
        System.out.println("Item: " + item);
        System.out.println("Quantidade: " + amount);
    }
    
    public static void main(String[] args) {
        parseCommand("/give Steve diamond_sword 1");
    }
}

Formatar nome de exibição do jogador

public class PlayerFormatter {
    public static String formatName(String name, int level, String rank) {
        StringBuilder formatted = new StringBuilder();
        
        if (rank != null && !rank.isEmpty()) {
            formatted.append("[").append(rank).append("] ");
        }
        
        formatted.append(name);
        formatted.append(" (Lv. ").append(level).append(")");
        
        return formatted.toString();
    }
    
    public static void main(String[] args) {
        String display1 = formatName("Alice", 10, "VIP");
        System.out.println(display1);  // "[VIP] Alice (Lv. 10)"
        
        String display2 = formatName("Bob", 5, null);
        System.out.println(display2);  // "Bob (Lv. 5)"
    }
}

Validar username

public class UsernameValidator {
    public static boolean isValid(String username) {
        // Regras: 3-16 caracteres, somente letras e números
        
        if (username == null || username.isEmpty()) {
            return false;
        }
        
        username = username.trim();
        
        if (username.length() < 3 || username.length() > 16) {
            return false;
        }
        
        for (int i = 0; i < username.length(); i++) {
            char c = username.charAt(i);
            if (!Character.isLetterOrDigit(c)) {
                return false;
            }
        }
        
        return true;
    }
    
    public static void main(String[] args) {
        System.out.println(isValid("Steve"));      // correto
        System.out.println(isValid("Player_123")); // errado (possui sublinhado)
        System.out.println(isValid("ab"));         // errado (muito curto)
        System.out.println(isValid(""));           // errado (vazio)
    }
}

Criador de Descrições de Itens

public class ItemDescription {
    public static String buildDescription(String name, String rarity, 
                                         int damage, int durability) {
        StringBuilder desc = new StringBuilder();
        
        // Título com código de cor de raridade
        desc.append(getRarityColor(rarity));
        desc.append(name);
        desc.append("\n");
        
        // Status
        desc.append("Damage: ").append(damage).append("\n");
        desc.append("Durability: ").append(durability).append("/");
        desc.append(durability).append("\n");
        desc.append("Rarity: ").append(rarity);
        
        return desc.toString();
    }
    
    private static String getRarityColor(String rarity) {
        switch (rarity.toLowerCase()) {
            case "legendary": return "§6";  // Dourado
            case "epic": return "§5";       // Roxo
            case "rare": return "§9";       // Azul
            case "common": return "§f";     // Branco
            default: return "§7";           // Cinza
        }
    }
    
    public static void main(String[] args) {
        String desc = buildDescription("Excalibur", "Legendary", 50, 1000);
        System.out.println(desc);
    }
}

Filtro de Mensagens de Chat

public class ChatFilter {
    private static String[] bannedWords = {"badword1", "badword2"};
    
    public static String filterMessage(String message) {
        String filtered = message.toLowerCase();
        
        for (String word : bannedWords) {
            if (filtered.contains(word)) {
                String replacement = "*".repeat(word.length());
                filtered = filtered.replace(word, replacement);
            }
        }
        
        return filtered;
    }
    
    public static void main(String[] args) {
        String message = "This is a badword1 test";
        String clean = filterMessage(message);
        System.out.println(clean);  // "this is a ******** test"
    }
}

Formatação de String

Usando String.format()

String name = "Alice";
int level = 10;
double health = 85.5;

String formatted = String.format("%s is level %d with %.1f%% health", 
                                 name, level, health);
System.out.println(formatted);
// "Alice está no nível 10 com 85.5% de vida"
Especificadores de Formatação

Códigos de formato comum:

  • %s — String
  • %d — Integer
  • %f — Ponto float
  • %.2f — Float com 2 casas decimais
  • %n — Nova linha (independente da plataforma)
String.format("Name: %s", "Steve");          // "Nome: Steve"
String.format("Level: %d", 10);              // "Nível: 10"
String.format("Health: %.1f", 85.5);         // "Vida: 85.5"
String.format("Position: (%d, %d, %d)", 
              10, 64, -5);                    // "Posição: (10, 64, -5)"

Operações Comuns de Strings

Verificar se a string está vazia

String text = "";

// Verificar se está vazio ou nulo
if (text == null || text.isEmpty()) {
    System.out.println("Empty!");
}

// Verificar apenas se há valores vazios, nulos ou espaços em branco
if (text == null || text.trim().isEmpty()) {
    System.out.println("Empty or whitespace!");
}

Contagem de ocorrências

public static int countOccurrences(String text, String target) {
    int count = 0;
    int index = 0;
    
    while ((index = text.indexOf(target, index)) != -1) {
        count++;
        index += target.length();
    }
    
    return count;
}

// Uso
int count = countOccurrences("hello hello world", "hello");
System.out.println(count);  // 2

Reverter uma Cadeia

public static String reverse(String text) {
    StringBuilder sb = new StringBuilder(text);
    return sb.reverse().toString();
}

// Uso
String reversed = reverse("Hello");
System.out.println(reversed);  // "olleH"

Verifique se é um Palíndromo

public static boolean isPalindrome(String text) {
    String cleaned = text.toLowerCase().replaceAll("[^a-z0-9]", "");
    String reversed = new StringBuilder(cleaned).reverse().toString();
    return cleaned.equals(reversed);
}

// Usage
System.out.println(isPalindrome("racecar"));     // Correto
System.out.println(isPalindrome("hello"));       // Errado

Exercícios Práticos

  1. Verificador de Usuário: Escreva um método que verifique se um nome de usuário:

    • Deve ter entre 3 e 16 caracteres
    • Conter apenas letras, números e sublinhados
    • Não pode começar com um número
    • Retorna true se for válido, e false se não for
  2. Command Parse: Analisar este formato do comando: /teleport x y z

    • Extrair as coordenadas
    • Converter para números inteiros
    • Retorna uma matriz de três valores
  3. Formatador de Chat: Crie um método que formate as mensagens de chat:

    • Input: nome do jogador, cargo, mensagem
    • Output: "[RANK] Nome do Jogador: mensagem"
    • Se não houver rank, apenas mostre "Nome do Jogador: mensagem"
  4. Contagem de Palavras: Contar quantas palavras há em uma frase (as palavras são separadas por espaços)

  5. Casos de Título: Converter uma sequência de caracteres para maiúsculas e minúsculas:

    • Input: "hello world"
    • Output: "Hello World"