Skip to content

Commit

Permalink
Qfapi fixes (#359)
Browse files Browse the repository at this point in the history
* Update villager constructors to support rebalanced types

* Update library/entity/entity_extensions/src/main/java/org/quiltmc/qsl/entity/extensions/impl/TradeOfferInternals.java

* Switch licenser plugin. (#354)

* 1.20.2 Version 2

* Fix some licenses and formatting

* Fix networking issues with Fabric Server/Client

* Update library/core/networking/src/main/java/org/quiltmc/qsl/networking/impl/common/CommonPacketsImpl.java

Co-authored-by: ix0rai <ix0rai64@gmail.com>

---------

Co-authored-by: glitch <glitch.g3431@gmail.com>
Co-authored-by: LambdAurora <email@lambdaurora.dev>
Co-authored-by: ix0rai <ix0rai64@gmail.com>
  • Loading branch information
4 people authored Jan 17, 2024
1 parent aeba8b7 commit 681c7e8
Show file tree
Hide file tree
Showing 89 changed files with 1,317 additions and 520 deletions.
16 changes: 14 additions & 2 deletions build-logic/src/main/groovy/qsl.module.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import qsl.internal.Git
import qsl.internal.Versions
import qsl.internal.extension.QslLibraryExtension
import qsl.internal.extension.QslModuleExtension
import qsl.internal.extension.QslModuleExtensionImpl

Expand Down Expand Up @@ -104,6 +103,11 @@ sourceSets {
compileClasspath += sourceSets.main.compileClasspath
runtimeClasspath += sourceSets.main.runtimeClasspath
}

test {
compileClasspath += sourceSets.testmod.compileClasspath
runtimeClasspath += sourceSets.testmod.runtimeClasspath
}
}

processTestmodResources {
Expand All @@ -126,6 +130,14 @@ processTestmodResources {
dependencies {
// testmod sourceSet should depend on everything in the main source set.
testmodImplementation sourceSets.main.output

testImplementation "org.quiltmc:quilt-loader-junit:${Versions.LOADER_VERSION}"
testImplementation sourceSets.testmod.output
testImplementation 'org.mockito:mockito-core:5.4.0'
}

test {
useJUnitPlatform()
}

loom {
Expand Down Expand Up @@ -174,7 +186,7 @@ javadoc {
"https://asm.ow2.io/javadoc/",
"https://docs.oracle.com/en/java/javase/17/docs/api/",
"https://jenkins.liteloader.com/job/Mixin/javadoc/",
"https://logging.apache.org/log4j/2.x/log4j-api/apidocs/"
"https://logging.apache.org/log4j/2.x/javadoc/log4j-api/"
)

// Disable the overzealous doclint tool in Java 8
Expand Down
6 changes: 3 additions & 3 deletions build-logic/src/main/java/qsl/internal/Versions.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public final class Versions {
/**
* The QSL version
*/
public static final String QSL_VERSION = "7.0.0-alpha.1";
public static final String QSL_VERSION = "7.0.0-alpha.8";

/**
* The target Minecraft version.
Expand All @@ -38,12 +38,12 @@ public final class Versions {
/**
* The target Quilt Mappings build.
*/
public static final int MAPPINGS_BUILD = 2;
public static final int MAPPINGS_BUILD = 3;

/**
* The version of Quilt Loader to use.
*/
public static final String LOADER_VERSION = "0.20.2";
public static final String LOADER_VERSION = "0.23.0";

/**
* The target Java version.
Expand Down
9 changes: 8 additions & 1 deletion library/core/networking/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@ qslModule {
}
entrypoints {
init {
values = ["org.quiltmc.qsl.networking.impl.NetworkingImpl::init"]
values = [
"org.quiltmc.qsl.networking.impl.NetworkingImpl::init",
"org.quiltmc.qsl.networking.impl.common.CommonPacketsImpl::init"
]
}
client_init {
values = ["org.quiltmc.qsl.networking.impl.client.ClientNetworkingImpl::clientInit"]
}
}

injectedInterface("net/minecraft/class_8610") {
values = ["org/quiltmc/qsl/networking/api/ServerConfigurationTaskManager"]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
/**
* Offers access to events related to the connection to a client on a logical server while a client is in game.
*/
// TODO: Double check these events with fabric. Also make sure that the add tasks event is invoked or fold it into the ready event.
public final class ServerConfigurationConnectionEvents {
/**
* Event indicating a connection entered the CONFIGURATION state, ready for registering channel handlers.
Expand Down Expand Up @@ -61,6 +62,16 @@ public final class ServerConfigurationConnectionEvents {
}
});

/**
* An event for adding tasks to a server configuration network handler.
* Called once per connection when the optional tasks are also added.
*/
public static final Event<AddTasks> ADD_TASKS = Event.create(AddTasks.class, callbacks -> (handler, server) -> {
for (AddTasks callback : callbacks) {
callback.onAddTasks(handler, server);
}
});

private ServerConfigurationConnectionEvents() {
}

Expand All @@ -87,4 +98,12 @@ public interface Join extends EventAwareListener {
public interface Disconnect extends EventAwareListener {
void onConfigurationDisconnect(ServerConfigurationPacketHandler handler, MinecraftServer server);
}

/**
* @see #ADD_TASKS
*/
@FunctionalInterface
public interface AddTasks extends EventAwareListener {
void onAddTasks(ServerConfigurationPacketHandler handler, MinecraftServer server);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2024 The Quilt Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.quiltmc.qsl.networking.api;

import org.jetbrains.annotations.Nullable;

import net.minecraft.network.ServerConfigurationPacketHandler;
import net.minecraft.network.configuration.ConfigurationTask;

import org.quiltmc.qsl.base.api.util.InjectedInterface;

/**
* An injected interface for {@link net.minecraft.network.ServerConfigurationPacketHandler} that exposes the task system.
*/
@InjectedInterface(ServerConfigurationPacketHandler.class)
public interface ServerConfigurationTaskManager {
/**
* Adds a task to the handler that must complete before joining.
*
* @param task the task to add
*/
void addTask(ConfigurationTask task);

/**
* Finishes the task of the specified type. Will throw an error if a different or no task is running.
*
* @param type the type to finish
*/
void finishTask(ConfigurationTask.Type type);

/**
* Gets the currently running task for the configuration handler.
*
* @return the current task
*/
@Nullable ConfigurationTask getCurrentTask();
}
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ public interface CustomChannelReceiver<T extends CustomPayload> {

/**
* This functional interface should only be used when sending a raw {@link PacketByteBuf} is necessary.
*
* @deprecated use {@link CustomChannelReceiver}
*/
@Deprecated
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright 2016, 2017, 2018, 2019 FabricMC
* Copyright 2022 The Quilt Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -35,6 +36,8 @@
import net.minecraft.util.Identifier;

import org.quiltmc.qsl.networking.api.PacketSender;
import org.quiltmc.qsl.networking.impl.common.CommonPacketHandler;
import org.quiltmc.qsl.networking.impl.common.CommonRegisterPayload;
import org.quiltmc.qsl.networking.impl.payload.ChannelPayload;

/**
Expand All @@ -43,7 +46,7 @@
* @param <H> the channel handler type
*/
@ApiStatus.Internal
public abstract class AbstractChanneledNetworkAddon<H> extends AbstractNetworkAddon<H> implements PacketSender<CustomPayload> {
public abstract class AbstractChanneledNetworkAddon<H> extends AbstractNetworkAddon<H> implements PacketSender<CustomPayload>, CommonPacketHandler {
protected final ClientConnection connection;
protected final GlobalReceiverRegistry<H> receiver;
protected final Set<Identifier> sendableChannels;
Expand Down Expand Up @@ -157,4 +160,65 @@ public void sendPacket(Packet<?> packet, PacketSendListener callback) {
public Set<Identifier> getSendableChannels() {
return Collections.unmodifiableSet(this.sendableChannels);
}

/* Common Packet Handling */
protected int commonVersion = -1;

@Override
public void onCommonVersionPacket(int negotiatedVersion) {
assert negotiatedVersion == 1; // We only support version 1 for now

this.commonVersion = negotiatedVersion;
this.logger.debug("Negotiated common packet version {}", this.commonVersion);
}

@Override
public void onCommonRegisterPacket(CommonRegisterPayload payload) {
if (payload.version() != this.getNegotiatedVersion()) {
throw new IllegalStateException("Negotiated common packet version: %d but received packet with version: %d".formatted(this.commonVersion, payload.version()));
}

final String currentPhase = this.getPhase();

if (currentPhase == null) {
// We don't support receiving the register packet during this phase. See getPhase() for supported phases.
// The normal case where the play channels are sent during configuration is handled in the client/common configuration packet handlers.
logger.warn("Received common register packet for phase {} in network state: {}", payload.phase(), this.receiver.getState());
return;
}

if (!payload.phase().equals(currentPhase)) {
// We need to handle receiving the play phase during configuration!
throw new IllegalStateException("Register packet received for phase (%s) on handler for phase(%s)".formatted(payload.phase(), currentPhase));
}

this.register(new ArrayList<>(payload.channels()));
}

@Override
public CommonRegisterPayload createRegisterPayload() {
return new CommonRegisterPayload(this.getNegotiatedVersion(), this.getPhase(), this.getReceivableChannels());
}

@Override
public int getNegotiatedVersion() {
if (this.commonVersion == -1) {
throw new IllegalStateException("Not yet negotiated common packet version");
}

return this.commonVersion;
}

@Nullable
private String getPhase() {
return switch (this.receiver.getState()) {
case PLAY -> CommonRegisterPayload.PLAY_PHASE;
case CONFIGURATION -> CommonRegisterPayload.CONFIGURATION_PHASE;
default -> null; // We don't support receiving this packet on any other phase
};
}

public ChannelInfoHolder getChannelInfoHolder() {
return ((ChannelInfoHolder) this.connection);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright 2016, 2017, 2018, 2019 FabricMC
* Copyright 2022 The Quilt Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -41,7 +42,9 @@

import org.quiltmc.loader.api.ModContainer;
import org.quiltmc.loader.api.minecraft.ClientOnly;
import org.quiltmc.qsl.networking.api.CustomPayloads;
import org.quiltmc.qsl.networking.api.PacketByteBufs;
import org.quiltmc.qsl.networking.api.PacketSender;
import org.quiltmc.qsl.networking.api.client.ClientConfigurationConnectionEvents;
import org.quiltmc.qsl.networking.api.client.ClientConfigurationNetworking;
import org.quiltmc.qsl.networking.api.client.ClientLoginNetworking;
Expand All @@ -51,6 +54,9 @@
import org.quiltmc.qsl.networking.impl.GlobalReceiverRegistry;
import org.quiltmc.qsl.networking.impl.NetworkHandlerExtensions;
import org.quiltmc.qsl.networking.impl.NetworkingImpl;
import org.quiltmc.qsl.networking.impl.common.CommonPacketsImpl;
import org.quiltmc.qsl.networking.impl.common.CommonRegisterPayload;
import org.quiltmc.qsl.networking.impl.common.CommonVersionPayload;
import org.quiltmc.qsl.networking.impl.payload.PacketByteBufPayload;
import org.quiltmc.qsl.networking.mixin.accessor.ClientLoginNetworkHandlerAccessor;
import org.quiltmc.qsl.networking.mixin.accessor.ConnectScreenAccessor;
Expand Down Expand Up @@ -148,6 +154,34 @@ public static void clientInit(ModContainer mod) {
// Register a login query handler for early channel registration.
ClientLoginNetworking.registerGlobalReceiver(NetworkingImpl.EARLY_REGISTRATION_CHANNEL, ClientNetworkingImpl::receiveEarlyRegistration);
ClientLoginNetworking.registerGlobalReceiver(NetworkingImpl.EARLY_REGISTRATION_CHANNEL_FABRIC, ClientNetworkingImpl::receiveEarlyRegistration);

CustomPayloads.registerS2CPayload(CommonVersionPayload.PACKET_ID, CommonVersionPayload::new);
CustomPayloads.registerS2CPayload(CommonRegisterPayload.PACKET_ID, CommonRegisterPayload::new);

ClientConfigurationNetworking.registerGlobalReceiver(CommonVersionPayload.PACKET_ID, ClientNetworkingImpl::handleCommonVersion);
ClientConfigurationNetworking.registerGlobalReceiver(CommonRegisterPayload.PACKET_ID, ClientNetworkingImpl::handleCommonRegister);
}

private static void handleCommonVersion(MinecraftClient client, ClientConfigurationNetworkHandler handler, CommonVersionPayload payload, PacketSender<CustomPayload> sender) {
int negotiatedVersion = handleVersionPacket(payload, sender);
ClientNetworkingImpl.getAddon(handler).onCommonVersionPacket(negotiatedVersion);
}

private static void handleCommonRegister(MinecraftClient client, ClientConfigurationNetworkHandler handler, CommonRegisterPayload payload, PacketSender<CustomPayload> sender) {
ClientConfigurationNetworkAddon addon = ClientNetworkingImpl.getAddon(handler);

if (CommonRegisterPayload.PLAY_PHASE.equals(payload.phase())) {
if (payload.version() != addon.getNegotiatedVersion()) {
throw new IllegalStateException("Negotiated common packet version: %d but received packet with version: %d".formatted(addon.getNegotiatedVersion(), payload.version()));
}

addon.getChannelInfoHolder().getPendingChannelsNames(NetworkState.PLAY).addAll(payload.channels());
NetworkingImpl.LOGGER.debug("Received accepted channels from the server");
sender.sendPayload(new CommonRegisterPayload(addon.getNegotiatedVersion(), CommonRegisterPayload.PLAY_PHASE, ClientPlayNetworking.getGlobalReceivers()));
} else {
addon.onCommonRegisterPacket(payload);
sender.sendPayload(addon.createRegisterPayload());
}
}

private static CompletableFuture<PacketByteBuf> receiveEarlyRegistration(
Expand All @@ -174,5 +208,19 @@ private static CompletableFuture<PacketByteBuf> receiveEarlyRegistration(
NetworkingImpl.LOGGER.debug("Sent accepted channels to the server");
return CompletableFuture.completedFuture(response);
}

// Disconnect if there are no commonly supported versions.
// Client responds with the intersection of supported versions.
// Return the highest supported version
private static int handleVersionPacket(CommonVersionPayload payload, PacketSender<CustomPayload> packetSender) {
int version = CommonPacketsImpl.getHighestCommonVersion(payload.versions(), CommonPacketsImpl.SUPPORTED_COMMON_PACKET_VERSIONS);

if (version <= 0) {
throw new UnsupportedOperationException("Client does not support any requested versions from server");
}

packetSender.sendPayload(new CommonVersionPayload(new int[]{version}));
return version;
}
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright 2023 The Quilt Project
* Copyright 2016, 2017, 2018, 2019 FabricMC
* Copyright 2024 The Quilt Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,11 +15,14 @@
* limitations under the License.
*/

package org.quiltmc.qsl.registry.impl.sync.server;
package org.quiltmc.qsl.networking.impl.common;

public interface SyncTaskHolder {
QuiltSyncTask qsl$getQuiltSyncTask();
void qsl$finishQuiltSyncTask();
public interface CommonPacketHandler {
void onCommonVersionPacket(int negotiatedVersion);

void qsl$finishFabricSyncTask();
void onCommonRegisterPacket(CommonRegisterPayload payload);

CommonRegisterPayload createRegisterPayload();

int getNegotiatedVersion();
}
Loading

0 comments on commit 681c7e8

Please sign in to comment.