This commit is contained in:
FlorianMichael 2023-04-22 20:20:40 +02:00
parent 76949aa88d
commit 62e623de8b
31 changed files with 175 additions and 941 deletions

View File

@ -102,6 +102,7 @@ if you know a language well, feel free to make a PR and add translations for tha
| Reflect | https://github.com/Lenni0451/Reflect |
| ViaLoadingBase | https://github.com/FlorianMichael/ViaLoadingBase |
| Netty-transport-RakNet | https://github.com/CloudburstMC/Network/tree/develop |
| Classic4J | https://github.com/FlorianMichael/Classic4J |
</details>
### Setting up a Workspace

View File

@ -59,10 +59,12 @@ dependencies {
exclude group: "io.netty", module: "netty-codec"
exclude group: "io.netty", module: "netty-transport"
}
libs "com.github.FlorianMichael:Classic4J:${project.classic4j_version}"
libs "com.viaversion:viaversion:${project.viaversion_version}"
libs "com.viaversion:viabackwards-common:${project.viabackwards_version}"
libs "org.yaml:snakeyaml:${project.snake_yml_version}"
libs "org.jsoup:jsoup:1.15.4"
libs "net.raphimc:ViaLegacy:${project.vialegacy_version}"
libs "net.raphimc:ViaAprilFools:${project.viaaprilfools_version}"
@ -81,8 +83,6 @@ dependencies {
libs "net.lenni0451.mcstructs:text:${project.mcstructs_text_version}"
libs "net.lenni0451:Reflect:${project.reflect_version}"
libs "com.github.allinkdev:BetacraftServerListParser:${project.betacraft_version}"
modImplementation "com.terraformersmc:modmenu:${project.mod_menu_version}"
}

View File

@ -16,6 +16,7 @@ archives_base_name=viafabricplus
# base lib
vialoadingbase_version=ff86e681d7
raknet_transport_version=1.0.0.CR1-SNAPSHOT
classic4j_version=1.1.0
# viaversion (and required) libs
viaversion_version=4.7.0-23w16a-SNAPSHOT
@ -33,6 +34,5 @@ mcstructs_text_version=2.2.0
reflect_version=1.1.0
# other libs
betacraft_version=1.2.1
mod_menu_version=6.1.0-rc.4
netty_codec_http_version=4.1.90.Final

View File

@ -25,7 +25,7 @@ import de.florianmichael.viafabricplus.mappings.ItemReleaseVersionMappings;
import de.florianmichael.viafabricplus.mappings.PackFormatsMappings;
import de.florianmichael.viafabricplus.definition.bedrock.BedrockAccountHandler;
import de.florianmichael.viafabricplus.screen.ClassicItemSelectionScreen;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.protocol.CustomClassicProtocolExtensions;
import de.florianmichael.viafabricplus.definition.c0_30.command.ClassicProtocolCommands;
import de.florianmichael.viafabricplus.mappings.ArmorPointsMappings;

View File

@ -1,45 +0,0 @@
/*
* 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.util.ScreenUtil;
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;
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) {
ScreenUtil.crash("An unknown error occurred while authenticating with BetaCraft", e);
}
return "0";
}
}

View File

@ -15,11 +15,11 @@
* 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;
package de.florianmichael.viafabricplus.definition.c0_30;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
import de.florianmichael.classic4j.model.classicube.highlevel.CCAccount;
import de.florianmichael.viafabricplus.event.DisconnectConnectionCallback;
import de.florianmichael.viafabricplus.protocolhack.provider.vialegacy.ViaFabricPlusClassicMPPassProvider;
import de.florianmichael.viafabricplus.util.FileSaver;
@ -35,7 +35,7 @@ public class ClassiCubeAccountHandler extends FileSaver {
ClassiCubeAccountHandler.INSTANCE.init();
}
private ClassiCubeAccount account;
private CCAccount account;
public ClassiCubeAccountHandler() {
super("classicube.account");
@ -48,7 +48,7 @@ public class ClassiCubeAccountHandler extends FileSaver {
if (account == null) return;
account.token = null; // Token has to be created next time
for (Map.Entry<String, JsonElement> entry : account.toJson().entrySet()) {
for (Map.Entry<String, JsonElement> entry : account.asJson().entrySet()) {
object.add(entry.getKey(), entry.getValue());
}
}
@ -56,17 +56,17 @@ public class ClassiCubeAccountHandler extends FileSaver {
@Override
public void read(JsonObject object) {
try {
account = ClassiCubeAccount.fromJson(object);
account = CCAccount.fromJson(object);
} catch (Exception e) {
ScreenUtil.crash("Failed to log into ClassiCube account!", e);
}
}
public ClassiCubeAccount getAccount() {
public CCAccount getAccount() {
return account;
}
public void setAccount(ClassiCubeAccount account) {
public void setAccount(CCAccount account) {
this.account = account;
}
}

View File

@ -1,96 +0,0 @@
/*
* 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.auth;
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.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;
public ClassiCubeAccount(String username, String password) {
this.username = username;
this.password = password;
}
public ClassiCubeAccount(String token, String username, String password) {
this(username, password);
this.token = token;
}
public JsonObject toJson() {
final JsonObject object = new JsonObject();
object.addProperty("token", this.token);
object.addProperty("username", this.username);
object.addProperty("password", this.password);
return object;
}
public static ClassiCubeAccount fromJson(JsonObject jsonObject) {
String token = null;
if (jsonObject.has("token")) token = jsonObject.get("token").getAsString();
return new ClassiCubeAccount(token, jsonObject.get("username").getAsString(), jsonObject.get("password").getAsString());
}
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;
final ClassiCubeAuthenticationLoginRequest loginRequest = new ClassiCubeAuthenticationLoginRequest(initialTokenResponse, this, loginCode);
loginRequest.send().whenComplete((loginResponse, throwable1) -> {
if (throwable1 != null) {
processHandler.handleException(throwable1);
return;
}
if (loginResponse.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,64 +0,0 @@
/*
* 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.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.
* Taken from <a href="https://www.classicube.net/api/">the official ClassiCube API documentation</a>
*/
public class ClassiCubeAuthenticationData {
private final String username;
private final String password;
private final String previousToken;
@Nullable private final String loginCode;
public ClassiCubeAuthenticationData(String username, String password, String previousToken) {
this(username, password, previousToken, null);
}
public ClassiCubeAuthenticationData(String username, String password, String previousToken, @Nullable String loginCode) {
this.username = username;
this.password = password;
this.previousToken = previousToken;
this.loginCode = loginCode;
}
public ClassiCubeAuthenticationData getWithLoginToken(final String loginCode) {
return new ClassiCubeAuthenticationData(this.username, this.password, this.previousToken, loginCode);
}
public String getRequestBody() {
final StringBuilder builder = new StringBuilder("username=").append(URLEncoder.encode(username, StandardCharsets.UTF_8));
builder.append("&password=");
builder.append(URLEncoder.encode(password, StandardCharsets.UTF_8));
builder.append("&token=");
builder.append(URLEncoder.encode(previousToken, StandardCharsets.UTF_8));
if (loginCode != null) {
builder.append("&login_code=");
builder.append(URLEncoder.encode(loginCode, StandardCharsets.UTF_8));
}
return builder.toString();
}
}

View File

@ -1,40 +0,0 @@
/*
* 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.auth;
import net.minecraft.text.Text;
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 final Text description;
public final boolean fatal;
ClassiCubeError(Text description) {
this(description, true);
}
ClassiCubeError(Text description, boolean fatal) {
this.description = description;
this.fatal = fatal;
}
}

View File

@ -1,27 +0,0 @@
/*
* 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.auth.process;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeAccount;
public interface ILoginProcessHandler {
void handleMfa(final ClassiCubeAccount account);
void handleSuccessfulLogin(final ClassiCubeAccount account);
void handleException(final Throwable throwable);
}

View File

@ -1,25 +0,0 @@
/*
* 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.data;
import com.google.gson.annotations.SerializedName;
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,48 +0,0 @@
/*
* 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.request;
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;
protected ClassiCubeRequest(ClassiCubeAccount account) {
this.account = account;
}
protected HttpRequest buildWithCookies(final HttpRequest.Builder builder) {
return this.account.cookieStore.appendCookies(builder)
.build();
}
protected void updateCookies(final HttpResponse<?> response) {
this.account.cookieStore.mergeFromResponse(response);
}
}

View File

@ -1,63 +0,0 @@
/*
* 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.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;
import javax.annotation.Nullable;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class ClassiCubeAuthenticationLoginRequest extends ClassiCubeAuthenticationRequest {
private final ClassiCubeAuthenticationData authenticationData;
private final ClassiCubeAccount account;
public ClassiCubeAuthenticationLoginRequest(ClassiCubeAuthenticationResponse previousResponse, ClassiCubeAccount account) {
this(previousResponse, account, null);
}
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 = this.buildWithCookies(HttpRequest.newBuilder()
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.uri(ClassiCubeRequest.AUTHENTICATION_URI)
.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,33 +0,0 @@
/*
* 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.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;
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,52 +0,0 @@
/*
* 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.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;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
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(() -> {
final HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(ClassiCubeRequest.AUTHENTICATION_URI)
.build();
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,64 +0,0 @@
/*
* 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.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;
import java.net.URI;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public class ClassiCubeServerInfoRequest extends ClassiCubeRequest {
private final Set<String> serverHashes;
public ClassiCubeServerInfoRequest(final ClassiCubeAccount account, final String serverHash) {
this(account, Set.of(serverHash));
}
public ClassiCubeServerInfoRequest(final ClassiCubeAccount account, final Set<String> serverHashes) {
super(account);
this.serverHashes = serverHashes;
}
private URI generateUri() {
final String joined = String.join(",", serverHashes);
return SERVER_INFO_URI.resolve(joined);
}
public CompletableFuture<ClassiCubeServerInfoResponse> send() {
return CompletableFuture.supplyAsync(() -> {
final URI uri = this.generateUri();
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,48 +0,0 @@
/*
* 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.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;
import java.net.http.HttpRequest;
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 = 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

@ -1,27 +0,0 @@
/*
* 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.response;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public abstract class ClassiCubeResponse {
protected final static Gson GSON = new GsonBuilder()
.serializeNulls()
.create();
}

View File

@ -1,72 +0,0 @@
/*
* 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.response.auth;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.auth.ClassiCubeError;
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.
* Most fields, except for authenticated and errors, are null in the first request.
* As such, they are annotated as {@link Nullable}.
*/
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<String> errors) {
this.token = token;
this.username = username;
this.authenticated = authenticated;
this.errors = errors;
}
public boolean shouldError() {
return errors.size() > 0;
}
public String getErrorDisplay() {
final StringBuilder builder = new StringBuilder();
for (String error : this.errors) {
builder.append(ClassiCubeError.valueOf(error.toUpperCase()).description.getString()).append("\n");
}
return builder.toString()
.trim();
}
public Set<ClassiCubeError> errors() {
return this.errors.stream().map(s -> ClassiCubeError.valueOf(s.toUpperCase(Locale.ROOT))).collect(Collectors.toSet());
}
public boolean mfaRequired() {
return this.errors().stream().anyMatch(e -> e == ClassiCubeError.LOGIN_CODE);
}
public static ClassiCubeAuthenticationResponse fromJson(final String json) {
return GSON.fromJson(json, ClassiCubeAuthenticationResponse.class);
}
}

View File

@ -1,39 +0,0 @@
/*
* 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.response.server;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.data.ClassiCubeServerInfo;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.response.ClassiCubeResponse;
import java.util.Set;
public class ClassiCubeServerInfoResponse extends ClassiCubeResponse {
private final Set<ClassiCubeServerInfo> servers;
public ClassiCubeServerInfoResponse(Set<ClassiCubeServerInfo> servers) {
this.servers = servers;
}
public Set<ClassiCubeServerInfo> getServers() {
return servers;
}
public static ClassiCubeServerInfoResponse fromJson(final String json) {
return GSON.fromJson(json, ClassiCubeServerInfoResponse.class);
}
}

View File

@ -1,116 +0,0 @@
/*
* 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.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

@ -0,0 +1,34 @@
/*
* 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.classic4j;
import de.florianmichael.classic4j.handler.classicube.auth.base.CCAuthenticationResponse;
import de.florianmichael.classic4j.model.classicube.highlevel.CCError;
import de.florianmichael.viafabricplus.integration.Classic4JImpl;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = CCAuthenticationResponse.class, remap = false)
public class MixinCCAuthenticationResponse {
@Redirect(method = "getErrorDisplay", at = @At(value = "FIELD", target = "Lde/florianmichael/classic4j/model/classicube/highlevel/CCError;description:Ljava/lang/String;"))
public String mapTranslations(CCError instance) {
return Classic4JImpl.fromError(instance).getString();
}
}

View File

@ -22,7 +22,7 @@ import com.viaversion.viaversion.api.minecraft.ProfileKey;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.definition.bedrock.BedrockAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.classicube.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.c0_30.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.injection.access.IPublicKeyData;
import de.florianmichael.viafabricplus.definition.v1_19_0.storage.ChatSession1_19_0;
import de.florianmichael.viafabricplus.definition.v1_19_2.storage.ChatSession1_19_2;
@ -83,7 +83,7 @@ public class MixinConnectScreen_1 {
@Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;send(Lnet/minecraft/network/packet/Packet;)V", ordinal = 1))
public void spoofUserName(ClientConnection instance, Packet<?> packet) {
if (AuthenticationSettings.INSTANCE.spoofUserNameIfUsingClassiCube.getValue() && ViaFabricPlusClassicMPPassProvider.classiCubeMPPass != null && ClassiCubeAccountHandler.INSTANCE.getAccount() != null) {
instance.send(new LoginHelloC2SPacket(ClassiCubeAccountHandler.INSTANCE.getAccount().username, Optional.ofNullable(MinecraftClient.getInstance().getSession().getUuidOrNull())));
instance.send(new LoginHelloC2SPacket(ClassiCubeAccountHandler.INSTANCE.getAccount().username(), Optional.ofNullable(MinecraftClient.getInstance().getSession().getUuidOrNull())));
return;
}

View File

@ -0,0 +1,58 @@
/*
* 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.integration;
import com.mojang.authlib.exceptions.AuthenticationException;
import de.florianmichael.classic4j.Classic4J;
import de.florianmichael.classic4j.model.classicube.highlevel.CCError;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
public class Classic4JImpl {
public final static Classic4J INSTANCE = new Classic4J(serverId -> {
final MinecraftClient mc = MinecraftClient.getInstance();
try {
mc.getSessionService().joinServer(mc.getSession().getProfile(), mc.getSession().getAccessToken(), serverId);
} catch (AuthenticationException e) {
e.printStackTrace();
}
});
public static Text fromError(final CCError error) {
switch (error) {
case TOKEN -> {
return Text.translatable("classicube.viafabricplus.error.token");
}
case USERNAME -> {
return Text.translatable("classicube.viafabricplus.error.username");
}
case PASSWORD -> {
return Text.translatable("classicube.viafabricplus.error.password");
}
case VERIFICATION -> {
return Text.translatable("classicube.viafabricplus.error.verification");
}
case LOGIN_CODE -> {
return Text.translatable("classicube.viafabricplus.error.logincode");
}
}
return Text.empty();
}
}

View File

@ -18,11 +18,13 @@
package de.florianmichael.viafabricplus.protocolhack.provider.vialegacy;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.definition.c0_30.BetaCraftImpl;
import de.florianmichael.viafabricplus.integration.Classic4JImpl;
import de.florianmichael.viafabricplus.settings.groups.AuthenticationSettings;
import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicMPPassProvider;
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.storage.HandshakeStorage;
import java.util.concurrent.atomic.AtomicReference;
public class ViaFabricPlusClassicMPPassProvider extends ClassicMPPassProvider {
public static String classiCubeMPPass;
@ -33,7 +35,7 @@ public class ViaFabricPlusClassicMPPassProvider extends ClassicMPPassProvider {
if (AuthenticationSettings.INSTANCE.useBetaCraftAuthentication.getValue()) {
final HandshakeStorage handshakeStorage = user.get(HandshakeStorage.class);
return BetaCraftImpl.getBetaCraftMpPass(user, user.getProtocolInfo().getUsername(), handshakeStorage.getHostname(), handshakeStorage.getPort());
return Classic4JImpl.INSTANCE.betaCraftHandler().requestMPPass(user.getProtocolInfo().getUsername(), handshakeStorage.getHostname(), handshakeStorage.getPort());
} else {
return super.getMpPass(user);
}

View File

@ -17,9 +17,9 @@
*/
package de.florianmichael.viafabricplus.screen;
import com.github.allinkdev.betacraftserverlistparser.BetacraftServerList;
import com.github.allinkdev.betacraftserverlistparser.Server;
import com.github.allinkdev.betacraftserverlistparser.Version;
import de.florianmichael.classic4j.model.betacraft.BCServerInfo;
import de.florianmichael.classic4j.model.betacraft.BCServerList;
import de.florianmichael.classic4j.model.betacraft.BCVersion;
import de.florianmichael.viafabricplus.definition.v1_14_4.LegacyServerAddress;
import de.florianmichael.viafabricplus.screen.base.MappedSlotEntry;
import de.florianmichael.viafabricplus.screen.settings.settingrenderer.meta.TitleRenderer;
@ -40,7 +40,7 @@ import java.awt.*;
import java.util.List;
public class BetaCraftScreen extends Screen {
public static BetacraftServerList SERVER_LIST;
public static BCServerList SERVER_LIST;
public final static BetaCraftScreen INSTANCE = new BetaCraftScreen();
public Screen prevScreen;
@ -88,11 +88,11 @@ public class BetaCraftScreen extends Screen {
public SlotList(MinecraftClient minecraftClient, int width, int height, int top, int bottom, int entryHeight) {
super(minecraftClient, width, height, top, bottom, entryHeight);
for (Version value : Version.values()) {
final List<Server> servers = SERVER_LIST.getServersOfVersion(value);
for (BCVersion value : BCVersion.values()) {
final List<BCServerInfo> servers = SERVER_LIST.serversOfVersion(value);
if (servers.isEmpty()) continue;
addEntry(new TitleRenderer(value.name()));
for (Server server : servers) {
for (BCServerInfo server : servers) {
addEntry(new ServerSlot(server));
}
}
@ -110,21 +110,21 @@ public class BetaCraftScreen extends Screen {
}
public static class ServerSlot extends MappedSlotEntry {
private final Server server;
private final BCServerInfo server;
public ServerSlot(Server server) {
public ServerSlot(BCServerInfo server) {
this.server = server;
}
@Override
public Text getNarration() {
return Text.literal(server.getName());
return Text.literal(server.name());
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
final ServerAddress serverAddress = LegacyServerAddress.parse(null, server.getHost() + ":" + server.getPort());
final ServerInfo entry = new ServerInfo(server.getName(), serverAddress.getAddress(), false);
final ServerAddress serverAddress = LegacyServerAddress.parse(null, server.host() + ":" + server.port());
final ServerInfo entry = new ServerInfo(server.name(), serverAddress.getAddress(), false);
ConnectScreen.connect(MinecraftClient.getInstance().currentScreen, MinecraftClient.getInstance(), serverAddress, entry);
ScreenUtil.playClickSound();
@ -134,12 +134,12 @@ public class BetaCraftScreen extends Screen {
@Override
public void mappedRenderer(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
drawCenteredTextWithShadow(matrices, textRenderer, server.getName() + Formatting.DARK_GRAY + " [" + server.getGameVersion() + "]", entryWidth / 2, entryHeight / 2 - textRenderer.fontHeight / 2, -1);
drawCenteredTextWithShadow(matrices, textRenderer, server.name() + Formatting.DARK_GRAY + " [" + server.gameVersion() + "]", entryWidth / 2, entryHeight / 2 - textRenderer.fontHeight / 2, -1);
if (server.isOnlineMode()) {
if (server.onlineMode()) {
drawTextWithShadow(matrices, textRenderer, Text.translatable("words.viafabricplus.online").formatted(Formatting.GREEN), 1, 1, -1);
}
final String playerText = server.getPlayerCount() + "/" + server.getPlayerLimit();
final String playerText = server.playerCount() + "/" + server.playerLimit();
drawTextWithShadow(matrices, textRenderer, playerText, entryWidth - textRenderer.getWidth(playerText) - 4 /* magic value from line 132 */ - 1, 1, -1);
}
}

View File

@ -17,11 +17,11 @@
*/
package de.florianmichael.viafabricplus.screen;
import com.github.allinkdev.betacraftserverlistparser.BetacraftServerList;
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.classic4j.model.classicube.highlevel.CCAccount;
import de.florianmichael.viafabricplus.definition.c0_30.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.integration.Classic4JImpl;
import de.florianmichael.viafabricplus.screen.classicube.ClassiCubeLoginScreen;
import de.florianmichael.viafabricplus.screen.classicube.ClassiCubeServerListScreen;
import de.florianmichael.viafabricplus.screen.settings.SettingsScreen;
@ -39,7 +39,6 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
import java.awt.*;
import java.util.concurrent.CompletableFuture;
@SuppressWarnings({"DataFlowIssue", "DuplicatedCode"})
public class ProtocolSelectionScreen extends Screen {
@ -64,7 +63,7 @@ public class ProtocolSelectionScreen extends Screen {
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());
final ClassiCubeAccount classiCubeAccount = ClassiCubeAccountHandler.INSTANCE.getAccount();
final CCAccount classiCubeAccount = ClassiCubeAccountHandler.INSTANCE.getAccount();
ButtonWidget.Builder classiCubeBuilder = ButtonWidget.builder(Text.literal("ClassiCube"), button -> {
if (classiCubeAccount == null || classiCubeAccount.token == null) {
client.setScreen(ClassiCubeLoginScreen.get(this));
@ -78,14 +77,11 @@ public class ProtocolSelectionScreen extends Screen {
this.addDrawableChild(classiCubeBuilder.build());
ButtonWidget.Builder betaCraftBuilder = ButtonWidget.builder(Text.literal("BetaCraft"), button -> {
if (BetaCraftScreen.SERVER_LIST == null) {
CompletableFuture.runAsync(() -> BetacraftServerList.getFuture().whenComplete((betacraftServerList, throwable) -> {
if (throwable != null) {
MinecraftClient.getInstance().execute(() -> MinecraftClient.getInstance().setScreen(new NoticeScreen(() -> RenderSystem.recordRenderCall(() -> client.setScreen(this)), Text.literal("Betacraft"), Text.translatable("betacraft.viafabricplus.error").append("\n" + throwable.getMessage()), Text.translatable("words.viafabricplus.cancel"), false)));
return;
}
BetaCraftScreen.SERVER_LIST = betacraftServerList;
Classic4JImpl.INSTANCE.betaCraftHandler().requestServerList(bcServerList -> {
BetaCraftScreen.SERVER_LIST = bcServerList;
RenderSystem.recordRenderCall(() -> client.setScreen(BetaCraftScreen.get(this)));
}));
}, throwable -> MinecraftClient.getInstance().execute(() -> MinecraftClient.getInstance().setScreen(new NoticeScreen(() -> RenderSystem.recordRenderCall(() -> client.setScreen(this)), Text.literal("Betacraft"), Text.translatable("betacraft.viafabricplus.error").append("\n" + throwable.getMessage()), Text.translatable("words.viafabricplus.cancel"), false))));
} else client.setScreen(BetaCraftScreen.get(this));
button.setMessage(Text.literal("BetaCraft"));

View File

@ -18,9 +18,10 @@
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 de.florianmichael.classic4j.api.LoginProcessHandler;
import de.florianmichael.classic4j.model.classicube.highlevel.CCAccount;
import de.florianmichael.viafabricplus.definition.c0_30.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.integration.Classic4JImpl;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
@ -58,24 +59,24 @@ public class ClassiCubeLoginScreen extends Screen {
nameField.setPlaceholder(Text.literal("Name"));
passwordField.setPlaceholder(Text.literal("Password"));
final ClassiCubeAccount classiCubeAccount = ClassiCubeAccountHandler.INSTANCE.getAccount();
final CCAccount classiCubeAccount = ClassiCubeAccountHandler.INSTANCE.getAccount();
if (classiCubeAccount != null) {
nameField.setText(classiCubeAccount.username);
passwordField.setText(classiCubeAccount.password);
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()));
ClassiCubeAccountHandler.INSTANCE.setAccount(new CCAccount(nameField.getText(), passwordField.getText()));
status = Text.translatable("classicube.viafabricplus.loading");
ClassiCubeAccountHandler.INSTANCE.getAccount().login(new ILoginProcessHandler() {
Classic4JImpl.INSTANCE.classiCubeHandler().requestAuthentication(ClassiCubeAccountHandler.INSTANCE.getAccount(), null, new LoginProcessHandler() {
@Override
public void handleMfa(ClassiCubeAccount account) {
public void handleMfa(CCAccount account) {
RenderSystem.recordRenderCall(() -> MinecraftClient.getInstance().setScreen(ClassiCubeMFAScreen.get(prevScreen)));
}
@Override
public void handleSuccessfulLogin(ClassiCubeAccount account) {
public void handleSuccessfulLogin(CCAccount account) {
RenderSystem.recordRenderCall(() -> ClassiCubeServerListScreen.open(MinecraftClient.getInstance().currentScreen, this));
}
@ -84,7 +85,7 @@ public class ClassiCubeLoginScreen extends Screen {
throwable.printStackTrace();
status = Text.literal(throwable.getMessage());
}
}, null);
});
}).position(width / 2 - 75, passwordField.getY() + (20 * 4) + 5).size(150, 20).build());
}

View File

@ -18,10 +18,11 @@
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.classic4j.api.LoginProcessHandler;
import de.florianmichael.classic4j.model.classicube.highlevel.CCAccount;
import de.florianmichael.classic4j.model.classicube.highlevel.CCError;
import de.florianmichael.viafabricplus.definition.c0_30.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.integration.Classic4JImpl;
import de.florianmichael.viafabricplus.screen.ProtocolSelectionScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
@ -42,7 +43,8 @@ public class ClassiCubeMFAScreen extends Screen {
public static ClassiCubeMFAScreen get(final Screen prevScreen) {
ClassiCubeMFAScreen.INSTANCE.prevScreen = prevScreen;
ClassiCubeMFAScreen.INSTANCE.status = ClassiCubeError.LOGIN_CODE.description;
ClassiCubeMFAScreen.INSTANCE.status = Classic4JImpl.fromError(CCError.LOGIN_CODE);
return ClassiCubeMFAScreen.INSTANCE;
}
@ -60,14 +62,16 @@ public class ClassiCubeMFAScreen extends Screen {
this.addDrawableChild(ButtonWidget.builder(Text.literal("Login"), button -> {
status = Text.translatable("classicube.viafabricplus.loading");
ClassiCubeAccountHandler.INSTANCE.getAccount().login(new ILoginProcessHandler() {
final CCAccount account = ClassiCubeAccountHandler.INSTANCE.getAccount();
Classic4JImpl.INSTANCE.classiCubeHandler().requestAuthentication(account, mfaField.getText(), new LoginProcessHandler() {
@Override
public void handleMfa(ClassiCubeAccount account) {
public void handleMfa(CCAccount account) {
// Not implemented in this case
}
@Override
public void handleSuccessfulLogin(ClassiCubeAccount account) {
public void handleSuccessfulLogin(CCAccount account) {
RenderSystem.recordRenderCall(() -> ClassiCubeServerListScreen.open(MinecraftClient.getInstance().currentScreen, this));
}
@ -75,7 +79,7 @@ public class ClassiCubeMFAScreen extends Screen {
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());
}

View File

@ -18,11 +18,12 @@
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.classic4j.api.LoginProcessHandler;
import de.florianmichael.classic4j.handler.classicube.server.CCServerListRequest;
import de.florianmichael.classic4j.model.classicube.CCServerInfo;
import de.florianmichael.viafabricplus.definition.c0_30.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import de.florianmichael.viafabricplus.integration.Classic4JImpl;
import de.florianmichael.viafabricplus.protocolhack.provider.vialegacy.ViaFabricPlusClassicMPPassProvider;
import de.florianmichael.viafabricplus.screen.ProtocolSelectionScreen;
import de.florianmichael.viafabricplus.screen.base.MappedSlotEntry;
@ -49,7 +50,7 @@ import java.util.ArrayList;
import java.util.List;
public class ClassiCubeServerListScreen extends Screen {
public final static List<ClassiCubeServerInfo> SERVERS = new ArrayList<>();
public final static List<CCServerInfo> SERVERS = new ArrayList<>();
private final static ClassiCubeServerListScreen INSTANCE = new ClassiCubeServerListScreen();
public Screen prevScreen;
@ -58,16 +59,11 @@ public class ClassiCubeServerListScreen extends Screen {
return ClassiCubeServerListScreen.INSTANCE;
}
public static void open(final Screen prevScreen, final ILoginProcessHandler loginProcessHandler) {
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());
public static void open(final Screen prevScreen, final LoginProcessHandler loginProcessHandler) {
Classic4JImpl.INSTANCE.classiCubeHandler().requestServerList(ClassiCubeAccountHandler.INSTANCE.getAccount(), ccServerList -> {
ClassiCubeServerListScreen.SERVERS.addAll(ccServerList.servers());
RenderSystem.recordRenderCall(() -> MinecraftClient.getInstance().setScreen(ClassiCubeServerListScreen.get(prevScreen)));
});
}, loginProcessHandler::handleException);
}
public ClassiCubeServerListScreen() {
@ -102,7 +98,7 @@ public class ClassiCubeServerListScreen extends Screen {
matrices.scale(2F, 2F, 2F);
drawCenteredTextWithShadow(matrices, textRenderer, "ViaFabricPlus", width / 4, 3, Color.ORANGE.getRGB());
matrices.pop();
drawCenteredTextWithShadow(matrices, textRenderer, Text.literal("ClassiCube Profile: " + ClassiCubeAccountHandler.INSTANCE.getAccount().username), width / 2, (textRenderer.fontHeight + 2) * 2 + 3, -1);
drawCenteredTextWithShadow(matrices, textRenderer, Text.literal("ClassiCube Profile: " + ClassiCubeAccountHandler.INSTANCE.getAccount().username()), width / 2, (textRenderer.fontHeight + 2) * 2 + 3, -1);
}
public static class SlotList extends AlwaysSelectedEntryListWidget<MappedSlotEntry> {
@ -126,9 +122,9 @@ public class ClassiCubeServerListScreen extends Screen {
public static class ServerSlot extends MappedSlotEntry {
private final ClassiCubeServerInfo classiCubeServerInfo;
private final CCServerInfo classiCubeServerInfo;
public ServerSlot(ClassiCubeServerInfo classiCubeServerInfo) {
public ServerSlot(CCServerInfo classiCubeServerInfo) {
this.classiCubeServerInfo = classiCubeServerInfo;
}
@ -141,7 +137,7 @@ public class ClassiCubeServerListScreen extends Screen {
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();
ViaFabricPlusClassicMPPassProvider.classiCubeMPPass = classiCubeServerInfo.mpPass();
if (AuthenticationSettings.INSTANCE.forceCPEIfUsingClassiCube.getValue()) {
((IServerInfo) entry).viafabricplus_forceVersion(ViaLoadingBase.fromProtocolVersion(LegacyProtocolVersion.c0_30cpe));
@ -158,7 +154,7 @@ public class ClassiCubeServerListScreen extends Screen {
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();
final String playerText = classiCubeServerInfo.players() + "/" + classiCubeServerInfo.maxPlayers();
drawTextWithShadow(matrices, textRenderer, playerText, entryWidth - textRenderer.getWidth(playerText) - 4 /* magic value from line 132 */ - 1, 1, -1);
}
}

View File

@ -157,7 +157,8 @@
"fixes.viaversion.protocol1_9to1_8.MixinViaIdleThread",
"jsonwebtoken.MixinClasses",
"jsonwebtoken.MixinDefaultCompressionCodecResolver",
"jsonwebtoken.MixinDefaultJwtParserBuilder"
"jsonwebtoken.MixinDefaultJwtParserBuilder",
"classic4j.MixinCCAuthenticationResponse"
],
"injectors": {
"defaultRequire": 1