Revision | 95a8511feba3e80744c5c2d344ba4ee1b6c19f31 (tree) |
---|---|
Time | 2012-09-22 16:21:19 |
Author | h2so5 <h2so5@git....> |
Commiter | h2so5 |
Merge branch 'master' of git.sourceforge.jp:/gitroot/mmo/main
Conflicts:
client/Card.hpp
client/ResourceManager.cpp
@@ -21,6 +21,8 @@ | ||
21 | 21 | #include "../common/database/AccountProperty.hpp" |
22 | 22 | #include "Profiler.hpp" |
23 | 23 | #include "GenerateJSON.hpp" |
24 | +#include "Music.hpp" | |
25 | + | |
24 | 26 | |
25 | 27 | char Card::STORAGE_DIR[] = "storage"; |
26 | 28 | char Card::SCRIPT_PATH[] = "resources/js"; |
@@ -78,6 +80,7 @@ Card::Card( | ||
78 | 80 | context->Global()->Set(String::New("Player"), script_object->Clone()); |
79 | 81 | context->Global()->Set(String::New("Model"), script_object->Clone()); |
80 | 82 | context->Global()->Set(String::New("Account"), script_object->Clone()); |
83 | + context->Global()->Set(String::New("Music"), script_object->Clone()); | |
81 | 84 | context->Global()->Set(String::New("InputBox"), script_object->Clone()); |
82 | 85 | context->Global()->Set(String::New("Card"), script_object->Clone()); |
83 | 86 | context->Global()->Set(String::New("Screen"), script_object->Clone()); |
@@ -222,6 +225,78 @@ Handle<Value> Card::Function_Player_stopMotion(const Arguments& args) | ||
222 | 225 | return Undefined(); |
223 | 226 | } |
224 | 227 | |
228 | +Handle<Value> Card::Function_Music_playBGM(const Arguments& args) | |
229 | +{ | |
230 | + | |
231 | + if (args.Length() >= 2 && args[0]->IsString()) { | |
232 | + auto name = std::string(*String::Utf8Value(args[0]->ToString())); | |
233 | + auto fade = args[1]->ToBoolean()->BooleanValue(); | |
234 | + ResourceManager::music()->Play(unicode::ToTString(name),fade); | |
235 | + } | |
236 | + | |
237 | + return Undefined(); | |
238 | +} | |
239 | + | |
240 | +Handle<Value> Card::Function_Music_stopBGM(const Arguments& args) | |
241 | +{ | |
242 | + | |
243 | + if (args.Length() == 1 && args[0]->IsBoolean()) { | |
244 | + auto fade = args[1]->ToBoolean()->BooleanValue(); | |
245 | + ResourceManager::music()->Stop(fade); | |
246 | + }else if(args.Length() == 0) { | |
247 | + ResourceManager::music()->Stop(false); | |
248 | + } | |
249 | + | |
250 | + return Undefined(); | |
251 | +} | |
252 | + | |
253 | +Handle<Value> Card::Function_Music_playME(const Arguments& args) | |
254 | +{ | |
255 | + | |
256 | + if (args.Length() == 1 && args[0]->IsString()) { | |
257 | + auto name = std::string(*String::Utf8Value(args[0]->ToString())); | |
258 | + ResourceManager::music()->PlayME(unicode::ToTString(name)); | |
259 | + } | |
260 | + | |
261 | + return Undefined(); | |
262 | +} | |
263 | + | |
264 | + | |
265 | +Handle<Value> Card::Function_Music_playSE(const Arguments& args) | |
266 | +{ | |
267 | + | |
268 | + if (args.Length() == 1 && args[0]->IsString()) { | |
269 | + auto name = std::string(*String::Utf8Value(args[0]->ToString())); | |
270 | + ResourceManager::music()->PlaySE(unicode::ToTString(name)); | |
271 | + } | |
272 | + | |
273 | + return Undefined(); | |
274 | +} | |
275 | + | |
276 | +Handle<Value> Card::Function_Music_all(const Arguments& args) | |
277 | +{ | |
278 | + HandleScope handle; | |
279 | + auto array = Array::New(); | |
280 | + | |
281 | + int i = 0; | |
282 | + BOOST_FOREACH(const boost::filesystem::path& music_path, ResourceManager::music()->GetMusicList()) { | |
283 | + array->Set(i, String::New(music_path.stem().string().c_str())); | |
284 | + i++; | |
285 | + } | |
286 | + return array; | |
287 | +} | |
288 | + | |
289 | + | |
290 | +Handle<Value> Card::Function_Music_IsLoadingDone(const Arguments& args) | |
291 | +{ | |
292 | + if (args.Length() == 1 && args[0]->IsString()) { | |
293 | + auto name = std::string(*String::Utf8Value(args[0]->ToString())); | |
294 | + auto check = ResourceManager::music()->CheckLoadedBGM(unicode::ToTString(name)); | |
295 | + return Boolean::New(check); | |
296 | + } | |
297 | + return Boolean::New(false); | |
298 | +} | |
299 | + | |
225 | 300 | Handle<Value> Card::Function_Account_id(const Arguments& args) |
226 | 301 | { |
227 | 302 | auto self = static_cast<Card*>(args.Holder()->GetPointerFromInternalField(0)); |
@@ -284,6 +359,7 @@ Handle<Value> Card::Function_Account_updateModelName(const Arguments& args) | ||
284 | 359 | auto name = std::string(*String::Utf8Value(args[0]->ToString())); |
285 | 360 | if (auto world_manager = self->manager_accessor_->world_manager().lock()) { |
286 | 361 | world_manager->myself()->LoadModel(unicode::ToTString(name)); |
362 | + world_manager->myself()->ResetMotion(); | |
287 | 363 | } |
288 | 364 | auto account_manager = self->manager_accessor_->account_manager().lock(); |
289 | 365 | auto command_manager = self->manager_accessor_->command_manager().lock(); |
@@ -683,7 +759,62 @@ void Card::SetFunctions() | ||
683 | 759 | * @static |
684 | 760 | */ |
685 | 761 | script_.SetFunction("Player.stopMotion", Function_Player_stopMotion); |
762 | + | |
763 | + /** | |
764 | + * 音楽を再生します | |
765 | + * | |
766 | + * @method playMotion | |
767 | + * @param {String} name BGM名 | |
768 | + * @static | |
769 | + */ | |
770 | + script_.SetFunction("Music.play", Function_Music_playBGM); | |
771 | + | |
686 | 772 | /** |
773 | + * 音楽を停止します | |
774 | + * | |
775 | + * @method playMotion | |
776 | + * @param | |
777 | + * @static | |
778 | + */ | |
779 | + script_.SetFunction("Music.stop", Function_Music_stopBGM); | |
780 | + | |
781 | + /** | |
782 | + * MEを再生します | |
783 | + * | |
784 | + * @method playMotion | |
785 | + * @param {String} name ME名 | |
786 | + * @static | |
787 | + */ | |
788 | + script_.SetFunction("Music.playME", Function_Music_playME); | |
789 | + | |
790 | + /** | |
791 | + * SEを再生します | |
792 | + * | |
793 | + * @method playMotion | |
794 | + * @param {String} name SE名 | |
795 | + * @static | |
796 | + */ | |
797 | + script_.SetFunction("Music.playSE", Function_Music_playSE); | |
798 | + | |
799 | + /** | |
800 | + * BGM,MEのロードが終了しているかチェックします | |
801 | + * | |
802 | + * @method playMotion | |
803 | + * @param {String} name BGM、ME名 | |
804 | + * @static | |
805 | + */ | |
806 | + script_.SetFunction("Music.loadCheck", Function_Music_IsLoadingDone); | |
807 | + | |
808 | + /** | |
809 | + * BGMのリストを返します | |
810 | + * | |
811 | + * @method playMotion | |
812 | + * @param | |
813 | + * @static | |
814 | + */ | |
815 | + script_.SetFunction("Music.all", Function_Music_all); | |
816 | + | |
817 | + /** | |
687 | 818 | * アカウント |
688 | 819 | * |
689 | 820 | * @class Account |
@@ -175,8 +175,8 @@ JsonGen::JsonGen() | ||
175 | 175 | DxLib::VECTOR prePos = {0},curPos = {0},lclPos = {0}; |
176 | 176 | DxLib::MATRIX chglcl = {0}; |
177 | 177 | |
178 | - char pmd_model_name_[256] = {0}; | |
179 | - TCHAR pmd_author_name_[256] = {0}; | |
178 | + char pmd_model_name_[MAX_PATH] = {0}; | |
179 | + TCHAR pmd_author_name_[MAX_PATH] = {0}; | |
180 | 180 | |
181 | 181 | int exist_num_pmd_ = 0; |
182 | 182 |
@@ -196,7 +196,7 @@ void MiniMap::DrawPosAndCalc() | ||
196 | 196 | if(tmp_pos_x < absolute_x() + 12)tmp_pos_x = absolute_x() + 12; |
197 | 197 | if(tmp_pos_x > absolute_x() + absolute_width() - 12)tmp_pos_x = absolute_x() + absolute_width() - 12; |
198 | 198 | if(tmp_pos_z < absolute_y() + 12)tmp_pos_z = absolute_y() + 12; |
199 | - if(tmp_pos_z > absolute_y() + absolute_height() -12)tmp_pos_z = absolute_y() + absolute_height() - 12; | |
199 | + if(tmp_pos_z > absolute_y() + absolute_height() -12 - 16)tmp_pos_z = absolute_y() + absolute_height() - 12 - 16; | |
200 | 200 | DrawCircle( tmp_pos_x, tmp_pos_z, 2, GetColor(23,162,175),TRUE); |
201 | 201 | } |
202 | 202 | prev_myself_pos_on_map_ = player_manager->char_data_providers()[player_manager->charmgr()->my_character_id()]->position(); |
@@ -0,0 +1,202 @@ | ||
1 | +// | |
2 | +// Music.cpp | |
3 | +// | |
4 | + | |
5 | +#include <boost/filesystem.hpp> | |
6 | +#include "Music.hpp" | |
7 | +#include "../common/Logger.hpp" | |
8 | +#include "../common/unicode.hpp" | |
9 | + | |
10 | +extern int LoadFile(const TCHAR *FilePath, void **FileImageAddr, int *FileSize); | |
11 | + | |
12 | +Music::Music() : | |
13 | +bgm_handle_(), | |
14 | +se_handle_(), | |
15 | +prev_bgm_(-1), | |
16 | +present_bgm_(-1), | |
17 | +requested_bgm_(-1), | |
18 | +music_paths_(), | |
19 | +crossfade_now_(false), | |
20 | +fade_count_(0) | |
21 | +{ | |
22 | +} | |
23 | + | |
24 | +void Music::Init() | |
25 | +{ | |
26 | + using namespace boost::filesystem; | |
27 | + using namespace std; | |
28 | + | |
29 | + music_paths_.clear(); | |
30 | + | |
31 | + path p("./resources/music"); | |
32 | + | |
33 | + try{ | |
34 | + if (exists(p) && is_directory(p)) { | |
35 | + for (auto it_dir = directory_iterator(p); it_dir != directory_iterator(); ++it_dir) { | |
36 | + if (!is_directory(*it_dir)) { | |
37 | + path music_path = it_dir->path(); | |
38 | + auto extension = music_path.extension().string(); | |
39 | + if( extension == ".wave" || extension == ".wav" || | |
40 | + extension == ".ogg" || extension == ".mp3") | |
41 | + { | |
42 | + music_paths_.push_back(music_path); | |
43 | + } | |
44 | + } | |
45 | + } | |
46 | + } | |
47 | + } catch (const filesystem_error& ex) { | |
48 | + Logger::Error(_T("%s"), unicode::ToTString(ex.what())); | |
49 | + } | |
50 | + | |
51 | + se_paths_.clear(); | |
52 | + | |
53 | + p = "./resources/se"; | |
54 | + | |
55 | + try{ | |
56 | + if (exists(p) && is_directory(p)) { | |
57 | + for (auto it_dir = directory_iterator(p); it_dir != directory_iterator(); ++it_dir) { | |
58 | + if (!is_directory(*it_dir)) { | |
59 | + path music_path = it_dir->path(); | |
60 | + auto extension = music_path.extension().string(); | |
61 | + if( extension == ".wave" || extension == ".wav" || | |
62 | + extension == ".ogg" || extension == ".mp3") | |
63 | + { | |
64 | + se_paths_.push_back(music_path); | |
65 | + } | |
66 | + } | |
67 | + } | |
68 | + } | |
69 | + } catch (const filesystem_error& ex) { | |
70 | + Logger::Error(_T("%s"), unicode::ToTString(ex.what())); | |
71 | + } | |
72 | + | |
73 | +} | |
74 | + | |
75 | +void Music::Play(tstring name,bool crossfade) | |
76 | +{ | |
77 | + if(bgm_handle_.find(name) == bgm_handle_.end()) | |
78 | + { | |
79 | + SetUseASyncLoadFlag(FALSE); | |
80 | + auto NameFind = [&](boost::filesystem::path& src)->bool | |
81 | + { | |
82 | + return src.stem().string() == unicode::ToString(name); | |
83 | + }; | |
84 | + auto bgm_it_ = std::find_if(music_paths_.begin(),music_paths_.end(),NameFind); | |
85 | + void *fileaddr; | |
86 | + int filesize; | |
87 | + LoadFile(unicode::ToTString(bgm_it_->string()).c_str(),&fileaddr,&filesize); | |
88 | + auto softhandle_ = LoadSoftSoundFromMemImage(fileaddr,filesize); | |
89 | + auto handle_ = LoadSoundMemByMemImage(fileaddr,filesize); | |
90 | + if(handle_ == -1)return; | |
91 | + bgm_handle_.insert(std::make_pair<tstring,int>(unicode::ToTString(bgm_it_->stem().string()),handle_)); | |
92 | + SetUseASyncLoadFlag(TRUE); | |
93 | + } | |
94 | + if(crossfade) | |
95 | + { | |
96 | + requested_bgm_ = bgm_handle_[name]; | |
97 | + }else{ | |
98 | + if(present_bgm_ != -1)StopSoundMem(present_bgm_); | |
99 | + present_bgm_ = bgm_handle_[name]; | |
100 | + PlaySoundMem(present_bgm_,DX_PLAYTYPE_LOOP); | |
101 | + } | |
102 | + fade_count_ = 0; | |
103 | + crossfade_now_ = crossfade; | |
104 | +} | |
105 | + | |
106 | +void Music::PlayME(tstring name) | |
107 | +{ | |
108 | + if(present_bgm_ != -1)prev_bgm_ = present_bgm_; | |
109 | + if(bgm_handle_.find(name) == bgm_handle_.end()) | |
110 | + { | |
111 | + SetUseASyncLoadFlag(FALSE); | |
112 | + auto NameFind = [&](boost::filesystem::path& src)->bool | |
113 | + { | |
114 | + return src.stem().string() == unicode::ToString(name); | |
115 | + }; | |
116 | + auto bgm_it_ = std::find_if(music_paths_.begin(),music_paths_.end(),NameFind); | |
117 | + void *fileaddr; | |
118 | + int filesize; | |
119 | + LoadFile(unicode::ToTString(bgm_it_->string()).c_str(),&fileaddr,&filesize); | |
120 | + auto softhandle_ = LoadSoftSoundFromMemImage(fileaddr,filesize); | |
121 | + auto handle_ = LoadSoundMemByMemImage(fileaddr,filesize); | |
122 | + if(handle_ == -1)return; | |
123 | + bgm_handle_.insert(std::make_pair<tstring,int>(unicode::ToTString(bgm_it_->stem().string()),handle_)); | |
124 | + SetUseASyncLoadFlag(TRUE); | |
125 | + } | |
126 | + if(present_bgm_ != -1)StopSoundMem(present_bgm_); | |
127 | + present_bgm_ = bgm_handle_[name]; | |
128 | + PlaySoundMem(present_bgm_,DX_PLAYTYPE_BACK); | |
129 | + crossfade_now_ = false; | |
130 | + fade_count_ = 0; | |
131 | +} | |
132 | + | |
133 | +void Music::Stop(bool fadeout) | |
134 | +{ | |
135 | + if(!CheckSoundMem(present_bgm_))return; | |
136 | + if(!fadeout) | |
137 | + { | |
138 | + StopSoundMem(present_bgm_); | |
139 | + } | |
140 | + crossfade_now_ = fadeout; | |
141 | + fade_count_ = 0; | |
142 | +} | |
143 | + | |
144 | +void Music::PlaySE(tstring name) | |
145 | +{ | |
146 | + if(se_handle_.find(name) == se_handle_.end()) | |
147 | + { | |
148 | + SetUseASyncLoadFlag(FALSE); | |
149 | + auto NameFind = [&](boost::filesystem::path& src)->bool | |
150 | + { | |
151 | + return src.stem().string() == unicode::ToString(name); | |
152 | + }; | |
153 | + auto se_it_ = std::find_if(se_paths_.begin(),se_paths_.end(),NameFind); | |
154 | + auto handle_ = LoadSoundMemToBufNumSitei(unicode::ToTString(se_it_->string()).c_str(),64); | |
155 | + if(handle_ == -1)return; | |
156 | + se_handle_.insert(std::make_pair<tstring,int>(unicode::ToTString(se_it_->stem().string()),handle_)); | |
157 | + } | |
158 | + PlaySoundMem(se_handle_[name],DX_PLAYTYPE_BACK); | |
159 | +} | |
160 | + | |
161 | +bool Music::CheckLoadedBGM(tstring name) | |
162 | +{ | |
163 | + if(bgm_handle_.find(name) == bgm_handle_.end())return true; | |
164 | + return CheckHandleASyncLoad(bgm_handle_[name]); | |
165 | +} | |
166 | + | |
167 | +void Music::Update() | |
168 | +{ | |
169 | + if(prev_bgm_ != -1) | |
170 | + { | |
171 | + if(!CheckSoundMem(present_bgm_)) | |
172 | + { | |
173 | + present_bgm_ = -1; | |
174 | + requested_bgm_ = prev_bgm_; | |
175 | + fade_count_ = 0; | |
176 | + crossfade_now_ = true; | |
177 | + } | |
178 | + } | |
179 | + if(!crossfade_now_)return; | |
180 | + if(CheckHandleASyncLoad(requested_bgm_) == false && requested_bgm_ != -1) | |
181 | + { | |
182 | + if(fade_count_ == 0)PlaySoundMem(requested_bgm_,DX_PLAYTYPE_LOOP); | |
183 | + if(fade_count_ >= 120) | |
184 | + { | |
185 | + ChangeVolumeSoundMem(100,requested_bgm_); | |
186 | + StopSoundMem(present_bgm_); | |
187 | + ChangeVolumeSoundMem(100,present_bgm_); | |
188 | + present_bgm_ = requested_bgm_; | |
189 | + requested_bgm_ = -1; | |
190 | + fade_count_ = 0; | |
191 | + crossfade_now_ = false; | |
192 | + } | |
193 | + ChangeVolumeSoundMem((int)(fade_count_/1.2),requested_bgm_); | |
194 | + ChangeVolumeSoundMem((int)((120-fade_count_)/1.2),present_bgm_); | |
195 | + ++fade_count_; | |
196 | + } | |
197 | +} | |
198 | + | |
199 | +std::vector<boost::filesystem::path>& Music::GetMusicList() | |
200 | +{ | |
201 | + return music_paths_; | |
202 | +} | |
\ No newline at end of file |
@@ -0,0 +1,42 @@ | ||
1 | +// | |
2 | +// Music.hpp | |
3 | +// | |
4 | +#include "../common/unicode.hpp" | |
5 | +#include <v8.h> | |
6 | +#include <map> | |
7 | +#include <vector> | |
8 | + | |
9 | +//解析する信号の長さ(秒) | |
10 | +#define SIGNAL_LENGTH 0.5 | |
11 | +//スペクトラムの数 | |
12 | +#define SPECTRUM_NUM 256 | |
13 | +//スペクトラムの拡大幅 | |
14 | +#define SPECTRUM_WIDTH 2 | |
15 | + | |
16 | + | |
17 | +class Music | |
18 | +{ | |
19 | +public: | |
20 | + Music(); | |
21 | + virtual ~Music(){}; | |
22 | + void Init(); | |
23 | + void Update(); | |
24 | + void Play(tstring name,bool crossfade); | |
25 | + void Stop(bool fadeout); | |
26 | + void PlaySE(tstring name); | |
27 | + void PlayME(tstring name); | |
28 | + bool CheckLoadedBGM(tstring name); | |
29 | + std::vector<boost::filesystem::path>& GetMusicList(); | |
30 | + | |
31 | +private: | |
32 | + bool crossfade_now_; | |
33 | + int fade_count_; | |
34 | + int present_bgm_; | |
35 | + int prev_bgm_; | |
36 | + int requested_bgm_; | |
37 | + std::map<tstring,int> bgm_handle_; | |
38 | + std::map<tstring,int> se_handle_; | |
39 | + | |
40 | + std::vector<boost::filesystem::path> music_paths_; | |
41 | + std::vector<boost::filesystem::path> se_paths_; | |
42 | +}; |
@@ -19,9 +19,11 @@ using boost::property_tree::ptree; | ||
19 | 19 | |
20 | 20 | class ImageHandle; |
21 | 21 | class ModelHandle; |
22 | +class Music; | |
22 | 23 | |
23 | 24 | typedef std::shared_ptr<ImageHandle> ImageHandlePtr; |
24 | 25 | typedef std::shared_ptr<ModelHandle> ModelHandlePtr; |
26 | +typedef std::shared_ptr<Music> MusicPtr; | |
25 | 27 | |
26 | 28 | struct ReadFuncData { |
27 | 29 | ReadFuncData(){}; |
@@ -86,6 +88,9 @@ class ResourceManager { | ||
86 | 88 | |
87 | 89 | static tstring NameToFullPath(const tstring& name); |
88 | 90 | |
91 | + //Musics | |
92 | + static MusicPtr& music(); | |
93 | + | |
89 | 94 | private: |
90 | 95 | static int default_font_handle_; |
91 | 96 | static std::unordered_map<tstring, ImageHandlePtr> graph_handles_; |
@@ -96,6 +101,8 @@ class ResourceManager { | ||
96 | 101 | static std::unordered_map<tstring, ModelHandle> model_handles_; |
97 | 102 | static std::vector<std::string> model_name_list_; |
98 | 103 | static float model_edge_size_; |
104 | + //Musics | |
105 | + static MusicPtr music_; | |
99 | 106 | }; |
100 | 107 | |
101 | 108 | class ImageHandle { |
@@ -0,0 +1,37 @@ | ||
1 | + | |
2 | +/***MetaData*** | |
3 | + | |
4 | +{ | |
5 | + "name": "BGMリスト", | |
6 | + "icon": "icon.png", | |
7 | + "api_version": 1 | |
8 | +} | |
9 | + | |
10 | +***MetaData***/ | |
11 | + | |
12 | +var list; | |
13 | +list = new UI.List({ | |
14 | + docking: UI.DOCKING_TOP | UI.DOCKING_LEFT | UI.DOCKING_RIGHT | UI.DOCKING_BOTTOM | |
15 | +}); | |
16 | + | |
17 | +var even_line = false; | |
18 | +var music_names = Music.all(); | |
19 | +for (var i = 0; i < music_names.length; i++) { | |
20 | + (function (music_name) { | |
21 | + list.addItem( | |
22 | + new UI.Label({ | |
23 | + docking: UI.DOCKING_TOP | UI.DOCKING_LEFT | UI.DOCKING_RIGHT, | |
24 | + text: music_name, | |
25 | + bgcolor: ((even_line = !even_line) ? "#EEAFEECC" : "#FFFFFFCC"), | |
26 | + onclick: function () { | |
27 | + Music.play(music_name,true) | |
28 | + } | |
29 | + }) | |
30 | + ); | |
31 | + })(music_names[i]) | |
32 | +} | |
33 | + | |
34 | +Card.board.width = 240; | |
35 | +Card.board.height = 120; | |
36 | +Card.board.docking = UI.DOCKING_BOTTOM | UI.DOCKING_LEFT | |
37 | +Card.board.addChild(list); | |
\ No newline at end of file |
@@ -10,6 +10,7 @@ | ||
10 | 10 | #include "../Core.hpp" |
11 | 11 | #include <shlwapi.h> |
12 | 12 | #include "ServerChange.hpp" |
13 | +#include "../Music.hpp" | |
13 | 14 | |
14 | 15 | namespace scene { |
15 | 16 | MainLoop::MainLoop(const ManagerAccessorPtr& manager_accessor) : |
@@ -54,6 +55,7 @@ void MainLoop::Update() | ||
54 | 55 | card_manager_->Update(); |
55 | 56 | minimap_.Update(); |
56 | 57 | world_manager_->Update(); |
58 | + ResourceManager::music()->Update(); | |
57 | 59 | } |
58 | 60 | |
59 | 61 | void MainLoop::ProcessInput(InputManager* input) |
@@ -9,7 +9,7 @@ | ||
9 | 9 | |
10 | 10 | #define MMO_VERSION_MAJOR 0 |
11 | 11 | #define MMO_VERSION_MINOR 3 |
12 | -#define MMO_VERSION_REVISION 8 | |
12 | +#define MMO_VERSION_REVISION 9 | |
13 | 13 | |
14 | 14 | #define MMO_PROTOCOL_VERSION 2 |
15 | 15 |