Skip to content

Commit

Permalink
Version 1.3.4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
EssentialGGBot committed Aug 28, 2024
1 parent a60d90b commit 11244c7
Show file tree
Hide file tree
Showing 18 changed files with 331 additions and 56 deletions.
8 changes: 8 additions & 0 deletions changelog/release-1.3.4.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Title: Bug Patch
Summary: Minor bug fixes

## Bug Fixes
- Fixed World Hosting failing to connect if your computer is set to certain languages
- Fixed timeout / bad connection issue some people were experiencing with World Hosting
- Multiple minor improvements to World Hosting connection quality
- Fixed skin being automatically selected when uploaded
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
version=1.3.4.1
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ open class EssentialModal(
}

protected val keyListener: UIComponent.(Char, Int) -> Unit = keyListener@{_, keyCode ->
if (isAnimating) { return@keyListener }
if (modalManager.isCurrentlyFadingIn) { return@keyListener }

when (keyCode) {
// Activate selected button on enter or primary button if no button is selected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ abstract class EssentialModal2(
/** See [styledButton], just an overload without any state to make it easier to call. */
fun LayoutScope.styledButton(
modifier: Modifier = Modifier,
style: StyledButton.Style = StyledButton.Style.GRAY,
style: StyledButton.Style,
enableRetexturing: Boolean = false,
action: suspend () -> Unit,
content: LayoutScope.(style: State<MenuButton.Style>) -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ abstract class Modal(val modalManager: ModalManager) : UIContainer() {
*/
protected lateinit var coroutineScope: CoroutineScope

var isAnimating = false

private var windowListListener: (UIComponent.(Char, Int) -> Unit)? = null
private val escapeListener: UIComponent.(Char, Int) -> Unit = { _, keyCode ->
if (keyCode == UKeyboard.KEY_ESCAPE) {
Expand All @@ -55,7 +53,7 @@ abstract class Modal(val modalManager: ModalManager) : UIContainer() {
}

onLeftClick { event ->
if (!isAnimating && event.target == this) {
if (!modalManager.isCurrentlyFadingIn && event.target == this) {
handleEscapeKeyPress()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,26 @@
package gg.essential.gui.overlay

import gg.essential.gui.common.modal.Modal
import kotlinx.coroutines.CoroutineScope

/**
* Queues [Modal]s to be displayed on a [Layer].
*/
interface ModalManager {
/**
* Coroutine scope which is cancelled once the last modal in the queue is closed and no followup modals are queued.
*
* Beware that if no modal is ever opened, this scope will never be cancelled.
*/
val coroutineScope: CoroutineScope

/**
* True for the short amount of time where the modal is already visible but still fading in.
* Modals should ideally ignore user input during this period, so they're not inadvertently dismissed before
* even being properly visible.
*/
val isCurrentlyFadingIn: Boolean

/**
* Queues the given modal to be displayed after existing modals (or immediately if there are no active modals).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ import gg.essential.elementa.utils.withAlpha
import gg.essential.gui.common.modal.Modal
import gg.essential.gui.common.modal.defaultEssentialModalFadeTime
import gg.essential.gui.elementa.transitions.FadeInTransition
import gg.essential.util.Client
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import java.awt.Color

/**
Expand All @@ -30,7 +35,13 @@ import java.awt.Color
class UIContainerModalManagerImpl(
backgroundColor: Color = Color.BLACK.withAlpha(150)
) : UIContainer(), ModalManager {
override val coroutineScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Client)

private val modalQueue = mutableListOf<Modal>()
override var isCurrentlyFadingIn: Boolean = false
private set

private var didFade: Boolean = false

private val background by UIBlock(backgroundColor).constrain {
x = 0.pixels
Expand All @@ -49,20 +60,20 @@ class UIContainerModalManagerImpl(
}

override fun queueModal(modal: Modal) {
// We can't immediately show a modal if this component doesn't have a parent.
modalQueue.add(modal)

if (hasParent && background.children.isEmpty()) {
pushModalFromQueue()
return
}

modalQueue.add(modal)
}

override fun modalClosed() {
val pushedModal = pushModalFromQueue()
if (pushedModal == null) {
// If there are no modals left, we can remove the manager from its parent.
parent.removeChild(this)
coroutineScope.cancel()
}
}

Expand All @@ -72,12 +83,7 @@ class UIContainerModalManagerImpl(
// If a modal was queued before we had a parent, we need to make it a child now for it to be
// displayed as expected.
if (background.children.isEmpty()) {
val modal = pushModalFromQueue() ?: return
modal.isAnimating = true

FadeInTransition(defaultEssentialModalFadeTime).transition(this) {
modal.isAnimating = false
}
pushModalFromQueue()
}
}

Expand All @@ -86,6 +92,15 @@ class UIContainerModalManagerImpl(
modal childOf background
modal.onOpen()

if (!didFade) {
didFade = true

isCurrentlyFadingIn = true
FadeInTransition(defaultEssentialModalFadeTime).transition(this) {
isCurrentlyFadingIn = false
}
}

return modal
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -439,11 +439,19 @@ abstract class IceManagerImpl(
}
}

private val inboundDataChannel = Channel<ByteArray>(10, BufferOverflow.DROP_OLDEST)
private val outboundDataChannel = Channel<ByteArray>(10, BufferOverflow.DROP_OLDEST)
private val inboundDataChannel = Channel<ByteArray>(1000, BufferOverflow.DROP_OLDEST) { packet ->
logger.warn("IceConnection.inboundDataChannel overflow, dropping packet of {} bytes", packet.size)
}
private val outboundDataChannel = Channel<ByteArray>(1000, BufferOverflow.DROP_OLDEST) { packet ->
logger.warn("IceConnection.outboundDataChannel overflow, dropping packet of {} bytes", packet.size)
}

private val inboundVoiceChannel = Channel<ByteArray>(10, BufferOverflow.DROP_OLDEST)
private val outboundVoiceChannel = Channel<ByteArray>(10, BufferOverflow.DROP_OLDEST)
private val inboundVoiceChannel = Channel<ByteArray>(1000, BufferOverflow.DROP_OLDEST) { packet ->
logger.warn("IceConnection.inboundVoiceChannel overflow, dropping packet of {} bytes", packet.size)
}
private val outboundVoiceChannel = Channel<ByteArray>(1000, BufferOverflow.DROP_OLDEST) { packet ->
logger.warn("IceConnection.outboundVoiceChannel overflow, dropping packet of {} bytes", packet.size)
}

val inboundPacketSortingJob = coroutineScope.launch(Dispatchers.Unconfined) {
for ((candidate, data) in agent.inboundDataChannel) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@
import gg.essential.event.essential.TosAcceptedEvent;
import gg.essential.event.network.server.ServerJoinEvent;
import gg.essential.gui.elementa.state.v2.ReferenceHolderImpl;
import gg.essential.lib.gson.Gson;
import gg.essential.lib.gson.JsonElement;
import gg.essential.lib.gson.JsonObject;
import gg.essential.lib.gson.JsonPrimitive;
import gg.essential.network.connectionmanager.ConnectionManager;
import gg.essential.network.connectionmanager.NetworkedManager;
import gg.essential.network.connectionmanager.queue.SequentialPacketQueue;
import gg.essential.universal.UMinecraft;
import gg.essential.util.Multithreading;
import me.kbrewster.eventbus.Subscribe;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
Expand All @@ -34,11 +39,17 @@
//$$ import oshi.hardware.CentralProcessor;
//#endif

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static gg.essential.network.connectionmanager.telemetry.TelemetryManagerKt.*;

Expand Down Expand Up @@ -103,6 +114,7 @@ private void init(InitializationEvent event) {
enqueue(new ClientTelemetryPacket("LANGUAGE", new HashMap<String, Object>(){{
put("lang", UMinecraft.getMinecraft().gameSettings.language);
}}));
queueInstallerTelemetryPacket();
}

/**
Expand Down Expand Up @@ -185,4 +197,50 @@ public void sendHardwareAndOSTelemetry(@NotNull final TosAcceptedEvent event) {
enqueue(new ClientTelemetryPacket("HARDWARE_V2", hardwareMap));
}

private void queueInstallerTelemetryPacket() {
// We go async, since we are reading a file
Multithreading.runAsync(() -> {
try {
Path installerMetadataPath = Essential.getInstance().getBaseDir().toPath().resolve("installer-metadata.json").toRealPath();

if (Files.notExists(installerMetadataPath))
return;

// Calculate the sha-1 checksum of the current game directory in the same way the installer does.
byte[] pathBytes = installerMetadataPath.toString().getBytes(StandardCharsets.UTF_8);
byte[] pathChecksumBytes = MessageDigest.getInstance("SHA-1").digest(pathBytes);
StringBuilder pathChecksumBuilder = new StringBuilder();
for (byte checksumByte : pathChecksumBytes) {
pathChecksumBuilder.append(String.format(Locale.ROOT, "%02x", checksumByte));
}
String pathChecksum = pathChecksumBuilder.toString();

// Grab the raw JSON object from the telemetry file
// This is to allow installer to add telemetry fields without having to update the mod
String rawFile = new String(Files.readAllBytes(installerMetadataPath), StandardCharsets.UTF_8);
JsonObject telemetryObject = new Gson().fromJson(rawFile, JsonObject.class);
// Convert to map
HashMap<String, Object> telemetryMap = new HashMap<>();
for (Map.Entry<String, JsonElement> entry : telemetryObject.entrySet()) {
telemetryMap.put(entry.getKey(), entry.getValue());
}
// Check if the game folder has been moved
boolean hasBeenMoved = false;
Object installPathChecksum = telemetryMap.get("installPathChecksum");
if (installPathChecksum instanceof JsonPrimitive) {
String installerPathChecksum = ((JsonPrimitive) installPathChecksum).getAsString();
hasBeenMoved = !installerPathChecksum.equals(pathChecksum);
}

telemetryMap.put("installPathChecksum", pathChecksum);
telemetryMap.put("hasBeenMoved", hasBeenMoved);
// Then queue the packet on the main thread again
Multithreading.scheduleOnMainThread(() -> enqueue(new ClientTelemetryPacket("INSTALLER", telemetryMap)), 0, TimeUnit.SECONDS);

} catch (Exception e) {
Essential.logger.warn("Error when trying to parse installer telemetry!", e);
}
});
}

}
29 changes: 21 additions & 8 deletions src/main/kotlin/gg/essential/gui/overlay/ModalManagerImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ import gg.essential.elementa.utils.withAlpha
import gg.essential.gui.common.modal.Modal
import gg.essential.gui.common.modal.defaultEssentialModalFadeTime
import gg.essential.gui.elementa.transitions.FadeInTransition
import gg.essential.util.Client
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import java.awt.Color

/**
Expand All @@ -29,13 +34,18 @@ class ModalManagerImpl(
private val overlayManager: OverlayManager,
private val backgroundColor: Color = Color.BLACK.withAlpha(150),
) : ModalManager {
override val coroutineScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Client)

private val modalQueue = mutableListOf<Modal>()

/**
* The [Layer] which [Modal]s will be displayed on.
*/
private var layer: Layer? = null

override var isCurrentlyFadingIn: Boolean = false
private set

override fun modalClosed() {
val nextModal = modalQueue.removeFirstOrNull()
if (nextModal != null) {
Expand All @@ -44,6 +54,8 @@ class ModalManagerImpl(
// If we have no modals left to push, we should remove the layer.
layer?.let { overlayManager.removeLayer(it) }
layer = null
isCurrentlyFadingIn = false
coroutineScope.cancel()
}
}

Expand All @@ -53,7 +65,8 @@ class ModalManagerImpl(
// If the layer is null, this means that this is our first modal, or, that the previous layer
// was cleaned up. We should create a new one for this modal to be pushed on to.
if (currentLayer == null) {
createAndSetupLayer(modal)
val layer = createAndSetupLayer()
layer.pushModal(modal)
return
}

Expand All @@ -62,21 +75,18 @@ class ModalManagerImpl(
modalQueue.add(modal)
}

private fun createAndSetupLayer(modal: Modal): Layer {
private fun createAndSetupLayer(): Layer {
return overlayManager.createPersistentLayer(LayerPriority.Modal).apply {
val background = UIBlock(backgroundColor).constrain {
UIBlock(backgroundColor).constrain {
x = 0.pixels
y = 0.pixels
width = 100.percentOfWindow()
height = 100.percentOfWindow()
} childOf window

modal childOf background
modal.onOpen()

modal.isAnimating = true
isCurrentlyFadingIn = true
FadeInTransition(defaultEssentialModalFadeTime).transition(window) {
modal.isAnimating = false
isCurrentlyFadingIn = false
}

this@ModalManagerImpl.layer = this
Expand All @@ -87,6 +97,9 @@ class ModalManagerImpl(
val background = window.children.first()

modal childOf background

// Beware: This call may recursively call [queueModal] and/or [modalClosed]. As such, it should ideally be the
// last thing which effectively happens in these methods.
modal.onOpen()
}
}
Loading

0 comments on commit 11244c7

Please sign in to comment.