Compare commits
12 Commits
g2/master
...
g2/feature
| Author | SHA1 | Date | |
|---|---|---|---|
|
b9400b110a
|
|||
|
c9f396a999
|
|||
|
980088b157
|
|||
|
045c9f1a04
|
|||
|
53e6d36ca4
|
|||
|
fa3c899120
|
|||
|
a3b5956cdd
|
|||
|
3dfff8c0f2
|
|||
|
c903554d7b
|
|||
|
da988b7172
|
|||
|
95b858d47c
|
|||
|
7494c3f92c
|
45
build.gradle
45
build.gradle
@@ -1,15 +1,36 @@
|
||||
apply plugin: 'java'
|
||||
subprojects {
|
||||
apply plugin: 'java'
|
||||
|
||||
project.group = projectGroup
|
||||
project.version = projectVersion
|
||||
project.group = projectGroup
|
||||
project.version = projectVersion
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
compileJava {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
ext {
|
||||
slf4j_version = '1.7.30'
|
||||
|
||||
library = [
|
||||
lombok: 'org.projectlombok:lombok:1.18.2',
|
||||
slf4j: ["org.slf4j:slf4j-api:$slf4j_version",
|
||||
"org.slf4j:jcl-over-slf4j:$slf4j_version"],
|
||||
]
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/* LOGGER */
|
||||
implementation library.slf4j
|
||||
|
||||
/* LOMBOK */
|
||||
annotationProcessor library.lombok
|
||||
compileOnly library.lombok
|
||||
}
|
||||
}
|
||||
|
||||
18
server-api/build.gradle
Normal file
18
server-api/build.gradle
Normal file
@@ -0,0 +1,18 @@
|
||||
ext {
|
||||
netty_version = '4.1.22.Final';
|
||||
|
||||
library = [
|
||||
rxjava: ['io.reactivex.rxjava3:rxjava:3.0.3'],
|
||||
netty: [
|
||||
"io.netty:netty-transport:$netty_version"
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/* COMPONENTS */
|
||||
compile project(':protocol')
|
||||
compile library.rxjava
|
||||
|
||||
implementation library.netty
|
||||
}
|
||||
6
server-api/src/main/java/mc/server/network/Server.java
Normal file
6
server-api/src/main/java/mc/server/network/Server.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package mc.server.network;
|
||||
|
||||
public interface Server {
|
||||
|
||||
void start(String host, int port);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package mc.server.reactive;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Data;
|
||||
import mc.protocol.Packet;
|
||||
|
||||
@Data
|
||||
public class NetworkContainer<T extends Packet> {
|
||||
|
||||
private final Channel channel;
|
||||
private final T packet;
|
||||
}
|
||||
28
server-api/src/main/java/mc/server/reactive/RxProvider.java
Normal file
28
server-api/src/main/java/mc/server/reactive/RxProvider.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package mc.server.reactive;
|
||||
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.core.Observer;
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject;
|
||||
import io.reactivex.rxjava3.subjects.Subject;
|
||||
import mc.protocol.Packet;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class RxProvider {
|
||||
|
||||
private final Map<Class, Subject> subjectMap = new HashMap<>();
|
||||
|
||||
public <T extends Packet> Observable<NetworkContainer<T>> getPacketObservable(Class<T> packetType) {
|
||||
return giveSubject(packetType);
|
||||
}
|
||||
|
||||
public Observer<NetworkContainer<? extends Packet>> getPacketObserver(Class<? extends Packet> packetType) {
|
||||
return giveSubject(packetType);
|
||||
}
|
||||
|
||||
private Subject giveSubject(Class<? extends Packet> packetType) {
|
||||
return subjectMap.computeIfAbsent(packetType, key -> PublishSubject.create());
|
||||
}
|
||||
}
|
||||
22
server/build.gradle
Normal file
22
server/build.gradle
Normal file
@@ -0,0 +1,22 @@
|
||||
ext {
|
||||
logback_version = '1.2.3'
|
||||
|
||||
library = [
|
||||
guice: ['com.google.inject:guice:4.1.0'],
|
||||
logger: ["ch.qos.logback:logback-core:$logback_version",
|
||||
"ch.qos.logback:logback-classic:$logback_version"],
|
||||
netty: ['io.netty:netty-all:4.1.22.Final'],
|
||||
commons: ['commons-io:commons-io:2.6']
|
||||
]
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/* LOGGER */
|
||||
implementation library.logger
|
||||
|
||||
/* COMPONENTS */
|
||||
implementation project(':server-api')
|
||||
implementation library.guice
|
||||
implementation library.netty
|
||||
implementation library.commons
|
||||
}
|
||||
16
server/src/main/java/mc/server/Main.java
Normal file
16
server/src/main/java/mc/server/Main.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package mc.server;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import mc.server.network.Server;
|
||||
import mc.server.network.config.NetworkModule;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
final Injector injector = Guice.createInjector(new NetworkModule());
|
||||
|
||||
final Server server = injector.getInstance(Server.class);
|
||||
server.start("127.0.0.1", 25565);
|
||||
}
|
||||
}
|
||||
39
server/src/main/java/mc/server/logic/HandshakeLogic.java
Normal file
39
server/src/main/java/mc/server/logic/HandshakeLogic.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package mc.server.logic;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.netty.channel.Channel;
|
||||
import io.reactivex.rxjava3.core.Scheduler;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.protocol.handshake.client.HandshakePacket;
|
||||
import mc.server.network.impl.NettyConstants;
|
||||
import mc.server.reactive.RxProvider;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||
public class HandshakeLogic {
|
||||
|
||||
private final RxProvider rxProvider;
|
||||
|
||||
public void setup() {
|
||||
log.info("HandshakeLogic setup");
|
||||
rxProvider.getPacketObservable(HandshakePacket.class)
|
||||
.observeOn(Schedulers.computation())
|
||||
.doOnNext(container -> handle(container.getChannel(), container.getPacket()))
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private void handle(Channel channel, HandshakePacket packet) {
|
||||
log.error("THREAD: {}|{}", Thread.currentThread().getId(), Thread.currentThread().getName());
|
||||
|
||||
log.info("HandshakePacket handle");
|
||||
channel.attr(NettyConstants.ATTR_STATE).set(packet.getNextState());
|
||||
|
||||
// try {
|
||||
// Thread.sleep(20_000);
|
||||
// } catch (InterruptedException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
}
|
||||
}
|
||||
41
server/src/main/java/mc/server/logic/LoginLogic.java
Normal file
41
server/src/main/java/mc/server/logic/LoginLogic.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package mc.server.logic;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.protocol.login.client.LoginStartPacket;
|
||||
import mc.protocol.login.server.DisconnectPacket;
|
||||
import mc.protocol.text.Text;
|
||||
import mc.protocol.text.TextColor;
|
||||
import mc.protocol.text.TextStyle;
|
||||
import mc.server.reactive.NetworkContainer;
|
||||
import mc.server.reactive.RxProvider;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||
public class LoginLogic {
|
||||
|
||||
private final RxProvider rxProvider;
|
||||
|
||||
public void setup() {
|
||||
log.info("LoginLogic setup");
|
||||
rxProvider.getPacketObservable(LoginStartPacket.class)
|
||||
.observeOn(Schedulers.computation())
|
||||
.map(NetworkContainer::getChannel)
|
||||
.doOnNext(channel -> {
|
||||
log.error("THREAD: {}|{}", Thread.currentThread().getId(), Thread.currentThread().getName());
|
||||
log.info("LoginLogic handle");
|
||||
|
||||
DisconnectPacket disconnectPacket = new DisconnectPacket();
|
||||
disconnectPacket.setReason(Text.builder()
|
||||
.append(Text.of(TextColor.WHITE, "Server is "))
|
||||
.color(TextColor.RED).style(TextStyle.BOLD).append("NOT ")
|
||||
.color(TextColor.WHITE).append("available.")
|
||||
.build());
|
||||
|
||||
channel.writeAndFlush(disconnectPacket).channel().disconnect();
|
||||
})
|
||||
.subscribe();
|
||||
}
|
||||
}
|
||||
75
server/src/main/java/mc/server/logic/StatusLogic.java
Normal file
75
server/src/main/java/mc/server/logic/StatusLogic.java
Normal file
@@ -0,0 +1,75 @@
|
||||
package mc.server.logic;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.netty.channel.Channel;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.protocol.ProtocolConstant;
|
||||
import mc.protocol.dto.ServerInfo;
|
||||
import mc.protocol.status.PingPacket;
|
||||
import mc.protocol.status.client.StatusServerRequest;
|
||||
import mc.protocol.status.server.StatusServerResponse;
|
||||
import mc.protocol.text.Text;
|
||||
import mc.server.reactive.RxProvider;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||
public class StatusLogic {
|
||||
|
||||
private static final String FAVICON_HEADER = "data:image/png;base64,";
|
||||
private final RxProvider rxProvider;
|
||||
|
||||
public void setup() {
|
||||
log.info("StatusLogic setup");
|
||||
rxProvider.getPacketObservable(StatusServerRequest.class)
|
||||
.observeOn(Schedulers.computation())
|
||||
.doOnNext(container -> status(container.getChannel(), container.getPacket()))
|
||||
.subscribe();
|
||||
|
||||
rxProvider.getPacketObservable(PingPacket.class)
|
||||
.observeOn(Schedulers.computation())
|
||||
.doOnNext(container -> {
|
||||
log.error("THREAD: {}|{}", Thread.currentThread().getId(), Thread.currentThread().getName());
|
||||
log.info("StatusLogic ping handle");
|
||||
container.getChannel().writeAndFlush(container.getPacket()).channel().disconnect();
|
||||
})
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private void status(Channel channel, StatusServerRequest packet) throws IOException {
|
||||
log.error("THREAD: {}|{}", Thread.currentThread().getId(), Thread.currentThread().getName());
|
||||
log.info("StatusLogic handle");
|
||||
log.info("{}", packet);
|
||||
|
||||
final ServerInfo.Version version = new ServerInfo.Version();
|
||||
version.setName(ProtocolConstant.PROTOCOL_VERSION_VALUE);
|
||||
version.setProtocol(ProtocolConstant.PROTOCOL_VERSION);
|
||||
|
||||
final ServerInfo.PlayersInfo playersInfo = new ServerInfo.PlayersInfo();
|
||||
playersInfo.setMax(20);
|
||||
playersInfo.setOnline(0);
|
||||
playersInfo.setSamplePlayers(Collections.emptyList());
|
||||
|
||||
final ServerInfo serverInfo = new ServerInfo();
|
||||
serverInfo.setVersion(version);
|
||||
serverInfo.setDescription(Text.of("MC-SERVER 1.8.8"));
|
||||
serverInfo.setFaviconBase64(getEmbeddedIconBase64());
|
||||
serverInfo.setPlayersInfo(playersInfo);
|
||||
|
||||
StatusServerResponse response = new StatusServerResponse();
|
||||
response.setServerInfoDto(serverInfo);
|
||||
|
||||
channel.writeAndFlush(response);
|
||||
}
|
||||
|
||||
private String getEmbeddedIconBase64() throws IOException {
|
||||
return FAVICON_HEADER + Base64.getEncoder()
|
||||
.encodeToString(IOUtils.toByteArray(getClass().getResourceAsStream("/icon.png")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package mc.server.network.config;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.name.Named;
|
||||
import com.google.inject.name.Names;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import mc.protocol.PacketDirection;
|
||||
import mc.protocol.io.coder.ProtocolDecoder;
|
||||
import mc.protocol.io.coder.ProtocolEncoder;
|
||||
import mc.protocol.io.coder.ProtocolSplitter;
|
||||
import mc.server.network.Server;
|
||||
import mc.server.network.impl.ChannelInitializer;
|
||||
import mc.server.network.impl.NettyServer;
|
||||
import mc.server.network.impl.codec.PacketDecoder;
|
||||
import mc.server.network.impl.codec.PacketEncoder;
|
||||
import mc.server.network.impl.codec.PacketSplitter;
|
||||
import mc.server.network.impl.handler.CommonPacketHandler;
|
||||
import mc.server.reactive.RxProvider;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class NetworkModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(Server.class).to(NettyServer.class).in(Singleton.class);
|
||||
bind(EventLoopGroup.class).annotatedWith(Names.named("bossGroup")).toInstance(new NioEventLoopGroup(1));
|
||||
bind(EventLoopGroup.class).annotatedWith(Names.named("workerGroup")).toInstance(new NioEventLoopGroup());
|
||||
bind(RxProvider.class).toInstance(new RxProvider());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ServerBootstrap serverBootstrap(@Named("bossGroup") EventLoopGroup bossGroup,
|
||||
@Named("workerGroup") EventLoopGroup workerGroup,
|
||||
ChannelInitializer channelChannelInitializer) {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||
|
||||
bootstrap.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(channelChannelInitializer);
|
||||
|
||||
return bootstrap;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("channelHandlerMap")
|
||||
Map<String, ChannelHandler> channelHandlerMap(CommonPacketHandler commonPacketHandler) {
|
||||
final Map<String, ChannelHandler> map = new LinkedHashMap<>();
|
||||
|
||||
map.put("logger", new LoggingHandler());
|
||||
map.put("packet_splitter", new PacketSplitter(new ProtocolSplitter()));
|
||||
map.put("packet_decoder", new PacketDecoder(new ProtocolDecoder(PacketDirection.SERVER_BOUND)));
|
||||
map.put("packet_encoder", new PacketEncoder(new ProtocolEncoder(PacketDirection.CLIENT_BOUND)));
|
||||
map.put("common_handler", commonPacketHandler);
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package mc.server.network.impl;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.name.Named;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Singleton
|
||||
public class ChannelInitializer extends io.netty.channel.ChannelInitializer<SocketChannel> {
|
||||
|
||||
private final Provider<Map<String, ChannelHandler>> channelHandlerMapProvider;
|
||||
|
||||
@Inject
|
||||
public ChannelInitializer(
|
||||
@Named("channelHandlerMap") Provider<Map<String, ChannelHandler>> channelHandlerMapProvider) {
|
||||
this.channelHandlerMapProvider = channelHandlerMapProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) {
|
||||
final ChannelPipeline pipeline = socketChannel.pipeline();
|
||||
channelHandlerMapProvider.get().forEach(pipeline::addLast);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package mc.server.network.impl;
|
||||
|
||||
import io.netty.util.AttributeKey;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import mc.protocol.State;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class NettyConstants {
|
||||
|
||||
public static final AttributeKey<State> ATTR_STATE = AttributeKey.newInstance("ATTR_STATE");
|
||||
}
|
||||
39
server/src/main/java/mc/server/network/impl/NettyServer.java
Normal file
39
server/src/main/java/mc/server/network/impl/NettyServer.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package mc.server.network.impl;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.server.logic.HandshakeLogic;
|
||||
import mc.server.logic.LoginLogic;
|
||||
import mc.server.logic.StatusLogic;
|
||||
import mc.server.network.Server;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||
public class NettyServer implements Server {
|
||||
|
||||
private final Provider<ServerBootstrap> serverBootstrapProvider;
|
||||
private final HandshakeLogic handshakeLogic;
|
||||
private final StatusLogic statusLogic;
|
||||
private final LoginLogic loginLogic;
|
||||
|
||||
@Override
|
||||
public void start(String host, int port) {
|
||||
handshakeLogic.setup();
|
||||
statusLogic.setup();
|
||||
loginLogic.setup();
|
||||
|
||||
try {
|
||||
log.info("Network starting: {}:{}", host, port);
|
||||
serverBootstrapProvider.get()
|
||||
.bind(host, port)
|
||||
.sync().channel().closeFuture().sync();
|
||||
} catch (InterruptedException e) {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("{}: {}", e.getClass().getSimpleName(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package mc.server.network.impl.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.Packet;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.io.coder.ProtocolDecoder;
|
||||
import mc.server.network.impl.io.ByteBufNetInputStream;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static mc.server.network.impl.NettyConstants.ATTR_STATE;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PacketDecoder extends ByteToMessageDecoder {
|
||||
|
||||
private final ProtocolDecoder protocolDecoder;
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
ctx.channel().attr(ATTR_STATE).set(State.HANDSHAKING);
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
ctx.channel().attr(ATTR_STATE).set(null);
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||
final State state = Objects.requireNonNull(ctx.channel().attr(ATTR_STATE).get());
|
||||
|
||||
final Packet packet = protocolDecoder.decode(state, new ByteBufNetInputStream(in));
|
||||
if (packet != null) {
|
||||
out.add(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package mc.server.network.impl.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.Packet;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.io.coder.ProtocolEncoder;
|
||||
import mc.server.network.impl.io.ByteBufNetOutputStream;
|
||||
|
||||
import static mc.server.network.impl.NettyConstants.ATTR_STATE;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PacketEncoder extends MessageToByteEncoder<Packet> {
|
||||
|
||||
private final ProtocolEncoder protocolEncoder;
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf out) {
|
||||
final State state = ctx.channel().attr(ATTR_STATE).get();
|
||||
protocolEncoder.encode(state, packet, new ByteBufNetOutputStream(out));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package mc.server.network.impl.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.io.NetInputStream;
|
||||
import mc.protocol.io.coder.ProtocolSplitter;
|
||||
import mc.server.network.impl.io.ByteBufNetInputStream;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PacketSplitter extends ByteToMessageDecoder {
|
||||
|
||||
private final ProtocolSplitter protocolSplitter;
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||
final NetInputStream netInputStream = protocolSplitter.split(new ByteBufNetInputStream(in));
|
||||
|
||||
if (netInputStream != null) {
|
||||
byte[] buff = new byte[netInputStream.readableBytes()];
|
||||
netInputStream.readBytes(buff);
|
||||
out.add(Unpooled.wrappedBuffer(buff));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package mc.server.network.impl.handler;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.Packet;
|
||||
import mc.server.reactive.NetworkContainer;
|
||||
import mc.server.reactive.RxProvider;
|
||||
|
||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||
public class CommonPacketHandler extends SimpleChannelInboundHandler<Packet> {
|
||||
|
||||
private final RxProvider rxProvider;
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, Packet packet) {
|
||||
rxProvider.getPacketObserver(packet.getClass())
|
||||
.onNext(new NetworkContainer<>(ctx.channel(), packet));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package mc.server.network.impl.io;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.io.NetInputStream;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ByteBufNetInputStream extends NetInputStream {
|
||||
|
||||
private final ByteBuf byteBuf;
|
||||
|
||||
@Override
|
||||
public void markReadIndex() {
|
||||
byteBuf.markReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetReadIndex() {
|
||||
byteBuf.resetReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readableBytes() {
|
||||
return byteBuf.readableBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() {
|
||||
return byteBuf.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readBytes(byte[] buffer, int offset, int lengtn) {
|
||||
return byteBuf.readBytes(buffer, offset, lengtn).readableBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readShort() {
|
||||
return byteBuf.readShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() {
|
||||
return byteBuf.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong() {
|
||||
return byteBuf.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float readFloat() {
|
||||
return byteBuf.readFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readDouble() {
|
||||
return byteBuf.readDouble();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package mc.server.network.impl.io;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.io.NetOutputStream;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ByteBufNetOutputStream extends NetOutputStream {
|
||||
|
||||
private final ByteBuf byteBuf;
|
||||
|
||||
@Override
|
||||
public void writeByte(int value) {
|
||||
byteBuf.writeByte(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(byte[] buffer, int offset, int lengtn) {
|
||||
byteBuf.writeBytes(buffer, offset, lengtn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeShort(int value) {
|
||||
byteBuf.writeShort(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeInt(int value) {
|
||||
byteBuf.writeInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLong(long value) {
|
||||
byteBuf.writeLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeFloat(float value) {
|
||||
byteBuf.writeFloat(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDouble(double value) {
|
||||
byteBuf.writeDouble(value);
|
||||
}
|
||||
}
|
||||
|
||||
BIN
server/src/main/resources/icon.png
Normal file
BIN
server/src/main/resources/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
@@ -1 +1,7 @@
|
||||
rootProject.name = projectName
|
||||
rootProject.name = projectName
|
||||
|
||||
include ':protocol'
|
||||
project(':protocol').projectDir = new File(settingsDir, '../mc-protocol')
|
||||
|
||||
include ':server-api'
|
||||
include ':server'
|
||||
@@ -1,8 +0,0 @@
|
||||
package mc.server;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("hello?");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user