Skip to content

Commit

Permalink
Version 1.3.5
Browse files Browse the repository at this point in the history
  • Loading branch information
EssentialGGBot committed Oct 30, 2024
1 parent b476030 commit 9485bdd
Show file tree
Hide file tree
Showing 45 changed files with 1,715 additions and 43 deletions.
9 changes: 9 additions & 0 deletions changelog/release-1.3.5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Title: Server Discovery Update
Summary: Improved Server List

## Multiplayer Menu
- Replaced the "Featured" tab with "Discover"

## Bug Fixes
- Fixed crash when exporting in Flashback mod
- Fixed crash when changing tick speed with G4mespeed mod
1 change: 1 addition & 0 deletions features.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
always=true
new_ice_backend=true
server_discovery=true
updated_gifting_modal=true
updated_coins_purchase_modal=true
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ org.gradle.configureondemand=true
org.gradle.parallel.threads=128
org.gradle.jvmargs=-Xmx16G
minecraftVersion=11202
version=1.3.4.3
version=1.3.5
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,12 @@ object EssentialPalette {

val BONUS_COINS_COLOR: Color = Color(0xFDC80A)

@JvmField
val MODAL_TITLE_BLUE: Color = Color(0x0A82FD)

@JvmField
val SERVER_DOWNLOAD_ICON: Color = Color(0x1D6AFF)

/** Gray/gray600 */
@JvmField
val CHECKBOX_BACKGROUND: Color = Color(0x323232)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import gg.essential.util.UuidNameLookup
import java.util.*

fun LayoutScope.playerAvatar(uuid: UUID, modifier: Modifier = Modifier) {
val image = CachedAvatarImage.ofUUID(uuid)
val image = CachedAvatarImage.create(uuid)
.effect(ShadowEffect())

image(modifier)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2024 ModCore Inc. All rights reserved.
*
* This code is part of ModCore Inc.'s Essential Mod repository and is protected
* under copyright registration # TX0009138511. For the full license, see:
* https://github.com/EssentialGG/Essential/blob/main/LICENSE
*
* You may not use, copy, reproduce, modify, sell, license, distribute,
* commercialize, or otherwise exploit, or create derivative works based
* upon, this file or any other in this repository, all of which is reserved by Essential.
*/
package gg.essential.gui.serverdiscovery

import gg.essential.gui.EssentialPalette
import gg.essential.gui.common.StyledButton
import gg.essential.gui.common.modal.EssentialModal2
import gg.essential.gui.common.textStyle
import gg.essential.gui.layoutdsl.Arrangement
import gg.essential.gui.layoutdsl.LayoutScope
import gg.essential.gui.layoutdsl.Modifier
import gg.essential.gui.layoutdsl.color
import gg.essential.gui.layoutdsl.image
import gg.essential.gui.layoutdsl.row
import gg.essential.gui.layoutdsl.tag
import gg.essential.gui.layoutdsl.text
import gg.essential.gui.layoutdsl.width
import gg.essential.gui.layoutdsl.wrappedText
import gg.essential.gui.overlay.ModalManager
import gg.essential.util.openInBrowser
import java.net.URI

class VersionDownloadModal(modalManager: ModalManager, private val recommendedVersion: String) : EssentialModal2(modalManager) {
override fun LayoutScope.layoutTitle() {
wrappedText(
"Your Minecraft version is not\nsupported. We recommend\nMinecraft $recommendedVersion to join.",
Modifier.color(EssentialPalette.MODAL_TITLE_BLUE),
centered = true
)
}

override fun LayoutScope.layoutBody() {
description("Easily install the required version\nusing the Essential Installer.")
}

override fun LayoutScope.layoutButtons() {
row(Arrangement.spacedBy(8f)) {
cancelButton("Cancel")

styledButton(
Modifier.width(91f).tag(PrimaryAction),
style = StyledButton.Style.BLUE,
action = {
openInBrowser(URI.create("https://essential.gg/download"))
}
) { style ->
row(Arrangement.spacedBy(5f)) {
text("Download", Modifier.textStyle(style))
image(EssentialPalette.ARROW_UP_RIGHT_5X5, Modifier.textStyle(style))
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2024 ModCore Inc. All rights reserved.
*
* This code is part of ModCore Inc.'s Essential Mod repository and is protected
* under copyright registration # TX0009138511. For the full license, see:
* https://github.com/EssentialGG/Essential/blob/main/LICENSE
*
* You may not use, copy, reproduce, modify, sell, license, distribute,
* commercialize, or otherwise exploit, or create derivative works based
* upon, this file or any other in this repository, all of which is reserved by Essential.
*/
package gg.essential.network.connectionmanager.knownservers

import gg.essential.connectionmanager.common.model.knownserver.KnownServer
import gg.essential.connectionmanager.common.packet.knownservers.ClientKnownServersRequestPacket
import gg.essential.connectionmanager.common.packet.knownservers.ServerKnownServersResponsePacket
import gg.essential.gui.elementa.state.v2.State
import gg.essential.gui.elementa.state.v2.combinators.map
import gg.essential.gui.elementa.state.v2.mutableStateOf
import gg.essential.network.CMConnection
import gg.essential.network.connectionmanager.NetworkedManager
import kotlinx.coroutines.launch
import java.util.regex.Pattern

class KnownServersManager(val connectionManager: CMConnection) : NetworkedManager {
private val mutableKnownServers = mutableStateOf(listOf<KnownServer>())
val knownServers: State<List<KnownServer>> = mutableKnownServers

private val serversByAddress = knownServers.map { servers ->
servers.flatMap { server -> server.addresses.filter { !isRegex(it) }.map { it to server } }.toMap()
}

private val serversByRegex = knownServers.map { servers ->
servers.flatMap { server -> server.addresses.filter{ isRegex(it) }.map { Pattern.compile(it) to server } }.toMap()
}

override fun onConnected() {
connectionManager.connectionScope.launch { refreshKnownServers() }
}

private suspend fun refreshKnownServers() {
val response =
connectionManager.call(ClientKnownServersRequestPacket())
.exponentialBackoff()
.await<ServerKnownServersResponsePacket>()
mutableKnownServers.set(response.knownServers)
}

fun findServerByAddress(address: String): KnownServer? {
serversByAddress.getUntracked()[address]?.let { return it }

for ((pattern, server) in serversByRegex.getUntracked()) {
if (pattern.matcher(address).matches()) {
return server
}
}

return null
}

fun normalizeAddress(address: String): String {
findServerByAddress(address)?.let { return it.addresses[0] }
return address
}

companion object {
private fun isRegex(address: String) = address.startsWith("^") && address.endsWith("$")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2024 ModCore Inc. All rights reserved.
*
* This code is part of ModCore Inc.'s Essential Mod repository and is protected
* under copyright registration # TX0009138511. For the full license, see:
* https://github.com/EssentialGG/Essential/blob/main/LICENSE
*
* You may not use, copy, reproduce, modify, sell, license, distribute,
* commercialize, or otherwise exploit, or create derivative works based
* upon, this file or any other in this repository, all of which is reserved by Essential.
*/
package gg.essential.network.connectionmanager.serverdiscovery

import gg.essential.connectionmanager.common.packet.serverdiscovery.ClientServerDiscoveryRequestPacket
import gg.essential.connectionmanager.common.packet.serverdiscovery.ServerServerDiscoveryResponsePacket
import gg.essential.gui.elementa.state.v2.State
import gg.essential.gui.elementa.state.v2.mutableStateOf
import gg.essential.network.connectionmanager.NetworkedManager
import gg.essential.connectionmanager.common.model.serverdiscovery.Server
import gg.essential.connectionmanager.common.packet.telemetry.ClientTelemetryPacket
import gg.essential.network.CMConnection
import gg.essential.network.connectionmanager.knownservers.KnownServersManager
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import java.time.Instant
import java.util.function.Consumer

class NewServerDiscoveryManager(
val connectionManager: CMConnection,
val knownServersManager: KnownServersManager,
val telemetryPacketConsumer: Consumer<ClientTelemetryPacket>,
) : NetworkedManager {
private var refreshServersJob: Job? = null

private val mutableServers = mutableStateOf(Servers(listOf(), listOf()))
val servers: State<Servers> = mutableServers

override fun onConnected() {
refreshServers()
}

fun refreshServers() {
if (refreshServersJob == null || refreshServersJob?.isCompleted == true) {
refreshServersJob = connectionManager.connectionScope.launch {
val response =
connectionManager.call(ClientServerDiscoveryRequestPacket())
.exponentialBackoff()
.await<ServerServerDiscoveryResponsePacket>()
mutableServers.set(Servers(response.featuredServers, response.recommendedServers))
}
}
}

fun interface ImpressionConsumer : Consumer<String>

inner class ImpressionTracker {
private val featured = mutableSetOf<String>()
private val recommended = mutableSetOf<String>()

val featuredConsumer = ImpressionConsumer { trackImpression(it, featured::add) }
val recommendedConsumer = ImpressionConsumer { trackImpression(it, recommended::add) }

private fun trackImpression(ip: String, idConsumer: Consumer<String>) {
knownServersManager.findServerByAddress(ip)?.also { idConsumer.accept(it.id) }
}

fun submit() {
if (featured.isEmpty() && recommended.isEmpty()) return
telemetryPacketConsumer.accept(ClientTelemetryPacket("DISCOVER_SERVER_IMPRESSION_1", mapOf(
"featured" to featured.toSet(),
"recommended" to recommended.toSet(),
)))
featured.clear()
recommended.clear()
}
}

data class Servers(val featured: List<Server>, val recommended: List<Server>) {
fun isEmpty() = featured.isEmpty() && recommended.isEmpty()
}

companion object {
val NEW_TAG_END_DATE = Instant.parse("2024-12-01T00:00:00Z")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2024 ModCore Inc. All rights reserved.
*
* This code is part of ModCore Inc.'s Essential Mod repository and is protected
* under copyright registration # TX0009138511. For the full license, see:
* https://github.com/EssentialGG/Essential/blob/main/LICENSE
*
* You may not use, copy, reproduce, modify, sell, license, distribute,
* commercialize, or otherwise exploit, or create derivative works based
* upon, this file or any other in this repository, all of which is reserved by Essential.
*/
package gg.essential.mixins.transformers.client.gui;

import gg.essential.mixins.DummyTarget;
import org.spongepowered.asm.mixin.Mixin;

@Mixin(DummyTarget.class)
public class AbstractListAccessor {
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.List;
Expand Down Expand Up @@ -216,8 +217,33 @@ private void drawEssentialGui(int mouseX, int mouseY, float partialTicks, Callba
essentialGui.draw(matrixStack);
}

@Inject(method = "connectToServer", at = @At("HEAD"))
@Inject(method = "connectToServer", at = @At("HEAD"), cancellable = true)
private void essential$onConnectToServer(ServerData server, CallbackInfo ci) {
essentialGui.onConnectToServer(server);
essentialGui.onConnectToServer(server, ci);
}

@Inject(method = "onGuiClosed", at = @At("HEAD"))
private void essential$onGuiClosed(CallbackInfo ci) {
essentialGui.onClosed();
}

@Inject(
//#if MC>=11600
//$$ method = "func_214284_c",
//#else
method = "confirmClicked",
slice = @Slice(
from = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/GuiMultiplayer;addingServer:Z"),
to = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/GuiMultiplayer;editingServer:Z")
),
//#endif
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ServerList;saveServerList()V", shift = At.Shift.AFTER),
cancellable = true
)
private void switchTabOnServerAdded(CallbackInfo ci) {
if (EssentialConfig.INSTANCE.getCurrentMultiplayerTab() != 0) {
ci.cancel();
essentialGui.switchTab(0);
}
}
}
Loading

0 comments on commit 9485bdd

Please sign in to comment.