Skip to content

WIP - New API #3243

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft

Conversation

Ingrim4
Copy link
Collaborator

@Ingrim4 Ingrim4 commented Sep 22, 2024

This PR initiates the development of a new API as outlined in #2996, aiming to improve the overall maintainability and flexibility of ProtocolLib. As this is the first draft, backward compatibility may be (temporarily) broken, and it will primarily serve to track progress and gather feedback on API design and concerns. The PR will remain a work-in-progress until all current features have been incorporated into the new API, with stability and structure refined for broader usage.

I encourage everyone to participate in shaping this new API. If you have suggestions, concerns, or alternative approaches, feel free to contribute your thoughts. Feedback on design decisions, modularity, or areas where backward compatibility might be preserved is especially welcome. This collaborative effort will help ensure the API meets the needs of both current and future developers. Please don’t hesitate to recommend changes or improvements as we refine the API together.

Register an async listener

protocolLib.createListener(plugin)
    .types(PacketTypes.Game.LEVEL_CHUNK)
    .priority(PacketListenerPriority.LOW)
    .registerAsync((packet, context) -> {
        Chunk chunk = Chunk.from(packet);
        
        // do processing here ...

        context.addTransmissionListener(chunk::markSent);
        context.resumeProcessing();
    });

Sending/Receiving packets

protocolLib.connection(player)
    .packetOperation()
    .skipProcessing()
    .postTransmission(chunk::markSent)
    .send(chunk.packet());

protocolLib.connection(player)
    .sendPacket(chunk.packet());

protocolLib.sendPacket(player, chunk.packet());
Some more API examples

public class Example {
private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool();
private static ProtocolLib protocolLib;
private static Plugin plugin;
// ========================
// Packet Listeners
// ========================
static void registerListeners() {
// sync read-only listener
protocolLib
.createListener(plugin)
.types(PacketTypes.Game.LEVEL_CHUNK)
.priority(PacketListenerPriority.LOW)
.includeCanceledPackets()
.bundleBehavior(PacketListenerBundleBehavior.SKIP_OUTSIDE_BUNDLE)
.registerSync((packet, context) -> {
Chunk chunk = Chunk.from(packet);
// Sync processing
});
// async modify packet on netty thread
protocolLib
.createListener(plugin)
.types(PacketTypes.Game.LEVEL_CHUNK)
.mutable()
.registerAsync((packet, context) -> {
Chunk chunk = Chunk.from(packet);
// do processing here ...
// write changes to packet ...
context.addTransmissionListener(chunk::markSent);
context.resumeProcessing();
});
// async modify packet on app thread-pool
protocolLib
.createListener(plugin)
.types(PacketTypes.Game.LEVEL_CHUNK)
.mutable()
.registerAsync((packet, context) -> {
Chunk chunk = Chunk.from(packet);
EXECUTOR.execute(() -> {
// do heavy processing here ...
// write changes to packet ...
context.addTransmissionListener(chunk::markSent);
context.resumeProcessing();
});
});
}
// ========================
// Packet Sending
// ========================
static void sendPackets(Player player, Chunk chunk) {
// full packet operation
protocolLib
.connection(player)
.packetOperation()
.skipProcessing()
.postTransmission(chunk::markSent)
.send(chunk.packet());
// connection shortcut
protocolLib
.connection(player)
.sendPacket(chunk.packet());
// direct API shortcut
protocolLib
.sendPacket(player, chunk.packet());
}
// ========================
// Chunk Implementation
// ========================
static class Chunk {
static Chunk from(PacketContainer packet) {
return new Chunk();
}
PacketContainer packet() { return null; }
void markSent() {}
}
}

@Ingrim4 Ingrim4 self-assigned this Sep 22, 2024
@Dymeth
Copy link

Dymeth commented Oct 21, 2024

At this stage everything looks easy to interact with.
I'd like to see the rest of the interfaces.

Separation of API and implementation is a change that has been needed for a long time, and I'm glad there is someone willing to take it on now.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants