refactored some code parts, refactored PR, implemented ClassiCube, fixed some bugs

This commit is contained in:
FlorianMichael 2023-03-25 21:42:43 +01:00
parent 67e6be3788
commit 236cedea59
50 changed files with 875 additions and 220 deletions

View File

@ -94,7 +94,6 @@ It should work fine with most if not all mods and modpacks.
- [x] Animation related fixes (1.7 Sneaking, c0.30 walking animation, ...)
- [x] Fixed clientside packet handling (1.16.5 transactions, 1.19.0 tablist, ...)
#### TODO:
- [ ] ClassiCube implementation for MP Pass
- [ ] BetaCraft server list screen
- [ ] More extensions for Classic Protocol Extensions protocol
- [ ] Window click interactions in <= 1.16.5

0
logs/latest.log Normal file
View File

View File

@ -19,25 +19,28 @@ package de.florianmichael.viafabricplus;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import de.florianmichael.viafabricplus.definition.ChatLengthDefinition;
import de.florianmichael.viafabricplus.definition.ItemReleaseVersionDefinition;
import de.florianmichael.viafabricplus.definition.PackFormatsDefinition;
import de.florianmichael.viafabricplus.definition.ChatLengthCalculation;
import de.florianmichael.viafabricplus.mappings.ItemReleaseVersionMappings;
import de.florianmichael.viafabricplus.mappings.PackFormatsMappings;
import de.florianmichael.viafabricplus.definition.bedrock.BedrockAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.ClassicItemSelectionScreen;
import de.florianmichael.viafabricplus.screen.ClassicItemSelectionScreen;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.protocol.CustomClassicProtocolExtensions;
import de.florianmichael.viafabricplus.definition.c0_30.command.ClassicProtocolCommands;
import de.florianmichael.viafabricplus.definition.v1_8_x.ArmorPointsDefinition;
import de.florianmichael.viafabricplus.mappings.ArmorPointsMappings;
import de.florianmichael.viafabricplus.event.FinishMinecraftLoadCallback;
import de.florianmichael.viafabricplus.event.PreLoadCallback;
import de.florianmichael.viafabricplus.information.InformationSystem;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.settings.SettingsSystem;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
public class ViaFabricPlus {
public final static Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public final static Logger LOGGER = LogManager.getLogger("ViaFabricPlus");
public final static File RUN_DIRECTORY = new File("ViaFabricPlus");
public final static ViaFabricPlus INSTANCE = new ViaFabricPlus();
@ -51,10 +54,13 @@ public class ViaFabricPlus {
// Classic Stuff
CustomClassicProtocolExtensions.create();
ClassicItemSelectionScreen.create();
ChatLengthDefinition.create();
ChatLengthCalculation.create();
ClassicProtocolCommands.create();
ClassiCubeAccountHandler.create();
// Bedrock Stuff
BedrockAccountHandler.create();
new ProtocolHack();
FinishMinecraftLoadCallback.EVENT.register(() -> {
@ -62,13 +68,10 @@ public class ViaFabricPlus {
settingsSystem.init();
informationSystem.init();
// General definitions
PackFormatsDefinition.load();
ItemReleaseVersionDefinition.create();
ArmorPointsDefinition.load();
// Bedrock Stuff
BedrockAccountHandler.create();
// Mappings
PackFormatsMappings.load();
ItemReleaseVersionMappings.create();
ArmorPointsMappings.load();
});
}

View File

@ -19,31 +19,31 @@ package de.florianmichael.viafabricplus.definition;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback;
import de.florianmichael.viafabricplus.event.LoadClassicProtocolExtensionCallback;
import net.minecraft.client.MinecraftClient;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.data.ClassicProtocolExtension;
public class ChatLengthDefinition {
public static ChatLengthDefinition INSTANCE;
public class ChatLengthCalculation {
public static ChatLengthCalculation INSTANCE;
private int maxLength = 256;
public static void create() {
INSTANCE = new ChatLengthDefinition();
INSTANCE = new ChatLengthCalculation();
ChangeProtocolVersionCallback.EVENT.register(protocolVersion -> {
INSTANCE.maxLength = 256;
if (protocolVersion.isOlderThanOrEqualTo(ProtocolVersion.v1_10)) {
INSTANCE.maxLength = 100;
if (protocolVersion.isOlderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) {
INSTANCE.maxLength = 64 - MinecraftClient.getInstance().getSession().getUsername().length() - 2;
}
if (protocolVersion.isOlderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) INSTANCE.maxLength = 64 - MinecraftClient.getInstance().getSession().getUsername().length() - 2;
}
});
}
private int maxLength = 256;
public void expand() {
maxLength = Short.MAX_VALUE * 2;
LoadClassicProtocolExtensionCallback.EVENT.register(classicProtocolExtension -> {
if (classicProtocolExtension == ClassicProtocolExtension.LONGER_MESSAGES) INSTANCE.maxLength = Short.MAX_VALUE * 2;
});
}
public int getMaxLength() {

View File

@ -19,6 +19,7 @@ package de.florianmichael.viafabricplus.definition.bedrock;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.util.FileSaver;
import net.raphimc.mcauth.MinecraftAuth;
import net.raphimc.mcauth.step.bedrock.StepMCChain;
@ -43,6 +44,8 @@ public class BedrockAccountHandler extends FileSaver {
@Override
public void write(JsonObject object) {
if (account == null) return;
for (Map.Entry<String, JsonElement> entry : account.toJson().entrySet()) {
object.add(entry.getKey(), entry.getValue());
}
@ -56,7 +59,7 @@ public class BedrockAccountHandler extends FileSaver {
account = MinecraftAuth.Bedrock.Title.MC_CHAIN.refresh(httpClient, account);
}
} catch (Exception e) {
e.printStackTrace();
ViaFabricPlus.LOGGER.error("Failed to log into Bedrock account!", e);
}
}

View File

@ -0,0 +1,46 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.definition.c0_30;
import com.google.common.hash.Hashing;
import com.google.common.io.Resources;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import net.raphimc.vialegacy.protocols.release.protocol1_3_1_2to1_2_4_5.providers.OldAuthProvider;
import java.net.InetAddress;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
public class BetaCraftImpl {
public static String getBetaCraftMpPass(final UserConnection user, final String username, final String serverIp, final int port) {
try {
final String server = InetAddress.getByName(serverIp).getHostAddress() + ":" + port;
Via.getManager().getProviders().get(OldAuthProvider.class).sendAuthRequest(user, Hashing.sha1().hashBytes(server.getBytes()).toString());
final String mppass = Resources.toString(new URL("http://api.betacraft.uk/getmppass.jsp?user=" + username + "&server=" + server), StandardCharsets.UTF_8);
if (mppass.contains("FAILED") || mppass.contains("SERVER NOT FOUND")) return "0";
return mppass;
} catch (Throwable e) {
ViaFabricPlus.LOGGER.error("An unknown error occurred while authenticating with BetaCraft");
}
return "0";
}
}

View File

@ -1,32 +1,53 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.definition.c0_30.classicube;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.process.ILoginProcessHandler;
import de.florianmichael.viafabricplus.event.DisconnectConnectionCallback;
import de.florianmichael.viafabricplus.protocolhack.provider.vialegacy.ViaFabricPlusClassicMPPassProvider;
import de.florianmichael.viafabricplus.util.FileSaver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.login.LoginException;
import java.util.Map;
public class ClassiCubeAccountHandler extends FileSaver implements ILoginProcessHandler {
public final static Logger LOGGER = LoggerFactory.getLogger("ViaFabricPlus/ClassiCube Account Handler");
public class ClassiCubeAccountHandler extends FileSaver {
public static ClassiCubeAccountHandler INSTANCE;
private ClassiCubeAccount account;
public ClassiCubeAccountHandler() {
super("classicube.account");
}
public static void create() {
ClassiCubeAccountHandler.INSTANCE = new ClassiCubeAccountHandler();
ClassiCubeAccountHandler.INSTANCE.init();
}
private ClassiCubeAccount account;
public ClassiCubeAccountHandler() {
super("classicube.account");
DisconnectConnectionCallback.EVENT.register(() -> ViaFabricPlusClassicMPPassProvider.classiCubeMPPass = null);
}
@Override
public void write(JsonObject object) {
if (account == null) return;
account.token = null; // Token has to be created next time
for (Map.Entry<String, JsonElement> entry : account.toJson().entrySet()) {
object.add(entry.getKey(), entry.getValue());
}
@ -36,23 +57,16 @@ public class ClassiCubeAccountHandler extends FileSaver implements ILoginProcess
public void read(JsonObject object) {
try {
account = ClassiCubeAccount.fromJson(object);
account.login(this);
} catch (LoginException e) {
LOGGER.error("Failed to log into ClassiCube account!", e);
} catch (Exception e) {
ViaFabricPlus.LOGGER.error("Failed to log into ClassiCube account!", e);
}
}
@Override
public void handleMfa(ClassiCubeAccount account) {
LOGGER.error("Failed to log into ClassiCube account due to MFA request.");
public ClassiCubeAccount getAccount() {
return account;
}
@Override
public void handleSuccessfulLogin(ClassiCubeAccount account) {
LOGGER.info("Successfully logged into ClassiCube!");
}
public ClassiCubeAccount getAccountClone() {
return new ClassiCubeAccount(account.token, account.username, account.password);
public void setAccount(ClassiCubeAccount account) {
this.account = account;
}
}

View File

@ -4,11 +4,13 @@ import com.google.gson.JsonObject;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.process.ILoginProcessHandler;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.request.auth.ClassiCubeAuthenticationLoginRequest;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.request.auth.ClassiCubeAuthenticationTokenRequest;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.response.auth.ClassiCubeAuthenticationResponse;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.store.CookieStore;
import javax.security.auth.login.LoginException;
public class ClassiCubeAccount {
public final CookieStore cookieStore = new CookieStore();
public String token;
public String username;
public String password;
@ -34,40 +36,44 @@ public class ClassiCubeAccount {
}
public static ClassiCubeAccount fromJson(JsonObject jsonObject) {
final String token = jsonObject.getAsString();
final String username = jsonObject.getAsString();
final String password = jsonObject.getAsString();
String token = null;
if (jsonObject.has("token")) token = jsonObject.get("token").getAsString();
return new ClassiCubeAccount(token, username, password);
return new ClassiCubeAccount(token, jsonObject.get("username").getAsString(), jsonObject.get("password").getAsString());
}
public void login(ILoginProcessHandler processHandler) throws LoginException {
final ClassiCubeAuthenticationTokenRequest initialTokenRequest = new ClassiCubeAuthenticationTokenRequest();
final ClassiCubeAuthenticationResponse initialTokenResponse = initialTokenRequest.send().join();
public void login(ILoginProcessHandler processHandler, String loginCode) {
final ClassiCubeAuthenticationTokenRequest initialTokenRequest = new ClassiCubeAuthenticationTokenRequest(this);
initialTokenRequest.send().whenComplete((initialTokenResponse, throwable) -> {
if (throwable != null) {
processHandler.handleException(throwable);
return;
}
// There should NEVER be any errors on the initial token response!
if (initialTokenResponse.shouldError()) {
final String errorDisplay = initialTokenResponse.getErrorDisplay();
processHandler.handleException(new LoginException(errorDisplay));
return;
}
this.token = initialTokenResponse.token;
// There should NEVER be any errors on the initial token response!
if (initialTokenResponse.shouldError()) {
final String errorDisplay = initialTokenResponse.getErrorDisplay();
throw new LoginException(errorDisplay);
}
final ClassiCubeAuthenticationLoginRequest loginRequest = new ClassiCubeAuthenticationLoginRequest(initialTokenResponse, this.username, this.password);
final ClassiCubeAuthenticationResponse loginResponse = loginRequest.send().join();
if (loginResponse.shouldError()) {
final String errorDisplay = loginResponse.getErrorDisplay();
throw new LoginException(errorDisplay);
}
this.token = loginResponse.token;
if (initialTokenResponse.mfaRequired()) {
processHandler.handleMfa(this);
return;
}
processHandler.handleSuccessfulLogin(this);
final ClassiCubeAuthenticationLoginRequest loginRequest = new ClassiCubeAuthenticationLoginRequest(initialTokenResponse, this, loginCode);
loginRequest.send().whenComplete((loginResponse, throwable1) -> {
if (throwable1 != null) {
processHandler.handleException(throwable1);
return;
}
if (initialTokenResponse.mfaRequired()) {
processHandler.handleMfa(this);
return;
}
if (loginResponse.shouldError()) {
final String errorDisplay = loginResponse.getErrorDisplay();
processHandler.handleException(new LoginException(errorDisplay));
return;
}
processHandler.handleSuccessfulLogin(this);
});
});
}
}

View File

@ -1,6 +1,8 @@
package de.florianmichael.viafabricplus.definition.c0_30.classicube.auth;
import javax.annotation.Nullable;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* Contains the authentication data that will be used in the URL parameters of the /api/login request.
@ -28,16 +30,16 @@ public class ClassiCubeAuthenticationData {
}
public String getRequestBody() {
final StringBuilder builder = new StringBuilder("username=").append(username);
final StringBuilder builder = new StringBuilder("username=").append(URLEncoder.encode(username, StandardCharsets.UTF_8));
builder.append("&password=");
builder.append(password);
builder.append(URLEncoder.encode(password, StandardCharsets.UTF_8));
builder.append("&token=");
builder.append(previousToken);
builder.append(URLEncoder.encode(previousToken, StandardCharsets.UTF_8));
if (loginCode != null) {
builder.append("&login_code=");
builder.append(loginCode);
builder.append(URLEncoder.encode(loginCode, StandardCharsets.UTF_8));
}
return builder.toString();

View File

@ -1,37 +1,23 @@
package de.florianmichael.viafabricplus.definition.c0_30.classicube.auth;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import net.minecraft.text.Text;
import java.lang.reflect.Type;
import java.util.Arrays;
public enum ClassiCubeError {
TOKEN(Text.translatable("classicube.viafabricplus.error.token")),
USERNAME(Text.translatable("classicube.viafabricplus.error.username")),
PASSWORD(Text.translatable("classicube.viafabricplus.error.password")),
VERIFICATION(Text.translatable("classicube.viafabricplus.error.verification"), false),
LOGIN_CODE(Text.translatable("classicube.viafabricplus.error.logincode"));
public enum ClassiCubeError implements JsonDeserializer<ClassiCubeError> {
TOKEN("Incorrect token. Is your ViaFabricPlus out of date?"),
USERNAME("Invalid username."),
PASSWORD("Invalid password."),
VERIFICATION("User hasn't verified their E-mail address yet.", false),
LOGIN_CODE("Multi-factor authentication requested. Please check your E-mail.");
public final String description;
public final Text description;
public final boolean fatal;
ClassiCubeError(String description) {
ClassiCubeError(Text description) {
this(description, true);
}
ClassiCubeError(String description, boolean fatal) {
ClassiCubeError(Text description, boolean fatal) {
this.description = description;
this.fatal = fatal;
}
@Override
public ClassiCubeError deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return Arrays.stream(ClassiCubeError.values())
.filter(e -> e.name().toLowerCase().equals(json.getAsString()))
.findFirst()
.orElse(null);
}
}

View File

@ -6,4 +6,5 @@ public interface ILoginProcessHandler {
void handleMfa(final ClassiCubeAccount account);
void handleSuccessfulLogin(final ClassiCubeAccount account);
void handleException(final Throwable throwable);
}

View File

@ -2,17 +2,7 @@ package de.florianmichael.viafabricplus.definition.c0_30.classicube.data;
import com.google.gson.annotations.SerializedName;
public record ClassiCubeServerInfo(
String hash,
@SerializedName("maxplayers") int maxPlayers,
String name,
int players,
String software,
long uptime,
@SerializedName("country_abbr") String countryCode,
boolean web,
boolean featured,
String ip,
int port,
String mppass) {
public record ClassiCubeServerInfo(String hash, int maxplayers, String name, int players, String software, long uptime,
@SerializedName("country_abbr") String countryCode, boolean web, boolean featured,
String ip, int port, String mppass) {
}

View File

@ -1,27 +1,31 @@
package de.florianmichael.viafabricplus.definition.c0_30.classicube.request;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public abstract class ClassiCubeRequest {
private final static URI CLASSICUBE_ROOT_URI = URI.create("https://www.classicube.net");
protected final static URI AUTHENTICATION_URI = CLASSICUBE_ROOT_URI.resolve("/api/login/");
protected final static URI SERVER_INFO_URI = CLASSICUBE_ROOT_URI.resolve("/api/server/");
protected final static URI SERVER_LIST_INFO_URI = CLASSICUBE_ROOT_URI.resolve("/api/servers/");
protected final static HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
protected final ClassiCubeAccount account;
public HttpRequest buildWithTokenHeader(final HttpRequest.Builder builder) {
final ClassiCubeAccountHandler accountHandler = ClassiCubeAccountHandler.INSTANCE;
final ClassiCubeAccount account = accountHandler.getAccountClone();
protected ClassiCubeRequest(ClassiCubeAccount account) {
this.account = account;
}
builder.header("Cookie", "session=" + account.token);
protected HttpRequest buildWithCookies(final HttpRequest.Builder builder) {
return this.account.cookieStore.appendCookies(builder)
.build();
}
return builder.build();
protected void updateCookies(final HttpResponse<?> response) {
this.account.cookieStore.mergeFromResponse(response);
}
}

View File

@ -1,5 +1,6 @@
package de.florianmichael.viafabricplus.definition.c0_30.classicube.request.auth;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAuthenticationData;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.request.ClassiCubeRequest;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.response.auth.ClassiCubeAuthenticationResponse;
@ -11,27 +12,33 @@ import java.util.concurrent.CompletableFuture;
public class ClassiCubeAuthenticationLoginRequest extends ClassiCubeAuthenticationRequest {
private final ClassiCubeAuthenticationData authenticationData;
private final ClassiCubeAccount account;
public ClassiCubeAuthenticationLoginRequest(ClassiCubeAuthenticationResponse previousResponse, String username, String password) {
this(previousResponse, username, password, null);
public ClassiCubeAuthenticationLoginRequest(ClassiCubeAuthenticationResponse previousResponse, ClassiCubeAccount account) {
this(previousResponse, account, null);
}
public ClassiCubeAuthenticationLoginRequest(ClassiCubeAuthenticationResponse previousResponse, String username, String password, @Nullable String loginCode) {
this.authenticationData = new ClassiCubeAuthenticationData(username, password, previousResponse.token, loginCode);
public ClassiCubeAuthenticationLoginRequest(ClassiCubeAuthenticationResponse previousResponse, ClassiCubeAccount account, @Nullable String loginCode) {
super(account);
this.authenticationData = new ClassiCubeAuthenticationData(account.username, account.password, previousResponse.token, loginCode);
this.account = account;
}
@Override
public CompletableFuture<ClassiCubeAuthenticationResponse> send() {
return CompletableFuture.supplyAsync(() -> {
final String requestBody = authenticationData.getRequestBody();
final HttpRequest request = HttpRequest.newBuilder()
final HttpRequest request = this.buildWithCookies(HttpRequest.newBuilder()
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.uri(ClassiCubeRequest.AUTHENTICATION_URI)
.build();
.header("content-type", "application/x-www-form-urlencoded"));
final HttpResponse<String> response = HTTP_CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.join();
this.updateCookies(response);
final String responseBody = response.body();
return ClassiCubeAuthenticationResponse.fromJson(responseBody);
});

View File

@ -1,5 +1,6 @@
package de.florianmichael.viafabricplus.definition.c0_30.classicube.request.auth;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.request.ClassiCubeRequest;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.response.auth.ClassiCubeAuthenticationResponse;
@ -7,5 +8,9 @@ import java.util.concurrent.CompletableFuture;
public abstract class ClassiCubeAuthenticationRequest extends ClassiCubeRequest {
protected ClassiCubeAuthenticationRequest(ClassiCubeAccount account) {
super(account);
}
public abstract CompletableFuture<ClassiCubeAuthenticationResponse> send();
}

View File

@ -1,5 +1,6 @@
package de.florianmichael.viafabricplus.definition.c0_30.classicube.request.auth;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.request.ClassiCubeRequest;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.response.auth.ClassiCubeAuthenticationResponse;
@ -11,6 +12,10 @@ import java.util.concurrent.CompletableFuture;
public class ClassiCubeAuthenticationTokenRequest extends ClassiCubeAuthenticationRequest {
private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
public ClassiCubeAuthenticationTokenRequest(ClassiCubeAccount account) {
super(account);
}
@Override
public CompletableFuture<ClassiCubeAuthenticationResponse> send() {
return CompletableFuture.supplyAsync(() -> {
@ -22,6 +27,7 @@ public class ClassiCubeAuthenticationTokenRequest extends ClassiCubeAuthenticati
final HttpResponse<String> response = HTTP_CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.join();
this.updateCookies(response);
final String responseBody = response.body();
return ClassiCubeAuthenticationResponse.fromJson(responseBody);
});

View File

@ -1,5 +1,6 @@
package de.florianmichael.viafabricplus.definition.c0_30.classicube.request.server;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.request.ClassiCubeRequest;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.response.server.ClassiCubeServerInfoResponse;
@ -12,11 +13,12 @@ import java.util.concurrent.CompletableFuture;
public class ClassiCubeServerInfoRequest extends ClassiCubeRequest {
private final Set<String> serverHashes;
public ClassiCubeServerInfoRequest(final String serverHash) {
this(Set.of(serverHash));
public ClassiCubeServerInfoRequest(final ClassiCubeAccount account, final String serverHash) {
this(account, Set.of(serverHash));
}
public ClassiCubeServerInfoRequest(final Set<String> serverHashes) {
public ClassiCubeServerInfoRequest(final ClassiCubeAccount account, final Set<String> serverHashes) {
super(account);
this.serverHashes = serverHashes;
}
@ -29,12 +31,14 @@ public class ClassiCubeServerInfoRequest extends ClassiCubeRequest {
public CompletableFuture<ClassiCubeServerInfoResponse> send() {
return CompletableFuture.supplyAsync(() -> {
final URI uri = this.generateUri();
final HttpRequest request = buildWithTokenHeader(HttpRequest.newBuilder()
final HttpRequest request = this.buildWithCookies(HttpRequest.newBuilder()
.GET()
.uri(uri));
final HttpResponse<String> response = HTTP_CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.join();
updateCookies(response);
final String body = response.body();
return ClassiCubeServerInfoResponse.fromJson(body);

View File

@ -1,5 +1,6 @@
package de.florianmichael.viafabricplus.definition.c0_30.classicube.request.server;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.request.ClassiCubeRequest;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.response.server.ClassiCubeServerInfoResponse;
@ -8,14 +9,20 @@ import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class ClassiCubeServerListRequest extends ClassiCubeRequest {
public ClassiCubeServerListRequest(ClassiCubeAccount account) {
super(account);
}
public CompletableFuture<ClassiCubeServerInfoResponse> send() {
return CompletableFuture.supplyAsync(() -> {
final HttpRequest request = buildWithTokenHeader(HttpRequest.newBuilder()
final HttpRequest request = this.buildWithCookies(HttpRequest.newBuilder()
.GET()
.uri(SERVER_LIST_INFO_URI));
final HttpResponse<String> response = HTTP_CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.join();
updateCookies(response);
final String body = response.body();
return ClassiCubeServerInfoResponse.fromJson(body);

View File

@ -4,7 +4,9 @@ import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCu
import de.florianmichael.viafabricplus.definition.c0_30.classicube.response.ClassiCubeResponse;
import javax.annotation.Nullable;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
/**
* The class containing the response from the ClassiCube authentication service.
@ -15,40 +17,36 @@ public class ClassiCubeAuthenticationResponse extends ClassiCubeResponse {
@Nullable public final String token;
@Nullable public final String username;
public final boolean authenticated;
public final Set<String> errors;
public ClassiCubeAuthenticationResponse(@Nullable String token, @Nullable String username, boolean authenticated, Set<ClassiCubeError> errors) {
public ClassiCubeAuthenticationResponse(@Nullable String token, @Nullable String username, boolean authenticated, Set<String> errors) {
this.token = token;
this.username = username;
this.authenticated = authenticated;
this.errors = errors;
}
public final Set<ClassiCubeError> errors;
public boolean shouldError() {
return errors.size() > 0 &&
errors.stream().anyMatch(e -> e.fatal);
return errors.size() > 0;
}
public String getErrorDisplay() {
final StringBuilder builder = new StringBuilder();
for (ClassiCubeError error : this.errors) {
builder.append(error.description)
.append("\n");
for (String error : this.errors) {
builder.append(ClassiCubeError.valueOf(error.toUpperCase()).description.getString()).append("\n");
}
return builder.toString()
.trim();
}
public boolean mfaRequired() {
return this.errors.stream().anyMatch(e -> e == ClassiCubeError.LOGIN_CODE);
public Set<ClassiCubeError> errors() {
return this.errors.stream().map(s -> ClassiCubeError.valueOf(s.toUpperCase(Locale.ROOT))).collect(Collectors.toSet());
}
public boolean isJustMfaError() {
return mfaRequired() &&
this.errors.stream().anyMatch(e -> e != ClassiCubeError.LOGIN_CODE);
public boolean mfaRequired() {
return this.errors().stream().anyMatch(e -> e == ClassiCubeError.LOGIN_CODE);
}
public static ClassiCubeAuthenticationResponse fromJson(final String json) {

View File

@ -0,0 +1,99 @@
package de.florianmichael.viafabricplus.definition.c0_30.classicube.store;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class CookieStore {
private final Map<String, String> values;
public CookieStore() {
this.values = new HashMap<>();
}
public CookieStore(Map<String, String> values) {
this.values = values;
}
public Map<String, String> getMap() {
return Collections.unmodifiableMap(values);
}
public void merge(CookieStore cookieStore) {
this.values.putAll(cookieStore.getMap());
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
int i = 0;
for (Map.Entry<String, String> entry : values.entrySet()) {
if (i != 0) {
builder.append(";");
}
builder.append(entry.getKey());
builder.append("=");
builder.append(entry.getValue());
i++;
}
return builder.toString();
}
public void mergeFromResponse(HttpResponse<?> response) {
final Optional<String> setCookieHeaderOptional = response.headers()
.firstValue("set-cookie");
if (setCookieHeaderOptional.isEmpty()) {
return;
}
final String setCookieHeader = setCookieHeaderOptional.get();
final CookieStore store = CookieStore.parse(setCookieHeader);
this.merge(store);
}
public HttpRequest.Builder appendCookies(HttpRequest.Builder builder) {
builder.header("Cookie", this.toString());
return builder;
}
public static CookieStore parse(final String value) {
final char[] characters = value.toCharArray();
StringBuilder currentKey = new StringBuilder();
StringBuilder currentValue = new StringBuilder();
boolean key = true;
final Map<String, String> values = new HashMap<>();
for (final char character : characters) {
if (character == '=' && key) {
currentValue = new StringBuilder();
key = false;
continue;
}
if (character == ';' && !key) {
key = true;
values.put(currentKey.toString(), currentValue.toString());
continue;
}
if (key) {
currentKey.append(character);
} else {
currentValue.append(character);
}
}
return new CookieStore(values);
}
}

View File

@ -18,8 +18,7 @@
package de.florianmichael.viafabricplus.definition.c0_30.protocol;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.definition.ChatLengthDefinition;
import de.florianmichael.viafabricplus.definition.c0_30.ClassicItemSelectionScreen;
import de.florianmichael.viafabricplus.screen.ClassicItemSelectionScreen;
import de.florianmichael.viafabricplus.event.LoadClassicProtocolExtensionCallback;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import io.netty.buffer.ByteBuf;
@ -44,7 +43,6 @@ public class CustomClassicProtocolExtensions {
EXT_WEATHER_TYPE = createNewPacket(ClassicProtocolExtension.ENV_WEATHER_TYPE, 31, (user, buf) -> buf.readByte());
LoadClassicProtocolExtensionCallback.EVENT.register(classicProtocolExtension -> {
if (classicProtocolExtension == ClassicProtocolExtension.LONGER_MESSAGES) ChatLengthDefinition.INSTANCE.expand();
if (classicProtocolExtension == ClassicProtocolExtension.CUSTOM_BLOCKS) ClassicItemSelectionScreen.INSTANCE.reload(ProtocolHack.getTargetVersion(), true);
});
}

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.definition;
package de.florianmichael.viafabricplus.definition.v1_14_4;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.vialoadingbase.platform.ComparableProtocolVersion;
@ -25,7 +25,7 @@ import net.minecraft.client.network.ServerAddress;
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
public class TileServerAddress {
public class LegacyServerAddress {
private final static ProtocolRange SRV_RANGE = new ProtocolRange(ProtocolVersion.v1_16_4, LegacyProtocolVersion.r1_3_1tor1_3_2);
public static ServerAddress parse(final ComparableProtocolVersion version, String address) {

View File

@ -0,0 +1,32 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.event;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface DisconnectConnectionCallback {
Event<DisconnectConnectionCallback> EVENT = EventFactory.createArrayBacked(DisconnectConnectionCallback.class, listeners -> () -> {
for (DisconnectConnectionCallback listener : listeners) {
listener.onDisconnect();
}
});
void onDisconnect();
}

View File

@ -18,6 +18,7 @@
package de.florianmichael.viafabricplus.injection.mixin.base;
import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback;
import de.florianmichael.viafabricplus.event.DisconnectConnectionCallback;
import de.florianmichael.viafabricplus.injection.access.IClientConnection;
import de.florianmichael.viafabricplus.protocolhack.constants.PreNettyConstants;
import de.florianmichael.viafabricplus.protocolhack.constants.BedrockRakNetConstants;
@ -108,6 +109,7 @@ public abstract class MixinClientConnection extends SimpleChannelInboundHandler<
@Inject(method = "disconnect", at = @At("RETURN"))
public void resetStorages(Text disconnectReason, CallbackInfo ci) {
ChangeProtocolVersionCallback.EVENT.invoker().onChangeProtocolVersion(ViaLoadingBase.getClassWrapper().getTargetVersion());
DisconnectConnectionCallback.EVENT.invoker().onDisconnect();
}
@Override

View File

@ -0,0 +1,35 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.base;
import de.florianmichael.viafabricplus.screen.classicube.ClassiCubeLoginScreen;
import net.minecraft.SharedConstants;
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.CallbackInfoReturnable;
@Mixin(SharedConstants.class)
public class MixinSharedConstants {
@Inject(method = "isValidChar", at = @At("HEAD"), cancellable = true)
private static void allowEveryCharacter(char chr, CallbackInfoReturnable<Boolean> cir) {
if (MinecraftClient.getInstance().currentScreen instanceof ClassiCubeLoginScreen) cir.setReturnValue(true);
}
}

View File

@ -35,6 +35,7 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
public class MixinServerInfo implements IServerInfo {
@Shadow public String name;
@Unique
private ComparableProtocolVersion viafabricplus_forcedVersion = null;

View File

@ -21,7 +21,7 @@ import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.definition.PackFormatsDefinition;
import de.florianmichael.viafabricplus.mappings.PackFormatsMappings;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.GameVersion;
import net.minecraft.client.resource.ServerResourcePackProvider;
@ -48,7 +48,7 @@ public class MixinServerResourcePackProvider {
@Redirect(method = "getDownloadHeaders", at = @At(value = "INVOKE", target = "Lnet/minecraft/SharedConstants;getGameVersion()Lnet/minecraft/GameVersion;"))
private static GameVersion editHeaders() {
return PackFormatsDefinition.current();
return PackFormatsMappings.current();
}
@Inject(method = "getDownloadHeaders", at = @At("TAIL"), cancellable = true)

View File

@ -17,7 +17,7 @@
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft;
import de.florianmichael.viafabricplus.definition.ChatLengthDefinition;
import de.florianmichael.viafabricplus.definition.ChatLengthCalculation;
import net.minecraft.util.StringHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.Constant;
@ -28,6 +28,6 @@ public class MixinStringHelper {
@ModifyConstant(method = "truncateChat", constant = @Constant(intValue = 256))
private static int expandChatLength(int constant) {
return ChatLengthDefinition.INSTANCE.getMaxLength();
return ChatLengthCalculation.INSTANCE.getMaxLength();
}
}

View File

@ -19,7 +19,7 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.entity;
import com.mojang.authlib.GameProfile;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.definition.v1_8_x.ArmorPointsDefinition;
import de.florianmichael.viafabricplus.mappings.ArmorPointsMappings;
import de.florianmichael.viafabricplus.event.SkipIdlePacketCallback;
import de.florianmichael.viafabricplus.injection.access.IClientPlayerEntity;
import de.florianmichael.viafabricplus.settings.groups.DebugSettings;
@ -221,7 +221,7 @@ public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity
@Override
public int getArmor() {
if (VisualSettings.INSTANCE.emulateArmorHud.getValue()) {
return ArmorPointsDefinition.sum();
return ArmorPointsMappings.sum();
}
return super.getArmor();
}

View File

@ -17,7 +17,7 @@
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.item;
import de.florianmichael.viafabricplus.definition.ItemReleaseVersionDefinition;
import de.florianmichael.viafabricplus.mappings.ItemReleaseVersionMappings;
import de.florianmichael.viafabricplus.settings.groups.GeneralSettings;
import net.minecraft.client.MinecraftClient;
import net.minecraft.item.Item;
@ -32,7 +32,7 @@ public class MixinItemGroup_EntriesImpl {
@Redirect(method = "add", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;isEnabled(Lnet/minecraft/resource/featuretoggle/FeatureSet;)Z"))
public boolean removeUnknownItems(Item instance, FeatureSet featureSet) {
if (!GeneralSettings.INSTANCE.removeNotAvailableItemsFromCreativeTab.getValue() || MinecraftClient.getInstance().isInSingleplayer()) return instance.isEnabled(featureSet);
if (ItemReleaseVersionDefinition.INSTANCE.getCurrentMap().contains(instance)) return instance.isEnabled(featureSet);
if (ItemReleaseVersionMappings.INSTANCE.getCurrentMap().contains(instance)) return instance.isEnabled(featureSet);
return false;
}

View File

@ -17,7 +17,7 @@
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.packet;
import de.florianmichael.viafabricplus.definition.ChatLengthDefinition;
import de.florianmichael.viafabricplus.definition.ChatLengthCalculation;
import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.Constant;
@ -28,6 +28,6 @@ public class MixinChatMessageC2SPacket {
@ModifyConstant(method = "write", constant = @Constant(intValue = 256))
public int expandChatLength(int constant) {
return ChatLengthDefinition.INSTANCE.getMaxLength();
return ChatLengthCalculation.INSTANCE.getMaxLength();
}
}

View File

@ -17,7 +17,7 @@
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen;
import de.florianmichael.viafabricplus.definition.ChatLengthDefinition;
import de.florianmichael.viafabricplus.definition.ChatLengthCalculation;
import de.florianmichael.viafabricplus.settings.groups.VisualSettings;
import net.minecraft.client.gui.hud.ChatHud;
import net.minecraft.client.gui.hud.MessageIndicator;
@ -37,7 +37,7 @@ public class MixinChatScreen {
@Inject(method = "init", at = @At("RETURN"))
public void changeChatLength(CallbackInfo ci) {
this.chatField.setMaxLength(ChatLengthDefinition.INSTANCE.getMaxLength());
this.chatField.setMaxLength(ChatLengthCalculation.INSTANCE.getMaxLength());
}
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;getIndicatorAt(DD)Lnet/minecraft/client/gui/hud/MessageIndicator;"))

View File

@ -17,7 +17,7 @@
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen;
import de.florianmichael.viafabricplus.definition.c0_30.ClassicItemSelectionScreen;
import de.florianmichael.viafabricplus.screen.ClassicItemSelectionScreen;
import de.florianmichael.viafabricplus.settings.groups.VisualSettings;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;

View File

@ -17,7 +17,7 @@
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen;
import de.florianmichael.viafabricplus.definition.TileServerAddress;
import de.florianmichael.viafabricplus.definition.v1_14_4.LegacyServerAddress;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.network.ServerAddress;
@ -42,6 +42,6 @@ public class MixinMultiplayerScreen {
@Redirect(method = "connect(Lnet/minecraft/client/network/ServerInfo;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ServerAddress;parse(Ljava/lang/String;)Lnet/minecraft/client/network/ServerAddress;"))
public ServerAddress doOwnParse(String address) {
return TileServerAddress.parse(((IServerInfo) viafabricplus_lastConnect).viafabricplus_forcedVersion(), address);
return LegacyServerAddress.parse(((IServerInfo) viafabricplus_lastConnect).viafabricplus_forcedVersion(), address);
}
}

View File

@ -17,7 +17,7 @@
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen;
import de.florianmichael.viafabricplus.definition.TileServerAddress;
import de.florianmichael.viafabricplus.definition.v1_14_4.LegacyServerAddress;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import net.minecraft.client.network.MultiplayerServerListPinger;
import net.minecraft.client.network.ServerAddress;
@ -46,7 +46,7 @@ public class MixinMultiplayerServerListPinger {
@Inject(method = "add", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AllowedAddressResolver;resolve(Lnet/minecraft/client/network/ServerAddress;)Ljava/util/Optional;"), locals = LocalCapture.CAPTURE_FAILHARD)
public void doOwnParse(ServerInfo entry, Runnable saver, CallbackInfo ci, ServerAddress serverAddress) {
viafabricplus_wrappedAddress = TileServerAddress.parse(((IServerInfo) viafabricplus_lastConnect).viafabricplus_forcedVersion(), serverAddress.getAddress());
viafabricplus_wrappedAddress = LegacyServerAddress.parse(((IServerInfo) viafabricplus_lastConnect).viafabricplus_forcedVersion(), serverAddress.getAddress());
}
@Redirect(method = "add", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ServerAddress;getAddress()Ljava/lang/String;"))

View File

@ -17,6 +17,7 @@
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.sodium;
import de.florianmichael.viafabricplus.settings.groups.VisualSettings;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
@ -29,6 +30,10 @@ public abstract class MixinChunkTracker {
@Redirect(method = "recalculateChunks", at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/longs/Long2IntOpenHashMap;get(J)I"))
private int modifyRenderCondition(Long2IntOpenHashMap instance, long k) {
return instance.getOrDefault(k, -1);
if (VisualSettings.INSTANCE.fixSodiumChunkRendering.getValue()) {
return instance.getOrDefault(k, -1);
}
return instance.get(k);
}
}

View File

@ -17,7 +17,7 @@
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion.protocol1_11to1_10;
import de.florianmichael.viafabricplus.definition.ChatLengthDefinition;
import de.florianmichael.viafabricplus.definition.ChatLengthCalculation;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
@ -27,6 +27,6 @@ public class MixinProtocol1_11To1_10 {
@ModifyConstant(method = "lambda$register$0", constant = @Constant(intValue = 100))
private static int changeMaxChatLength(int constant) {
return ChatLengthDefinition.INSTANCE.getMaxLength();
return ChatLengthCalculation.INSTANCE.getMaxLength();
}
}

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.definition.v1_8_x;
package de.florianmichael.viafabricplus.mappings;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ArmorType;
import net.minecraft.client.MinecraftClient;
@ -29,7 +29,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ArmorPointsDefinition {
public class ArmorPointsMappings {
public static final List<Item> ARMOR_ITEMS_IN_1_8 = Arrays.asList(
Items.LEATHER_HELMET,
Items.LEATHER_CHESTPLATE,
@ -66,6 +66,6 @@ public class ArmorPointsDefinition {
}
public static int sum() {
return MinecraftClient.getInstance().player.getInventory().armor.stream().mapToInt(ArmorPointsDefinition::getArmorPoints).sum();
return MinecraftClient.getInstance().player.getInventory().armor.stream().mapToInt(ArmorPointsMappings::getArmorPoints).sum();
}
}

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.definition;
package de.florianmichael.viafabricplus.mappings;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback;
@ -29,11 +29,11 @@ import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import java.util.*;
public class ItemReleaseVersionDefinition {
public static ItemReleaseVersionDefinition INSTANCE;
public class ItemReleaseVersionMappings {
public static ItemReleaseVersionMappings INSTANCE;
public static void create() {
INSTANCE = new ItemReleaseVersionDefinition();
INSTANCE = new ItemReleaseVersionMappings();
INSTANCE.load();
INSTANCE.update(ProtocolHack.getTargetVersion());

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.definition;
package de.florianmichael.viafabricplus.mappings;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
@ -28,7 +28,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class PackFormatsDefinition {
public class PackFormatsMappings {
private final static Map<Integer, GameVersion> protocolMap = new HashMap<>();
public static void load() {

View File

@ -17,42 +17,28 @@
*/
package de.florianmichael.viafabricplus.protocolhack.provider.vialegacy;
import com.google.common.hash.Hashing;
import com.google.common.io.Resources;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.definition.c0_30.BetaCraftImpl;
import de.florianmichael.viafabricplus.settings.groups.MPPassSettings;
import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicMPPassProvider;
import net.raphimc.vialegacy.protocols.release.protocol1_3_1_2to1_2_4_5.providers.OldAuthProvider;
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.storage.HandshakeStorage;
import java.net.InetAddress;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
public class ViaFabricPlusClassicMPPassProvider extends ClassicMPPassProvider {
public static String classiCubeMPPass;
@Override
public String getMpPass(UserConnection user) {
if (classiCubeMPPass != null) {
System.out.println(classiCubeMPPass);
return classiCubeMPPass;
}
if (MPPassSettings.INSTANCE.useBetaCraftAuthentication.getValue()) {
final HandshakeStorage handshakeStorage = user.get(HandshakeStorage.class);
return getBetaCraftMpPass(user, user.getProtocolInfo().getUsername(), handshakeStorage.getHostname(), handshakeStorage.getPort());
return BetaCraftImpl.getBetaCraftMpPass(user, user.getProtocolInfo().getUsername(), handshakeStorage.getHostname(), handshakeStorage.getPort());
} else {
return super.getMpPass(user);
}
}
private static String getBetaCraftMpPass(final UserConnection user, final String username, final String serverIp, final int port) {
try {
final String server = InetAddress.getByName(serverIp).getHostAddress() + ":" + port;
Via.getManager().getProviders().get(OldAuthProvider.class).sendAuthRequest(user, Hashing.sha1().hashBytes(server.getBytes()).toString());
final String mppass = Resources.toString(new URL("http://api.betacraft.uk/getmppass.jsp?user=" + username + "&server=" + server), StandardCharsets.UTF_8);
if (mppass.contains("FAILED") || mppass.contains("SERVER NOT FOUND")) return "0";
return mppass;
} catch (Throwable e) {
Via.getPlatform().getLogger().log(Level.WARNING, "An unknown error occurred while authenticating with BetaCraft", e);
}
return "0";
}
}

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.definition.c0_30;
package de.florianmichael.viafabricplus.screen;
import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback;
import de.florianmichael.vialoadingbase.platform.ComparableProtocolVersion;

View File

@ -19,8 +19,13 @@ package de.florianmichael.viafabricplus.screen;
import com.mojang.blaze3d.systems.RenderSystem;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.viafabricplus.screen.classicube.ClassiCubeLoginScreen;
import de.florianmichael.viafabricplus.screen.classicube.ClassiCubeServerListScreen;
import de.florianmichael.viafabricplus.screen.settings.SettingsScreen;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.util.ScreenUtil;
import de.florianmichael.vialoadingbase.ViaLoadingBase;
import de.florianmichael.vialoadingbase.platform.InternalProtocolList;
import net.minecraft.client.MinecraftClient;
@ -54,10 +59,18 @@ public class ProtocolSelectionScreen extends Screen {
protected void init() {
super.init();
this.addDrawableChild(new SlotList(this.client, width, height, 3 + 3 /* start offset */ + (textRenderer.fontHeight + 2) * 3 /* title is 2 */, height + 5, textRenderer.fontHeight + 4));
this.addDrawableChild(new SlotList(this.client, width, height, 3 + 3 /* start offset */ + (textRenderer.fontHeight + 2) * 3 /* title is 2 */, height - 30, textRenderer.fontHeight + 4));
this.addDrawableChild(ButtonWidget.builder(Text.literal("<-"), button -> this.close()).position(5, 5).size(20, 20).build());
this.addDrawableChild(ButtonWidget.builder(Text.translatable("words.viafabricplus.settings"), button -> client.setScreen(SettingsScreen.get(this))).position(width - 98 - 5, 5).size(98, 20).build());
this.addDrawableChild(ButtonWidget.builder(Text.translatable("ClassiCube"), button -> {
final ClassiCubeAccount classiCubeAccount = ClassiCubeAccountHandler.INSTANCE.getAccount();
if (classiCubeAccount == null || classiCubeAccount.token == null) {
client.setScreen(ClassiCubeLoginScreen.get(this));
return;
}
client.setScreen(ClassiCubeServerListScreen.get(this));
}).position(width - 98 - 5, height - 25).size(98, 20).build());
}
@Override
@ -101,7 +114,7 @@ public class ProtocolSelectionScreen extends Screen {
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
ViaLoadingBase.getClassWrapper().reload(this.protocolVersion);
MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
ScreenUtil.playClickSound();
return super.mouseClicked(mouseX, mouseY, button);
}

View File

@ -0,0 +1,111 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.screen.classicube;
import com.mojang.blaze3d.systems.RenderSystem;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.process.ILoginProcessHandler;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
public class ClassiCubeLoginScreen extends Screen {
public final static ClassiCubeLoginScreen INSTANCE = new ClassiCubeLoginScreen();
public Screen prevScreen;
public ClassiCubeLoginScreen() {
super(Text.literal("ClassiCube Login"));
}
public static ClassiCubeLoginScreen get(final Screen prevScreen) {
ClassiCubeLoginScreen.INSTANCE.prevScreen = prevScreen;
ClassiCubeLoginScreen.INSTANCE.status = Text.translatable("classicube.viafabricplus.account");
return ClassiCubeLoginScreen.INSTANCE;
}
private TextFieldWidget nameField;
private TextFieldWidget passwordField;
private Text status;
@Override
protected void init() {
super.init();
this.addDrawableChild(nameField = new TextFieldWidget(textRenderer, width / 2 - 150, 70 + 10, 300, 20, Text.empty()));
this.addDrawableChild(passwordField = new TextFieldWidget(textRenderer, width / 2 - 150, nameField.getY() + 20 + 5, 300, 20, Text.empty()));
passwordField.setRenderTextProvider((s, integer) -> Text.literal("*".repeat(s.length())).asOrderedText());
nameField.setPlaceholder(Text.literal("Name"));
passwordField.setPlaceholder(Text.literal("Password"));
final ClassiCubeAccount classiCubeAccount = ClassiCubeAccountHandler.INSTANCE.getAccount();
if (classiCubeAccount != null) {
nameField.setText(classiCubeAccount.username);
passwordField.setText(classiCubeAccount.password);
}
this.addDrawableChild(ButtonWidget.builder(Text.literal("Login"), button -> {
ClassiCubeAccountHandler.INSTANCE.setAccount(new ClassiCubeAccount(nameField.getText(), passwordField.getText()));
status = Text.translatable("classicube.viafabricplus.loading");
ClassiCubeAccountHandler.INSTANCE.getAccount().login(new ILoginProcessHandler() {
@Override
public void handleMfa(ClassiCubeAccount account) {
RenderSystem.recordRenderCall(() -> MinecraftClient.getInstance().setScreen(ClassiCubeMFAScreen.get(prevScreen)));
}
@Override
public void handleSuccessfulLogin(ClassiCubeAccount account) {
RenderSystem.recordRenderCall(() -> ClassiCubeServerListScreen.open(MinecraftClient.getInstance().currentScreen, this));
}
@Override
public void handleException(Throwable throwable) {
throwable.printStackTrace();
status = Text.literal(throwable.getMessage());
}
}, null);
}).position(width / 2 - 75, passwordField.getY() + (20 * 4) + 5).size(150, 20).build());
}
@Override
public void tick() {
super.tick();
nameField.tick();
passwordField.tick();
}
@Override
public void close() {
this.client.setScreen(this.prevScreen);
}
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices);
drawCenteredTextWithShadow(matrices, this.textRenderer, this.title, this.width / 2, 70, 16777215);
drawCenteredTextWithShadow(matrices, this.textRenderer, this.status, this.width / 2, 1, 16777215);
super.render(matrices, mouseX, mouseY, delta);
}
}

View File

@ -0,0 +1,100 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.screen.classicube;
import com.mojang.blaze3d.systems.RenderSystem;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeError;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.process.ILoginProcessHandler;
import de.florianmichael.viafabricplus.screen.ProtocolSelectionScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.TitleScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
public class ClassiCubeMFAScreen extends Screen {
public final static ClassiCubeMFAScreen INSTANCE = new ClassiCubeMFAScreen();
public Screen prevScreen;
public ClassiCubeMFAScreen() {
super(Text.literal("ClassiCube MFA"));
}
public static ClassiCubeMFAScreen get(final Screen prevScreen) {
ClassiCubeMFAScreen.INSTANCE.prevScreen = prevScreen;
ClassiCubeMFAScreen.INSTANCE.status = ClassiCubeError.LOGIN_CODE.description;
return ClassiCubeMFAScreen.INSTANCE;
}
private TextFieldWidget mfaField;
private Text status;
@Override
protected void init() {
super.init();
this.addDrawableChild(mfaField = new TextFieldWidget(textRenderer, width / 2 - 150, 70 + 10, 300, 20, Text.empty()));
mfaField.setPlaceholder(Text.literal("MFA"));
this.addDrawableChild(ButtonWidget.builder(Text.literal("Login"), button -> {
ClassiCubeAccountHandler.INSTANCE.getAccount().login(new ILoginProcessHandler() {
@Override
public void handleMfa(ClassiCubeAccount account) {
// Not implemented in this case
}
@Override
public void handleSuccessfulLogin(ClassiCubeAccount account) {
RenderSystem.recordRenderCall(() -> ClassiCubeServerListScreen.open(MinecraftClient.getInstance().currentScreen, this));
}
@Override
public void handleException(Throwable throwable) {
status = Text.literal(throwable.getMessage());
}
}, mfaField.getText());
}).position(width / 2 - 75, mfaField.getY() + (20 * 4) + 5).size(150, 20).build());
}
@Override
public void tick() {
super.tick();
mfaField.tick();
}
@Override
public void close() {
ProtocolSelectionScreen.open(new MultiplayerScreen(new TitleScreen()));
}
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices);
drawCenteredTextWithShadow(matrices, this.textRenderer, this.title, this.width / 2, 70, 16777215);
drawCenteredTextWithShadow(matrices, this.textRenderer, this.status, this.width / 2, 70 + textRenderer.fontHeight, 16777215);
super.render(matrices, mouseX, mouseY, delta);
}
}

View File

@ -0,0 +1,176 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.screen.classicube;
import com.mojang.blaze3d.systems.RenderSystem;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.process.ILoginProcessHandler;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.data.ClassiCubeServerInfo;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.request.server.ClassiCubeServerListRequest;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import de.florianmichael.viafabricplus.protocolhack.provider.vialegacy.ViaFabricPlusClassicMPPassProvider;
import de.florianmichael.viafabricplus.screen.ProtocolSelectionScreen;
import de.florianmichael.viafabricplus.settings.groups.MPPassSettings;
import de.florianmichael.viafabricplus.util.ScreenUtil;
import de.florianmichael.vialoadingbase.platform.InternalProtocolList;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.screen.ConnectScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.TitleScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.network.ServerAddress;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class ClassiCubeServerListScreen extends Screen {
public final static List<ClassiCubeServerInfo> SERVERS = new ArrayList<>();
private final static ClassiCubeServerListScreen INSTANCE = new ClassiCubeServerListScreen();
public Screen prevScreen;
public static ClassiCubeServerListScreen get(final Screen prevScreen) {
ClassiCubeServerListScreen.INSTANCE.prevScreen = prevScreen;
return ClassiCubeServerListScreen.INSTANCE;
}
public static void open(final Screen prevScreen, final ILoginProcessHandler loginProcessHandler) {
if (ClassiCubeServerListScreen.SERVERS.isEmpty()) {
final ClassiCubeServerListRequest request = new ClassiCubeServerListRequest(ClassiCubeAccountHandler.INSTANCE.getAccount());
request.send().whenComplete((server, throwable) -> {
if (throwable != null) {
loginProcessHandler.handleException(throwable);
return;
}
ClassiCubeServerListScreen.SERVERS.addAll(server.getServers());
RenderSystem.recordRenderCall(() -> MinecraftClient.getInstance().setScreen(ClassiCubeServerListScreen.get(prevScreen)));
});
return;
}
MinecraftClient.getInstance().setScreen(ClassiCubeServerListScreen.get(prevScreen));
}
public ClassiCubeServerListScreen() {
super(Text.literal("ClassiCube ServerList"));
}
@Override
protected void init() {
super.init();
this.addDrawableChild(new SlotList(this.client, width, height, 3 + 3 /* start offset */ + (textRenderer.fontHeight + 2) * 3 /* title is 2 */, height + 5, (textRenderer.fontHeight + 4) * 3));
this.addDrawableChild(ButtonWidget.builder(Text.literal("<-"), button -> this.close()).position(5, 5).size(20, 20).build());
this.addDrawableChild(ButtonWidget.builder(Text.literal("Logout"), button -> {
client.setScreen(prevScreen);
ClassiCubeAccountHandler.INSTANCE.setAccount(null);
SERVERS.clear();
}).position(width - 98 - 5, 5).size(98, 20).build());
}
@Override
public void close() {
ProtocolSelectionScreen.open(new MultiplayerScreen(new TitleScreen()));
}
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices);
super.render(matrices, mouseX, mouseY, delta);
matrices.push();
matrices.scale(2F, 2F, 2F);
drawCenteredTextWithShadow(matrices, textRenderer, "ViaFabricPlus", width / 4, 3, Color.ORANGE.getRGB());
matrices.pop();
drawCenteredTextWithShadow(matrices, textRenderer, Text.literal("Logged in as " + ClassiCubeAccountHandler.INSTANCE.getAccount().username), width / 2, (textRenderer.fontHeight + 2) * 2 + 3, -1);
}
public static class SlotList extends AlwaysSelectedEntryListWidget<ServerSlot> {
public SlotList(MinecraftClient minecraftClient, int width, int height, int top, int bottom, int entryHeight) {
super(minecraftClient, width, height, top, bottom, entryHeight);
SERVERS.forEach(serverInfo -> this.addEntry(new ServerSlot(serverInfo)));
}
@Override
public int getRowWidth() {
return super.getRowWidth() + 140;
}
@Override
protected int getScrollbarPositionX() {
return this.width - 5;
}
}
public static class ServerSlot extends AlwaysSelectedEntryListWidget.Entry<ServerSlot> {
private final ClassiCubeServerInfo classiCubeServerInfo;
public ServerSlot(ClassiCubeServerInfo classiCubeServerInfo) {
this.classiCubeServerInfo = classiCubeServerInfo;
}
@Override
public Text getNarration() {
return Text.literal(classiCubeServerInfo.name());
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
final ServerAddress serverAddress = ServerAddress.parse(classiCubeServerInfo.ip() + ":" + classiCubeServerInfo.port());
final ServerInfo entry = new ServerInfo(classiCubeServerInfo.name(), serverAddress.getAddress(), false);
ViaFabricPlusClassicMPPassProvider.classiCubeMPPass = classiCubeServerInfo.mppass();
if (MPPassSettings.INSTANCE.forceCPEIfUsingClassiCube.getValue()) {
((IServerInfo) entry).viafabricplus_forceVersion(InternalProtocolList.fromProtocolVersion(LegacyProtocolVersion.c0_30cpe));
}
ConnectScreen.connect(MinecraftClient.getInstance().currentScreen, MinecraftClient.getInstance(), serverAddress, entry);
ScreenUtil.playClickSound();
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
matrices.push();
matrices.translate(x, y, 0);
DrawableHelper.fill(matrices, 0, 0, entryWidth - 4 /* int i = this.left + (this.width - entryWidth) / 2; int j = this.left + (this.width + entryWidth) / 2; */, entryHeight, Integer.MIN_VALUE);
final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
drawCenteredTextWithShadow(matrices, textRenderer, classiCubeServerInfo.name(), entryWidth / 2, entryHeight / 2 - textRenderer.fontHeight / 2, -1);
drawTextWithShadow(matrices, textRenderer, classiCubeServerInfo.software().replace('&', Formatting.FORMATTING_CODE_PREFIX), 1, 1, -1);
final String playerText = classiCubeServerInfo.players() + "/" + classiCubeServerInfo.maxplayers();
drawTextWithShadow(matrices, textRenderer, playerText, entryWidth - textRenderer.getWidth(playerText) - 4 /* magic value from line 132 */ - 1, 1, -1);
matrices.pop();
}
}
}

View File

@ -27,6 +27,7 @@ public class MPPassSettings extends SettingGroup {
public final BooleanSetting useBetaCraftAuthentication = new BooleanSetting(this, Text.translatable("mppass.viafabricplus.betacraft"), true);
public final BooleanSetting allowViaLegacyToCallJoinServerToVerifySession = new BooleanSetting(this, Text.translatable("mppass.viafabricplus.verify"), true);
public final BooleanSetting disconnectIfJoinServerCallFails = new BooleanSetting(this, Text.translatable("mppass.viafabricplus.fail"), true);
public final BooleanSetting forceCPEIfUsingClassiCube = new BooleanSetting(this, Text.translatable("mppass.viafabricplus.classicube"), true);
public MPPassSettings() {
super("MP Pass");

View File

@ -52,6 +52,7 @@ public class VisualSettings extends SettingGroup {
// a1_0_15 -> c0_28toc0_30
public final ProtocolSyncBooleanSetting replaceCreativeInventory = new ProtocolSyncBooleanSetting(this, Text.translatable("visual.viafabricplus.classic"), ProtocolRange.andOlder(LegacyProtocolVersion.c0_28toc0_30));
public final ProtocolSyncBooleanSetting oldWalkingAnimation = new ProtocolSyncBooleanSetting(this, Text.translatable("visual.viafabricplus.walkanimation"), ProtocolRange.andOlder(LegacyProtocolVersion.c0_28toc0_30));
public final ProtocolSyncBooleanSetting fixSodiumChunkRendering = new ProtocolSyncBooleanSetting(this, Text.translatable("visual.viafabricplus.sodium"), ProtocolRange.andOlder(LegacyProtocolVersion.c0_28toc0_30));
public VisualSettings() {
super("Visual");

View File

@ -35,6 +35,7 @@
"mppass.viafabricplus.betacraft": "Use BetaCraft authentication",
"mppass.viafabricplus.verify": "Allow ViaLegacy to call joinServer() to verify session",
"mppass.viafabricplus.fail": "Disconnect if joinServer() call fails",
"mppass.viafabricplus.classicube": "Force CPE Version if using ClassiCube MP Pass",
"visual.viafabricplus.secure": "Disable secure chat warning",
"visual.viafabricplus.indicator": "Hide signature indicator",
@ -46,9 +47,19 @@
"visual.viafabricplus.betahud": "Remove newer HUD elements",
"visual.viafabricplus.classic": "Replace creative inventory",
"visual.viafabricplus.walkanimation": "Old walking animation",
"visual.viafabricplus.sodium": "Fix Sodium Chunk renderer",
"bedrocklogin.viafabricplus.text": "Your browser should have opened.\nPlease enter the following Code: %s\nClosing this screen will cancel the process!",
"bedrocklogin.viafabricplus.error": "An error has occurred! See the latest.log for more information,\nplease report the bug at: \nhttps://github.com/FlorianMichael/ViaFabricPlus/issues",
"forceversion.viafabricplus.title": "Please select the version with which the server should be pinged/connected"
"forceversion.viafabricplus.title": "Please select the version with which the server should be pinged/connected",
"classicube.viafabricplus.account": "You can create an account here: https://www.classicube.net/",
"classicube.viafabricplus.loading": "Loading profile information and server list...",
"classicube.viafabricplus.error.token": "Incorrect token. Is your ViaFabricPlus out of date?",
"classicube.viafabricplus.error.username": "Invalid username.",
"classicube.viafabricplus.error.password": "Invalid password.",
"classicube.viafabricplus.error.verification": "User hasn't verified their E-mail address yet.",
"classicube.viafabricplus.error.logincode": "Multi-factor authentication requested. Please check your E-mail."
}

View File

@ -5,6 +5,7 @@
"compatibilityLevel": "JAVA_17",
"client": [
"base.MixinClientConnection",
"base.MixinClientConnection_1",
"base.MixinClientLoginNetworkHandler",
"base.MixinMain",
"base.MixinMinecraftClient",
@ -16,9 +17,6 @@
"bridge.MixinDownloadingTerrainScreen",
"bridge.MixinOptionsScreen",
"bridge.MixinServerInfo",
"jsonwebtoken.MixinClasses",
"jsonwebtoken.MixinDefaultCompressionCodecResolver",
"jsonwebtoken.MixinDefaultJwtParserBuilder",
"fixes.minecraft.MixinBipedEntityModel",
"fixes.minecraft.MixinCamera",
"fixes.minecraft.MixinClientPlayerInteractionManager",
@ -150,9 +148,14 @@
"fixes.viaversion.protocol1_9to1_8.MixinMetadataRewriter1_9To1_8",
"fixes.viaversion.protocol1_9to1_8.MixinMovementTracker",
"fixes.viaversion.protocol1_9to1_8.MixinViaIdleThread",
"base.MixinClientConnection_1"
"jsonwebtoken.MixinClasses",
"jsonwebtoken.MixinDefaultCompressionCodecResolver",
"jsonwebtoken.MixinDefaultJwtParserBuilder"
],
"injectors": {
"defaultRequire": 1
}
},
"mixins": [
"base.MixinSharedConstants"
]
}