diff --git a/src/main/java/com/projectswg/common/data/location/Location.java b/src/main/java/com/projectswg/common/data/location/Location.java index 0a21e8b..7b78454 100644 --- a/src/main/java/com/projectswg/common/data/location/Location.java +++ b/src/main/java/com/projectswg/common/data/location/Location.java @@ -310,6 +310,14 @@ public class Location implements Encodable, MongoPersistable { return point.getZ(); } + public Point3D getPosition() { + return point; + } + + public Quaternion getOrientation() { + return orientation; + } + public double getOrientationX() { return orientation.getX(); } diff --git a/src/main/java/com/projectswg/common/data/location/Quaternion.java b/src/main/java/com/projectswg/common/data/location/Quaternion.java index 6acef47..9c39da1 100644 --- a/src/main/java/com/projectswg/common/data/location/Quaternion.java +++ b/src/main/java/com/projectswg/common/data/location/Quaternion.java @@ -164,10 +164,18 @@ public class Quaternion implements Encodable, MongoPersistable { public void rotateDegrees(double degrees, double axisX, double axisY, double axisZ) { double rad = Math.toRadians(degrees) / 2; double sin = Math.sin(rad); - w = Math.cos(rad); - x = sin * axisX; - y = sin * axisY; - z = sin * axisZ; + double w = Math.cos(rad); + double x = sin * axisX; + double y = sin * axisY; + double z = sin * axisZ; + double nW = w * this.w - x * this.x - y * this.y - z * this.z; + double nX = w * this.x + x * this.w + y * this.z - z * this.y; + double nY = w * this.y + y * this.w + z * this.x - x * this.z; + double nZ = w * this.z + z * this.w + x * this.y - y * this.x; + this.w = nW; + this.x = nX; + this.y = nY; + this.z = nZ; normalize(); } diff --git a/src/main/java/com/projectswg/common/network/packets/PacketType.java b/src/main/java/com/projectswg/common/network/packets/PacketType.java index b829960..0db2bae 100644 --- a/src/main/java/com/projectswg/common/network/packets/PacketType.java +++ b/src/main/java/com/projectswg/common/network/packets/PacketType.java @@ -30,6 +30,7 @@ import com.projectswg.common.data.EnumLookup; import com.projectswg.common.network.packets.swg.holo.login.HoloLoginRequestPacket; import com.projectswg.common.network.packets.swg.holo.login.HoloLoginResponsePacket; import com.projectswg.common.network.packets.swg.zone.*; +import com.projectswg.common.network.packets.swg.zone.space.ShipUpdateTransformMessage; import com.projectswg.common.network.packets.swg.zone.structures.EnterStructurePlacementModeMessage; import me.joshlarson.jlcommon.log.Log; import com.projectswg.common.network.packets.swg.ErrorMessage; @@ -307,6 +308,9 @@ public enum PacketType { NEW_TICKET_ACTIVITY_RESPONSE_MESSAGE (NewTicketActivityResponseMessage.CRC, NewTicketActivityResponseMessage.class), ATTRIBUTE_LIST_MESSAGE (AttributeListMessage.CRC, AttributeListMessage.class), OPENED_CONTAINER_MESSAGE (ClientOpenContainerMessage.CRC, ClientOpenContainerMessage.class), + + // Space + SHIP_UPDATE_TRANSFORM_MESSAGE (ShipUpdateTransformMessage.CRC, ShipUpdateTransformMessage.class), // Combat UPDATE_PVP_STATUS_MESSAGE (UpdatePvpStatusMessage.CRC, UpdatePvpStatusMessage.class), diff --git a/src/main/java/com/projectswg/common/network/packets/swg/zone/space/ShipUpdateTransformMessage.java b/src/main/java/com/projectswg/common/network/packets/swg/zone/space/ShipUpdateTransformMessage.java new file mode 100644 index 0000000..621085a --- /dev/null +++ b/src/main/java/com/projectswg/common/network/packets/swg/zone/space/ShipUpdateTransformMessage.java @@ -0,0 +1,164 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of PSWGCommon. * + * * + * --------------------------------------------------------------------------------* + * * + * PSWGCommon is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * PSWGCommon is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with PSWGCommon. If not, see . * + ***********************************************************************************/ +package com.projectswg.common.network.packets.swg.zone.space; + +import com.projectswg.common.data.location.Location; +import com.projectswg.common.data.location.Point3D; +import com.projectswg.common.network.NetBuffer; +import com.projectswg.common.network.packets.SWGPacket; +import org.jetbrains.annotations.NotNull; + +public class ShipUpdateTransformMessage extends SWGPacket { + public static final int CRC = getCrc("ShipUpdateTransformMessage"); + + private short shipId; + private Location l; + private Point3D velocity; + private float yawRate; + private float pitchRate; + private float rollRate; + private int syncStamp; + + public ShipUpdateTransformMessage(short shipId, Location l, Point3D velocity, float yawRate, float pitchRate, float rollRate, int syncStamp) { + this.shipId = shipId; + this.l = l; + this.velocity = velocity; + this.yawRate = yawRate; + this.pitchRate = pitchRate; + this.rollRate = rollRate; + this.syncStamp = syncStamp; + } + + public ShipUpdateTransformMessage() { + this((short) 0, Location.builder().build(), new Point3D(), 0.0f, 0.0f, 0.0f, 0); + } + + public void decode(@NotNull NetBuffer data) { + if (!super.checkDecode(data, CRC)) + return; + this.shipId = data.getShort(); + Location.LocationBuilder location = Location.builder(); + location.setOrientationW(data.getByte()); + location.setOrientationX(data.getByte()); + location.setOrientationY(data.getByte()); + location.setOrientationZ(data.getByte()); + location.getOrientation().normalize(); + { + final float MULTIPLIER = 8000 / 32767f; + location.setX(data.getShort() * MULTIPLIER); + location.setY(data.getShort() * MULTIPLIER); + location.setZ(data.getShort() * MULTIPLIER); + } + this.l = location.build(); + decodePackedVelocity(data); + { + final float MULTIPLIER = 3.1415926535f / 254; + yawRate = data.getByte() * MULTIPLIER; + pitchRate = data.getByte() * MULTIPLIER; + rollRate = data.getByte() * MULTIPLIER; + } + syncStamp = data.getInt(); + } + + public NetBuffer encode() { + NetBuffer data = NetBuffer.allocate(64); + data.addShort(7); + data.addInt(CRC); + data.addShort(shipId); + data.addByte((byte) (l.getOrientationW() * 127)); + data.addByte((byte) (l.getOrientationX() * 127)); + data.addByte((byte) (l.getOrientationY() * 127)); + data.addByte((byte) (l.getOrientationZ() * 127)); + data.addShort((short) (l.getX() * 32767 / 8000)); + data.addShort((short) (l.getY() * 32767 / 8000)); + data.addShort((short) (l.getZ() * 32767 / 8000)); + encodePackedVelocity(data); + float ROT_RATE_MULTIPLIER = 254 / 3.1415926535f; + data.addByte(((int) (yawRate * ROT_RATE_MULTIPLIER)) & 0xFF); + data.addByte(((int) (pitchRate * ROT_RATE_MULTIPLIER)) & 0xFF); + data.addByte(((int) (rollRate * ROT_RATE_MULTIPLIER)) & 0xFF); + data.addInt(syncStamp); + return data; + } + + public void setShipId(short shipId) { this.shipId = shipId; } + public void setLocation(Location l) { this.l = l; } + public void setVelocity(Point3D velocity) { this.velocity = velocity; } + public void setYawRate(float yawRate) { this.yawRate = yawRate; } + public void setPitchRate(float pitchRate) { this.pitchRate = pitchRate; } + public void setRollRate(float rollRate) { this.rollRate = rollRate; } + public void setSyncStamp(int syncStamp) { this.syncStamp = syncStamp; } + + public short getShipId() { return shipId; } + public Location getLocation() { return l; } + public Point3D getVelocity() { return velocity; } + public float getYawRate() { return yawRate; } + public float getPitchRate() { return pitchRate; } + public float getRollRate() { return rollRate; } + public int getSyncStamp() { return syncStamp; } + + @Override + protected String getPacketData() { + return createPacketInformation( + "shipId", shipId, + "location", l, + "velocity", velocity, + "yawRate", yawRate, + "pitchRate", pitchRate, + "rollRate", rollRate, + "syncStamp", syncStamp + ); + } + + // *sigh* why SOE -- was 4 fewer bytes really worth so many bitwise operations? + private void decodePackedVelocity(@NotNull NetBuffer buffer) { + final double speed = (buffer.getShort() & 0xFFFF) * 512 / 32767f; + final int directionPacked = buffer.getShort() & 0xFFFF; + double x = ((directionPacked >> 6) & 0x3F) * (((directionPacked & 0x8000) != 0) ? -1 : 1); + double y = (directionPacked & 0x3F) * (((directionPacked & 0x4000) != 0) ? -1 : 1); + double z = (0x3F - x - y) * (((directionPacked & 0x2000) != 0) ? -1 : 1); + double mag = Math.sqrt(x*x + y*y + z*z); + velocity = new Point3D(x * speed / mag, y * speed / mag, z * speed / mag); + } + + private void encodePackedVelocity(@NotNull NetBuffer buffer) { + final double speed = Math.sqrt(velocity.getX()*velocity.getX() + velocity.getY()*velocity.getY() + velocity.getZ()*velocity.getZ()); + buffer.addShort((short) (speed * 32767 / 512)); + int directionPacked = 0; + if (velocity.getX() < 0) + directionPacked |= 0x8000; + if (velocity.getY() < 0) + directionPacked |= 0x4000; + if (velocity.getZ() < 0) + directionPacked |= 0x2000; + double magic = ((double) 0x3E) / (velocity.getX() + velocity.getY() + velocity.getZ()); + directionPacked |= (((int) (velocity.getX() * magic)) & 0x3F) << 6; + directionPacked |= ((int) (velocity.getY() * magic)) & 0x3F; + buffer.addShort(directionPacked); + } + +} diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 3277a1e..cdb97b9 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -69,6 +69,7 @@ module com.projectswg.common { exports com.projectswg.common.network.packets.swg.zone.object_controller.quest; exports com.projectswg.common.network.packets.swg.zone.resource; exports com.projectswg.common.network.packets.swg.zone.server_ui; + exports com.projectswg.common.network.packets.swg.zone.space; exports com.projectswg.common.network.packets.swg.zone.spatial; exports com.projectswg.common.network.packets.swg.zone.structures; exports com.projectswg.common.network.packets.swg.zone.trade;