msw-ai-tf/maplestory-worlds-creator-docs huggingface dataset:
SortableDataStoragePages

Provides a feature that can inquire about SortableDataStorage of the world.

# Properties

[{"index":"boolean IsLastPage (ReadOnly)","0":"Checks whether the current page is the last."}]

# Methods

[{"index":"table GetCurrentPageDatas() (ServerOnly)","0":"Gets a SortableDataStorage list of the current page."}]

[{"index":"int32 LoadNextPageAndWait() (ServerOnly) (Yield)","0":"Loads the next page and returns the error code. Can move to the loaded page using the MoveToNextPageAndWait() function. Suspends script executions during performance."}]

[{"index":"void MoveToNextPageAndWait() (ServerOnly) (Yield)","0":"Goes to the next page. Script executions are suspended during the operation."}]

# Examples

This is an example of code of traversing through pages.
    
    
    @Component
    script ContentPageIterator extends Component
        @ExecSpace("ServerOnly")
        method void OnBeginPlay()
            while true do
            	local datas = pages:GetCurrentPageDatas()
            	for _, data in pairs(datas) do
            		log(data.Name)
            	end
            
            	-- You can check if the current page is the last page using the IsLastPage property.
            	if pages.IsLastPage == true then
            		return
            	end
            
            	-- Preloads the data for the next page and stops the inquiry if the next page is invalid.
            	local loadResultCode = pages:LoadNextPageAndWait()
            	if loadResultCode ~= 0 then
            		return
            	end
            
            	-- Moves to the next page.
            	pages:MoveToNextPageAndWait()
            end
        end
    end
    

# SeeAlso

  * [Learning DataStorage Use Limits](/docs?postId=1044)
  * [Utilizing DataStorage](/docs?postId=692)
  * [Utilizing DataStorage Use Limits](/docs?postId=1045)
MapleAvatarBodyActionState

Identifies the specific animation of the avatar. Receives an event as BodyActionStateChangeEvent and outputs the avatar animation. It corresponds to the ActionSheet value of AvatarStateAnimationComponent.

# Members

[{"Name":"Invalid","Value":"0","Desc":"This is the default. Not used."},{"Name":"Stand","Value":"1","Desc":"stand value. Outputs the standing avatar."},{"Name":"Walk","Value":"2","Desc":"walk value. Outputs the walking avatar."},{"Name":"Attack","Value":"3","Desc":"attack value. Outputs the attacking avatar."},{"Name":"Alert","Value":"4","Desc":"alert value. Outputs the alert avatar."},{"Name":"Crouch","Value":"5","Desc":"crouch value. Outputs the crouching avatar."},{"Name":"Fall","Value":"6","Desc":"fall value. Outputs the avatar falling from the air."},{"Name":"Sit","Value":"7","Desc":"sit value. Outputs the sitting avatar."},{"Name":"Rope","Value":"8","Desc":"rope value. Outputs the avatar hanging on the rope."},{"Name":"Ladder","Value":"9","Desc":"ladder value. Outputs the avatar hanging from the ladder."},{"Name":"Dead","Value":"10","Desc":"dead value. Outputs the dead avatar."},{"Name":"Blink","Value":"11","Desc":"blink value. Outputs the temporarily disappearing avatar."},{"Name":"Fly","Value":"12","Desc":"fly value. Outputs the flying avatar."},{"Name":"Heal","Value":"13","Desc":"The heal value. Outputs the appearance of the avatar healing."},{"Name":"Hit","Value":"14","Desc":"hit value. Outputs the avatar being hit."}]

# Methods

[{"index":"MapleAvatarBodyActionState CastFrom(number value) (Static)","0":"Converts numbers to the applicable type."}]

[{"index":"MapleAvatarBodyActionState CastFrom(string value) (Static)","0":"Converts strings to the applicable type."}]
RandomSelectorNode

Randomly selects and executes a child node.

# Properties

##### inherited from BTNode:

[{"index":"boolean ExclusiveExecutionWhenRunning (Deprecated)","0":"This property is deprecated."}]

[{"index":"func InitFunction","0":"Initialization calls this function."}]

[{"index":"string Name","0":"The name of the node."}]

[{"index":"AIComponent ParentAI (ReadOnly) (HideFromInspector)","0":"AIComponent to have the node."}]

# Constructors

[{"index":"RandomSelectorNode(string name = \"RandomSelectorNode\")","0":"Initializes RandomSelectorNode to the specified name."}]

# Methods

[{"index":"void AttachChild(BTNode node, number probability)","0":"Incorporates the node as a child node. This child node will have probability. Probability ranges from 0 to 1."}]

[{"index":"boolean SetChildNodeProbability(BTNode node, number probability)","0":"Sets the probability of a child node. Probability ranges from 0 to 1."}]

##### inherited from CompositeNode:

[{"index":"void AttachChild(BTNode node)","0":"Incorporates the node as a child."}]

[{"index":"void AttachChildAt(BTNode node, int32 index)","0":"Incorporates the node as a child at the index position. Index starts at 1."}]

[{"index":"boolean DetachChild(BTNode node)","0":"Detaches a child node."}]

[{"index":"boolean DetachChild(string nodeName)","0":"Finds and detaches nodeName child node."}]

[{"index":"void DetachChildAt(int32 index)","0":"Detaches the child node at index position. Index starts at 1."}]

##### inherited from BTNode:

[{"index":"BehaviourTreeStatus Behave(float deltaTime)","0":"Executes the node. The deltaTime refers to the duration between the previous frame and the current frame. Defined in seconds."}]
UserDataSet

This is a user-created data table.

# Properties

[{"index":"ReadOnlyList Columns (ReadOnly) (HideFromInspector)","0":"A list containing the contents of each column in the data table."}]

[{"index":"string Id (ReadOnly) (HideFromInspector)","0":"The Id of the data table."}]

[{"index":"string Name (ReadOnly) (HideFromInspector)","0":"The name of the data table."}]

[{"index":"boolean ServerOnly (ReadOnly)","0":"Sets whether the data table is used exclusively in the server. If true, it can only be used on the server."}]

# Methods

[{"index":"UserDataRow FindRow(string columnName, string value)","0":"Gets the row wherein the value among the cells of the columns corresponding to columnName is the same as the value. If not present, nil is returned."}]

[{"index":"table GetAllRow()","0":"Gets the contents of all rows in a table."}]

[{"index":"string GetCell(int32 row_1based, int32 col_1based)","0":"Gets the contents of a cell in a table. When accessing a cell out of range, nil is returned."}]

[{"index":"string GetCell(int32 row_1based, string columnName)","0":"Gets the contents of a cell in a table. When accessing a cell out of range, nil is returned."}]

[{"index":"table GetColumn(int32 index_1based)","0":"Gets the contents of that column. When accessing a column out of range, nil is returned."}]

[{"index":"table GetColumn(string columnName)","0":"Gets the contents of the specified column. When accessing a column out of range, nil is returned."}]

[{"index":"UserDataRow GetRow(int32 index_1based)","0":"Gets the contents of that row. When accessing a row out of range, nil is returned."}]

[{"index":"int32 GetRowCount()","0":"Gets the contents of a row in a table."}]
DamageSkinSpawnerComponent

Outputs the damage skin when a hit event occurs on the Entity.

# Properties

[{"index":"Vector2 DamageSkinOffset (Sync)","0":"Sets the location for the damage skin to be output."}]

##### inherited from Component:

[{"index":"boolean Enable (Sync)","0":"Checks whether Component is activated or not."}]

[{"index":"boolean EnableInHierarchy (ReadOnly) (HideFromInspector)","0":"Displays whether this Component is Enable in the hierarchy. If Entity Enable is false regardless of Component Enable, returns false."}]

[{"index":"Entity Entity (ReadOnly)","0":"The Entity that owns this component."}]

# Methods

##### inherited from Component:

[{"index":"boolean IsClient()","0":"Returns whether the current execution environment is a client or not."}]

[{"index":"boolean IsServer()","0":"Returns whether the current execution environment is a server or not."}]

# Examples

This is an example where damage is output to the top center based on the ColliderOffset and BoxSize of the current HitComponent.
    
    
    @Component
    script DamageSkinOffsetAdjuster extends Component
        @ExecSpace("ServerOnly")
        method void OnBeginPlay()
        local damageSkinSpawnerComponent = self.Entity.DamageSkinSpawnerComponent
    
        if damageSkinSpawnerComponent == nil then
            return
        end
    
        local transformComponent = self.Entity.TransformComponent
    
        if transformComponent == nil then
        	return
        end
    
        local hitComponent = self.Entity.HitComponent
    
        if hitComponent == nil then
            return
        end 
    
        local weight = self.Entity.TransformComponent.Scale:ToVector2()
    
        local hitBoxOffset = hitComponent.ColliderOffset * weight
        local hitBoxSize = hitComponent.BoxSize * weight
    
        local damageOffset = Vector2(hitBoxOffset.x, hitBoxOffset.y + hitBoxSize.y / 2)
    
        damageSkinSpawnerComponent.DamageSkinOffset = damageOffset
        end
    end
    

# SeeAlso

  * HitComponent
  * TransformComponent
  * Vector2
DynamicMapResultCode

This code indicates the results of processing requests related to the dynamic map.

# Members

[{"Name":"InternalError","Value":"-1","Desc":"An internal error has occurred."},{"Name":"Success","Value":"0","Desc":"Successfully created or destroyed the dynamic map."},{"Name":"InvalidMapName","Value":"1","Desc":"Invalid map name. A character that can't be used in the original map and dynamic name. \\\, \/, :, *, ?, \", <, >, |, #, &, = can't be used."},{"Name":"DuplicateMapName","Value":"2","Desc":"Duplicate map name. You must use a name that's not a duplicate of newMapName."},{"Name":"SourceMapNotFound","Value":"3","Desc":"The original map doesn't exist. Please check if the original map that applies to sourceMapName exists."},{"Name":"DynamicMapNotFound","Value":"4","Desc":"The dynamic map with the map name that will be destroyed doesn't exist."},{"Name":"RoomAndSourceMapTypeMismatch","Value":"5","Desc":"This map cannot be used as the original map in the room. Only static maps can be used as the original map in static rooms. And only instance maps can be used as the original map in instance rooms."},{"Name":"SourceMapNotLoadable","Value":"6","Desc":"The original map is not included in the instance room. Please check if an instance map is in the instance room."},{"Name":"UserExistsInDynamicMap","Value":"7","Desc":"A user has entered the dynamic map. You can view the User Entities in the map using the UserService's GetUsersByMapName() or GetUsersByMapComponent() functions."},{"Name":"DynamicMapNotAllowedAsSourceMap","Value":"8","Desc":"The dynamic map cannot be used as an original map."}]

# Methods

[{"index":"DynamicMapResultCode CastFrom(number value) (Static)","0":"Converts numbers to the applicable type."}]

[{"index":"DynamicMapResultCode CastFrom(string value) (Static)","0":"Converts strings to the applicable type."}]
List<V>

An array of dynamic size. It's possible to access elements with a 1-based index and provide functions to add, remove, and search data. V represents the data type that can be added to the array.

# Properties

[{"index":"number Count (ReadOnly)","0":"Gets the number of elements in the List."}]

# Methods

[{"index":"boolean Contains(V item)","0":"Checks whether the List contains an element."}]

[{"index":"number IndexOf(V item)","0":"Returns the index of the first element in the List."}]

[{"index":"table ToTable()","0":"Generates a table with the elements included in the List."}]

[{"index":"void Add(V item)","0":"Adds an element to the end of the List."}]

[{"index":"void AddRange(table items)","0":"Adds the table element to the end of the List."}]

[{"index":"void Clear()","0":"Removes all elements in the List."}]

[{"index":"void Insert(number index, V item)","0":"Inserts an element into the List at the specified index."}]

[{"index":"number LastIndexOf(V item)","0":"Returns the index of the last element in the List."}]

[{"index":"boolean Remove(V item)","0":"Removes the first occurrence of the specific element in the List."}]

[{"index":"void RemoveAt(number index)","0":"Removes the element at the specified index from the List."}]

[{"index":"void RemoveRange(number index, number count)","0":"Removes the element from the List according to the specified range."}]

[{"index":"table GetRange(number index, number count)","0":"Generates a table with the elements from the List according to the specified range."}]

[{"index":"void Reverse()","0":"Reverses the order of elements in a List."}]

[{"index":"void Reverse(number index, number count)","0":"Reverses the order of elements within the specified range."}]

[{"index":"void Sort()","0":"Arranges all elements of the List."}]
LogService

Provides log-related features.

# Methods

[{"index":"void SetShouldShowServerLog(boolean shouldShowServerLog) (ServerOnly)","0":"Sets whether to output the log generated by the server."}]

##### inherited from Service:

[{"index":"EventHandlerBase ConnectEvent(string key, IScriptFunction eventHandler)","0":"Links events. When a key-type event occurs in this service, a handler is notified. The handler receives event parameters."}]

[{"index":"EventHandlerBase ConnectEvent(Type eventType, IScriptFunction eventHandler)","0":"Links events. This service notifies a handler when an eventType event occurs. The handler receives event parameters."}]

[{"index":"boolean DisconnectEvent(string key, EventHandlerBase eventHandler)","0":"Disconnects the event with the key-type event and the handler."}]

[{"index":"boolean DisconnectEvent(Type eventType, EventHandlerBase eventHandler)","0":"Disconnects the eventType event from its handler."}]

[{"index":"void SendEvent(EventType sendEvent)","0":"Generates an event."}]

# Examples

This is an example of setting whether or not to output logs from the server and outputting logs in each type on the server and client.
    
    
    @Component
    script LogExample extends Component
        @ExecSpace("ClientOnly")
        method void OnBeginPlay()
        -- Outputs client and server logs
        self:SetShouldShowServerLog(true)
        self:LogClient()
        self:LogServer()
    
        -- Outputs only client logs
        self:SetShouldShowServerLog(false)
        self:LogClient()
        self:LogServer()
        end
    
        @ExecSpace("ServerOnly")
        method void LogServer()
        log("log server")
        log_warning("log_warning server")
        log_error("log_error server")
        end
    
        @ExecSpace("ClientOnly")
        method void LogClient()
        log("log client")
        log_warning("log_warning client")
        log_error("log_error client")
        end
    
        @ExecSpace("ServerOnly")
        method void SetShouldShowServerLog(boolean shouldShowLog)
        _LogService:SetShouldShowServerLog(shouldShowLog)
        end
    end
DataStorageItemPages

Provides a feature of inquiring about the data saved in DataStorage.

# Properties

[{"index":"boolean IsLastPage (ReadOnly)","0":"Checks whether the current page is the last."}]

# Methods

[{"index":"table GetCurrentPageDatas() (ServerOnly)","0":"Gets a data list of the current page."}]

[{"index":"int32 LoadNextPageAndWait() (ServerOnly) (Yield)","0":"Loads the next page and returns the error code. Can move to the loaded page using the MoveToNextPageAndWait() function. Suspends script executions during performance."}]

[{"index":"void MoveToNextPageAndWait() (ServerOnly) (Yield)","0":"Goes to the next page. Script executions are suspended during the operation."}]

# Examples

This is an example of traversing through pages.
    
    
    @Component
    script PagedDataInspector extends Component
        @ExecSpace("ServerOnly")
        method void OnBeginPlay()
            while true do
            	-- Retrieves the list of items on the current page.
            	local datas = pages:GetCurrentPageDatas()
            	for _, data in pairs(datas) do
            		-- You can inquire the key, version, tag, and value using DataStorageItem.
            		log(data.KeyInfo.Key)
            		log(data.KeyInfo.Tag)
            		log(data.KeyInfo.Version)
            		log(data.Value)
            	end
            
            	-- Checks if the current page is the last page.
            	if pages.IsLastPage == true then
            		break
            	end
            
            	-- Preloads the data for the next page and stops the inquiry if the next page is invalid.
            	local loadResultCode = pages:LoadNextPageAndWait()
            	if loadResultCode ~= 0 then
            		break
            	end
            
            	-- Moves to the next page.
            	pages:MoveToNextPageAndWait()
            end
        end
    end
    

# SeeAlso

  * [Learning DataStorage Use Limits](/docs?postId=1044)
  * [Utilizing DataStorage](/docs?postId=692)
  * [Utilizing DataStorage Use Limits](/docs?postId=1045)
Welcome to MSW (ENG)

# What is the MSW platform?

$$youtube /watch?v=2HbhtnKQsYQ&list=PLbuLziGH_EjW6by0RXvbDqYpt4WUUE2wE $$

1-1. Welcome to MSW 1-2. MSW Client Overview 1-3. Navigation menu and Scene panel 1-4. Model List, Hierarchy, and Workspace 1-5. Layer, Script, and Resources

# Basic concepts and LuaScript

$$youtube /watch?v=qH-KJQwMteg&list=PLbuLziGH_EjXgpOACMZBev82INb71AT9Z $$

2-1. Entity, Component, and Property 2-2. Model, Service and Logic 2-3. Creating Scripts 2-4. Script Logic and Script Component 2-5. Table and Variable 2-6. Function

# Understanding Network in MSW

$$youtube /watch?v=aV2fqDIOOWA&list=PLbuLziGH_EjUdCFx4ddXaMl3g5NSoKnsc $$

3-1. Property Synchronization 3-2. Function control 3-3. What is Network 3-4. Local UI and Input Logic

# Create your own game: My Adventure

$$youtube /watch?v=USSJjX7de4M&list=PLbuLziGH_EjVG8pmwD87P-tWmrarnE3aZ $$

4-1. Game Overview 4-2. Designing the map 4-3. Coin Collectibles 4-4. Monster 4-5. Flagpole

# Publish and Monetize

$$youtube /watch?v=wdAm0xSmYlY&list=PLbuLziGH_EjXttuQEQ9lFFpasf9Y-w9t2 $$

5-1. Make your own paid items 5-2. Logics and Components to purchase an item 5-3. Using the item and The End
Setting Up Server-Only Entries

# Course Introduction

When a creator creates a world, there may be a function in DataSet or a script that the creator does not want to disclose to users who play the game due to security issues. Today, let's learn how to set DataSet or a function to server-only.

# The Need for Server-Only Entries

When creating a world, for example, it is safest to ensure that information such as coupon codes, important keys used in the game, damage formulas, or internal logic is processed only on the server. If such sensitive information exists on both the server and the client, it may be a security vulnerability because the client can also access the sensitive information. In this case, you need to solve the security issue by setting it so that the important DataSet or the implementation part of the functions in the script are not transferred to the client.

# Server-Only DataSet settings

If you check the ServerOnly checkbox in the DataSet's Property , you can process it so that the DataSet content is not delivered to the client when the game world is played. [png](1661169318239863cf967cd4a46d3b1467ddcf4659ddc) DataSet set to ServerOnly cannot be accessed by clients, so creators have to write scripts with this in mind. If some data from that DataSet is needed at a specific timing, it needs to be passed to the client, such as by execution control or synchronization.

# Setting the Execution Space of a Function

If the execution space of a function in the script is set to ServerOnly or Server, the implementation of that function is not passed to the client.

  1. After clicking the function setting button, select the Execution Space Setting menu. [png](1661216740609c9bbe61a337e4b62ba90e21ab21e65e2)
  2. Set the execution space to Server or ServerOnly. [png](1727152502360be98b8648a034dcfb8a09a5a5855ba30) The implementation of the function set in this way is not passed to the client. [png](166117015841552bb10e2fffd476b82770fe72c0a5787)
Utilizing DataStorage Usage Limits 2

# Course Introduction

You may have difficulty managing data due to save failures or querying data if you don't use DataStorage efficiently and reach the usage limit. Let's learn how to effectively manage the DataStorage usage.

##### Guide

  * 
  * 
  * 



# Not Saving Data

When new data you want to save is the same as the previous, `Set` functions like `SetAndWait` and `SetAsync` will consume Credits. To save Credits, only send a change request to DataStorage when the value changes. For example, if a user won't log in to multiple instances simultaneously and change data, UserDataStorage can use this method.

> Tip We recommend you only save data that can't be changed in another world instance to the world instance's Lua Table.
    
    
    @Component
    script CachedProfileDataSetter extends Component
        property table cache = {}
    
        @ExecSpace("ServerOnly")
        method void TestAndSetData(string key, string value)
        local profileCode = self.Entity.PlayerComponent.ProfileCode
        if self.cache[profileCode] ~= nil and self.cache[profileCode][key] == value then
          return
        end
    
        local userDataStorage = _DataStorageService:GetUserDataStorage(profileCode)
        if userDataStorage == nil then
           return
        end
    
        local errorCode = userDataStorage:SetAndWait(key, value)
        if errorCode ~= 0 then
            log("ErrorCode : "..errorCode)
        else
            if self.cache[profileCode] == nil then
                self.cache[profileCode] = {}
            end
            self.cache[profileCode][key] = value
        end
        end
    end
    

> Learn More You can also pre-load the data using `GetAndWait` and place it in `self.cache` when a user logs in for the first time. Select the best method based on the reading and writing patterns, so it can fit the creator's world. If the value itself is a long string, simple comparison will require heavy CPU usage, so it's better to use it when the data is relatively small. Caching all data may deplete the world instance's memory, so we recommend caching only hot data that is read and written often.
Foothold

Indicates various kinds of information about foothold.

# Properties

[{"index":"Vector2 EndPoint (ReadOnly)","0":"Indicates the end point of Foothold. Always located on the right side of StartPoint."}]

[{"index":"int32 Id (ReadOnly)","0":"The Foothold ID. It is given when saving a foothold."}]

[{"index":"boolean IsDynamic (ReadOnly)","0":"Indicates whether the Foothold is a dynamic Foothold."}]

[{"index":"float Length (ReadOnly)","0":"Foothold's length."}]

[{"index":"int32 NextFootholdId (ReadOnly)","0":"The Id of the next Foothold. Always located on the right side of this Foothold."}]

[{"index":"string OwnerId (ReadOnly)","0":"The Id of the Entity that owns this Foothold. The Entity has either TileMapComponent or CustomFootholdComponent."}]

[{"index":"int32 PreviousFootholdId (ReadOnly)","0":"The Id of the previous Foothold. Always located on the left side of this Foothold."}]

[{"index":"Vector2 StartPoint (ReadOnly)","0":"Indicates the start point of Foothold. Always located on the left side of EndPoint."}]

[{"index":"Vector2 Variance (ReadOnly)","0":"Refers to the variance from the end to start points of Foothold. It can tell the slope."}]

# Methods

[{"index":"Vector2 GetCenter()","0":"Returns the location of the Foothold center."}]

[{"index":"float GetHeight()","0":"Returns the height of Foothold."}]

[{"index":"float GetWidth()","0":"Returns the width of Foothold."}]

[{"index":"float GetYByX(float x)","0":"Returns the Y-axis value when the Foothold's X-axis value is x."}]

[{"index":"boolean IsHorizontal()","0":"Returns whether the Foothold is a horizontal Foothold."}]

[{"index":"boolean IsVertical()","0":"Returns whether the Foothold is a vertical Foothold."}]