Compare commits

...

6 Commits

Author SHA1 Message Date
rtm516 e45922a630
Merge 46f19dd6f7 into 42a9ba617b 2024-04-26 23:07:56 +00:00
rtm516 46f19dd6f7
Add originalSkin method to event 2024-04-27 00:07:49 +01:00
rtm516 92e4439075
Get rid of array and preserve original skin data 2024-04-27 00:00:41 +01:00
rtm516 d2a9ee53e8
Ajust for review and bump version to 2.2.4 2024-04-26 22:29:01 +01:00
RK_01 42a9ba617b
Update ViaProxy platform (#4607)
* Update ViaProxy API usage

* Don't reference ViaProxy API in dummy application
2024-04-26 20:06:37 +02:00
chris a57e7b54dc
Update ViaVersion api usage to be compatible with ViaVersion 4.10 (#4606) 2024-04-26 16:36:47 +02:00
13 changed files with 64 additions and 73 deletions

View File

@ -1,5 +1,6 @@
<component name="CopyrightManager">
<copyright>
<option name="allowReplaceRegexp" value="Copyright" />
<option name="notice" value="Copyright (c) &amp;#36;originalComment.match(&quot;Copyright \(c\) (\d+)&quot;, 1, &quot;-&quot;)&amp;#36;today.year GeyserMC. http://geysermc.org&#10;&#10;Permission is hereby granted, free of charge, to any person obtaining a copy&#10;of this software and associated documentation files (the &quot;Software&quot;), to deal&#10;in the Software without restriction, including without limitation the rights&#10;to use, copy, modify, merge, publish, distribute, sublicense, and/or sell&#10;copies of the Software, and to permit persons to whom the Software is&#10;furnished to do so, subject to the following conditions:&#10;&#10;The above copyright notice and this permission notice shall be included in&#10;all copies or substantial portions of the Software.&#10;&#10;THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR&#10;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,&#10;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE&#10;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER&#10;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,&#10;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN&#10;THE SOFTWARE.&#10;&#10;@author GeyserMC&#10;@link https://github.com/GeyserMC/Geyser" />
<option name="myName" value="Geyser" />
</copyright>

View File

@ -46,7 +46,7 @@ public abstract class SessionSkinApplyEvent extends ConnectionEvent {
private final UUID uuid;
private final boolean slim;
private final boolean bedrock;
private final SkinData skinData;
private final SkinData originalSkinData;
public SessionSkinApplyEvent(@NonNull GeyserConnection connection, String username, UUID uuid, boolean slim, boolean bedrock, SkinData skinData) {
super(connection);
@ -54,7 +54,7 @@ public abstract class SessionSkinApplyEvent extends ConnectionEvent {
this.uuid = uuid;
this.slim = slim;
this.bedrock = bedrock;
this.skinData = skinData;
this.originalSkinData = skinData;
}
/**
@ -93,14 +93,21 @@ public abstract class SessionSkinApplyEvent extends ConnectionEvent {
return bedrock;
}
/**
* The original skin data of the player.
*
* @return the original skin data of the player
*/
public SkinData originalSkin() {
return originalSkinData;
}
/**
* The skin data of the player.
*
* @return the skin data of the player
*/
public SkinData skinData() {
return skinData;
}
public abstract SkinData skinData();
/**
* Change the skin of the player.

View File

@ -58,7 +58,7 @@ public class GeyserSpigotLegacyNativeWorldManager extends GeyserSpigotNativeWorl
int newBlockId = oldBlockId;
// protocolList should *not* be null; we checked for that before initializing this class
for (int i = protocolList.size() - 1; i >= 0; i--) {
MappingData mappingData = protocolList.get(i).getProtocol().getMappingData();
MappingData mappingData = protocolList.get(i).protocol().getMappingData();
if (mappingData != null) {
newBlockId = mappingData.getNewBlockStateId(newBlockId);
}

View File

@ -26,7 +26,7 @@ package org.geysermc.geyser.platform.viaproxy;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.viaproxy.cli.options.Options;
import net.raphimc.viaproxy.ViaProxy;
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
import java.io.File;
@ -43,7 +43,7 @@ public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration {
@Override
public int getPingPassthroughInterval() {
int interval = super.getPingPassthroughInterval();
if (interval < 15 && Options.PROTOCOL_VERSION != null && Options.PROTOCOL_VERSION.olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
if (interval < 15 && ViaProxy.getConfig().getTargetVersion() != null && ViaProxy.getConfig().getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
// <= 1.6.4 servers sometimes block incoming connections from an IP address if too many connections are made
interval = 15;
}

View File

@ -26,7 +26,6 @@ package org.geysermc.geyser.platform.viaproxy;
import lombok.Getter;
import net.raphimc.viaproxy.ViaProxy;
import net.raphimc.viaproxy.cli.options.Options;
import net.raphimc.viaproxy.plugins.ViaProxyPlugin;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.text.AsteriskSerializer;
@ -49,8 +48,8 @@ public class GeyserViaProxyDumpInfo extends BootstrapDumpInfo {
public GeyserViaProxyDumpInfo() {
this.platformVersion = ViaProxy.VERSION;
this.onlineMode = Options.ONLINE_MODE;
if (Options.BIND_ADDRESS instanceof InetSocketAddress inetSocketAddress) {
this.onlineMode = ViaProxy.getConfig().isProxyOnlineMode();
if (ViaProxy.getConfig().getBindAddress() instanceof InetSocketAddress inetSocketAddress) {
this.serverIP = inetSocketAddress.getHostString();
this.serverPort = inetSocketAddress.getPort();
} else {

View File

@ -25,7 +25,6 @@
package org.geysermc.geyser.platform.viaproxy;
import net.raphimc.viaproxy.plugins.PluginManager;
import org.geysermc.geyser.GeyserMain;
public class GeyserViaProxyMain extends GeyserMain {
@ -39,7 +38,7 @@ public class GeyserViaProxyMain extends GeyserMain {
}
public String getPluginFolder() {
return PluginManager.PLUGINS_DIR.getName();
return "plugins";
}
}

View File

@ -27,7 +27,6 @@ package org.geysermc.geyser.platform.viaproxy;
import net.lenni0451.lambdaevents.EventHandler;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.viaproxy.ViaProxy;
import net.raphimc.viaproxy.cli.options.Options;
import net.raphimc.viaproxy.plugins.PluginManager;
import net.raphimc.viaproxy.plugins.ViaProxyPlugin;
import net.raphimc.viaproxy.plugins.events.ConsoleCommandEvent;
@ -137,7 +136,7 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst
GeyserImpl.start();
if (Options.PROTOCOL_VERSION != null && Options.PROTOCOL_VERSION.newerThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) {
if (ViaProxy.getConfig().getTargetVersion() != null && ViaProxy.getConfig().getTargetVersion().newerThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) {
// Only initialize the ping passthrough if the protocol version is above beta 1.7.3, as that's when the status protocol was added
this.pingPassthrough = GeyserLegacyPingPassthrough.init(this.geyser);
}
@ -186,19 +185,19 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst
@NotNull
@Override
public String getServerBindAddress() {
if (Options.BIND_ADDRESS instanceof InetSocketAddress socketAddress) {
if (ViaProxy.getConfig().getBindAddress() instanceof InetSocketAddress socketAddress) {
return socketAddress.getHostString();
} else {
throw new IllegalStateException("Unsupported bind address type: " + Options.BIND_ADDRESS.getClass().getName());
throw new IllegalStateException("Unsupported bind address type: " + ViaProxy.getConfig().getBindAddress().getClass().getName());
}
}
@Override
public int getServerPort() {
if (Options.BIND_ADDRESS instanceof InetSocketAddress socketAddress) {
if (ViaProxy.getConfig().getBindAddress() instanceof InetSocketAddress socketAddress) {
return socketAddress.getPort();
} else {
throw new IllegalStateException("Unsupported bind address type: " + Options.BIND_ADDRESS.getClass().getName());
throw new IllegalStateException("Unsupported bind address type: " + ViaProxy.getConfig().getBindAddress().getClass().getName());
}
}

View File

@ -2,4 +2,4 @@ name: "${name}-ViaProxy"
version: "${version}"
author: "${author}"
main: "org.geysermc.geyser.platform.viaproxy.GeyserViaProxyPlugin"
min-version: "3.2.0"
min-version: "3.2.1"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -116,7 +116,7 @@ public class SkullResourcePackManager {
return;
}
BufferedImage image = SkinProvider.requestImage(skinUrl, null);
BufferedImage image = SkinProvider.requestImage(skinUrl, false);
// Resize skins to 48x16 to save on space and memory
BufferedImage skullTexture = new BufferedImage(48, 16, image.getType());
// Reorder skin parts to fit into the space

View File

@ -94,6 +94,7 @@ public class FakeHeadProvider {
// Avoiding memory leak
fakeHeadEntry.setEntity(null);
fakeHeadEntry.setSession(null);
return new SkinData(mergedSkin, cape, geometry);
}

View File

@ -261,25 +261,31 @@ public class SkinProvider {
// Call event to allow extensions to modify the skin, cape and geo
boolean isBedrock = GeyserImpl.getInstance().connectionByUuid(entity.getUuid()) != null;
final SkinData[] skinData = {new SkinData(skin, cape, geometry)};
GeyserImpl.getInstance().eventBus().fire(new SessionSkinApplyEvent(session, entity.getUsername(), entity.getUuid(), data.isAlex(), isBedrock, skinData[0]) {
SkinData skinData = new SkinData(skin, cape, geometry);
final EventSkinData eventSkinData = new EventSkinData(skinData);
GeyserImpl.getInstance().eventBus().fire(new SessionSkinApplyEvent(session, entity.getUsername(), entity.getUuid(), data.isAlex(), isBedrock, skinData) {
@Override
public SkinData skinData() {
return eventSkinData.skinData();
}
@Override
public void skin(@NonNull Skin newSkin) {
skinData[0] = new SkinData(newSkin, skinData[0].cape(), skinData[0].geometry());
eventSkinData.skinData(new SkinData(newSkin, skinData.cape(), skinData.geometry()));
}
@Override
public void cape(@NonNull Cape newCape) {
skinData[0] = new SkinData(skinData[0].skin(), newCape, skinData[0].geometry());
eventSkinData.skinData(new SkinData(skinData.skin(), newCape, skinData.geometry()));
}
@Override
public void geometry(@NonNull SkinGeometry newGeometry) {
skinData[0] = new SkinData(skinData[0].skin(), skinData[0].cape(), newGeometry);
eventSkinData.skinData(new SkinData(skinData.skin(), skinData.cape(), newGeometry));
}
});
return skinData[0];
return eventSkinData.skinData();
} catch (Exception e) {
GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.skin.fail", entity.getUuid()), e);
}
@ -292,10 +298,9 @@ public class SkinProvider {
return CompletableFuture.supplyAsync(() -> {
long time = System.currentTimeMillis();
CapeProvider provider = capeUrl != null ? CapeProvider.MINECRAFT : null;
SkinAndCape skinAndCape = new SkinAndCape(
getOrDefault(requestSkin(playerId, skinUrl, false), EMPTY_SKIN, 5),
getOrDefault(requestCape(capeUrl, provider, false), EMPTY_CAPE, 5)
getOrDefault(requestCape(capeUrl, false), EMPTY_CAPE, 5)
);
GeyserImpl.getInstance().getLogger().debug("Took " + (System.currentTimeMillis() - time) + "ms for " + playerId);
@ -332,7 +337,7 @@ public class SkinProvider {
return future;
}
private static CompletableFuture<Cape> requestCape(String capeUrl, CapeProvider provider, boolean newThread) {
private static CompletableFuture<Cape> requestCape(String capeUrl, boolean newThread) {
if (capeUrl == null || capeUrl.isEmpty()) return CompletableFuture.completedFuture(EMPTY_CAPE);
CompletableFuture<Cape> requestedCape = requestedCapes.get(capeUrl);
if (requestedCape != null) {
@ -346,14 +351,14 @@ public class SkinProvider {
CompletableFuture<Cape> future;
if (newThread) {
future = CompletableFuture.supplyAsync(() -> supplyCape(capeUrl, provider), getExecutorService())
future = CompletableFuture.supplyAsync(() -> supplyCape(capeUrl), getExecutorService())
.whenCompleteAsync((cape, throwable) -> {
CACHED_JAVA_CAPES.put(capeUrl, cape);
requestedCapes.remove(capeUrl);
});
requestedCapes.put(capeUrl, future);
} else {
Cape cape = supplyCape(capeUrl, provider); // blocking
Cape cape = supplyCape(capeUrl); // blocking
future = CompletableFuture.completedFuture(cape);
CACHED_JAVA_CAPES.put(capeUrl, cape);
}
@ -377,17 +382,17 @@ public class SkinProvider {
private static Skin supplySkin(UUID uuid, String textureUrl) {
try {
byte[] skin = requestImageData(textureUrl, null);
byte[] skin = requestImageData(textureUrl, false);
return new Skin(textureUrl, skin);
} catch (Exception ignored) {} // just ignore I guess
return new Skin("empty", EMPTY_SKIN.skinData(), true);
}
private static Cape supplyCape(String capeUrl, CapeProvider provider) {
private static Cape supplyCape(String capeUrl) {
byte[] cape = EMPTY_CAPE.capeData();
try {
cape = requestImageData(capeUrl, provider);
cape = requestImageData(capeUrl, true);
} catch (Exception ignored) {
} // just ignore I guess
@ -402,7 +407,7 @@ public class SkinProvider {
}
@SuppressWarnings("ResultOfMethodCallIgnored")
public static BufferedImage requestImage(String imageUrl, CapeProvider provider) throws IOException {
public static BufferedImage requestImage(String imageUrl, boolean isCape) throws IOException {
BufferedImage image = null;
// First see if we have a cached file. We also update the modification stamp so we know when the file was last used
@ -417,7 +422,7 @@ public class SkinProvider {
// If no image we download it
if (image == null) {
image = downloadImage(imageUrl, provider);
image = downloadImage(imageUrl);
GeyserImpl.getInstance().getLogger().debug("Downloaded " + imageUrl);
// Write to cache if we are allowed
@ -433,7 +438,7 @@ public class SkinProvider {
}
// if the requested image is a cape
if (provider != null) {
if (isCape) {
if (image.getWidth() > 64 || image.getHeight() > 32) {
// Prevent weirdly-scaled capes from being cut off
BufferedImage newImage = new BufferedImage(128, 64, BufferedImage.TYPE_INT_ARGB);
@ -465,8 +470,8 @@ public class SkinProvider {
return image;
}
private static byte[] requestImageData(String imageUrl, CapeProvider provider) throws Exception {
BufferedImage image = requestImage(imageUrl, provider);
private static byte[] requestImageData(String imageUrl, boolean isCape) throws Exception {
BufferedImage image = requestImage(imageUrl, isCape);
byte[] data = bufferedImageToImageData(image);
image.flush();
return data;
@ -529,7 +534,7 @@ public class SkinProvider {
});
}
private static BufferedImage downloadImage(String imageUrl, CapeProvider provider) throws IOException {
private static BufferedImage downloadImage(String imageUrl) throws IOException {
HttpURLConnection con = (HttpURLConnection) new URL(imageUrl).openConnection();
con.setRequestProperty("User-Agent", WebUtils.getUserAgent());
con.setConnectTimeout(10000);
@ -538,7 +543,7 @@ public class SkinProvider {
BufferedImage image = ImageIO.read(con.getInputStream());
if (image == null) {
throw new IllegalArgumentException("Failed to read image from: %s (cape provider=%s)".formatted(imageUrl, provider));
throw new IllegalArgumentException("Failed to read image from: %s".formatted(imageUrl));
}
return image;
}
@ -616,39 +621,19 @@ public class SkinProvider {
public record SkinAndCape(Skin skin, Cape cape) {
}
/*
* Sorted by 'priority'
*/
@AllArgsConstructor
@NoArgsConstructor
@Getter
public enum CapeProvider {
MINECRAFT;
public static class EventSkinData {
private SkinData skinData;
public static final CapeProvider[] VALUES = Arrays.copyOfRange(values(), 1, 5);
private String url;
private CapeUrlType type;
public String getUrlFor(String type) {
return String.format(url, type);
public EventSkinData(SkinData skinData) {
this.skinData = skinData;
}
public String getUrlFor(UUID uuid, String username) {
return getUrlFor(toRequestedType(type, uuid, username));
public SkinData skinData() {
return skinData;
}
public static String toRequestedType(CapeUrlType type, UUID uuid, String username) {
return switch (type) {
case UUID -> uuid.toString().replace("-", "");
case UUID_DASHED -> uuid.toString();
default -> username;
};
public void skinData(SkinData skinData) {
this.skinData = skinData;
}
}
public enum CapeUrlType {
USERNAME,
UUID,
UUID_DASHED
}
}

View File

@ -7,5 +7,5 @@ org.gradle.vfs.watch=false
group=org.geysermc
id=geyser
version=2.2.3-SNAPSHOT
version=2.2.4-SNAPSHOT
description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers.

View File

@ -29,7 +29,7 @@ adapters = "1.11-SNAPSHOT"
commodore = "2.2"
bungeecord = "a7c6ede"
velocity = "3.1.1"
viaproxy = "3.2.0-SNAPSHOT"
viaproxy = "3.2.1"
fabric-minecraft = "1.20.4"
fabric-loader = "0.15.2"
fabric-api = "0.91.2+1.20.4"