@Override public PositionMessage decode(ChannelBuffer buffer) throws IOException { double x = buffer.readDouble(); double y = buffer.readDouble(); double stance = buffer.readDouble(); double z = buffer.readDouble(); boolean flying = buffer.readByte() == 1; return new PositionMessage(x, y, z, stance, flying); }
@Override public PlayerPositionLookMessage decode(ChannelBuffer buffer) throws IOException { double x = buffer.readDouble(); double y = buffer.readDouble(); double stance = buffer.readDouble(); double z = buffer.readDouble(); float yaw = buffer.readFloat(); float pitch = buffer.readFloat(); boolean onGround = buffer.readByte() == 1; return new PlayerPositionLookMessage(x, y, z, stance, yaw, pitch, onGround); }
/** * Read double from this packet buffer. * * @return double */ protected final double readDF() { try { return buf.readDouble(); } catch (Exception e) { log.error("Missing DF for: " + this); } return 0; }
/* (non-Javadoc) * @see name.martingeisse.stackd.server.StackdServer#onApplicationPacketReceived(name.martingeisse.stackd.server.StackdSession, name.martingeisse.stackd.common.netty.StackdPacket) */ @Override protected void onApplicationPacketReceived(MinerSession session, StackdPacket packet) { ChannelBuffer buffer = packet.getBuffer(); switch (packet.getType()) { case MinerPacketConstants.TYPE_C2S_UPDATE_POSITION: { session.setX(buffer.readDouble()); session.setY(buffer.readDouble()); session.setZ(buffer.readDouble()); session.setLeftAngle(buffer.readDouble()); session.setUpAngle(buffer.readDouble()); break; } case MinerPacketConstants.TYPE_C2S_RESUME_PLAYER: { byte[] tokenBytes = new byte[buffer.readInt()]; buffer.readBytes(tokenBytes); String token = new String(tokenBytes, StandardCharsets.UTF_8); String tokenSubject = SecurityTokenUtil.validateToken( token, new Instant(), MinerServerSecurityConstants.SECURITY_TOKEN_SECRET); long playerId = Long.parseLong(tokenSubject); try { final SQLQuery query = EntityConnectionManager.getConnection().createQuery(); query.from(QPlayer.player); query.where(QPlayer.player.id.eq(playerId)); Player player = query.singleResult(QPlayer.player); if (player == null) { throw new RuntimeException("player not found, id: " + playerId); } session.setPlayerId(player.getId()); session.setName(player.getName()); session.setX(player.getX().doubleValue()); session.setY(player.getY().doubleValue()); session.setZ(player.getZ().doubleValue()); session.setLeftAngle(player.getLeftAngle().doubleValue()); session.setUpAngle(player.getUpAngle().doubleValue()); session.sendCoinsUpdate(); } finally { EntityConnectionManager.disposeConnections(); } StackdPacket responsePacket = new StackdPacket(MinerPacketConstants.TYPE_S2C_PLAYER_RESUMED, 40); ChannelBuffer responseBuffer = responsePacket.getBuffer(); responseBuffer.writeDouble(session.getX()); responseBuffer.writeDouble(session.getY()); responseBuffer.writeDouble(session.getZ()); responseBuffer.writeDouble(session.getLeftAngle()); responseBuffer.writeDouble(session.getUpAngle()); broadcast(responsePacket); break; } case MinerPacketConstants.TYPE_C2S_DIG_NOTIFICATION: { // determine the cube being dug away int shiftBits = getSectionWorkingSet().getClusterSize().getShiftBits(); int x = buffer.readInt(), sectionX = (x >> shiftBits); int y = buffer.readInt(), sectionY = (y >> shiftBits); int z = buffer.readInt(), sectionZ = (z >> shiftBits); SectionId id = new SectionId(sectionX, sectionY, sectionZ); SectionCubesCacheEntry sectionDataCacheEntry = (SectionCubesCacheEntry) getSectionWorkingSet().get(new SectionDataId(id, SectionDataType.DEFINITIVE)); byte oldCubeType = sectionDataCacheEntry.getCubeAbsolute(x, y, z); // determine whether digging is successful boolean success; if (oldCubeType == 1 || oldCubeType == 5 || oldCubeType == 15) { success = true; } else { success = (new Random().nextInt(3) < 1); } if (!success) { // TODO enable god mode -- digging always succeeds // break; } // remove the cube and notify other clients sectionDataCacheEntry.setCubeAbsolute(x, y, z, (byte) 0); // TODO should not be necessary with auto-save sectionDataCacheEntry.save(); // notify listeners notifyClientsAboutModifiedSections(id); for (AxisAlignedDirection neighborDirection : getSectionWorkingSet().getClusterSize().getBorderDirections(x, y, z)) { notifyClientsAboutModifiedSections(id.getNeighbor(neighborDirection)); } // trigger special logic (e.g. add a unit of ore to the player's inventory) try { DigUtil.onCubeDugAway(session, x, y, z, oldCubeType); } finally { EntityConnectionManager.disposeConnections(); } break; } } }