Initial commit
commit
d5efddd10d
|
@ -0,0 +1,2 @@
|
||||||
|
.idea/
|
||||||
|
vendor/
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"react/event-loop": "^1.5",
|
||||||
|
"react/http": "^1.9",
|
||||||
|
"react/stream": "^1.3",
|
||||||
|
"react/async": "^4.2",
|
||||||
|
"react/promise": "^3.1",
|
||||||
|
"react/socket": "^1.15",
|
||||||
|
"cboden/ratchet": "^0.4.4"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'vendor/autoload.php';
|
||||||
|
|
||||||
|
spl_autoload_register(function(string $class) {
|
||||||
|
require_once str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
|
||||||
|
});
|
||||||
|
|
||||||
|
use Emulator\HabboEnvironment;
|
||||||
|
|
||||||
|
HabboEnvironment::getInstance()->initialize();
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Core\Logging;
|
||||||
|
|
||||||
|
enum LogLevel {
|
||||||
|
case Debug;
|
||||||
|
case Info;
|
||||||
|
case Warn;
|
||||||
|
case Fatal;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Core\Logging;
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
private const array colorCodes = [
|
||||||
|
'r' => 31,
|
||||||
|
'b' => 34
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function log(LogLevel $level, string $text): void {
|
||||||
|
if (preg_match_all('/\[([a-z]{1,2})]/', $text, $matches)) {
|
||||||
|
foreach ($matches[1] as $code) {
|
||||||
|
$colorCode = self::colorCodes[$code];
|
||||||
|
$text = str_replace(["[$code]", "[/$code]"], ["\033[{$colorCode}m", "\033[0m"], $text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "[$level->name] $text" . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function debug(string $text): void {
|
||||||
|
self::log(LogLevel::Debug, $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function info(string $text): void {
|
||||||
|
self::log(LogLevel::Info, $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function warn(string $text): void {
|
||||||
|
self::log(LogLevel::Warn, $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fatal(string $text): void {
|
||||||
|
self::log(LogLevel::Fatal, $text);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Encoding;
|
||||||
|
|
||||||
|
class ByteEncoding {
|
||||||
|
public static function getInt32(array $raw): int{
|
||||||
|
|
||||||
|
return ($raw[0] << 24) | ($raw[1] << 16) | ($raw[2] << 8) | $raw[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getInt16(array $raw): int {
|
||||||
|
return (($raw[0] << 8) | $raw[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function int32ToArray(int $value): array {
|
||||||
|
return [$value >> 24, $value >> 16, $value >> 8, $value];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function int16ToArray(int $value): array {
|
||||||
|
return [$value >> 8, $value];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator;
|
||||||
|
|
||||||
|
use Emulator\Core\Logging\Logger;
|
||||||
|
use Emulator\Messages\MessageHandler;
|
||||||
|
use Emulator\Network\Game\GameNetworkServer;
|
||||||
|
|
||||||
|
class HabboEnvironment {
|
||||||
|
private static ?HabboEnvironment $instance = null;
|
||||||
|
|
||||||
|
public function initialize(): void {
|
||||||
|
Logger::info("Starting up [b]HabboEmulator[/b] (PHP Edition) for [r]$_SERVER[USER][/r]");
|
||||||
|
|
||||||
|
MessageHandler::getInstance();
|
||||||
|
|
||||||
|
GameNetworkServer::getInstance()->start(2096);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getInstance(): HabboEnvironment {
|
||||||
|
if (self::$instance === null)
|
||||||
|
self::$instance = new self();
|
||||||
|
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages\Incoming;
|
||||||
|
|
||||||
|
use Emulator\Encoding\ByteEncoding;
|
||||||
|
|
||||||
|
class ClientMessage {
|
||||||
|
private readonly array $packet;
|
||||||
|
private readonly int $header;
|
||||||
|
private int $readerIndex;
|
||||||
|
|
||||||
|
public function __construct(array $packet) {
|
||||||
|
$this->packet = $packet;
|
||||||
|
$this->readerIndex = 0;
|
||||||
|
$this->header = $this->readInt16();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function readBytes(int $amount): array {
|
||||||
|
$bytes = [];
|
||||||
|
for ($i = 0; $i < $amount && $this->readerIndex < count($this->packet); $i++) {
|
||||||
|
$bytes[$i] = $this->packet[$this->readerIndex++];
|
||||||
|
}
|
||||||
|
return $bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readInt16(): int {
|
||||||
|
return ByteEncoding::getInt16($this->readBytes(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readInt32(): int {
|
||||||
|
return ByteEncoding::getInt32($this->readBytes(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readBoolean(): bool {
|
||||||
|
return $this->packet[$this->readerIndex++] === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readString(): string {
|
||||||
|
return call_user_func_array('pack', array_merge(['C*'], $this->readBytes($this->readInt16())));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHeader(): int{
|
||||||
|
return $this->header;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages\Incoming\Handshake;
|
||||||
|
|
||||||
|
use Emulator\Messages\Incoming\ClientMessage;
|
||||||
|
use Emulator\Messages\Incoming\Header;
|
||||||
|
use Emulator\Messages\Incoming\IMessageEvent;
|
||||||
|
use Emulator\Network\Game\Sessions\Session;
|
||||||
|
use Override;
|
||||||
|
|
||||||
|
class ReleaseVersionMessageEvent implements IMessageEvent {
|
||||||
|
#[Override] function handle(Session $session, ClientMessage $clientMessage): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Override] function getHeader(): Header {
|
||||||
|
return Header::ReleaseVersion;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages\Incoming\Handshake;
|
||||||
|
|
||||||
|
use Emulator\Messages\Incoming\ClientMessage;
|
||||||
|
use Emulator\Messages\Incoming\Header;
|
||||||
|
use Emulator\Messages\Incoming\IMessageEvent;
|
||||||
|
use Emulator\Messages\Outgoing\Handshake\AuthenticatedComposer;
|
||||||
|
use Emulator\Network\Game\Sessions\Session;
|
||||||
|
use Override;
|
||||||
|
|
||||||
|
class SecurityTicketMessageEvent implements IMessageEvent {
|
||||||
|
#[Override] function handle(Session $session, ClientMessage $clientMessage): void {
|
||||||
|
$session->sendComposer(new AuthenticatedComposer());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Override] function getHeader(): Header {
|
||||||
|
return Header::ReleaseVersion;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,471 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages\Incoming;
|
||||||
|
|
||||||
|
enum Header : int
|
||||||
|
{
|
||||||
|
case AchievementList = 219;
|
||||||
|
case Authentication = -1;
|
||||||
|
case BotConfiguration = 1986;
|
||||||
|
case BotPickup = 3323;
|
||||||
|
case BotPlace = 1592;
|
||||||
|
case BotSkillSave = 2624;
|
||||||
|
case GetClubOffers = 3285;
|
||||||
|
case GetClubGiftInfo = 487;
|
||||||
|
case GetCatalogIndex = 1195;
|
||||||
|
case GetCatalogPage = 412;
|
||||||
|
case CatalogPurchase = 3492;
|
||||||
|
case CatalogPurchaseGift = 1411;
|
||||||
|
case GetProductOffer = 2594;
|
||||||
|
case ClientLatency = 295;
|
||||||
|
case ClientLatencyMeasure = 96;
|
||||||
|
case ClientPolicy = 26979;
|
||||||
|
case ClientPong = 2596;
|
||||||
|
case ClientToolbarToggle = 2313;
|
||||||
|
case ClientVariables = 1053;
|
||||||
|
case GetCurrentTimingCode = 2912;
|
||||||
|
case DesktopView = 105;
|
||||||
|
case GetBundleDiscountRuleset = 223;
|
||||||
|
case EventTracker = 3457;
|
||||||
|
case FindNewFriends = 516;
|
||||||
|
case FurnitureAliases = 3898;
|
||||||
|
case FurnitureFloorUpdate = 248;
|
||||||
|
case FurnitureMultistate = 99;
|
||||||
|
case FurniturePickup = 3456;
|
||||||
|
case FurniturePlace = 1258;
|
||||||
|
case FurniturePostitPlace = 2248;
|
||||||
|
case FurniturePostitSaveStickyPole = 3283;
|
||||||
|
case FurnitureRandomstate = 3617;
|
||||||
|
case FurnitureWallMultistate = 210;
|
||||||
|
case FurnitureWallUpdate = 168;
|
||||||
|
case GamesInit = 2914;
|
||||||
|
case GamesList = 741;
|
||||||
|
case Acceptgameinvite = 3802;
|
||||||
|
case Gameunloadedmessage = 3207;
|
||||||
|
case Getgameachievementsmessage = 2399;
|
||||||
|
case Getgamestatusmessage = 3171;
|
||||||
|
case Getusergameachievementsmessage = 389;
|
||||||
|
case Joinqueuemessage = 1458;
|
||||||
|
case Leavequeuemessage = 2384;
|
||||||
|
case Resetresolutionachievementmessage = 3144;
|
||||||
|
case Getweeklygamerewardwinners = 1054;
|
||||||
|
case Game2Getaccountgamestatusmessage = 11;
|
||||||
|
case Game2Checkgamedirectorystatusmessage = 3259;
|
||||||
|
case Game2Exitgamemessage = 1445;
|
||||||
|
case Game2Gamechatmessage = 2502;
|
||||||
|
case Game2Loadstagereadymessage = 2415;
|
||||||
|
case Game2Playagainmessage = 3196;
|
||||||
|
case Game2Requestfullstatusupdatemessage = 1598;
|
||||||
|
case Game2Getweeklyfriendsleaderboard = 1232;
|
||||||
|
case Game2Getweeklyleaderboard = 2565;
|
||||||
|
case GetGiftWrappingConfig = 418;
|
||||||
|
case GroupAdminAdd = 2894;
|
||||||
|
case GroupAdminRemove = 722;
|
||||||
|
case GroupCreateOptions = 798;
|
||||||
|
case GroupFavorite = 3549;
|
||||||
|
case GetForumStats = 3149;
|
||||||
|
case GetForumThreads = 873;
|
||||||
|
case GetForumsList = 436;
|
||||||
|
case GetForumMessages = 232;
|
||||||
|
case GetForumThread = 3900;
|
||||||
|
case GetUnreadForumsCount = 2908;
|
||||||
|
case ForumModerateMessage = 286;
|
||||||
|
case ForumModerateThread = 1397;
|
||||||
|
case ForumPostMessage = 3529;
|
||||||
|
case UpdateForumReadMarker = 1855;
|
||||||
|
case UpdateForumSettings = 2214;
|
||||||
|
case ForumUpdateThread = 3045;
|
||||||
|
case GroupInfo = 2991;
|
||||||
|
case GroupDelete = 1134;
|
||||||
|
case GroupMemberRemoveConfirm = 3593;
|
||||||
|
case GroupMemberRemove = 593;
|
||||||
|
case GroupMembers = 312;
|
||||||
|
case GroupMemberships = 367;
|
||||||
|
case GroupRequest = 998;
|
||||||
|
case GroupRequestAccept = 3386;
|
||||||
|
case GroupRequestDecline = 1894;
|
||||||
|
case GroupSettings = 1004;
|
||||||
|
case GroupParts = 813;
|
||||||
|
case GroupBuy = 230;
|
||||||
|
case GroupSaveInformation = 3137;
|
||||||
|
case GroupSaveBadge = 1991;
|
||||||
|
case GroupSaveColors = 1764;
|
||||||
|
case GroupSavePreferences = 3435;
|
||||||
|
case GroupBadges = 21;
|
||||||
|
case GroupUnblockMember = 2864;
|
||||||
|
case GetBadgePointsLimits = 1371;
|
||||||
|
case Requestabadge = 3077;
|
||||||
|
case Getisbadgerequestfulfilled = 1364;
|
||||||
|
case ItemClothingRedeem = 3374;
|
||||||
|
case ItemColorWheelClick = 2144;
|
||||||
|
case ItemDiceClick = 1990;
|
||||||
|
case ItemDiceClose = 1533;
|
||||||
|
case ItemDimmerSave = 1648;
|
||||||
|
case ItemDimmerSettings = 2813;
|
||||||
|
case ItemDimmerToggle = 2296;
|
||||||
|
case ItemExchangeRedeem = 3115;
|
||||||
|
case ItemPaint = 711;
|
||||||
|
case SetObjectData = 3608;
|
||||||
|
case ItemStackHelper = 3839;
|
||||||
|
case MarketplaceConfig = 2597;
|
||||||
|
case AcceptFriend = 137;
|
||||||
|
case MessengerChat = 3567;
|
||||||
|
case DeclineFriend = 2890;
|
||||||
|
case FollowFriend = 3997;
|
||||||
|
case MessengerFriends = 1523;
|
||||||
|
case MessengerInit = 2781;
|
||||||
|
case MessengerRelationships = 2138;
|
||||||
|
case SetRelationshipStatus = 3768;
|
||||||
|
case RemoveFriend = 1689;
|
||||||
|
case RequestFriend = 3157;
|
||||||
|
case GetFriendRequests = 2448;
|
||||||
|
case SendRoomInvite = 1276;
|
||||||
|
case HabboSearch = 1210;
|
||||||
|
case FriendListUpdate = 1419;
|
||||||
|
case ModToolUserInfo = 3295;
|
||||||
|
case GetUserFlatCats = 3027;
|
||||||
|
case NavigatorInit = 2110;
|
||||||
|
case NavigatorSearch = 249;
|
||||||
|
case NavigatorSearchClose = 1834;
|
||||||
|
case NavigatorSearchOpen = 637;
|
||||||
|
case NavigatorSearchSave = 2226;
|
||||||
|
case GetUserEventCats = 1782;
|
||||||
|
case NavigatorSettingsSave = 3159;
|
||||||
|
case NavigatorCategoryListMode = 1202;
|
||||||
|
case NavigatorDeleteSavedSearch = 1954;
|
||||||
|
case PetInfo = 2934;
|
||||||
|
case PetPickup = 1581;
|
||||||
|
case PetPlace = 2647;
|
||||||
|
case PetRespect = 3202;
|
||||||
|
case PetRide = 1036;
|
||||||
|
case PetMove = 3449;
|
||||||
|
case PetOpenPackage = 3698;
|
||||||
|
case PetSelected = 549;
|
||||||
|
case PetsBreed = 1638;
|
||||||
|
case PetCancelBreeding = 2713;
|
||||||
|
case PetConfirmBreeding = 3382;
|
||||||
|
case GetPetTrainingPanel = 2161;
|
||||||
|
case RecyclerPrizes = 398;
|
||||||
|
case RecyclerStatus = 1342;
|
||||||
|
case RecyclerItems = 2771;
|
||||||
|
case ReleaseVersion = 4000;
|
||||||
|
case CallForHelp = 1691;
|
||||||
|
case RoomAmbassadorAlert = 2996;
|
||||||
|
case RoomBanGive = 1477;
|
||||||
|
case RoomBanList = 2267;
|
||||||
|
case RoomBanRemove = 992;
|
||||||
|
case RoomCreate = 2752;
|
||||||
|
case RoomDelete = 532;
|
||||||
|
case RoomDoorbell = 1644;
|
||||||
|
case RoomEnter = 2312;
|
||||||
|
case RoomFavorite = 3817;
|
||||||
|
case RoomFavoriteRemove = 309;
|
||||||
|
case CanCreateRoom = 2128;
|
||||||
|
case CancelRoomEvent = 2725;
|
||||||
|
case EditRoomEvent = 3991;
|
||||||
|
case CompetitionRoomSearch = 433;
|
||||||
|
case ForwardToRandomPromotedRoom = 10;
|
||||||
|
case ForwardToSomeRoom = 1703;
|
||||||
|
case GetCategoriesWithUserCount = 3782;
|
||||||
|
case GetGuestRoom = 2230;
|
||||||
|
case GetOfficialRooms = 1229;
|
||||||
|
case GetPopularRoomTags = 826;
|
||||||
|
case GuildBaseSearch = 2930;
|
||||||
|
case MyFavouriteRoomsSearch = 2578;
|
||||||
|
case MyFrequentRoomHistorySearch = 1002;
|
||||||
|
case MyFriendsRoomSearch = 2266;
|
||||||
|
case MyGuildBasesSearch = 39;
|
||||||
|
case MyRecommendedRooms = 2537;
|
||||||
|
case MyRoomHistorySearch = 2264;
|
||||||
|
case MyRoomRightsSearch = 272;
|
||||||
|
case MyRoomsSearch = 2277;
|
||||||
|
case PopularRoomsSearch = 2758;
|
||||||
|
case RoomAdEventTabClicked = 2412;
|
||||||
|
case RoomAdEventTabViewed = 2668;
|
||||||
|
case RoomAdSearch = 2809;
|
||||||
|
case RoomTextSearch = 3943;
|
||||||
|
case RoomsWhereMyFriendsAre = 1786;
|
||||||
|
case RoomsWithHighestScoreSearch = 2939;
|
||||||
|
case SetRoomSessionTags = 3305;
|
||||||
|
case UpdateRoomThumbnail = 2468;
|
||||||
|
case RoomKick = 1320;
|
||||||
|
case RoomLike = 3582;
|
||||||
|
case RoomModel = 2300;
|
||||||
|
case GetOccupiedTiles = 1687;
|
||||||
|
case GetRoomEntryTile = 3559;
|
||||||
|
case RoomModelSave = 875;
|
||||||
|
case RoomMute = 3637;
|
||||||
|
case RoomMuteUser = 3485;
|
||||||
|
case RoomRightsGive = 808;
|
||||||
|
case RoomRightsList = 3385;
|
||||||
|
case RoomRightsRemove = 2064;
|
||||||
|
case RoomRightsRemoveAll = 2683;
|
||||||
|
case RoomRightsRemoveOwn = 3182;
|
||||||
|
case RoomSettings = 3129;
|
||||||
|
case RoomSettingsSave = 1969;
|
||||||
|
case RoomSettingsUpdateRoomCategoryAndTrade = 1265;
|
||||||
|
case RoomStaffPick = 1918;
|
||||||
|
case RoomFilterWords = 1911;
|
||||||
|
case RoomFilterWordsModify = 3001;
|
||||||
|
case Mysteryboxwaitingcanceledmessage = 2012;
|
||||||
|
case MysteryboxOpenTrophy = 3074;
|
||||||
|
case SecurityMachine = 2490;
|
||||||
|
case SecurityTicket = 2419;
|
||||||
|
case Trade = 1481;
|
||||||
|
case TradeAccept = 3863;
|
||||||
|
case TradeCancel = 2341;
|
||||||
|
case TradeClose = 2551;
|
||||||
|
case TradeConfirm = 2760;
|
||||||
|
case TradeItem = 3107;
|
||||||
|
case TradeItemRemove = 3845;
|
||||||
|
case TradeItems = 1263;
|
||||||
|
case TradeUnaccept = 1444;
|
||||||
|
case UnitAction = 2456;
|
||||||
|
case UnitChat = 1314;
|
||||||
|
case UnitChatShout = 2085;
|
||||||
|
case UnitChatWhisper = 1543;
|
||||||
|
case UnitDance = 2080;
|
||||||
|
case UnitDropHandItem = 2814;
|
||||||
|
case UnitGiveHanditem = 2941;
|
||||||
|
case UnitLook = 3301;
|
||||||
|
case UnitPosture = 2235;
|
||||||
|
case UnitSign = 1975;
|
||||||
|
case UnitTyping = 1597;
|
||||||
|
case UnitTypingStop = 1474;
|
||||||
|
case UnitWalk = 3320;
|
||||||
|
case UserBadges = 2769;
|
||||||
|
case UserBadgesCurrent = 2091;
|
||||||
|
case UserBadgesCurrentUpdate = 644;
|
||||||
|
case UserBots = 3848;
|
||||||
|
case UserCurrency = 273;
|
||||||
|
case UserEffectActivate = 2959;
|
||||||
|
case UserEffectEnable = 1752;
|
||||||
|
case UserFigure = 2730;
|
||||||
|
case UserFurniture = 3150; // sent when in room
|
||||||
|
case Requestfurniinventorywhennotinroom = 3500; // sent when not in room
|
||||||
|
case UserHomeRoom = 1740;
|
||||||
|
case UserInfo = 357;
|
||||||
|
case UserMotto = 2228;
|
||||||
|
case UserIgnored = 3878;
|
||||||
|
case UserPets = 3095;
|
||||||
|
case UserProfile = 3265;
|
||||||
|
case UserProfileByName = 2249;
|
||||||
|
case UserRespect = 2694;
|
||||||
|
case GetSoundSettings = 2388;
|
||||||
|
case UserSettingsCamera = 1461;
|
||||||
|
case UserSettingsChatStyle = 1030;
|
||||||
|
case UserSettingsInvites = 1086;
|
||||||
|
case UserSettingsOldChat = 1262;
|
||||||
|
case UserSettingsVolume = 1367;
|
||||||
|
case UserSubscription = 3166;
|
||||||
|
case GetWardrobe = 2742;
|
||||||
|
case SaveWardrobeOutfit = 800;
|
||||||
|
case UserTags = 17;
|
||||||
|
case PeerUsersClassification = 1160;
|
||||||
|
case UserClassification = 2285;
|
||||||
|
case VisitUser = 2970;
|
||||||
|
case WiredActionSave = 2281;
|
||||||
|
case WiredApplySnapshot = 3373;
|
||||||
|
case WiredConditionSave = 3203;
|
||||||
|
case WiredOpen = 768;
|
||||||
|
case WiredTriggerSave = 1520;
|
||||||
|
case GetItemData = 3964;
|
||||||
|
case OneWayDoorClick = 2765;
|
||||||
|
case RemoveWallItem = 3336;
|
||||||
|
case SetItemData = 3666;
|
||||||
|
case CatalogRedeemVoucher = 339;
|
||||||
|
case RoomTonerApply = 2880;
|
||||||
|
case FriendFurniConfirmLock = 3775;
|
||||||
|
case MannequinSaveName = 2850;
|
||||||
|
case MannequinSaveLook = 2209;
|
||||||
|
case PresentOpenPresent = 3558;
|
||||||
|
case CatalogSelectVipGift = 2276;
|
||||||
|
case UserIgnoreId = 3314;
|
||||||
|
case UserIgnore = 1117;
|
||||||
|
case UserUnignore = 2061;
|
||||||
|
case ModtoolRequestRoomInfo = 707;
|
||||||
|
case ModtoolChangeRoomSettings = 3260;
|
||||||
|
case ModtoolRequestUserChatlog = 1391;
|
||||||
|
case ModtoolRequestRoomChatlog = 2587;
|
||||||
|
case ModtoolSanctionAlert = 229;
|
||||||
|
case ModtoolSanctionBan = 2766;
|
||||||
|
case ModtoolSanctionKick = 2582;
|
||||||
|
case ModtoolSanctionTradelock = 3742;
|
||||||
|
case ModtoolAlertevent = 1840;
|
||||||
|
case ModtoolSanctionMute = 1945;
|
||||||
|
case ModtoolRequestUserRooms = 3526;
|
||||||
|
case ModtoolRoomAlert = 3842;
|
||||||
|
case ModtoolPreferences = 31;
|
||||||
|
case CloseIssueDefaultAction = 2717;
|
||||||
|
case CloseIssues = 2067;
|
||||||
|
case DefaultSanction = 1681;
|
||||||
|
case GetCfhChatlog = 211;
|
||||||
|
case ModtoolSanction = 1392;
|
||||||
|
case PickIssues = 15;
|
||||||
|
case ReleaseIssues = 1572;
|
||||||
|
case ConvertGlobalRoomId = 314;
|
||||||
|
case RequestSellItem = 848;
|
||||||
|
case RequestMarketplaceItemStats = 3288;
|
||||||
|
case MarketplaceSellItem = 3447;
|
||||||
|
case MarketplaceRequestOwnItems = 2105;
|
||||||
|
case MarketplaceTakeBackItem = 434;
|
||||||
|
case MarketplaceRedeemCredits = 2650;
|
||||||
|
case MarketplaceRequestOffers = 2407;
|
||||||
|
case MarketplaceBuyOffer = 1603;
|
||||||
|
case MarketplaceBuyTokens = 1866;
|
||||||
|
case CatalogRequesetPetBreeds = 1756;
|
||||||
|
case ApproveName = 2109;
|
||||||
|
case UnitGiveHanditemPet = 2768;
|
||||||
|
case PetSupplement = 749;
|
||||||
|
case FurnitureGroupInfo = 2651;
|
||||||
|
case AchievementResolutionOpen = 359;
|
||||||
|
case UsePetProduct = 1328;
|
||||||
|
case RemovePetSaddle = 186;
|
||||||
|
case TogglePetRiding = 1472;
|
||||||
|
case TogglePetBreeding = 3379;
|
||||||
|
case UnseenResetCategory = 3493;
|
||||||
|
case UnseenResetItems = 2343;
|
||||||
|
case CommunityGoalVoteComposer = 3536;
|
||||||
|
case GetPromoArticles = 1827;
|
||||||
|
case AcceptQuest = 3604;
|
||||||
|
case ActivateQuest = 793;
|
||||||
|
case CancelQuest = 3133;
|
||||||
|
case FriendRequestQuestComplete = 1148;
|
||||||
|
case GetCommunityGoalEarnedPrizes = 2688;
|
||||||
|
case GetCommunityGoalHallOfFame = 2167;
|
||||||
|
case GetCommunityGoalProgress = 1145;
|
||||||
|
case GetConcurrentUsersGoalProgress = 1343;
|
||||||
|
case GetConcurrentUsersReward = 3872;
|
||||||
|
case GetDailyQuest = 2486;
|
||||||
|
case GetQuests = 3333;
|
||||||
|
case GetSeasonalQuestsOnly = 1190;
|
||||||
|
case OpenQuestTracker = 2750;
|
||||||
|
case RedeemCommunityGoalPrize = 90;
|
||||||
|
case RejectQuest = 2397;
|
||||||
|
case StartCampaign = 1697;
|
||||||
|
case GetBonusRareInfo = 957;
|
||||||
|
case Craft = 3591;
|
||||||
|
case CraftSecret = 1251;
|
||||||
|
case GetCraftableProducts = 633;
|
||||||
|
case GetCraftingRecipe = 1173;
|
||||||
|
case GetCraftingRecipesAvailable = 3086;
|
||||||
|
case PhotoCompetition = 3959;
|
||||||
|
case PublishPhoto = 2068;
|
||||||
|
case PurchasePhoto = 2408;
|
||||||
|
case RenderRoom = 3226;
|
||||||
|
case RenderRoomThumbnail = 1982;
|
||||||
|
case RequestCameraConfiguration = 796;
|
||||||
|
case AddJukeboxDisk = 753;
|
||||||
|
case GetJukeboxPlaylist = 1435;
|
||||||
|
case GetNowPlaying = 1325;
|
||||||
|
case GetOfficialSongId = 3189;
|
||||||
|
case GetSongInfo = 3082;
|
||||||
|
case GetSoundMachinePlaylist = 3498;
|
||||||
|
case GetUserSongDisks = 2304;
|
||||||
|
case RemoveJukeboxDisk = 3050;
|
||||||
|
case InterstitialShown = 1109;
|
||||||
|
case GetInterstitial = 2519;
|
||||||
|
case ChangeUsername = 2977;
|
||||||
|
case CheckUsername = 3950;
|
||||||
|
case OpenCampaignCalendarDoorStaff = 3889;
|
||||||
|
case OpenCampaignCalendarDoor = 2257;
|
||||||
|
case BuildersClubPlaceRoomItem = 1051;
|
||||||
|
case BuildersClubPlaceWallItem = 462;
|
||||||
|
case BuildersClubQueryFurniCount = 2529;
|
||||||
|
case GetCatalogPageExpiration = 742;
|
||||||
|
case GetCatalogPageWithEarliestExp = 3135;
|
||||||
|
case GetDirectClubBuyAvailable = 801;
|
||||||
|
case GetHabboBasicMembershipExtendOffer = 603;
|
||||||
|
case GetHabboClubExtendOffer = 2462;
|
||||||
|
case GetIsOfferGiftable = 1347;
|
||||||
|
case GetLimitedOfferAppearingNext = 410;
|
||||||
|
case GetNextTargetedOffer = 596;
|
||||||
|
case GetRoomAdPurchaseInfo = 1075;
|
||||||
|
case GetSeasonalCalendarDailyOffer = 3257;
|
||||||
|
case GetTargetedOffer = 2487;
|
||||||
|
case MarkCatalogNewAdditionsPageOpened = 2150;
|
||||||
|
case PurchaseBasicMembershipExtension = 2735;
|
||||||
|
case PurchaseRoomAd = 777;
|
||||||
|
case PurchaseTargetedOffer = 1826;
|
||||||
|
case PurchaseVipMembershipExtension = 3407;
|
||||||
|
case RoomAdPurchaseInitiated = 2283;
|
||||||
|
case SetTargettedOfferState = 2041;
|
||||||
|
case ShopTargetedOfferViewed = 3483;
|
||||||
|
case HelperTalentTrack = 196;
|
||||||
|
case TalentTrackGetLevel = 2127;
|
||||||
|
case ForwardToACompetitionRoom = 172;
|
||||||
|
case ForwardToASubmittableRoom = 1450;
|
||||||
|
case ForwardToRandomCompetitionRoom = 865;
|
||||||
|
case GetIsUserPartOfCompetition = 2077;
|
||||||
|
case GetSecondsUntil = 271;
|
||||||
|
case RoomCompetitionInit = 1334;
|
||||||
|
case SubmitRoomToCompetition = 2595;
|
||||||
|
case VoteForRoom = 143;
|
||||||
|
case GetGift = 2436;
|
||||||
|
case ResetPhoneNumberState = 2741;
|
||||||
|
case SetPhoneNumberVerificationStatus = 1379;
|
||||||
|
case TryPhoneNumber = 790;
|
||||||
|
case VerifyCode = 2721;
|
||||||
|
case ControlYoutubeDisplayPlayback = 3005;
|
||||||
|
case GetYoutubeDisplayStatus = 336;
|
||||||
|
case SetYoutubeDisplayPlaylist = 2069;
|
||||||
|
case GoToFlat = 685;
|
||||||
|
case ChangeQueue = 3093;
|
||||||
|
case CallForHelpFromForumMessage = 1412;
|
||||||
|
case CallForHelpFromForumThread = 534;
|
||||||
|
case CallForHelpFromIm = 2950;
|
||||||
|
case CallForHelpFromPhoto = 2492;
|
||||||
|
case CallForHelpFromSelfie = 2755;
|
||||||
|
case ChatReviewGuideDecides = 3365;
|
||||||
|
case ChatReviewGuideDetached = 2501;
|
||||||
|
case ChatReviewGuideVote = 3961;
|
||||||
|
case ChatReviewSessionCreate = 3060;
|
||||||
|
case DeletePendingCallsForHelp = 3605;
|
||||||
|
case GetCfhStatus = 2746;
|
||||||
|
case GetFaqCategory = 3445;
|
||||||
|
case GetFaqText = 1849;
|
||||||
|
case GetGuideReportingStatus = 3786;
|
||||||
|
case GetPendingCallsForHelp = 3267;
|
||||||
|
case GetQuizQuestions = 1296;
|
||||||
|
case GuideSessionCreate = 3338;
|
||||||
|
case GuideSessionFeedback = 477;
|
||||||
|
case GuideSessionGetRequesterRoom = 1052;
|
||||||
|
case GuideSessionGuideDecides = 1424;
|
||||||
|
case GuideSessionInviteRequester = 234;
|
||||||
|
case GuideSessionIsTyping = 519;
|
||||||
|
case GuideSessionMessage = 3899;
|
||||||
|
case GuideSessionOnDutyUpdate = 1922;
|
||||||
|
case GuideSessionReport = 3969;
|
||||||
|
case GuideSessionRequesterCancels = 291;
|
||||||
|
case GuideSessionResolved = 887;
|
||||||
|
case PostQuizAnswers = 3720;
|
||||||
|
case SearchFaqs = 2031;
|
||||||
|
case PollAnswer = 3505;
|
||||||
|
case PollReject = 1773;
|
||||||
|
case PollStart = 109;
|
||||||
|
case PollVoteCounter = 6200;
|
||||||
|
case Disconnect = 2445;
|
||||||
|
case ScrGetKickbackInfo = 869;
|
||||||
|
case CompostPlant = 3835;
|
||||||
|
case HarvestPet = 1521;
|
||||||
|
case SetClothingChangeData = 924;
|
||||||
|
case GroupUnfavorite = 1820;
|
||||||
|
case NewUserExperienceGetGifts = 1822;
|
||||||
|
case NewUserExperienceScriptProceed = 1299;
|
||||||
|
case HandshakeInitDiffie = 3110;
|
||||||
|
case HandshakeCompleteDiffie = 773;
|
||||||
|
case WelcomeOpenGift = 2638;
|
||||||
|
case WelcomeGiftChangeEmail = 66;
|
||||||
|
case EmailGetStatus = 2557;
|
||||||
|
case EmailChange = 3965;
|
||||||
|
case ApproveAllMembershipRequests = 882;
|
||||||
|
case RentableSpaceCancelRent = 1667;
|
||||||
|
case RentableSpaceRent = 2946;
|
||||||
|
case RentableSpaceStatus = 872;
|
||||||
|
case TrackingPerformanceLog = 3230;
|
||||||
|
case TrackingLagWarningReport = 3847;
|
||||||
|
case RoomDirectoryRoomNetworkOpenConnection = 3736;
|
||||||
|
case RentableExtendRentOrBuyoutStripItem = 2115;
|
||||||
|
case RentableExtendRentOrBuyoutFurni = 1071;
|
||||||
|
case RentableGetRentOrBuyoutOffer = 2518;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages\Incoming;
|
||||||
|
|
||||||
|
use Emulator\Network\Game\Sessions\Session;
|
||||||
|
|
||||||
|
interface IMessageEvent {
|
||||||
|
function handle(Session $session, ClientMessage $clientMessage): void;
|
||||||
|
function getHeader(): Header;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages;
|
||||||
|
|
||||||
|
use Emulator\Core\Logging\Logger;
|
||||||
|
use Emulator\Messages\Incoming\ClientMessage;
|
||||||
|
use Emulator\Messages\Incoming\Handshake\ReleaseVersionMessageEvent;
|
||||||
|
use Emulator\Messages\Incoming\Handshake\SecurityTicketMessageEvent;
|
||||||
|
use Emulator\Messages\Incoming\Header;
|
||||||
|
use Emulator\Network\Game\Sessions\Session;
|
||||||
|
use SplObjectStorage;
|
||||||
|
|
||||||
|
class MessageHandler {
|
||||||
|
private static ?MessageHandler $instance = null;
|
||||||
|
private SplObjectStorage $handlers;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->handlers = new SplObjectStorage();
|
||||||
|
$this->handlers[Header::ReleaseVersion] = new ReleaseVersionMessageEvent();
|
||||||
|
$this->handlers[Header::SecurityTicket] = new SecurityTicketMessageEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handlePacket(Session $session, ClientMessage $request): void {
|
||||||
|
if (($header = Header::tryFrom($request->getHeader()))) {
|
||||||
|
if ($this->handlers->contains($header)) {
|
||||||
|
$this->handlers[$header]->handle($session, $request);
|
||||||
|
} else {
|
||||||
|
Logger::warn("[{$request->getHeader()}] [$header->name] - Unregistered!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger::warn("[{$request->getHeader()}] - Unregistered!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getInstance(): MessageHandler {
|
||||||
|
if (self::$instance === null)
|
||||||
|
self::$instance = new self();
|
||||||
|
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages\Outgoing\Handshake;
|
||||||
|
|
||||||
|
use Emulator\Messages\Outgoing\Header;
|
||||||
|
use Emulator\Messages\Outgoing\IMessageComposer;
|
||||||
|
use Emulator\Messages\Outgoing\ServerMessage;
|
||||||
|
use Override;
|
||||||
|
|
||||||
|
class AuthenticatedComposer implements IMessageComposer
|
||||||
|
{
|
||||||
|
|
||||||
|
#[Override] function compose(ServerMessage $message): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Override] function getHeader(): Header {
|
||||||
|
return Header::Authenticated;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,467 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages\Outgoing;
|
||||||
|
|
||||||
|
enum Header : int {
|
||||||
|
case AchievementList = 305;
|
||||||
|
case Authenticated = 2491;
|
||||||
|
case Authentication = -1;
|
||||||
|
case AvailabilityStatus = 2033;
|
||||||
|
case ClubOffers = 2405;
|
||||||
|
case CatalogPage = 804;
|
||||||
|
case CatalogPageList = 1032;
|
||||||
|
case CatalogPurchaseOk = 869;
|
||||||
|
case CatalogPurchaseError = 1404;
|
||||||
|
case CatalogPurchaseNotAllowed = 3770;
|
||||||
|
case ProductOffer = 3388;
|
||||||
|
case LimitedSoldOut = 377;
|
||||||
|
case CatalogPublished = 1866;
|
||||||
|
case CfhResultMessage = 3635;
|
||||||
|
case ClientLatency = 10;
|
||||||
|
case ClientPing = 3928;
|
||||||
|
case DesktopView = 122;
|
||||||
|
case BundleDiscountRuleset = 2347;
|
||||||
|
case FirstLoginOfDay = 793;
|
||||||
|
case FurnitureAliases = 1723;
|
||||||
|
case FurnitureData = 2547;
|
||||||
|
case FurnitureFloor = 1778;
|
||||||
|
case FurnitureFloorAdd = 1534;
|
||||||
|
case FurnitureFloorRemove = 2703;
|
||||||
|
case FurnitureFloorUpdate = 3776;
|
||||||
|
case FurnitureItemdata = 2202;
|
||||||
|
case FurnitureState = 2376;
|
||||||
|
case FurnitureGroupContextMenuInfo = 3293;
|
||||||
|
case FurniturePostitStickyPoleOpen = 2366;
|
||||||
|
case GameCenterAchievements = 2265;
|
||||||
|
case GameCenterGameList = 222;
|
||||||
|
case GameCenterStatus = 2893;
|
||||||
|
case GameCenterInArenaQueue = 872;
|
||||||
|
case GameCenterStopCounter = 3191;
|
||||||
|
case GameCenterUserLeftGame = 3138;
|
||||||
|
case GameCenterDirectoryStatus = 2246;
|
||||||
|
case GameCenterStartingGameFailed = 2142;
|
||||||
|
case GameCenterJoiningFailed = 1730;
|
||||||
|
case Gamestatusmessage = 3805;
|
||||||
|
case Gameachievements = 1689;
|
||||||
|
case Gameinvite = 904;
|
||||||
|
case Joiningqueuefailed = 3035;
|
||||||
|
case Joinedqueuemessage = 2260;
|
||||||
|
case Leftqueue = 1477;
|
||||||
|
case LoadGameUrl = 2624;
|
||||||
|
case Loadgame = 3654;
|
||||||
|
case Unloadgame = 1715;
|
||||||
|
case Achievementresolutioncompleted = 740;
|
||||||
|
case Achievementresolutionprogress = 3370;
|
||||||
|
case Achievementresolutions = 66;
|
||||||
|
case GenericAlert = 3801;
|
||||||
|
case ModeratorMessage = 2030;
|
||||||
|
case GenericError = 1600;
|
||||||
|
case GiftWrapperConfig = 2234;
|
||||||
|
case GroupBadges = 2402;
|
||||||
|
case GroupCreateOptions = 2159;
|
||||||
|
case GroupForumData = 3011;
|
||||||
|
case GroupForumList = 3001;
|
||||||
|
case GroupForumThreads = 1073;
|
||||||
|
case GroupForumPost = 2049;
|
||||||
|
case GroupForumPostThread = 1862;
|
||||||
|
case GroupForumThreadMessages = 509;
|
||||||
|
case GroupForumUnreadCount = 2379;
|
||||||
|
case GroupForumUpdateMessage = 324;
|
||||||
|
case GroupForumUpdateThread = 2528;
|
||||||
|
case GroupInfo = 1702;
|
||||||
|
case GroupList = 420;
|
||||||
|
case GroupMember = 265;
|
||||||
|
case GroupMembers = 1200;
|
||||||
|
case GroupMembersRefresh = 2445;
|
||||||
|
case GroupMemberRemoveConfirm = 1876;
|
||||||
|
case GroupPurchased = 2808;
|
||||||
|
case GroupSettings = 3965;
|
||||||
|
case GroupBadgeParts = 2238;
|
||||||
|
case GroupMembershipRequested = 1180;
|
||||||
|
case GroupDetailsChanged = 1459;
|
||||||
|
case GroupHabboJoinFailed = 762;
|
||||||
|
case GuildEditFailed = 3988;
|
||||||
|
case GuildMemberMgmtFailed = 818;
|
||||||
|
case ItemDimmerSettings = 2710;
|
||||||
|
case ItemStackHelper = 2816;
|
||||||
|
case ItemWall = 1369;
|
||||||
|
case ItemWallAdd = 2187;
|
||||||
|
case ItemWallRemove = 3208;
|
||||||
|
case ItemWallUpdate = 2009;
|
||||||
|
case MarketplaceConfig = 1823;
|
||||||
|
case MessengerAcceptFriends = 896;
|
||||||
|
case MessengerChat = 1587;
|
||||||
|
case MessengerFindFriends = 1210;
|
||||||
|
case MessengerFollowFailed = 3048;
|
||||||
|
case MessengerFriendNotification = 3082;
|
||||||
|
case MessengerFriends = 3130;
|
||||||
|
case MessengerInit = 1605;
|
||||||
|
case MessengerInstanceMessageError = 3359;
|
||||||
|
case MessengerInvite = 3870;
|
||||||
|
case MessengerInviteError = 462;
|
||||||
|
case MessengerMinimailCount = 2803;
|
||||||
|
case MessengerMinimailNew = 1911;
|
||||||
|
case MessengerRelationships = 2016;
|
||||||
|
case MessengerRequest = 2219;
|
||||||
|
case MessengerRequestError = 892;
|
||||||
|
case MessengerRequests = 280;
|
||||||
|
case MessengerSearch = 973;
|
||||||
|
case MessengerUpdate = 2800;
|
||||||
|
case ModerationTool = 2696;
|
||||||
|
case ModerationUserInfo = 2866;
|
||||||
|
case MotdMessages = 2035;
|
||||||
|
case NavigatorCategories = 1562;
|
||||||
|
case NavigatorCollapsed = 1543;
|
||||||
|
case NavigatorEventCategories = 3244;
|
||||||
|
case NavigatorLifted = 3104;
|
||||||
|
case NavigatorMetadata = 3052;
|
||||||
|
case NavigatorOpenRoomCreator = 2064;
|
||||||
|
case NavigatorSearch = 2690;
|
||||||
|
case NavigatorSearches = 3984;
|
||||||
|
case NavigatorSettings = 518;
|
||||||
|
case ThumbnailUpdateResult = 1927;
|
||||||
|
case CanCreateRoom = 378;
|
||||||
|
case CategoriesWithVisitorCount = 1455;
|
||||||
|
case CompetitionRoomsData = 3954;
|
||||||
|
case ConvertedRoomId = 1331;
|
||||||
|
case GuestRoomSearchResult = 52;
|
||||||
|
case NotificationList = 1992;
|
||||||
|
case NotificationOfferRewardDelivered = 2125;
|
||||||
|
case NotificationSimpleAlert = 5100;
|
||||||
|
case NotificationElementPointer = 1787;
|
||||||
|
case PetFigureUpdate = 1924;
|
||||||
|
case PetInfo = 2901;
|
||||||
|
case PetTrainingPanel = 1164;
|
||||||
|
case PetLevelUpdate = 2824;
|
||||||
|
case PetScratchFailed = 1130;
|
||||||
|
case PetOpenPackageRequested = 2380;
|
||||||
|
case PetOpenPackageResult = 546;
|
||||||
|
case PetBreeding = 1746;
|
||||||
|
case PetConfirmBreedingResult = 1625;
|
||||||
|
case PetGoToBreedingNestFailure = 2621;
|
||||||
|
case PetNestBreedingSuccess = 2527;
|
||||||
|
case PetConfirmBreedingRequest = 634;
|
||||||
|
case PetBreedingResult = 1553;
|
||||||
|
case RecyclerPrizes = 3164;
|
||||||
|
case RecyclerStatus = 3433;
|
||||||
|
case RecyclerFinished = 468;
|
||||||
|
case RoomBanList = 1869;
|
||||||
|
case RoomBanRemove = 3429;
|
||||||
|
case RoomCreated = 1304;
|
||||||
|
case RoomDoorbell = 2309;
|
||||||
|
case RoomDoorbellAccepted = 3783;
|
||||||
|
case RoomDoorbellRejected = 878;
|
||||||
|
case RoomEnter = 758;
|
||||||
|
case RoomEnterError = 899;
|
||||||
|
case RoomForward = 160;
|
||||||
|
case RoomHeightMap = 2753;
|
||||||
|
case RoomHeightMapUpdate = 558;
|
||||||
|
case RoomInfo = 687;
|
||||||
|
case RoomInfoOwner = 749;
|
||||||
|
case RoomModel = 1301;
|
||||||
|
case RoomModelBlockedTiles = 3990;
|
||||||
|
case RoomModelDoor = 1664;
|
||||||
|
case RoomModelName = 2031;
|
||||||
|
case RoomMuted = 2533;
|
||||||
|
case RoomPaint = 2454;
|
||||||
|
case RoomPromotion = 2274;
|
||||||
|
case RoomQueueStatus = 2208;
|
||||||
|
case RoomRights = 780;
|
||||||
|
case RoomRightsClear = 2392;
|
||||||
|
case RoomRightsList = 1284;
|
||||||
|
case RoomRightsListAdd = 2088;
|
||||||
|
case RoomRightsListRemove = 1327;
|
||||||
|
case RoomRightsOwner = 339;
|
||||||
|
case RoomRolling = 3207;
|
||||||
|
case RoomScore = 482;
|
||||||
|
case RoomSettings = 1498;
|
||||||
|
case RoomSettingsChat = 1191;
|
||||||
|
case RoomSettingsSave = 948;
|
||||||
|
case RoomSettingsSaveError = 1555;
|
||||||
|
case RoomInfoUpdated = 3297;
|
||||||
|
case RoomSpectator = 1033;
|
||||||
|
case RoomThickness = 3547;
|
||||||
|
case RoomGetFilterWords = 2937;
|
||||||
|
case RoomMessageNotification = 1634;
|
||||||
|
case RoomPopularTagsResult = 2012;
|
||||||
|
case InfoFeedEnable = 3284;
|
||||||
|
case SecurityMachine = 1488;
|
||||||
|
case MysteryBoxKeys = 2833;
|
||||||
|
case Gotmysteryboxprizemessage = 3712;
|
||||||
|
case Cancelmysteryboxwaitmessage = 596;
|
||||||
|
case Showmysteryboxwaitmessage = 3201;
|
||||||
|
case TradeAccepted = 2568;
|
||||||
|
case TradeClosed = 1373;
|
||||||
|
case TradeCompleted = 1001;
|
||||||
|
case TradeConfirmation = 2720;
|
||||||
|
case TradeListItem = 2024;
|
||||||
|
case TradeNotOpen = 3128;
|
||||||
|
case TradeOpen = 2505;
|
||||||
|
case TradeOpenFailed = 217;
|
||||||
|
case TradeOtherNotAllowed = 1254;
|
||||||
|
case TradeYouNotAllowed = 3058;
|
||||||
|
case TradeNoSuchItem = 2873;
|
||||||
|
case Unit = 374;
|
||||||
|
case UnitChangeName = 2182;
|
||||||
|
case UnitChat = 1446;
|
||||||
|
case UnitChatShout = 1036;
|
||||||
|
case UnitChatWhisper = 2704;
|
||||||
|
case UnitDance = 2233;
|
||||||
|
case UnitEffect = 1167;
|
||||||
|
case UnitExpression = 1631;
|
||||||
|
case UnitHandItem = 1474;
|
||||||
|
case UnitIdle = 1797;
|
||||||
|
case UnitInfo = 3920;
|
||||||
|
case UnitNumber = 2324;
|
||||||
|
case UnitRemove = 2661;
|
||||||
|
case UnitStatus = 1640;
|
||||||
|
case UnitTyping = 1717;
|
||||||
|
case UnseenItems = 2103;
|
||||||
|
case UserAchievementScore = 1968;
|
||||||
|
case UserBadges = 717;
|
||||||
|
case UserBadgesAdd = 2493;
|
||||||
|
case UserBadgesCurrent = 1087;
|
||||||
|
case UserBots = 3086;
|
||||||
|
case UserChangeName = 118;
|
||||||
|
case UserClothing = 1450;
|
||||||
|
case UserCredits = 3475;
|
||||||
|
case UserCurrency = 2018;
|
||||||
|
case ActivityPointNotification = 2275;
|
||||||
|
case UserFavoriteRoom = 2524;
|
||||||
|
case UserFavoriteRoomCount = 151;
|
||||||
|
case UserFigure = 2429;
|
||||||
|
case UserFurniture = 994;
|
||||||
|
case UserFurnitureAdd = 104;
|
||||||
|
case UserFurniturePostitPlaced = 1501;
|
||||||
|
case UserFurnitureRefresh = 3151;
|
||||||
|
case UserFurnitureRemove = 159;
|
||||||
|
case UserHomeRoom = 2875;
|
||||||
|
case RoomEventCancel = 3479;
|
||||||
|
case RoomEvent = 1840;
|
||||||
|
case UserIgnored = 126;
|
||||||
|
case UserIgnoredResult = 207;
|
||||||
|
case UserInfo = 2725;
|
||||||
|
case UserPerks = 2586;
|
||||||
|
case UserPermissions = 411;
|
||||||
|
case UserPetAdd = 2101;
|
||||||
|
case UserPetRemove = 3253;
|
||||||
|
case UserPets = 3522;
|
||||||
|
case UserProfile = 3898;
|
||||||
|
case UserRespect = 2815;
|
||||||
|
case UserSanctionStatus = 3679;
|
||||||
|
case UserSettings = 513;
|
||||||
|
case UserSubscription = 954;
|
||||||
|
case UserWardrobePage = 3315;
|
||||||
|
case UserClassification = 966;
|
||||||
|
case GetUserTags = 1255;
|
||||||
|
case WiredAction = 1434;
|
||||||
|
case WiredCondition = 1108;
|
||||||
|
case WiredError = 156;
|
||||||
|
case WiredOpen = 1830;
|
||||||
|
case WiredReward = 178;
|
||||||
|
case WiredSave = 1155;
|
||||||
|
case WiredTrigger = 383;
|
||||||
|
case PlayingGame = 448;
|
||||||
|
case FurnitureState2 = 3431;
|
||||||
|
case RemoveBotFromInventory = 233;
|
||||||
|
case AddBotToInventory = 1352;
|
||||||
|
case AchievementProgressed = 2107;
|
||||||
|
case ModtoolRoomInfo = 1333;
|
||||||
|
case ModtoolUserChatlog = 3377;
|
||||||
|
case ModtoolRoomChatlog = 3434;
|
||||||
|
case ModtoolVisitedRoomsUser = 1752;
|
||||||
|
case ModeratorActionResult = 2335;
|
||||||
|
case IssueDeleted = 3192;
|
||||||
|
case IssueInfo = 3609;
|
||||||
|
case IssuePickFailed = 3150;
|
||||||
|
case CfhChatlog = 607;
|
||||||
|
case ModeratorToolPreferences = 1576;
|
||||||
|
case LovelockFurniStart = 3753;
|
||||||
|
case LovelockFurniFriendComfirmed = 382;
|
||||||
|
case LovelockFurniFinished = 770;
|
||||||
|
case GiftReceiverNotFound = 1517;
|
||||||
|
case GiftOpened = 56;
|
||||||
|
case FloodControl = 566;
|
||||||
|
case RemainingMute = 826;
|
||||||
|
case UserEffectList = 340;
|
||||||
|
case UserEffectListAdd = 2867;
|
||||||
|
case UserEffectListRemove = 2228;
|
||||||
|
case UserEffectActivate = 1959;
|
||||||
|
case AvatarEffectSelected = 3473;
|
||||||
|
case ClubGiftInfo = 619;
|
||||||
|
case RedeemVoucherError = 714;
|
||||||
|
case RedeemVoucherOk = 3336;
|
||||||
|
case InClientLink = 2023;
|
||||||
|
case BotCommandConfiguration = 1618;
|
||||||
|
case BotSkillListUpdate = 69;
|
||||||
|
case BotForceOpenContextMenu = 296;
|
||||||
|
case HandItemReceived = 354;
|
||||||
|
case PetPlacingError = 2913;
|
||||||
|
case BotError = 639;
|
||||||
|
case MarketplaceSellItem = 54;
|
||||||
|
case MarketplaceItemStats = 725;
|
||||||
|
case MarketplaceOwnItems = 3884;
|
||||||
|
case MarketplaceCancelSale = 3264;
|
||||||
|
case MarketplaceItemPosted = 1359;
|
||||||
|
case MarketplaceItemsSearched = 680;
|
||||||
|
case MarketplaceAfterOrderStatus = 2032;
|
||||||
|
case CatalogReceivePetBreeds = 3331;
|
||||||
|
case CatalogApproveNameResult = 1503;
|
||||||
|
case ObjectsDataUpdate = 1453;
|
||||||
|
case PetExperience = 2156;
|
||||||
|
case CommunityGoalVoteEvent = 1435;
|
||||||
|
case PromoArticles = 286;
|
||||||
|
case CommunityGoalEarnedPrizes = 3319;
|
||||||
|
case CommunityGoalProgress = 2525;
|
||||||
|
case ConcurrentUsersGoalProgress = 2737;
|
||||||
|
case QuestDaily = 1878;
|
||||||
|
case QuestCancelled = 3027;
|
||||||
|
case QuestCompleted = 949;
|
||||||
|
case CommunityGoalHallOfFame = 3005;
|
||||||
|
case EpicPopup = 3945;
|
||||||
|
case SeasonalQuests = 1122;
|
||||||
|
case Quests = 3625;
|
||||||
|
case Quest = 230;
|
||||||
|
case BonusRareInfo = 1533;
|
||||||
|
case CraftableProducts = 1000;
|
||||||
|
case CraftingRecipe = 2774;
|
||||||
|
case CraftingRecipesAvailable = 2124;
|
||||||
|
case CraftingResult = 618;
|
||||||
|
case CameraPublishStatus = 2057;
|
||||||
|
case CameraPurchaseOk = 2783;
|
||||||
|
case CameraStorageUrl = 3696;
|
||||||
|
case CameraSnapshot = 463;
|
||||||
|
case CompetitionStatus = 133;
|
||||||
|
case InitCamera = 3878;
|
||||||
|
case ThumbnailStatus = 3595;
|
||||||
|
case AchievementNotification = 806;
|
||||||
|
case ClubGiftNotification = 2188;
|
||||||
|
case InterstitialMessage = 1808;
|
||||||
|
case RoomAdError = 1759;
|
||||||
|
case AvailabilityTime = 600;
|
||||||
|
case HotelClosedAndOpens = 3728;
|
||||||
|
case HotelClosesAndOpensAt = 2771;
|
||||||
|
case HotelWillCloseMinutes = 1050;
|
||||||
|
case HotelMaintenance = 1350;
|
||||||
|
case JukeboxPlaylistFull = 105;
|
||||||
|
case JukeboxSongDisks = 34;
|
||||||
|
case NowPlaying = 469;
|
||||||
|
case OfficialSongId = 1381;
|
||||||
|
case Playlist = 1748;
|
||||||
|
case PlaylistSongAdded = 1140;
|
||||||
|
case TraxSongInfo = 3365;
|
||||||
|
case UserSongDisksInventory = 2602;
|
||||||
|
case CheckUserName = 563;
|
||||||
|
case CfhSanction = 2782;
|
||||||
|
case CfhTopics = 325;
|
||||||
|
case CfhSanctionStatus = 2221;
|
||||||
|
case CampaignCalendarData = 2531;
|
||||||
|
case CampaignCalendarDoorOpened = 2551;
|
||||||
|
case BuildersClubFurniCount = 3828;
|
||||||
|
case BuildersClubSubscription = 1452;
|
||||||
|
case CatalogPageExpiration = 2668;
|
||||||
|
case CatalogEarliestExpiry = 2515;
|
||||||
|
case ClubGiftSelected = 659;
|
||||||
|
case TargetOfferNotFound = 1237;
|
||||||
|
case TargetOffer = 119;
|
||||||
|
case DirectSmsClubBuy = 195;
|
||||||
|
case RoomAdPurchase = 2468;
|
||||||
|
case NotEnoughBalance = 3914;
|
||||||
|
case LimitedOfferAppearingNext = 44;
|
||||||
|
case IsOfferGiftable = 761;
|
||||||
|
case ClubExtendedOffer = 3964;
|
||||||
|
case SeasonalCalendarOffer = 1889;
|
||||||
|
case CompetitionEntrySubmit = 1177;
|
||||||
|
case CompetitionVotingInfo = 3506;
|
||||||
|
case CompetitionTimingCode = 1745;
|
||||||
|
case CompetitionUserPartOf = 3841;
|
||||||
|
//case CompetitionNoOwnedRooms = 2064;
|
||||||
|
case CompetitionSecondsUntil = 3926;
|
||||||
|
case BadgePointLimits = 2501;
|
||||||
|
case BadgeRequestFulfilled = 2998;
|
||||||
|
case HelperTalentTrack = 3406;
|
||||||
|
case TalentTrackLevel = 1203;
|
||||||
|
case TalentTrackLevelUp = 638;
|
||||||
|
case UserBanned = 1683;
|
||||||
|
case BotReceived = 3684;
|
||||||
|
case PetLevelNotification = 859;
|
||||||
|
case PetReceived = 1111;
|
||||||
|
case ModerationCaution = 1890;
|
||||||
|
case YoutubeControlVideo = 1554;
|
||||||
|
case YoutubeDisplayPlaylists = 1112;
|
||||||
|
case YoutubeDisplayVideo = 1411;
|
||||||
|
case CfhDisabledNotify = 1651;
|
||||||
|
case Question = 2665;
|
||||||
|
case PollContents = 2997;
|
||||||
|
case PollError = 662;
|
||||||
|
case PollOffer = 3785;
|
||||||
|
case PollRoomResult = 5201;
|
||||||
|
case PollStartRoom = 5200;
|
||||||
|
case QuestionAnswered = 2589;
|
||||||
|
case QuestionFinished = 1066;
|
||||||
|
case CfhPendingCalls = 1121;
|
||||||
|
case GuideOnDutyStatus = 1548;
|
||||||
|
case GuideSessionAttached = 1591;
|
||||||
|
case GuideSessionDetached = 138;
|
||||||
|
case GuideSessionEnded = 1456;
|
||||||
|
case GuideSessionError = 673;
|
||||||
|
case GuideSessionInvitedToGuideRoom = 219;
|
||||||
|
case GuideSessionMessage = 841;
|
||||||
|
case GuideSessionPartnerIsTyping = 1016;
|
||||||
|
case GuideSessionRequesterRoom = 1847;
|
||||||
|
case GuideSessionStarted = 3209;
|
||||||
|
case GuideTicketCreationResult = 3285;
|
||||||
|
case GuideTicketResolution = 2674;
|
||||||
|
case GuideReportingStatus = 3463;
|
||||||
|
case HotelMergeNameChange = 1663;
|
||||||
|
case IssueCloseNotification = 934;
|
||||||
|
case QuizData = 2927;
|
||||||
|
case QuizResults = 2772;
|
||||||
|
case CfhPendingCallsDeleted = 77;
|
||||||
|
case CfhReply = 3796;
|
||||||
|
case ChatReviewSessionDetached = 30;
|
||||||
|
case ChatReviewSessionOfferedToGuide = 735;
|
||||||
|
case ChatReviewSessionResults = 3276;
|
||||||
|
case ChatReviewSessionStarted = 143;
|
||||||
|
case ChatReviewSessionVotingStatus = 1829;
|
||||||
|
case ScrSendKickbackInfo = 3277;
|
||||||
|
case PetStatus = 1907;
|
||||||
|
case GroupDeactivate = 3129;
|
||||||
|
case PetRespected = 2788;
|
||||||
|
case PetSupplement = 3441;
|
||||||
|
case NoobnessLevel = 3738;
|
||||||
|
case DisconnectReason = 4000;
|
||||||
|
case CanCreateRoomEvent = 2599;
|
||||||
|
case FavoriteGroupUdpate = 3403;
|
||||||
|
case NoSuchFlat = 84;
|
||||||
|
case RoomSettingsError = 2897;
|
||||||
|
case ShowEnforceRoomCategory = 3896;
|
||||||
|
case CustomUserNotification = 909;
|
||||||
|
case NewUserExperienceGiftOffer = 3575;
|
||||||
|
case RestoreClient = 426;
|
||||||
|
case FireworkChargeData = 5210;
|
||||||
|
case NewUserExperienceNotComplete = 3639;
|
||||||
|
case ConnectionError = 1004;
|
||||||
|
case AccountSafetyLockStatusChange = 1243;
|
||||||
|
case PhoneCollectionState = 2890;
|
||||||
|
case PhoneTryNumberResult = 800;
|
||||||
|
case PhoneTryVerificationCodeResult = 91;
|
||||||
|
case ExtendedProfileChanged = 876;
|
||||||
|
case WelcomeGiftChangeEmailResult = 2293;
|
||||||
|
case WelcomeGiftStatus = 2707;
|
||||||
|
case HandshakeInitDiffie = 1347;
|
||||||
|
case HandshakeCompleteDiffie = 3885;
|
||||||
|
case RentableSpaceRentOk = 2046;
|
||||||
|
case RentableSpaceStatus = 3559;
|
||||||
|
case RentableSpaceRentFailed = 1868;
|
||||||
|
case EmailStatus = 612;
|
||||||
|
case ChangeEmailResult = 1815;
|
||||||
|
case WeeklyGameReward = 2641;
|
||||||
|
case WeeklyGameRewardWinners = 3097;
|
||||||
|
case WeeklyCompetitiveLeaderboard = 3512;
|
||||||
|
case WeeklyCompetitiveFriendsLeaderboard = 3560;
|
||||||
|
case WeeklyGame2FriendsLeaderboard = 2270;
|
||||||
|
case WeeklyGame2Leaderboard = 2196;
|
||||||
|
case RentableFurniRentOrBuyoutOffer = 35;
|
||||||
|
case HandshakeIdentityAccount = 3523;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages\Outgoing;
|
||||||
|
|
||||||
|
interface IMessageComposer {
|
||||||
|
function compose(ServerMessage $message): void;
|
||||||
|
function getHeader(): Header;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Messages\Outgoing;
|
||||||
|
|
||||||
|
use Emulator\Encoding\ByteEncoding;
|
||||||
|
|
||||||
|
class ServerMessage {
|
||||||
|
private array $packet = [];
|
||||||
|
|
||||||
|
function __construct(int $header) {
|
||||||
|
$this->writeInt16($header);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeInt16(int $value): void {
|
||||||
|
$this->packet = array_merge($this->packet, ByteEncoding::int16ToArray($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeInt32(int $value): void {
|
||||||
|
$this->packet = array_merge($this->packet, ByteEncoding::int32ToArray($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeBoolean(bool $value): void {
|
||||||
|
$this->packet[] = ($value ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeString(string $value): void {
|
||||||
|
$this->writeInt16(strlen($value));
|
||||||
|
$this->packet = array_merge($this->packet, unpack('C*', $value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPacket(): array {
|
||||||
|
return $this->packet;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Network\Game;
|
||||||
|
|
||||||
|
use Emulator\Core\Logging\Logger;
|
||||||
|
use Emulator\Encoding\ByteEncoding;
|
||||||
|
use Emulator\Messages\Incoming\ClientMessage;
|
||||||
|
use Emulator\Messages\MessageHandler;
|
||||||
|
use Emulator\Network\Game\Sessions\Session;
|
||||||
|
use Override;
|
||||||
|
use Ratchet\ConnectionInterface;
|
||||||
|
use Ratchet\Http\HttpServer;
|
||||||
|
use Ratchet\RFC6455\Messaging\MessageInterface;
|
||||||
|
use Ratchet\Server\IoServer;
|
||||||
|
use Ratchet\WebSocket\MessageComponentInterface;
|
||||||
|
use Ratchet\WebSocket\WsConnection;
|
||||||
|
use Ratchet\WebSocket\WsServer;
|
||||||
|
use React\EventLoop\Loop;
|
||||||
|
use React\Socket\SocketServer;
|
||||||
|
|
||||||
|
class GameNetworkServer implements MessageComponentInterface {
|
||||||
|
private static ?GameNetworkServer $instance = null;
|
||||||
|
private array $sessions;
|
||||||
|
|
||||||
|
public function start(int $port): void {
|
||||||
|
$loop = Loop::get();
|
||||||
|
|
||||||
|
$this->sessions = [];
|
||||||
|
$socketServer = new SocketServer("127.0.0.1:{$port}", loop: $loop);
|
||||||
|
new IoServer(
|
||||||
|
new HttpServer(
|
||||||
|
new WsServer($this)
|
||||||
|
),
|
||||||
|
$socketServer,
|
||||||
|
$loop
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getInstance(): GameNetworkServer {
|
||||||
|
if (self::$instance === null) {
|
||||||
|
self::$instance = new self();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Override] function onOpen(ConnectionInterface $conn): void {
|
||||||
|
$this->sessions[$conn->resourceId] = new Session(new WsConnection($conn));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Override] function onClose(ConnectionInterface $conn): void {
|
||||||
|
unset($this->sessions[$conn->resourceId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Override] function onError(ConnectionInterface $conn, \Exception $e): void {
|
||||||
|
Logger::fatal($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Override] public function onMessage(ConnectionInterface $conn, MessageInterface $msg): void {
|
||||||
|
$raw = $msg->getPayload();
|
||||||
|
$data = unpack('C*', $raw);
|
||||||
|
|
||||||
|
if (count($data) >= 6) {
|
||||||
|
$length = ByteEncoding::getInt32(array_slice($data, 1, 4));
|
||||||
|
$packet = array_slice($data, 4, $length);
|
||||||
|
|
||||||
|
MessageHandler::getInstance()->handlePacket($this->sessions[$conn->resourceId], new ClientMessage($packet));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Emulator\Network\Game\Sessions;
|
||||||
|
|
||||||
|
use Emulator\Encoding\ByteEncoding;
|
||||||
|
use Emulator\Messages\Outgoing\IMessageComposer;
|
||||||
|
use Emulator\Messages\Outgoing\ServerMessage;
|
||||||
|
use Ratchet\RFC6455\Messaging\Frame;
|
||||||
|
use Ratchet\RFC6455\Messaging\Message;
|
||||||
|
use Ratchet\WebSocket\WsConnection;
|
||||||
|
|
||||||
|
readonly class Session {
|
||||||
|
private WsConnection $connection;
|
||||||
|
|
||||||
|
public function __construct(WsConnection $connection) {
|
||||||
|
$this->connection = $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendComposer(IMessageComposer $composer): void {
|
||||||
|
$headerData = pack('n', 2491);
|
||||||
|
$length = strlen($headerData);
|
||||||
|
$lengthData = pack('N', $length);
|
||||||
|
$binaryMessage = $lengthData . $headerData;
|
||||||
|
$frame = new Frame($binaryMessage, true, Frame::OP_BINARY);
|
||||||
|
$this->connection->send($frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
function encode($text) {
|
||||||
|
$b1 = 0x80 | (0x1 & 0x0f);
|
||||||
|
$length = strlen($text);
|
||||||
|
if ($length <= 125)
|
||||||
|
$header = pack('CC', $b1, $length);
|
||||||
|
elseif($length > 125 && $length < 65536)
|
||||||
|
$header = pack('CCn', $b1, 126, $length);
|
||||||
|
elseif($length >= 65536)
|
||||||
|
$header = pack('CCNN', $b1, 127, $length);
|
||||||
|
|
||||||
|
return $header.$text;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue