From 820a7462ea490fb1aa59c019d1b6ca5440631bc2 Mon Sep 17 00:00:00 2001 From: Eduardo Alonso Date: Tue, 1 Jan 2019 20:16:30 +0100 Subject: [PATCH] Add some of habbo's data structures Co-authored-by: ArachisH Co-authored-by: Speaqer Signed-off-by: Eduardo Alonso --- .../gearth/extensions/parsers/HAction.java | 9 + .../gearth/extensions/parsers/HDirection.java | 12 ++ .../gearth/extensions/parsers/HEntity.java | 122 +++++++++++++ .../extensions/parsers/HEntityUpdate.java | 107 ++++++++++++ .../gearth/extensions/parsers/HFloorItem.java | 164 ++++++++++++++++++ .../gearth/extensions/parsers/HGender.java | 17 ++ .../gearth/extensions/parsers/HGroup.java | 59 +++++++ .../gearth/extensions/parsers/HPoint.java | 37 ++++ .../java/gearth/extensions/parsers/HSign.java | 23 +++ .../gearth/extensions/parsers/HStance.java | 7 + .../gearth/extensions/parsers/HWallItem.java | 80 +++++++++ .../gearth/extensions/parsers/IFurni.java | 9 + .../extensions/parsers/UserProfile.java | 95 ++++++++++ 13 files changed, 741 insertions(+) create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HAction.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HDirection.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HEntity.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HEntityUpdate.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HFloorItem.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HGender.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HGroup.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HPoint.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HSign.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HStance.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/HWallItem.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/IFurni.java create mode 100644 G-Earth/src/main/java/gearth/extensions/parsers/UserProfile.java diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HAction.java b/G-Earth/src/main/java/gearth/extensions/parsers/HAction.java new file mode 100644 index 0000000..829afd0 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HAction.java @@ -0,0 +1,9 @@ +package gearth.extensions.parsers; + +public enum HAction { + None, + Move, + Sit, + Lay, + Sign +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HDirection.java b/G-Earth/src/main/java/gearth/extensions/parsers/HDirection.java new file mode 100644 index 0000000..d4b7bec --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HDirection.java @@ -0,0 +1,12 @@ +package gearth.extensions.parsers; + +public enum HDirection { + North, + NorthEast, + East, + SouthEast, + South, + SouthWest, + West, + NorthWest +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HEntity.java b/G-Earth/src/main/java/gearth/extensions/parsers/HEntity.java new file mode 100644 index 0000000..adbee01 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HEntity.java @@ -0,0 +1,122 @@ +package gearth.extensions.parsers; + +import gearth.protocol.HPacket; + +public class HEntity { + private int id; + private int index; + private HPoint tile; + private String name; + private String motto; + private HGender gender; + private int entityType; + private String figureId; + private String favoriteGroup; + private HEntityUpdate lastUpdate; + + public HEntity(HPacket packet) { + id = packet.readInteger(); + name = packet.readString(); + motto = packet.readString(); + figureId = packet.readString(); + index = packet.readInteger(); + tile = new HPoint(packet.readInteger(), packet.readInteger(), + Double.parseDouble(packet.readString())); + + packet.readInteger(); + entityType = packet.readInteger(); + + switch (entityType) { + case 1: + gender = HGender.valueOf(packet.readString()); + packet.readInteger(); + packet.readInteger(); + favoriteGroup = packet.readString(); + packet.readString(); + packet.readInteger(); + packet.readBoolean(); + break; + case 2: + packet.readInteger(); + packet.readInteger(); + packet.readString(); + packet.readInteger(); + packet.readBoolean(); + packet.readBoolean(); + packet.readBoolean(); + packet.readBoolean(); + packet.readBoolean(); + packet.readBoolean(); + packet.readInteger(); + packet.readString(); + break; + case 4: + + packet.readString(); + packet.readInteger(); + packet.readString(); + for (int j = packet.readInteger(); j > 0; j--) + { + packet.readShort(); + } + break; + } + } + + public static HEntity[] parse(HPacket packet) { + HEntity[] entities = new HEntity[packet.readInteger()]; + + for (int i = 0; i < entities.length; i++) + entities[i] = new HEntity(packet); + + return entities; + } + + public boolean tryUpdate(HEntityUpdate update) { + if (index != update.index) return false; + + tile = update.tile; + lastUpdate = update; + return true; + } + + public int getId() { + return id; + } + + public int getIndex() { + return index; + } + + public HPoint getTile() { + return tile; + } + + public String getName() { + return name; + } + + public String getMotto() { + return motto; + } + + public HGender getGender() { + return gender; + } + + public int getEntityType() { + return entityType; + } + + public String getFigureId() { + return figureId; + } + + public String getFavoriteGroup() { + return favoriteGroup; + } + + public HEntityUpdate getLastUpdate() { + return lastUpdate; + } +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HEntityUpdate.java b/G-Earth/src/main/java/gearth/extensions/parsers/HEntityUpdate.java new file mode 100644 index 0000000..eccb5c3 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HEntityUpdate.java @@ -0,0 +1,107 @@ +package gearth.extensions.parsers; + +import gearth.protocol.HPacket; + +public class HEntityUpdate { + private int index; + private boolean isController; + + private HPoint tile; + private HPoint movingTo; + + private HSign sign; + private HStance stance; + private HAction action; + private HDirection headFacing; + private HDirection bodyFacing; + + private HEntityUpdate(HPacket packet) { + index = packet.readInteger(); + tile = new HPoint(packet.readInteger(), packet.readInteger(), + Double.parseDouble(packet.readString())); + + headFacing = HDirection.values()[packet.readInteger()]; + bodyFacing = HDirection.values()[packet.readInteger()]; + + String action = packet.readString(); + String[] actionData = action.split("/"); + + for (String actionInfo : actionData) { + String[] actionValues = actionInfo.split(" "); + + if (actionValues.length < 2) continue; + if (actionValues[0].isEmpty()) continue; + + switch(actionValues[0]) { + case "flatctrl": + isController = true; + break; + case "mv": + String[] values = actionValues[1].split(","); + if (values.length >= 3) + movingTo = new HPoint(Integer.decode(values[0]), Integer.decode(values[1]), + Double.parseDouble(values[2])); + + this.action = HAction.Move; + break; + case "sit": + this.action = HAction.Sit; + stance = HStance.Sit; + break; + case "lay": + this.action = HAction.Lay; + stance = HStance.Lay; + break; + case "sign": + sign = HSign.values()[Integer.decode(actionValues[1])]; + this.action = HAction.Sign; + break; + } + } + } + + + public static HEntityUpdate[] parse(HPacket packet) { + HEntityUpdate[] updates = new HEntityUpdate[packet.readInteger()]; + for (int i = 0; i < updates.length; i++) + updates[i] = new HEntityUpdate(packet); + + return updates; + } + + public int getIndex() { + return index; + } + + public boolean isController() { + return isController; + } + + public HPoint getTile() { + return tile; + } + + public HPoint getMovingTo() { + return movingTo; + } + + public HSign getSign() { + return sign; + } + + public HStance getStance() { + return stance; + } + + public HAction getAction() { + return action; + } + + public HDirection getHeadFacing() { + return headFacing; + } + + public HDirection getBodyFacing() { + return bodyFacing; + } +} \ No newline at end of file diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HFloorItem.java b/G-Earth/src/main/java/gearth/extensions/parsers/HFloorItem.java new file mode 100644 index 0000000..5684ea0 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HFloorItem.java @@ -0,0 +1,164 @@ +package gearth.extensions.parsers; + +import gearth.protocol.HPacket; + +import java.util.HashMap; + +public class HFloorItem implements IFurni { + private int id; + private int typeId; + private HPoint tile; + private HDirection facing; + + private int category; + + private int secondsToExpiration; + private int usagePolicy; + private int ownerId; + private String ownerName; + + public HFloorItem(HPacket packet) { + id = packet.readInteger(); + typeId = packet.readInteger(); + + int x = packet.readInteger(); + int y = packet.readInteger(); + facing = HDirection.values()[packet.readInteger()]; + + tile = new HPoint(x, y, Double.parseDouble(packet.readString())); + + packet.readString(); + packet.readInteger(); + + category = packet.readInteger(); + + setStuffData(packet); + + secondsToExpiration = packet.readInteger(); + usagePolicy = packet.readInteger(); + + ownerId = packet.readInteger(); + + if (typeId < 0) + packet.readString(); + + } + + private void setStuffData(HPacket packet) + { + int kind = packet.readInteger(); + switch(kind) + { + case 0: // RegularFurni + packet.readString(); + break; + case 1: // MapStuffData + { + int max = packet.readInteger(); + for (int i = 0; i < max; i++) { + packet.readString(); + packet.readString(); + } + } + break; + case 2: // StringArrayStuffData + { + int max = packet.readInteger(); + for (int i = 0; i < max; i++) + packet.readString(); + } + break; + case 3: // idk about this one lol + packet.readString(); + packet.readInteger(); + break; + case 4: // neither about this one + break; + case 5: // IntArrayStuffData + { + int max = packet.readInteger(); + + for (int i = 0; i < max; i++) + packet.readInteger(); + } + break; + case 6: // HighScoreStuffData + { + packet.readString(); + packet.readInteger(); + packet.readInteger(); + int max = packet.readInteger(); + + for (int i = 0; i < max; i++) { + packet.readInteger(); + int dataCount = packet.readInteger(); + for (int j = 0; j < dataCount; j++) + packet.readString(); + } + } + break; + case 7: // Crackables (Eggs and stuff) + packet.readString(); + packet.readInteger(); + packet.readInteger(); + break; + } + } + + public static HFloorItem[] parse(HPacket packet) { + int ownersCount = packet.readInteger(); + HashMap owners = new HashMap<>(ownersCount); + + for (int i = 0; i < ownersCount; i++) + owners.put(packet.readInteger(), packet.readString()); + + HFloorItem[] furniture = new HFloorItem[packet.readInteger()]; + for (int i = 0; i < furniture.length; i++) { + HFloorItem furni = new HFloorItem(packet); + furni.ownerName = owners.get(furni.ownerId); + + furniture[i] = furni; + } + return furniture; + } + + @Override + public int getId() { + return id; + } + + @Override + public int getTypeId() { + return typeId; + } + + @Override + public int getUsagePolicy() { + return usagePolicy; + } + + @Override + public int getOwnerId() { + return ownerId; + } + + public String getOwnerName() { + return ownerName; + } + + public int getSecondsToExpiration() { + return secondsToExpiration; + } + + public int getCategory() { + return category; + } + + public HDirection getFacing() { + return facing; + } + + public HPoint getTile() { + return tile; + } +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HGender.java b/G-Earth/src/main/java/gearth/extensions/parsers/HGender.java new file mode 100644 index 0000000..07d2d27 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HGender.java @@ -0,0 +1,17 @@ +package gearth.extensions.parsers; + +public enum HGender { + Unisex("U"), + Male("M"), + Female("F"); + + private final String id; + + HGender(String id) { + this.id = id; + } + + public String toString() { + return id; + } +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HGroup.java b/G-Earth/src/main/java/gearth/extensions/parsers/HGroup.java new file mode 100644 index 0000000..bda4181 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HGroup.java @@ -0,0 +1,59 @@ +package gearth.extensions.parsers; + +import gearth.protocol.HPacket; + +public class HGroup { + private int id; + private String name; + private String badgeCode; + private String primaryColor; + private String secondaryColor; + + private boolean isFavorite; + private int ownerId; + private boolean hasForum; + + public HGroup(HPacket packet) { + id = packet.readInteger(); + name = packet.readString(); + badgeCode = packet.readString(); + primaryColor = packet.readString(); + secondaryColor = packet.readString(); + + isFavorite = packet.readBoolean(); + ownerId = packet.readInteger(); + hasForum = packet.readBoolean(); + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public String getBadgeCode() { + return badgeCode; + } + + public String getPrimaryColor() { + return primaryColor; + } + + public String getSecondaryColor() { + return secondaryColor; + } + + public boolean isFavorite() { + return isFavorite; + } + + public int getOwnerId() { + return ownerId; + } + + public boolean isHasForum() { + return hasForum; + } +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HPoint.java b/G-Earth/src/main/java/gearth/extensions/parsers/HPoint.java new file mode 100644 index 0000000..bdbbe83 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HPoint.java @@ -0,0 +1,37 @@ +package gearth.extensions.parsers; + +public class HPoint { + private int x; + private int y; + private double z; + + public HPoint(int x, int y) { + this(x, y, 0); + } + + public HPoint(int x, int y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public double getZ() { + return z; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof HPoint)) return false; + + HPoint p = (HPoint) o; + return this.x == p.getX() && this.y == p.getY() && this.z == p.getZ(); + } +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HSign.java b/G-Earth/src/main/java/gearth/extensions/parsers/HSign.java new file mode 100644 index 0000000..3bee4a7 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HSign.java @@ -0,0 +1,23 @@ +package gearth.extensions.parsers; + +public enum HSign { + Zero, + One, + Two, + Three, + Four, + Five, + Six, + Seven, + Eight, + Nine, + Ten, + Heart, + Skull, + Exclamation, + Soccerball, + Smiley, + Redcard, + Yellowcard, + Invisible +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HStance.java b/G-Earth/src/main/java/gearth/extensions/parsers/HStance.java new file mode 100644 index 0000000..5105e6d --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HStance.java @@ -0,0 +1,7 @@ +package gearth.extensions.parsers; + +public enum HStance { + Stand, + Sit, + Lay +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HWallItem.java b/G-Earth/src/main/java/gearth/extensions/parsers/HWallItem.java new file mode 100644 index 0000000..9beaf94 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HWallItem.java @@ -0,0 +1,80 @@ +package gearth.extensions.parsers; + +import gearth.protocol.HPacket; + +import java.util.HashMap; + +public class HWallItem implements IFurni { + private int id; + private int typeId; + + private String state; + private String location; + private int usagePolicy; + private int secondsToExpiration; + + private int ownerId; + private String ownerName; + + public HWallItem(HPacket packet) { + id = Integer.decode(packet.readString()); + typeId = packet.readInteger(); + + location = packet.readString(); + state = packet.readString(); + secondsToExpiration = packet.readInteger(); + usagePolicy = packet.readInteger(); + + ownerId = packet.readInteger(); + } + + static HWallItem[] parse(HPacket packet) { + int ownersCount = packet.readInteger(); + HashMap owners = new HashMap<>(ownersCount); + + for (int i = 0; i < ownersCount; i++) + owners.put(packet.readInteger(), packet.readString()); + + HWallItem[] furniture = new HWallItem[packet.readInteger()]; + + for (int i = 0; i < furniture.length; i++) { + HWallItem furni = new HWallItem(packet); + furni.ownerName = owners.get(furni.ownerId); + + furniture[i] = furni; + } + return furniture; + } + + public int getId() { + return id; + } + + public int getTypeId() { + return typeId; + } + + public int getUsagePolicy() { + return usagePolicy; + } + + public int getOwnerId() { + return ownerId; + } + + public String getOwnerName() { + return ownerName; + } + + public String getState() { + return state; + } + + public String getLocation() { + return location; + } + + public int getSecondsToExpiration() { + return secondsToExpiration; + } +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/IFurni.java b/G-Earth/src/main/java/gearth/extensions/parsers/IFurni.java new file mode 100644 index 0000000..0b1994d --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/IFurni.java @@ -0,0 +1,9 @@ +package gearth.extensions.parsers; + +public interface IFurni { + int getId(); + int getTypeId(); + int getUsagePolicy(); + int getOwnerId(); + String getOwnerName(); +} diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/UserProfile.java b/G-Earth/src/main/java/gearth/extensions/parsers/UserProfile.java new file mode 100644 index 0000000..9297fcb --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/parsers/UserProfile.java @@ -0,0 +1,95 @@ +package gearth.extensions.parsers; + +import gearth.protocol.HPacket; + +public class UserProfile { + private int id; + private String username; + private String motto; + private String figure; + private String creationDate; + private int achievementScore; + private int friendCount; + + private boolean isFriend; + private boolean isRequestedFriend; + private boolean isOnline; + + private HGroup[] groups; + + private int lastAccessSince; + private boolean openProfile; + + public UserProfile(HPacket packet) { + id = packet.readInteger(); + username = packet.readString(); + motto = packet.readString(); + figure = packet.readString(); + creationDate = packet.readString(); + achievementScore = packet.readInteger(); + friendCount = packet.readInteger(); + + isFriend = packet.readBoolean(); + isRequestedFriend = packet.readBoolean(); + isOnline = packet.readBoolean(); + + groups = new HGroup[packet.readInteger()]; + for (int i = 0; i < groups.length; i++) + groups[i] = new HGroup(packet); + + lastAccessSince = packet.readInteger(); + openProfile = packet.readBoolean(); + } + + public int getId() { + return id; + } + + public String getUsername() { + return username; + } + + public String getMotto() { + return motto; + } + + public String getFigure() { + return figure; + } + + public String getCreationDate() { + return creationDate; + } + + public int getAchievementScore() { + return achievementScore; + } + + public int getFriendCount() { + return friendCount; + } + + public boolean isFriend() { + return isFriend; + } + + public boolean isRequestedFriend() { + return isRequestedFriend; + } + + public boolean isOnline() { + return isOnline; + } + + public HGroup[] getGroups() { + return groups; + } + + public int getLastAccessSince() { + return lastAccessSince; + } + + public boolean isOpenProfile() { + return openProfile; + } +}