/* Copyright 2003-2007 ROBLOX Corporation, All Rights Reserved */ #pragma once #include "rbx/rbxTime.h" #include "v8tree/instance.h" #include "v8datamodel/team.h" #include "V8Datamodel/FriendService.h" #include "V8DataModel/Camera.h" #include "V8DataModel/StarterPlayerService.h" #include "Util/BrickColor.h" #include "Util/G3DCore.h" #include "Util/HeapValue.h" #include "Util/Rect.h" #include "util/RunningAverage.h" // for player mouse #include "V8Datamodel/Mouse.h" #include #include "v8datamodel/TeleportService.h" LOGGROUP(Network) LOGGROUP(Player) namespace RakNet { struct SystemAddress; } namespace RBX { class Visit; class ModelInstance; class Backpack; class TimerService; class Region2; class DataModelMesh; class Adorn; class Primitive; class PartInstance; class Humanoid; class DataModel; class SpawnLocation; namespace Network { class PersistentDataStore; extern const char* const sPlayer; class Player : public DescribedCreatable , public Diagnostics::Countable { private: typedef DescribedCreatable Super; shared_ptr character; // The ModelInstance that this player is represented by BrickColor teamColor; bool neutral; int loadAppearanceCounter; int dataComplexityLimit; bool dataReady; weak_ptr respawnLocation; CoordinateFrame cloudEditCameraCFrame; bool loadedStarterGear; // User Profile data bool superSafeChat; bool under13; int userId; // For Group Building bool hasGroupBuildTools; HeapValue personalServerRank; rbx::signals::scoped_connection characterDiedConnection; rbx::signals::scoped_connection backendDiedSignalConnection; rbx::signals::scoped_connection spawnLocationChangedConnection; rbx::signals::scoped_connection simulationRadiusChangedConnection; rbx::signals::scoped_connection setShutdownMessageConnection; boost::function teamStatusChangedCallback; // CharacterAppearance is the url of a handler that returns a delimited list of asset ids std::string characterAppearance; bool canLoadCharacterAppearance; // Distributed Simulation float simulationRadius; float maxSimulationRadius; std::string osPlatform; std::string vrDevice; int loadingInstances; bool appearanceDidLoad; bool characterAppearanceLoaded; // Only valid on the server! shared_ptr remoteAddress; bool forceEarlySpawnLocationCalculation; bool hasSpawnedAtLeastOnce; std::string teleportSpawnName; bool teleported; // describes whether player is currently in the middle of teleporting out bool teleportedIn; // describes whether player joined current place by teleporting std::string gameSessionID; struct SpawnData { Vector3 position; int forceFieldDuration; CoordinateFrame cf; SpawnData() : position(Vector3::zero()), forceFieldDuration(0) {} SpawnData(Vector3 position, int forceFieldDuration, CoordinateFrame frame) : position(position), forceFieldDuration(forceFieldDuration), cf(frame) {} }; boost::scoped_ptr nextSpawnLocation; int followUserId; // Instance /*override*/ bool askAddChild(const Instance* instance) const {return true;} /*override*/ void verifySetParent(const Instance* instance) const; /*override*/ void onServiceProvider(ServiceProvider* oldProvider, ServiceProvider* newProvider); void onCharacterChangedFrontend(); void registerLocalPlayerNotIdle(); void loadInsertPanel(DataModel* dataModel); shared_ptr persistentData; std::list > waitForDataReadyWaiters; void fireWaitForDataReady(); static void LoadDataResultHelper(boost::weak_ptr weakPlayer, shared_ptr result); void loadDataResult(shared_ptr result); bool autoJumpEnabled; public: enum MembershipType { MEMBERSHIP_NONE = 0, MEMBERSHIP_BUILDERS_CLUB = 1, MEMBERSHIP_TURBO_BUILDERS_CLUB = 2, MEMBERSHIP_OUTRAGEOUS_BUILDERS_CLUB = 3 }; enum ChatMode { CHAT_MODE_MENU = 0, CHAT_MODE_TEXT_AND_MENU = 1 }; enum ChatFilterType { CHAT_FILTER_WHITELIST, CHAT_FILTER_BLACKLIST }; // debug timer RBX::Timer appearanceFetchTimer; static Reflection::PropDescriptor prop_userId; static Reflection::PropDescriptor prop_userIdDeprecated; static Reflection::PropDescriptor prop_SuperSafeChat; static Reflection::BoundProp prop_SimulationRadius; static Reflection::BoundProp prop_MaxSimulationRadius; static Reflection::PropDescriptor prop_DeprecatedMaxSimulationRadius; static Reflection::BoundProp prop_OsPlatform; static Reflection::BoundProp prop_VRDevice; static Reflection::RemoteEventDesc)> event_cloudEditSelectionChanged; rbx::remote_signal scriptSecurityErrorSignal; rbx::remote_signal remoteInsertSignal; rbx::remote_signal connectDiedSignalBackend; rbx::remote_signal remoteFriendServiceSignal; rbx::remote_signal killPlayerSignal; rbx::remote_signal simulationRadiusChangedSignal; rbx::remote_signal statsSignal; rbx::signals::scoped_connection charChildAddedConnection; rbx::signal)> chattedSignal; rbx::signal)> characterAddedSignal; rbx::remote_signal)> CharacterAppearanceLoadedSignal; rbx::signal)> characterRemovingSignal; rbx::signal nextSpawnLocationChangedSignal; rbx::signal idledSignal; rbx::signal, FriendService::FriendStatus)> friendStatusChangedSignal; rbx::remote_signal onTeleportSignal; rbx::remote_signal, shared_ptr)> onTeleportInternalSignal; rbx::remote_signal setShutdownMessageSignal; rbx::remote_signal)> cloudEditSelectionChanged; Player(); ~Player(); void doFirstSpawnLocationCalculation(const ServiceProvider* serviceProvider, const std::string& preferedSpawnName); void reportScriptSecurityError(const std::string& hash, const std::string& error, const std::string& stack); void killPlayer(); void requestFriendship(shared_ptr player); void revokeFriendship(shared_ptr player); // Keyboard/Mouse input API shared_ptr getMouse() { return mouse; } shared_ptr getMouseInstance(); //Persistent Data API void loadData(); void saveData(); void saveLeaderboardData(); int getDataComplexityLimit() const { return dataComplexityLimit; } void setDataComplexityLimit(int value); int getDataComplexity() const; bool getDataReady() const { return dataReady; } void waitForDataReady(boost::function resumeFunction, boost::function errorFunction); double loadNumber(std::string key); void saveNumber(std::string key, double value); std::string loadString(std::string key); void saveString(std::string key, std::string value); bool loadBoolean(std::string key); void saveBoolean(std::string key, bool value); shared_ptr loadInstance(std::string key); void saveInstance(std::string key, shared_ptr value); shared_ptr loadList(std::string key); void saveList(std::string key, shared_ptr value); shared_ptr loadTable(std::string key); void saveTable(std::string key, shared_ptr value); /*override*/ void setName(const std::string& value); /*override*/ bool canClientCreate() { return true; } ModelInstance* getDangerousCharacter() const {return character.get();} boost::shared_ptr getSharedCharacter() {return character; } ModelInstance* getCharacter() {return character.get();} const ModelInstance* getConstCharacter() const {return character.get();} void setCharacter(ModelInstance* value); const SpawnLocation* getConstRespawnLocation() const { if (shared_ptr shared_respawnLocation = respawnLocation.lock()) return shared_respawnLocation.get(); else return NULL; } SpawnLocation* getDangerousRespawnLocation() const { if (shared_ptr shared_respawnLocation = respawnLocation.lock()) return shared_respawnLocation.get(); else return NULL; } void setRespawnLocation(SpawnLocation* value); bool getCanLoadCharacterAppearance() const { return canLoadCharacterAppearance;} void setCanLoadCharacterAppearance(bool value); bool getAutoJumpEnabled() const { return autoJumpEnabled; } void setAutoJumpEnabled(bool value); const PartInstance* hasCharacterHead(CoordinateFrame& headPos) const; bool getHasGroupBuildTools() const { return hasGroupBuildTools; } void setHasGroupBuildTools(bool value); void giveBuildTools(); void removeBuildTools(); void setAppearanceLoaded(); // Personal Server API void getWebPersonalServerRank(boost::function resumeFunction, boost::function errorFunction); void setWebPersonalServerRank(int newRank, boost::function resumeFunction, boost::function errorFunction); int getPersonalServerRank() const { return (personalServerRank > 255) ? 0 : personalServerRank; } // 255 is max rank allowed by setter. void setPersonalServerRank(int value); const Primitive* getConstCharacterRoot() const; BrickColor getTeamColor() const {return teamColor;} void setTeamColor(BrickColor value); bool getNeutral() const {return neutral;} void setNeutral(bool value); std::string getCharacterAppearance() const {return characterAppearance;} void setCharacterAppearance(const std::string& value); static void setAppearanceParent(weak_ptr player, weak_ptr instance, bool equipped); static void setGearParent(weak_ptr player, weak_ptr instance, bool equipped); bool getSuperSafeChat() const; void setSuperSafeChat(bool value); float getDeprecatedMaxSimulationRadius() const {return 0.f;} void setDeprecatedMaxSimulationRadius(float val){} ChatMode getChatMode() const; void setUnder13(bool value); bool getUnder13() {return under13;}; void setUserId(int value); int getUserID() const {return userId;} void setGameSessionID(std::string value); std::string getGameSessionID() { return gameSessionID; } bool isGuest() const { return userId < 0; } void setMembershipType(MembershipType value); MembershipType getMembershipType() const {return membershipType;} void setCameraMode(RBX::Camera::CameraMode value); RBX::Camera::CameraMode getCameraMode() const {return cameraMode;} void setNameDisplayDistance(float value); float getNameDisplayDistance() const {return nameDisplayDistance;} void setHealthDisplayDistance(float value); float getHealthDisplayDistance() const {return healthDisplayDistance;} void setCameraMaxZoomDistance(float _cameraMaxZoomDistance); float getCameraMaxZoomDistance() const {return cameraMaxZoomDistance;} void setCameraMinZoomDistance(float _cameraMinZoomDistance); float getCameraMinZoomDistance() const {return cameraMinZoomDistance;} void setDevEnableMouseLockOption(bool setting); bool getDevEnableMouseLockOption() const {return enableMouseLockOption;} void setDevTouchCameraMode(StarterPlayerService::DeveloperTouchCameraMovementMode setting); StarterPlayerService::DeveloperTouchCameraMovementMode getDevTouchCameraMode() const {return touchCameraMovementMode;} void setDevComputerCameraMode(StarterPlayerService::DeveloperComputerCameraMovementMode setting); StarterPlayerService::DeveloperComputerCameraMovementMode getDevComputerCameraMode() const {return computerCameraMovementMode;} void setDevCameraOcclusionMode(StarterPlayerService::DeveloperCameraOcclusionMode setting); StarterPlayerService::DeveloperCameraOcclusionMode getDevCameraOcclusionMode() const {return cameraOcclusionMode;} void setDevTouchMovementMode(StarterPlayerService::DeveloperTouchMovementMode setting); StarterPlayerService::DeveloperTouchMovementMode getDevTouchMovementMode() const {return touchMovementMode;} void setDevComputerMovementMode(StarterPlayerService::DeveloperComputerMovementMode setting); StarterPlayerService::DeveloperComputerMovementMode getDevComputerMovementMode() const {return computerMovementMode;} void setAccountAge(int value); int getAccountAge() const {return accountAge;} void updateSimulationRadius(float value); float getSimulationRadius() const {return simulationRadius;} void setSimulationRadius(float value); float getMaxSimulationRadius() const {return maxSimulationRadius;} void setMaxSimulationRadius(float value); CoordinateFrame getCloudEditCameraCoordinateFrame() const { return cloudEditCameraCFrame; } void setCloudEditCameraCoordinateFrame(const CoordinateFrame& cframe); std::string getOsPlatform() const {return osPlatform;} void rebuildBackpack(); // Copy the backpack from the StartPack service void rebuildGui(); // Copy the gui from the StarterGui service void rebuildPlayerScripts(); // Copy the LocalScripts from the StarterPlayer/PlayerScripts service void createPlayerGui(); Backpack* getPlayerBackpack(); const Backpack* getConstPlayerBackpack() const; void luaJumpCharacter(); void luaMoveCharacter(Vector2 walkDirection, float maxWalkDelta); void move(Vector3 walkVector, bool relativeToCamera); float distanceFromCharacter(Vector3 point); void luaLoadCharacter(bool inGame); void loadCharacter(bool inGame, std::string preferedSpawnName); void removeCharacter(); void removeCharacterAppearance(); void removeCharacterAppearanceScript(); void loadCharacterAppearance(bool blockingCall); void loadCharacterAppearanceScript(shared_ptr asset); static void onLocalPlayerNotIdle(RBX::ServiceProvider* serviceProvider); void renderDPhysicsRegion(Adorn* adorn); void renderStreamedRegion(Adorn* adorn); void renderPartMovementPath(Adorn* adorn); static bool physicsOutBandwidthExceeded(const RBX::Instance* context); static double getNetworkBufferHealth(const RBX::Instance* context); void reportStat(std::string stat); void addToLoadingInstances(int newInstances) { loadingInstances += newInstances; } void removeFromLoadingInstances(int oldInstances) { loadingInstances -= oldInstances; } int getLoadingInstances() { return loadingInstances; } bool getAppearanceDidLoad() const { return appearanceDidLoad; } bool getAppearanceDidLoadNonConst() { return appearanceDidLoad; } void setAppearanceDidLoad(bool value); bool getCharacterAppearanceLoaded() const { return characterAppearanceLoaded; } void setCharacterAppearanceLoaded(bool value); void onFriendStatusChanged(shared_ptr player, FriendService::FriendStatus friendStatus); FriendService::FriendStatus getFriendStatus(shared_ptr player); void isFriendsWith(int otherUserId, boost::function resumeFunction, boost::function errorFunction); void isBestFriendsWith(int otherUserId, boost::function resumeFunction, boost::function errorFunction); void isInGroup(int groupId, boost::function resumeFunction, boost::function errorFunction); void getRankInGroup(int groupId, boost::function resumeFunction, boost::function errorFunction); void getRoleInGroup(int groupId, boost::function resumeFunction, boost::function errorFunction); void getFriendsOnline(int maxFriends, boost::function)> resumeFunction, boost::function errorFunction); void loadChatInfo(); // should be called with at least data model read lock bool isChatInfoValid() const; ChatFilterType getChatFilterType() const; // for testing only void setChatInfo(ChatFilterType filterType); void kick(std::string msg); void handleTeleportInternalSignal(TeleportService::TeleportState teleportState, shared_ptr teleportInfo, shared_ptr customLoadingGUI); void handleTeleportSignalBackend(TeleportService::TeleportState teleportState); void setForceEarlySpawnLocationCalculation(); bool calculatesSpawnLocationEarly() const; const RakNet::SystemAddress& getRemoteAddress() const; const SystemAddress getRemoteAddressAsRbxAddress() const; void setRemoteAddress(const RakNet::SystemAddress& address); void onTeleport(TeleportService::TeleportState teleportState, int placeId, std::string instanceIdOrSpawnName); void onTeleportInternal(TeleportService::TeleportState teleportState, shared_ptr teleportInfo, shared_ptr customLoadingGUI = shared_ptr()); bool getTeleported() const { return teleported; } bool getTeleportedIn() const { return teleportedIn; } void setTeleportedIn(bool value); int getFollowUserId() const { return followUserId; } void setFollowUserId(int followUserId) { this->followUserId = followUserId; } void loadStarterGear(); void onCharacterDied(); /*override*/ void destroy(); private: void setupHumanoid(shared_ptr humanoid); void characterChildAdded(shared_ptr child); void doPeriodicIdleCheck(); void checkContextReadyToSpawnCharacter(); static void calculateNextSpawnLocationHelper( weak_ptr& weakPlayer, const ServiceProvider* serviceProvider); void calculateNextSpawnLocation(const ServiceProvider* serviceProvider); SpawnData calculateSpawnLocation(const std::string& preferedSpawnName); static void loadChatInfoInternal(weak_ptr weakPlayer); Time lastActivityTime; MembershipType membershipType; int accountAge; bool chatInfoHasBeenLoaded; ChatFilterType chatFilterType; shared_ptr mouse; RBX::Camera::CameraMode cameraMode; float nameDisplayDistance; float healthDisplayDistance; float cameraMaxZoomDistance; float cameraMinZoomDistance; bool enableMouseLockOption; RBX::StarterPlayerService::DeveloperTouchCameraMovementMode touchCameraMovementMode; RBX::StarterPlayerService::DeveloperComputerCameraMovementMode computerCameraMovementMode; RBX::StarterPlayerService::DeveloperCameraOcclusionMode cameraOcclusionMode; RBX::StarterPlayerService::DeveloperTouchMovementMode touchMovementMode; RBX::StarterPlayerService::DeveloperComputerMovementMode computerMovementMode; bool copiedGuiOnce; }; } // namespace } // namespace