diff --git a/ReadMe.md b/ReadMe.md index b8d943a10..b1fa6caab 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -28,7 +28,7 @@ Minosoft is an open source minecraft client, written from scratch in kotlin (and - RAM: ~500Mib. With overhead, etc 2Gib recommended - Disk space: Minosoft itself is pretty small (2-3 Mib), the libraries are a bit bigger. You also need to have the "normal" minecraft assets (~ 300 MB for one version). - GPU: OpenGL 3.3+. Every moden GPU works and is recommended. -- Java 16 (This is really important, we use features that are only available in this version. Java 8 is currently **not** supported). +- Java 14+, 16 recommended (This is really important, we use features that are only available in this version. Java 8 is currently **not** supported). ## Rendering diff --git a/src/main/java/de/bixilon/minosoft/data/commands/CommandNode.java b/src/main/java/de/bixilon/minosoft/data/commands/CommandNode.java index 9c5bdbe97..2fadd70d2 100644 --- a/src/main/java/de/bixilon/minosoft/data/commands/CommandNode.java +++ b/src/main/java/de/bixilon/minosoft/data/commands/CommandNode.java @@ -116,13 +116,13 @@ public abstract class CommandNode { if (stringReader.getRemainingLength() == 0) { if (this.isExecutable) { if (this.executor != null) { - if (this.executor instanceof CommandExecutor commandExecutor) { - commandExecutor.execute(stack); - } else if (this.executor instanceof CommandConnectionExecutor commandConnectionExecutor) { + if (this.executor instanceof CommandExecutor) { + ((CommandExecutor) this.executor).execute(stack); + } else if (this.executor instanceof CommandConnectionExecutor) { if (connection == null) { throw new NoConnectionCommandParseException(stringReader, stringReader.getString()); } - commandConnectionExecutor.execute(connection, stack); + ((CommandConnectionExecutor) this.executor).execute(connection, stack); } } @@ -171,11 +171,12 @@ public abstract class CommandNode { public CommandNode addChildren(Set children) { for (CommandNode child : children) { - if (child instanceof CommandArgumentNode argumentNode) { - this.argumentsChildren.add(argumentNode); + if (child instanceof CommandArgumentNode) { + this.argumentsChildren.add(((CommandArgumentNode) child)); continue; } - if (child instanceof CommandLiteralNode literalNode) { + if (child instanceof CommandLiteralNode) { + CommandLiteralNode literalNode = (CommandLiteralNode) child; this.literalChildren.put(literalNode.getName(), literalNode); } } diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/LegacyResourceLocation.java b/src/main/java/de/bixilon/minosoft/data/mappings/LegacyResourceLocation.kt similarity index 53% rename from src/main/java/de/bixilon/minosoft/data/mappings/LegacyResourceLocation.java rename to src/main/java/de/bixilon/minosoft/data/mappings/LegacyResourceLocation.kt index 297328207..a9c17f8ee 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/LegacyResourceLocation.java +++ b/src/main/java/de/bixilon/minosoft/data/mappings/LegacyResourceLocation.kt @@ -10,36 +10,25 @@ * * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ +package de.bixilon.minosoft.data.mappings -package de.bixilon.minosoft.data.mappings; +class LegacyResourceLocation(resourceLocation: String) : ResourceLocation("", resourceLocation) { + override val full: String = path -public class LegacyResourceLocation extends ResourceLocation { - - public LegacyResourceLocation(String resourceLocation) { - super(null, resourceLocation); + override fun hashCode(): Int { + return this.path.hashCode() } - @Override - public String getFull() { - return getPath(); - } - - @Override - public int hashCode() { - return this.path.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (super.equals(obj)) { - return true; + override fun equals(other: Any?): Boolean { + if (other === this) { + return true } - if (hashCode() != obj.hashCode()) { - return false; + if (hashCode() != other.hashCode()) { + return false } - if (obj instanceof ResourceLocation legacyResourceLocation) { - return getPath().equals(legacyResourceLocation.getPath()); + if (other !is ResourceLocation) { + return false } - return false; + return path == other.path } } diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/ResourceLocation.java b/src/main/java/de/bixilon/minosoft/data/mappings/ResourceLocation.java deleted file mode 100644 index e5f55cf6b..000000000 --- a/src/main/java/de/bixilon/minosoft/data/mappings/ResourceLocation.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020 Moritz Zwerger - * - * 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 . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.data.mappings; - -import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; -import de.bixilon.minosoft.util.Util; -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; - -public class ResourceLocation implements Comparable { - public final String full; - protected final String namespace; - protected final String path; - - public ResourceLocation(String namespace, String path) { - this.namespace = namespace; - this.path = path; - this.full = namespace + ":" + path; - } - - public ResourceLocation(String full) { - String[] split = full.split(":"); - if (split.length == 1) { - this.namespace = ProtocolDefinition.DEFAULT_NAMESPACE; - this.path = full; - } else { - this.namespace = split[0]; - this.path = split[1]; - } - this.full = this.namespace + ":" + this.path; - } - - public static ResourceLocation getResourceLocation(String resourceLocation) throws IllegalArgumentException { - // if (!ProtocolDefinition.RESOURCE_LOCATION_PATTERN.matcher(resourceLocation).matches()) { - // throw new IllegalArgumentException(String.format("%s in not a valid resource location!", resourceLocation)); - // } - - if (Util.doesStringContainsUppercaseLetters(resourceLocation)) { - // just a string but wrapped into a resourceLocation (like old plugin channels MC|BRAND or ...) - return new LegacyResourceLocation(resourceLocation); - } - - return new ResourceLocation(resourceLocation); - } - - public static ResourceLocation getPathResourceLocation(String resourceLocation) { - if (resourceLocation.contains(":")) { - return new ResourceLocation(resourceLocation); - } - String[] split = resourceLocation.split("/", 2); - return new ResourceLocation(split[0], split[1]); - } - - public String getNamespace() { - return this.namespace; - } - - public String getPath() { - return this.path; - } - - public String getFull() { - return this.full; - } - - @Override - public int hashCode() { - return Objects.hash(this.namespace, this.path); - } - - @Override - public boolean equals(Object obj) { - if (super.equals(obj)) { - return true; - } - if (hashCode() != obj.hashCode()) { - return false; - } - if (obj instanceof LegacyResourceLocation legacyModIdentifier) { - return getPath().equals(legacyModIdentifier.getPath()); - } - ResourceLocation their = (ResourceLocation) obj; - return getPath().equals(their.getPath()) && getNamespace().equals(their.getNamespace()); - } - - @Override - public String toString() { - return getFull(); - } - - @Override - public int compareTo(@NotNull ResourceLocation resourceLocation) { - return resourceLocation.hashCode() - this.hashCode(); - } -} diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/ResourceLocation.kt b/src/main/java/de/bixilon/minosoft/data/mappings/ResourceLocation.kt new file mode 100644 index 000000000..f8470c2f3 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/mappings/ResourceLocation.kt @@ -0,0 +1,92 @@ +/* + * Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ +package de.bixilon.minosoft.data.mappings + +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition +import de.bixilon.minosoft.util.Util +import java.util.* + +open class ResourceLocation( + val namespace: String = ProtocolDefinition.DEFAULT_NAMESPACE, + val path: String, +) : Comparable { // compare is for moshi + open val full: String = "$namespace:$path" + + constructor(full: String) : this(full.namespace, full.path) + + override fun hashCode(): Int { + return Objects.hash(namespace, path) + } + + override fun equals(other: Any?): Boolean { + if (other === this) { + return true + } + if (hashCode() != other.hashCode()) { + return false + } + if (other is LegacyResourceLocation) { + return path == other.path + } + if (other !is ResourceLocation) { + return false + } + return path == other.path && namespace == other.namespace + } + + override fun toString(): String { + return full + } + + companion object { + val String.namespace: String + get() { + val split = this.split(':', limit = 2) + if (split.size == 1) { + return ProtocolDefinition.DEFAULT_NAMESPACE + } + return split[0] + } + + val String.path: String + get() { + val split = this.split(':', limit = 2) + if (split.size == 1) { + return split[0] + } + return split[1] + } + + fun getResourceLocation(resourceLocation: String): ResourceLocation { + // if (!ProtocolDefinition.RESOURCE_LOCATION_PATTERN.matcher(resourceLocation).matches()) { + // throw new IllegalArgumentException(String.format("%s in not a valid resource location!", resourceLocation)); + // } + return if (Util.doesStringContainsUppercaseLetters(resourceLocation)) { + // just a string but wrapped into a resourceLocation (like old plugin channels MC|BRAND or ...) + LegacyResourceLocation(resourceLocation) + } else ResourceLocation(resourceLocation) + } + + fun getPathResourceLocation(resourceLocation: String): ResourceLocation { + if (resourceLocation.contains(":")) { + return ResourceLocation(resourceLocation) + } + val split = resourceLocation.split("/".toRegex(), 2).toTypedArray() + return ResourceLocation(split[0], split[1]) + } + } + + override fun compareTo(other: ResourceLocation): Int { + return hashCode() - other.hashCode() + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/text/HoverEvent.java b/src/main/java/de/bixilon/minosoft/data/text/HoverEvent.java index f2c03cdc6..e17920930 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/HoverEvent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/HoverEvent.java @@ -62,7 +62,16 @@ public class HoverEvent { SHOW_ACHIEVEMENT } - public static record EntityHoverData(UUID uuid, ResourceLocation resourceLocation, ChatComponent name) { + public static final class EntityHoverData { + private final UUID uuid; + private final ResourceLocation resourceLocation; + private final ChatComponent name; + + public EntityHoverData(UUID uuid, ResourceLocation resourceLocation, ChatComponent name) { + this.uuid = uuid; + this.resourceLocation = resourceLocation; + this.name = name; + } public static EntityHoverData deserialize(JsonElement data) { JsonObject json; @@ -81,5 +90,17 @@ public class HoverEvent { } return new EntityHoverData(Util.getUUIDFromString(json.get("id").getAsString()), type, ChatComponent.Companion.of(json.get("name"))); } + + public UUID uuid() { + return this.uuid; + } + + public ResourceLocation resourceLocation() { + return this.resourceLocation; + } + + public ChatComponent name() { + return this.name; + } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/main/GUITools.java b/src/main/java/de/bixilon/minosoft/gui/main/GUITools.java index ae971217b..eb9028e6a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/GUITools.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/GUITools.java @@ -75,8 +75,8 @@ public class GUITools { public static Scene initializeScene(Scene scene) { scene.getStylesheets().add("/assets/minosoft/layout/style.css"); // ToDo: Migrate to minosoft assets manager - if (scene.getWindow() instanceof Stage stage) { - stage.getIcons().add(MINOSOFT_LOGO); + if (scene.getWindow() instanceof Stage) { + ((Stage) scene.getWindow()).getIcons().add(MINOSOFT_LOGO); } return scene; } @@ -93,7 +93,8 @@ public class GUITools { stage.initModality(modality); double width = 600; double height = 400; - if (root instanceof Pane pane) { + if (root instanceof Pane) { + Pane pane = (Pane) root; width = pane.getPrefWidth(); height = pane.getPrefHeight(); } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/norender/ExplosionEmitterParticle.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/norender/ExplosionEmitterParticle.kt index 4e2472b19..077427b7a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/norender/ExplosionEmitterParticle.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/norender/ExplosionEmitterParticle.kt @@ -18,6 +18,7 @@ import de.bixilon.minosoft.data.mappings.particle.data.ParticleData import de.bixilon.minosoft.gui.rendering.particle.ParticleFactory import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.ExplosionParticle +import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.util.KUtil.asResourceLocation import glm_.vec3.Vec3 @@ -33,11 +34,8 @@ class ExplosionEmitterParticle(connection: PlayConnection, particleRenderer: Par override fun realTick() { super.realTick() for (i in 0 until 6) { - val position = Vec3( - x = position.x + (random.nextFloat() - random.nextFloat()) * 4.0f, - y = position.y + (random.nextFloat() - random.nextFloat()) * 4.0f, - z = position.z + (random.nextFloat() - random.nextFloat()) * 4.0f - ) + val position = position + { (random.nextFloat() - random.nextFloat()) * 4.0f } + particleRenderer.add(ExplosionParticle(connection, particleRenderer, position, explosionParticleType.simple(), (tickAge.toFloat() / maxTickAge))) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt index 770b27352..9cdcff005 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt @@ -76,6 +76,14 @@ object VecUtil { ) } + infix operator fun Vec3.plus(lambda: () -> Float): Vec3 { + return Vec3( + x = x + lambda(), + y = y + lambda(), + z = z + lambda(), + ) + } + fun getRotatedValues(x: Float, y: Float, sin: Float, cos: Float, rescale: Boolean): Vec2 { val result = Vec2(x * cos - y * sin, x * sin + y * cos) if (rescale) { diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/socket/BlockingSocketNetwork.java b/src/main/java/de/bixilon/minosoft/protocol/network/socket/BlockingSocketNetwork.java index 3b44deda1..5ba369233 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/socket/BlockingSocketNetwork.java +++ b/src/main/java/de/bixilon/minosoft/protocol/network/socket/BlockingSocketNetwork.java @@ -199,9 +199,9 @@ public class BlockingSocketNetwork extends Network { this.outputStream.write(prepareC2SPacket(packet)); this.outputStream.flush(); - if (packet instanceof EncryptionResponseC2SP packetEncryptionResponse) { + if (packet instanceof EncryptionResponseC2SP) { // enable encryption - enableEncryption(packetEncryptionResponse.getSecretKey()); + enableEncryption(((EncryptionResponseC2SP) packet).getSecretKey()); // wake up other thread this.socketReceiveThread.interrupt(); } diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/socket/NonBlockingSocketNetwork.java b/src/main/java/de/bixilon/minosoft/protocol/network/socket/NonBlockingSocketNetwork.java index e29d2ab88..0437ac954 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/socket/NonBlockingSocketNetwork.java +++ b/src/main/java/de/bixilon/minosoft/protocol/network/socket/NonBlockingSocketNetwork.java @@ -89,9 +89,9 @@ public class NonBlockingSocketNetwork extends Network { this.socketChannel.write(sendBuffer); } - if (packet instanceof EncryptionResponseC2SP packetEncryptionResponse) { + if (packet instanceof EncryptionResponseC2SP) { // enable encryption - enableEncryption(packetEncryptionResponse.getSecretKey()); + enableEncryption(((EncryptionResponseC2SP) packet).getSecretKey()); } }