子曰:巧言乱德!

关于游戏进程中变量存储

关于游戏进程中变量存储,转自https://bbs.nga.cn/read.php?&tid=19488777

概述
一些插件在退出界面登出后,可能需要保存一些游戏中运行时的用户设置和数据。
正如 [@39055961] 在[https://bbs.nga.cn/read.php?tid=18978160] 提到的那样,插件开发对于配置变量的存储管理可以看做这几个不同程度:
第0级:最最初级的配置文件编写方式就是没有配置文件,全都写死在代码里。使用者必须找到有关变量的位置自行更改。
第1级:稍微人性化一点的,会把有关变量单独汇总在一个单独的lua文件里。这样用户可以比最开始的方法更简单的更改这些变量,而不会花费大量时间在查找变量中。
第2级:设置好单独的交互命令,比如命令行设置的方式,供在游戏内使用。
第3级:也就是用户量最多的那些插件所拥有的图形化的设置界面。
如何做到呢?后面会对第2和第3级的实现,做一些说明(可视化UI略过)。
插件可能会定义一些变量,以便在离线之前保存这些个性化设置,以及在玩家重新登入游戏时再次读取之前的设置。这些被客户端保存到本地的变量被暴雪称为SavedVariables,这是一个特定的称谓。

指定被保存的变量
在你开发的插件的.TOC文件中,你可以用以下两种指令,并在冒号“:”后面指定变量名,告诉WoW客户端你要保存哪个变量,多个变量的列表可以用逗号“,”分隔。
这些变量名在定义时必须为全局环境(global),也就是不能用local关键字修饰。
Code lua:
##SavedVariables
以上指令为每个游戏账号保存变量清单,如果这个账号下有多个角色,这些变量在这些角色间共享。
Code lua:
##SavedVariablesPerCharacter
以上指令为每个角色保存变量清单,可以用于不同角色具有不同的插件设置。
例:要保存一个变量 PlayerOptions时,你可能要在插件的.TOC文件中添加以下内容
Code lua:
##SavedVariables: PlayerOptions

Code lua:
##SavedVariablesPerCharacter: PlayerOptions


加载过程
用以上指令方式保存的变量,并非在插件加载时是实时可用的,而是要等一小会儿。
WoW客户端会触发一些事件(events),很多时候,插件通过监听这些事件,来确定自己是否可以进行某些操作。这也是大多数插件与WoW客户端交互的方式。加载顺序一般如下:
1.WoW FrameXML 代码被加载和执行。
2.插件代码被加载和执行。
3.某插件的SavedVariables变量被加载和执行,之后该插件的ADDON_LOADED事件(event)被触发。
4.VARIABLES_LOADED事件(event)被触发,以便通知所有插件的所有变量加载完毕。
通常开发插件时,推荐监听ADDON_LOADED事件来确定何时自己的本地变量已可存取。此事件具有一个参数,是触发这个事件的当前插件的名字,往往很有用处。
你可能会保险一点,想使用VARIABLES_LOADED事件来监听所有插件变量加载完毕,但因为Load on demand(按需加载)的插件存在,导致并不会触发VARIABLES_LOADED事件,因此尽量避免使用。

其他:
1..TOC文件末的Lua文件排放顺序是依次加载的顺序。
2.全局变量在Lua文件间共享。
3.local变量在它所在的作用域内,作用。
4.lua文件尽量以功能划分,尽量不要1个lua中长篇大论混杂各种功能,最后和插件名字的初衷背离,适当添加注释,增强易读性便于维护,适当注意内存性能。
5.其实插件开发好简单啊……lua也很简洁,只是需求是很啰嗦的,有功能了用户又要DIY配置,能DIY配置了用户又要求图形化界面,图形化了可能又嫌弃图标太丑

保存到本地
WoW客户端在你小退、断线、登出游戏、重载界面(/RELOADUI)时,会自动保存所需变量到本地。
如果你想让你的插件,在登出游戏的最后时刻保存配置,你可能要监听PLAYER_LOGOUT事件。这个事件通知插件,用户当前正欲log out,赶紧保存你自定义的配置变量吧。

你可能想用的一些事件
这里是一些可能用到的events,其他的可以自己去WoWWiKi或WoWAPI等地去找。
附原文注释供参考,以便更加深刻地理解“那个”时间点。搞开发的应该都不用翻译,或者等我有空了补上,普惠大众。
"ADDON_LOADED"
− 原文注释 ...
This event fires whenever an AddOn is loaded (fires once for each AddOn loaded if multiple AddOns are being loaded), whether that is during the inital Loading Phase or when an AddOn is loaded using the LoadAddOn("addonname") or UIParentLoadAddon("addonname") function. This event always fires after SavedVariables of the AddOn have been loaded from disk and its OnLoad function has been executed.
"PLAYER_ENTERING_WORLD"
− 原文注释 ...
Fired when the player enters the world, enters/leaves an instance, or respawns at a graveyard. Also fires any other time the player sees a loading screen.

To check if the player is entering an instance, check [[API_IsInInstance|IsInInstance].

Correction on the above comment: When PLAYER_ENTERING_WORLD fires, you'll notice that WORLD_MAP_UPDATE fires just before it. My instincts tell that leaving an instance puts the player in void space momentarily. So for the case that you are entering AND leaving an instance, GetPlayerMapPosition always returns the coordinates [0,0] and hence there is no way to determine using the event PLAYER_ENTERING_WORLD if the player is entering an instance or not. When leaving an instance the following events fire (ignoring party/raid events).
WORLD_MAP_UPDATE PLAYER_ENTERING_WORLD WORLD_MAP_UPDATE <--- Player coordinates are non-zero here
Instances do have coordinates for units once the second WORLD_MAP_UPDATE event has fired. For the case of entering a battleground such as WSG, WORLD_MAP_UPDATE won't fire until you leave Silverwing Hold or Warsong Lumber Mill and you are outside. --Salanex
"PLAYER_LOGIN"
− 点击显示隐藏的内容 ...
Triggered immediately before PLAYER_ENTERING_WORLD on login and UI Reload, but NOT when entering/leaving instances.

Note: Player skills such as those available through GetNumSkillLines() and relatives does not appear to be available when this event or PLAYER_ENTERING_WORLD fires during an actual player login from character-selection, as all the GetNumSkillLines()-function returns is 0 in those cases. When these events trigger from other reasons, such as zoning, the skill-related functions appear to work normally.
"PLAYER_LOGOUT"
− 点击显示隐藏的内容 ...
Sent when the player logs out or the UI is reloaded, just before SavedVariables are saved. The event fires after PLAYER_LEAVING_WORLD.
"PLAYER_QUITING"
− 点击显示隐藏的内容 ...
Fired when the player tries to quit, as opposed to logout, while outside an inn. This event does not indicate that the "player has quit", but instead that the "player has the quitting option".
"VARIABLES_LOADED"
− 点击显示隐藏的内容 ...
Fired in response to the CVars, Keybindings and other associated "Blizzard" variables being loaded. Since key bindings and macros in particular may be stored on the server they event may be delayed a bit beyond the original loading sequence.

Previously (prior to 3.0.1) the VARIABLES_LOADED event was part of the loading sequence. Although it still occurs within the same general timeframe as the other events, it no longer has a guaranteed order that can be relied on. This may be problematic to addons that relied on the order of VARIABLES_LOADED, specifically that it would fire before PLAYER_ENTERING_WORLD.

Addons should not use this event to check if their addon's saved variables have loaded. They can use ADDON_LOADED (testing for arg1 being the name of the addon) or another appropriate event to initialize, ensuring that the addon works when loaded on demand.

关于命令行
命令行是游戏中的一个很方便的功能,从用户角度来看,只要在聊天框输入少量的字符,即可实现一些强大方便的功能。
1.我需要FPS。
2.使用命令行时需要确定一个指令唯一标识符,如/ccy的ccy。
3.考虑用户输入的容错性,使用lower()处理字符串兼容大小写,使用缩写和全称等多种替代情况,如/DBM、/DeadlyBossMode、/DBM ? 、/DBM help等。
3.可以使用形如/ccy c on这样的多参数,将字符串按“ ”分离,处理到table中,灵活用于多种情况。
4.定义命令行的格式为:
SLASH_ABC1 = "/ABC"
SLASH_ABC2 = "/abc"
SLASH_ABC3 = "/aBeautifulCoder"
SlashCmdList["ABC"] = function(text)
text = text:lower()
...
end
以上例子为假设有一个aBeautifulCoder插件,想注册一个ABC命令行,共有3种指令,分别为/ABC、/abc、/aBeautifulCoder
不难看出格式为‘SLASH_’+‘你自定义的标识符’+‘数字’,其中的ABC为可根据你的情况进行替换的标识符,需要在下面的SlashCmdList中指定,并同时在function中指定需要实现的功能。
不想使用本地变量存储,希望傻瓜化插件,但在游戏中留有手动调节余地的时候,适合用命令行来实时修改默认配置。(诚然,命令行能干的事情很多……图形界面能干的它都能干,除了图形本身。)

posted on 2020-10-13 01:28  usyw  阅读(280)  评论(0编辑  收藏  举报

导航