在本文中,筆者將以webgame研發(fā)者角度,符合游戲營業(yè)模塊邏輯,從營業(yè)需求,數(shù)據(jù)庫設(shè)計,法度編寫,把持編制上來講授縫隙構(gòu)成道理,規(guī)避方案,也歡迎大年夜家會商。
登錄認證
近幾年,網(wǎng)頁游戲幾近都是以聯(lián)運編制運營,意味著游戲辦事器本身不保留用戶暗碼,用戶登錄在平臺,經(jīng)由過程平臺跟游戲辦事器的接口對接登錄。接口做加密認證。故webgame的帳號暗碼安然標題問題,這里不提了。但登錄認證的hash字符串安然,也仍是要寄望的。好比登錄hash字符串的生效時候,hash字符串的加密參數(shù)來歷,好比包含用戶名、登錄IP,瀏覽器user-agent等數(shù)據(jù),以避免改hash被泄漏了,也是很難經(jīng)由過程辦事器的驗證。
游戲充值
webgame的游戲充值流程,跟通俗網(wǎng)頁充值流程一致,沒有特別的處所,其不合點就是跟其他浩繁平臺做結(jié)合運營時,勢需要每個公司做接口對接,且接口規(guī)范各色各樣,且游戲廠商沒有話語權(quán),必需遵循他們的接口規(guī)范來,這其實毒手。騰訊的充值接口的驗證編制,安然性做的較為凸起,大年夜約代碼:
// 返回參數(shù)列表
$signKey = array('openid','appid','ts','payitem','token','billno','version','zoneid','providetype','amt','payamt_coins','pubacct_payamt_coins');
$sign = array();
//從GET參數(shù)中,對比找出上面參數(shù)的值
foreach($signKey as $key ) {
if (isset($data[$key]))
{
$sign[$key] = $data[$key]; //只有 GET里有的參數(shù),才介入sig的計較
}
}
######開端生成簽名############
//1: URL編碼 URI
$url = rawurlencode($url);
//2:遵循key進行字典升序擺列
ksort($sign);
//3: &拼接,并URL編碼
$arrQuery = array();
foreach ($sign as $key => $val )
{
$arrQuery[] = $key . '=' . str_replace('-','%2D',$val);
}
$query_string = join('&', $arrQuery);
//4 以POST編制拼接 1、3 和URL
$src = 'GET&'.$url.'&'.rawurlencode($query_string);
// ## 機關(guān)密鑰
$key = $this->config->get('qq_appkey').'&';
//### 生成簽名
$sig = base64_encode(hash_hmac("sha1", $src, strtr($key, '-_', '+/'), true));
if ( $sig != $data['sig'] ) {
$return['ret'] = 4;
$return['msg'] = '要求參數(shù)弊端:(sig)';
$this->output->set(json_encode($return));
return ;
}
在此根本上,還可以做的嚴謹點:
增加隨機參數(shù)名、參數(shù)值。隨機參數(shù)名、參數(shù)值由聯(lián)運方隨機生成,遵循參數(shù)名的字符串所屬ASCII碼挨次排序,參數(shù)名、參數(shù)值均介入sign的計較,增加暴力破解密鑰(app key)難度。
增加回調(diào)驗證訂單號,金額信息。游戲充值辦事器領(lǐng)遭到充值要求時,反向到該平臺回調(diào)接口,確認此筆訂單有效性,以避免加密密鑰泄漏的標題問題。
長途文件引進
在網(wǎng)頁游戲的研發(fā)中,大都都是利用框架來做,即便用REQUEST來的參數(shù),作為要求文件名的一部門,來利用,那么很等閑構(gòu)成長途文件引進的縫隙。在我們之前的游戲中,曾呈現(xiàn)過一例如許的縫隙標題問題。
// Load the local application controller
// Note: The Router class automatically validates the controller path. If this include fails it
// means that the default controller in the Routes.php file is not resolving to something valid.
if ( ! file_exists(APPROOT.'controllers/'.load('Router')->getDirectory().load('Router')->getClass().EXT))
{
load('Errors')->show404('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.');
}
include(APPROOT.'controllers/'.load('Router')->getDirectory().load('Router')->getClass().EXT);
load('Benchmark')->mark('load_basic_class_time_end');
webgame中的長途文件引進
從代碼和案例圖中,可以看到對REQUEST的參數(shù)沒有過濾措置,直接作為文件名來include引進的,故導致這類標題問題,近似上頁圖中QQ群網(wǎng)站的縫隙。若PHP version <5.3.4 ,還會產(chǎn)生Null(%00) 截斷的標題問題,帶來更大年夜的安然標題問題。在我們新的項目中,我們更改了實現(xiàn)編制,我們游戲所有接口城市走gateway,gateway里,對節(jié)制器名做類名規(guī)范的檢測措置,再在指定幾個目次下做autoload加載文件,且還會對REQUEST的類名、編制用ReflectionClass反射類的措置,檢測到類、編制、參數(shù)是不是合法。一來避免『長途文件引進』縫隙標題問題,二來便于前后端聯(lián)調(diào)時,拋出更具體的異常,便利調(diào)試。下面為參考代碼:
require_once CONFIG_PATH . "/auto.php";
spl_autoload_register("__autoload");
……
//默許動靜格局
$view->clear();
$view->error(MLanguages::COM__INVALID_REQUST);
$msg = new Afx_Amf_plugins_AcknowledgeMessage($val->data[0]->$messageIdField);
$msg->setBody($view->get());
$message->data = $msg;
…
$a = new Yaf_Request_Simple();
$a->setControllerName($method[0]);
$a->setActionName($method[1]);
$objC = new ReflectionClass($method[0]."Controller");
$arrParamenter = $objC->getMethod($method[1]."Action")->getParameters();
$arrRequest = isset($val->data[0]->body[0]) ? (array)$val->data[0]->body[0] : array();
$bCanCall = true;
foreach ($arrParamenter as $objParam)
{
$parm = $objParam->getName();
$bIsOption = $objParam->isOptional(); //是不是為可選參數(shù)
if (isset($arrRequest[$parm]))
{
$a->setParam($parm , $arrRequest[$parm]);
}
elseif ($objParam->isOptional())
{
//可選參數(shù)
}
else
{
$bCanCall = false;
}
}
if ($bCanCall)
{
$rp = $app->getDispatcher()->dispatch($a);
$msg = new Afx_Amf_plugins_AcknowledgeMessage($val->data[0]->$messageIdField);
$msg->setBody($view->get());
$message->data = $msg;
}
SQL 注進
SQL注進道理、編制,跟通俗web利用一樣,沒甚么出格的,在利用REQUEST來的參數(shù)時,過濾措置便可。可能在動靜格局,和注進把持精練上,會蒙蔽研發(fā)人員的眼睛,被忽視掉落了。好比我們項目標AMF動靜格局,在前端界面沒出來之前,我們后端法度員一般利用Pinta來摹擬把持,調(diào)試法度。前端界面出來以后,會利用Charles proxy來捕獲http要求。在這些過程中,要求接口、參數(shù)的機關(guān),沒有通俗web那么簡單。研發(fā)人員也等閑忽視對要求參數(shù)的過濾,故很等閑構(gòu)成這類標題問題。構(gòu)成道理見:《WEB開辟安然與運維安然淺見》,防御編制做過濾措置,或SQL預編譯。

AMF動靜格局的WEBGAME中的SQL注進

AMF動靜格局的WEBGAME中的SQL注進
為了進步游戲辦事器的吞吐能力,網(wǎng)頁游戲的架構(gòu)也是一向在演變的。在之前以Mysql作為數(shù)據(jù)存儲的webgame架構(gòu)中,其他節(jié)點都是可以程度擴大,或說依托簡單粗莽的增加辦事器來解決,單單作為獨一數(shù)據(jù)存儲中間,不克不及這么做。為此,良多webgame的數(shù)據(jù)存儲改用Nosql來代替,乃至java、C/C++的游戲數(shù)據(jù),直接在內(nèi)存中把持,游戲關(guān)服時,才寫進到DB中。故SQL注進的標題問題,也會愈來愈少。
通信和談與動靜格局
網(wǎng)頁游戲當然名字叫網(wǎng)頁游戲,但通信和談并不是滿是http,也有良多利用socket,和http+socket并用的做法。我們是http和談+amf動靜格局,和socket并用來實現(xiàn)。在http與https的棄取上,我們考慮到ssl的啟用后,大年夜量的ssl解密加密運算,必將會增加辦事器大年夜量的CPU計較壓力。而傳輸?shù)膬?nèi)容,大都是游戲營業(yè)的把持,響應(yīng),是能接管被監(jiān)聽嗅探的行動的(認證信息除外)。站在安然角度,這不克不及理解。但站在產(chǎn)品角度,考慮一下 投進產(chǎn)出,然后選擇http通信,也是可以理解的。socket在我們游戲中,除在聊天利用上利用外,在一些組隊、幫派戰(zhàn)之類需要多個玩家之間同步數(shù)據(jù)信息時,我們也會利用socket來推送數(shù)據(jù)。在利用socket作為所有營業(yè)傳輸?shù)暮驼剷r,和談格局一般都是開源和談,好比msgpack、protobuf之類,或自定義的和談。利用自定義和談時,務(wù)必檢測全部動靜包的每個參數(shù),類型范圍,避免個別超大年夜數(shù)值、鴻溝數(shù)值呈現(xiàn),導致主法度內(nèi)存越界,乃至于辦事宕機,沒法正常辦事的環(huán)境產(chǎn)生。
金幣復制-整型溢出
上周周六開周會時,聽到其他項目組的一個關(guān)于整型溢出導致產(chǎn)生刷金幣的標題問題。在這里,我抽象該案例,分享一下。商城出售開啟背包格子的所需道具『梧桐木』。在游戲中,用戶包裹格子數(shù)量一般城市作為一個收費點,一款游戲的格子大年夜約為每行7格子,一共8行如許。好比前面3行是默許開放的,第4行是收費的,并且第一個格子所需品梧桐木的代價1個銀子,第二個梧桐木是2個銀子,第三個是4個銀子。順次類推,意味著這些梧桐木的代價總和其實就是一個第一項為1,公比為2,項為35的等比數(shù)列。 當用戶選擇采辦梧桐木數(shù)量大年夜于31時,好比32-36中這些數(shù)字時,這些等比數(shù)列的和就是大年夜于2147483647。(只是舉例,實際上不會以如許的代價出售物品)
在java中,4字節(jié)的存放int型變量的范圍是-2147483648至2147483647。在java、c的有符號int型中存儲時,數(shù)的最高位描述符號位,4字節(jié)共32位,除往最高位的符號位,剩下31位,每個位上能暗示2個數(shù)字,4字節(jié)的有符號的整數(shù)暗示范圍為:負整數(shù)2^31個,范圍為『-1至-2147483648』;正整數(shù)2^31個,范圍為『2147483647至1』。 好比下圖(寄望十進制數(shù)字跟二進制暗示的改變挨次):
當開啟格子數(shù)字為大年夜于31時,好比32,那么所需費用就是2147483647個銀兩,再買點其他物品,湊成超越2147483647的數(shù)字,好比又買了3個銀子的其他道具,總共破鈔2147483650個銀子,在4字節(jié)的有符號int中暗示出來的成果,變成符號位為1,即負整數(shù)。數(shù)值位為0000000 00000000 00000000 00000010,也就是10000000 00000000 00000000 00000010,對應(yīng)十進制的-2147483646。法度邏輯上,再鑒定現(xiàn)有銀兩是不是足夠付出此筆破鈔時,是經(jīng)由過程的。當利用當前余額減往這筆破鈔時,將變成減往一個負數(shù),那么實際上就是加上一個正整數(shù)。變成了本身銀兩賬戶余額的增加。而余額字段類型是long,則準確的存儲了這些余額,溢出漏洞被操縱。在C中,利用無符號的數(shù)值類型,便可完成數(shù)值類型溢出刷錢的行動,但在java中,仿佛沒有沒有符號的類型。這也能夠先肯定所有介入計較的數(shù)值必需為正整數(shù)作為需要前提(游戲營業(yè)特點,游戲內(nèi)所稀有字,必定全為正整數(shù),乃至都不包含零),先做大年夜小鑒定,再做正正相加,不克不及得負;負負相加,不克不及得正。來鑒定是不是產(chǎn)生了溢出標題問題。在PHP中,不消擔憂溢出標題問題。
金幣復制-并發(fā)要求
Rpg類型的網(wǎng)頁游戲中,大都都有道具出售的功能,直接賣到商鋪,和道具材料從商鋪買進功能。當玩家同時針對買進、賣出兩個把持,剎時大年夜量并發(fā)要求時,在辦事器的措置邏輯一般有分別的兩個過程措置,共享數(shù)據(jù)別離數(shù)據(jù)庫中的對應(yīng)賬戶余額表,以下圖:

webgame買進、賣出并發(fā)要求措置
//賣出
// startTrans
$iBalance = $obj->getBalance('user1'); //余額50
//UPDATE `role_gold` SET gold = 150 WHERE role_id = 1
if(!$obj->setBalance('user1',$iBalance + 100))
{
//rollback
}
//扣除物品
if (!$obj->delItems($items))
{
//rollback
}
//commit
//買進
// startTrans
$iBalance = $obj->getBalance('user1'); //余額50
//UPDATE `role_gold` SET gold = 0 WHERE role_id = 1
if(!$obj->setBalance('user1',$iBalance - 50))
{
//rollback
}
//發(fā)放物品
if (!$obj->addItems($items))
{
//rollback
}
//commit
賣出要求的措置過程為1,買進要求的措置過程為2。在過程1還沒將成果寫進到DB時,過程2也從DB讀取到余額為50。這是,兩個過程拿到的余額信息都是50。過程1遵循邏輯代碼,計較出殘剩余額是150;過程2計較出的殘剩余額是0。最后,不管阿誰過程最后寫進余額,都是弊端的成果。(注:這里的代碼邏輯把持,跟mysql事務(wù)無任何干系,事務(wù)只能包管單個過程的事務(wù)范圍內(nèi)多條語句都準確履行,或回滾。好比能包管扣錢成功,且物品刪除掉落的兩個語句都準確履行。能包管此中之一的語句履行掉敗時,都準確回滾。)
其實,在事物開啟時辰,SELECT語句是不是可以取到最新的數(shù)據(jù),或是不是需要等候鎖釋放,取決于MYSQL的事務(wù)隔離級別。在MYSQL的事務(wù)隔離級別中,有一下幾種隔離級別:
READ-UNCOMMITTED(讀取未提交內(nèi)容)級別
READ-COMMITTED(讀取提交內(nèi)容
REPEATABLE-READ(可重讀)
SERIERLIZED(可串行化)
對READ-UNCOMMITTED,可以讀取其他事務(wù)中未提交的數(shù)據(jù),并且傳聞機能還高不到哪里往,幾近沒有在實際利用中利用;對READ-COMMITTED,在統(tǒng)一事務(wù)中,會因為其他事務(wù)隨時可能有新的commit,導致統(tǒng)一select可能返回不合成果。這個也不合適游戲營業(yè);再說第四個SERIERLIZED,只要事務(wù)開啟,所有其他查詢,均列隊等候該事務(wù)提交以后,對上面提到的賣出買進環(huán)境,第二個事務(wù)的SELECT把持,不會當即返回,會處于鎖等候狀況,一向到前一個事務(wù)結(jié)束。這個隔離級別,當然能避免上面的標題問題,但機能較差,一般不會往利用。而REPEATABLE-READ隔離級別,也是mysql默許的隔離級別,從功能上,比較合適游戲營業(yè)需要,也應(yīng)當是廣大年夜webgame架構(gòu)中mysql的默許隔離級別。
對這個標題問題,你可能很快就給出解決編制,把UPDATE語句改成UPDATE `role_gold` SET gold = gold + 100 WHERE role_id = 1或UPDATE `role_gold` SET gold = 150 WHERE role_id = 1 AND gold = 100來解決,但這類多個事務(wù)同時把持點竄多個表的多筆記及時,還等閑激發(fā)死鎖標題問題,好比《webgame中Mysql Deadlock ERROR 1213 (40001)弊端的排查過程》。并且,當前提為跨表內(nèi)數(shù)據(jù)是不是存在,或別的前提不在MYSQL中,而在其他收集接口的響應(yīng)中時,若何做呢?
金幣復制--邏輯縫隙
援引DNF的縫隙新聞 《操縱網(wǎng)游縫隙狂刷游戲幣賺錢 玩家自曝3天賺17萬》
玩家曝出刷幣縫隙 一個游戲道具可刷400人平易近幣
該縫隙事實是甚么?本來游戲中“云冪袖珍罐”這個道具,可以開出2件一樣的游戲設(shè)備,還有極少概率開出游戲幣,開出的設(shè)備不值錢,但假定開出金幣了,則分為5000萬、8000萬和1億游戲幣。而1億游戲幣,按正常市場行情,可在生意網(wǎng)上賣400多元人平易近幣。據(jù)玩家稱,在游戲中,角色的設(shè)備是需要用包裹來存放的,不外今朝角色的包裹最多只有48格,也就是只能存放最多48件設(shè)備??p隙就是操縱包裹的有限空間,存放47件設(shè)備(存放滿了又沒法開罐子),只留下一格空位,而在開“云冪袖珍罐”出設(shè)備時,就會因包裹空間不足,而導致開罐掉敗,而罐子還存在。玩家繼續(xù)開罐,直到呈現(xiàn)金幣,但金幣不會據(jù)有包裹的空間,是以開罐成功,然后罐子消掉。發(fā)現(xiàn)這個縫隙后,部門玩家狂刷游戲幣,然后頓時在第三方生意平臺出售游戲幣,兌換成現(xiàn)金。
這類標題問題,都是研發(fā)人員邏輯不嚴謹導致,這類標題問題,也較難發(fā)現(xiàn)。規(guī)避編制可以依托下面提到的『運營數(shù)據(jù)監(jiān)控』。
道具復制--背包清算
跟上面的賣出、買進一樣,同時穿設(shè)備、清算包裹。在設(shè)計時,可能會將身上設(shè)備設(shè)計在設(shè)備表中;將不在身上的設(shè)備,設(shè)計到背包表中。當同時進行穿設(shè)備跟清算包裹的要求并發(fā)時,也會產(chǎn)生跟上面賣出,買進的環(huán)境,線程1讀取DB,發(fā)現(xiàn)包裹里有這設(shè)備,然后預備刪除背包表的這筆記實,當預備寫進到設(shè)備表時,別的一個清算包裹要求的線程來了,讀取了全部背包表,進行道具的歸并、排序。這時候,之前的線程將這個設(shè)備寫進到設(shè)備表,并刪除背包表里的數(shù)據(jù),并提交事務(wù)。這個穿設(shè)備的所有把持都是合理、正常,且準確履行的。但別的一個清算背包的線程讀取了之前的背包表里的數(shù)據(jù),包含那件被穿上的設(shè)備。在游戲中,清算背包需要對可堆疊道具做堆疊把持的,意味著需要歸并多個道具,刪除部門道具。這意味著這里的把持,當前cgi線程的內(nèi)存中的數(shù)據(jù),將城市以籠蓋的情勢,寫進到DB中,那么意味著,之前被穿到身上的那件設(shè)備,也會從頭被寫進到背包中。那就變成兩張表里呈現(xiàn)了兩個不異獨一ID的不異屬性的道具。玩家便可以把背包中的這個道具出售給其他玩家。
在java或C之類法度中,數(shù)據(jù)放內(nèi)存中的游戲,也會存在這個標題問題,除非做讀鎖,但讀鎖會帶來鎖等候,鎖等候會導致線程被占用,梗阻后面要求的措置,聚積大年夜量要求。導致系統(tǒng)負載升高,辦事器繁忙,乃至于沒法響應(yīng)。好了,大年夜約理解道具復制的構(gòu)成啟事了嗎?這個標題問題,我們從根來歷根底因想想,標題問題到底呈此刻哪里?若何規(guī)避呢?細心的同窗不難發(fā)現(xiàn),對穿設(shè)備的把持成果,會對下一個要求產(chǎn)生影響的,當前把持未獲得辦事端響應(yīng)之前,辦事端是不克不及措置下一個響應(yīng)的。對此,我們做了響應(yīng)措置鎖--『用戶并發(fā)要求鎖』。
用戶并發(fā)要求鎖的實現(xiàn),php中session以文件情勢存儲時,php會對session文件加鎖,不釋放(假定不特意履行session_write_close),知道當前響應(yīng)完成。別的一個線程才可以正常讀取,這簡介的構(gòu)成了單個用戶的并發(fā)要求鎖,可是,后面的過程一向處于等候狀況,也會占用一個php-fpm過程,梗阻其他用戶的正常要求對php線程的利用。為此,我們利用NOSQL的K-V情勢布局,以user_name為key的情勢,實現(xiàn)用戶并發(fā)要求鎖,第一個要求,生成這個k-v數(shù)據(jù),后一個要求發(fā)現(xiàn)有這個key了,那么當即拋出異常,結(jié)束響應(yīng),F(xiàn)LASH按照異常內(nèi)容,提示用戶不要進行歹意把持。即不會產(chǎn)生并發(fā)要求,又不會梗阻要求措置。同時,在要求結(jié)束的析構(gòu)函數(shù)里,對這個鎖進行刪除把持,不影響下一個正常要求。若因為法度異常,產(chǎn)生語法弊端,導致析構(gòu)函數(shù)沒法履行,沒有刪除用戶鎖時,可以在生成鎖的時辰,設(shè)置過不時候,好比5秒,乃至2秒,操縱nosql的過機會制,實現(xiàn)用戶解鎖,避免用戶長時候沒法正常游戲。
類CC報復打擊-多用戶共享資本鎖的timebomb
我們此刻研發(fā)的項目,是以NOSQL Redis作為DB,來存儲數(shù)據(jù)的,redis并沒有成熟的事務(wù)措置機制,watch乃至算不上關(guān)系型數(shù)據(jù)庫中的事務(wù)措置。對此,更需要對表進行加鎖解鎖。java之類說話的項目,良多都是直接把持內(nèi)存的,更是需要資本鎖,來解決并發(fā)標題問題,解決多個要求把持統(tǒng)一份數(shù)據(jù)的標題問題。公司有別的一個項目,呈現(xiàn)過一次因為鎖的顆粒度較大年夜,帶來的鎖等候timebomb的標題問題,也導致了線程繁梗阻忙,要求聚積,系統(tǒng)負載上升,導致宕機的標題問題。這個項目標鎖是針對所有效戶的鎖,每個用戶的要求發(fā)來時,當火線程會對所有效戶的數(shù)據(jù)加鎖,直到響應(yīng)完成,才釋放掉落。這么做,是為體味決因當前把持,會影響到其他用戶數(shù)據(jù),好比多人PK,多個玩家之間的交互。

當其他要求一并發(fā)來時,那么資本會當即被鎖住,直到上一個要求結(jié)束,才釋放鎖,那么其他線程都處于等候狀況。用戶基數(shù)小時,是看不出來鎖帶來的影響的,內(nèi)存把持都比較快。當用戶基數(shù)大年夜時,或說要求數(shù)增大年夜時,后面的要求的等候時候會愈來愈長,超越webserver的等候時候,直接返回timeout,不克不及正常供給辦事。
這類標題問題標產(chǎn)生,是因為鎖的顆粒太大年夜了,不該該將所有效戶都鎖住,最好細化到當前要求所影響到的單個用戶,只鎖住單個用戶的數(shù)據(jù)。如許,才削減timebomb的產(chǎn)生。
其他
知乎里的伴侶提到,良多webgame 的前端做了鑒定,而后端沒做鑒定的標題問題,這類標題問題,實屬不該存在。在我們的項目中,后端做的驗證鑒定,遠比前端多的多。有時辰,為了界面上的動畫表示,前端flash一般會在用戶把持以后,當即襯著,然后,再按照后端響應(yīng),決定是不是繼續(xù)做界面元素改動。好比脫設(shè)備,玩家把持時,會先襯著設(shè)備從角色面板,跳到背包里的動畫,然后,再按照后端響應(yīng)成果,決定是不是反轉(zhuǎn)展動彈畫。如許,避免顯得把持后,一按時候的反應(yīng)癡鈍假象,以進步用戶體驗。當然,后端是必然會做鑒定的,鑒定角色背包是不是有空格之類。此刻的webgame研發(fā),一般都不會存在前端鑒定,而后端不鑒定的做法了。假定有,也應(yīng)當是個別漏掉環(huán)境。
好比往年的time33算法的hash dos的標題問題,利用json動靜格局的webgame必然要寄望,php只是在領(lǐng)受要求時,做了最大年夜數(shù)量標限制。但在json解碼以后的數(shù)據(jù)中,是沒有措置的。這里千萬別健忘了。
運營數(shù)據(jù)異常監(jiān)控
再完美的防御辦法,都仍會有安然縫隙。恰當?shù)谋O(jiān)控辦法,也必然要有,監(jiān)控等第、金幣、游戲幣、經(jīng)驗、珍貴物品的改變等等,一旦發(fā)現(xiàn),當即報警,在縫隙未分散之前,第一時候往修復縫隙,以削減損掉,保護游戲均衡。
日記系統(tǒng)
日記系統(tǒng)必然不克不及漏掉,所有把持,必需寫進日記,當安然事務(wù)產(chǎn)生后,可以作為各類數(shù)據(jù)回滾,生意膠葛措置的靠得住數(shù)據(jù)。也是作為數(shù)據(jù)監(jiān)控的最準確的數(shù)據(jù)來歷。
假定你用了我畫的小清爽般的插圖,請記得為圖片寫上簽名來歷,畫圖是最破鈔我時候的一件事。