package net.glowstone.net.handler.play.game;
import com.flowpowered.networking.MessageHandler;
import com.flowpowered.networking.util.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.glowstone.GlowServer;
import net.glowstone.net.GlowBufUtils;
import net.glowstone.net.GlowSession;
import net.glowstone.net.message.play.game.PluginMessage;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
public final class PluginMessageHandler implements MessageHandler<GlowSession, PluginMessage> {
@Override
public void handle(GlowSession session, PluginMessage message) {
final String channel = message.getChannel();
// register and unregister: NUL-separated list of channels
if (channel.equals("REGISTER")) {
for (String regChannel : string(message.getData()).split("\0")) {
GlowServer.logger.info(session + " registered channel: " + regChannel);
session.getPlayer().addChannel(regChannel);
}
} else if (channel.equals("UNREGISTER")) {
for (String regChannel : string(message.getData()).split("\0")) {
GlowServer.logger.info(session + " unregistered channel: " + regChannel);
session.getPlayer().removeChannel(regChannel);
}
} else if (channel.startsWith("MC|")) {
// internal Minecraft channels
handleInternal(session, channel, message.getData());
} else {
session.getServer().getMessenger().dispatchIncomingMessage(session.getPlayer(), channel, message.getData());
}
}
private void handleInternal(GlowSession session, String channel, byte[] data) {
/*
MC|Brand
entire data: string of client's brand (e.g. "vanilla")
MC|BEdit
item stack: new book item (should be verified)
MC|BSign
item stack: new book item (should be verified)
MC|TrSel
int: villager trade to select
MC|AdvCdm
byte: mode
if 0:
int x, int y, int z (command block in world)
if 1:
int entity (command block minecart)
string: command to set
MC|Beacon
two ints, presumably the selected enchants
MC|ItemName
entire data: name to apply to item in anvil
*/
ByteBuf buf = Unpooled.wrappedBuffer(data);
switch (channel) {
case "MC|Brand": {
// vanilla server doesn't handle this, for now just log it
String brand = null;
try {
brand = ByteBufUtils.readUTF8(buf);
} catch (IOException e) {
GlowServer.logger.log(Level.WARNING, "Error reading client brand of " + session, e);
}
if (brand != null && !brand.equals("vanilla")) {
GlowServer.logger.info("Client brand of " + session.getPlayer().getName() + " is: " + brand);
}
break;
}
case "MC|BEdit": {
// read and verify stack
ItemStack item = GlowBufUtils.readSlot(buf);
//GlowServer.logger.info("BookEdit [" + session.getPlayer().getName() + "]: " + item);
if (item == null || item.getType() != Material.BOOK_AND_QUILL) {
return;
}
ItemMeta meta = item.getItemMeta();
if (!(meta instanceof BookMeta)) {
return;
}
BookMeta book = (BookMeta) meta;
if (!book.hasPages()) {
return;
}
// verify item in hand
ItemStack inHand = session.getPlayer().getItemInHand();
if (inHand == null || inHand.getType() != Material.BOOK_AND_QUILL) {
return;
}
ItemMeta handMeta = inHand.getItemMeta();
if (!(handMeta instanceof BookMeta)) {
return;
}
BookMeta handBook = (BookMeta) handMeta;
// apply pages to book
handBook.setPages(book.getPages());
inHand.setItemMeta(handBook);
session.getPlayer().setItemInHand(inHand);
break;
}
case "MC|BSign": {
// read and verify stack
ItemStack item = GlowBufUtils.readSlot(buf);
//GlowServer.logger.info("BookSign [" + session.getPlayer().getName() + "]: " + item);
if (item == null || item.getType() != Material.WRITTEN_BOOK) {
return;
}
ItemMeta meta = item.getItemMeta();
if (!(meta instanceof BookMeta)) {
return;
}
BookMeta book = (BookMeta) meta;
if (!book.hasPages() || !book.hasTitle()) {
return;
}
// verify item in hand
ItemStack inHand = session.getPlayer().getItemInHand();
if (inHand == null || inHand.getType() != Material.BOOK_AND_QUILL) {
return;
}
ItemMeta handMeta = inHand.getItemMeta();
if (!(handMeta instanceof BookMeta)) {
return;
}
BookMeta handBook = (BookMeta) handMeta;
// apply pages, title, and author to book
handBook.setAuthor(session.getPlayer().getName());
handBook.setTitle(book.getTitle());
handBook.setPages(book.getPages());
inHand.setType(Material.WRITTEN_BOOK);
inHand.setItemMeta(handBook);
session.getPlayer().setItemInHand(inHand);
break;
}
default:
GlowServer.logger.info(session + " used unknown Minecraft channel: " + channel);
break;
}
if (buf.refCnt() > 0) {
buf.release(buf.refCnt());
}
}
private String string(byte[] data) {
return new String(data, StandardCharsets.UTF_8);
}
}