├── docs ├── README.md └── SQL.md ├── tools ├── README.md ├── sql2struct │ ├── dbr.exe │ ├── sql2struct.bat │ └── struct.xorm.kwx.tpl └── exportmysql │ └── main_mysql_export_go_struct.go ├── cmd ├── game │ ├── build.sh │ ├── blocks │ │ └── xinshoucun.block │ └── start_server.sh ├── gate │ ├── build.sh │ ├── start_server.sh │ └── main.go ├── web │ ├── build.sh │ └── start_server.sh └── master │ ├── build.sh │ ├── start_server.sh │ └── main.go ├── pkg ├── aoi │ ├── Makefile │ ├── aoi.go │ └── README.md ├── security │ ├── sql.go │ ├── validity.go │ └── validity_test.go ├── utils │ └── utils.go ├── async │ └── async.go ├── path │ └── path.go ├── algoutil │ ├── password_test.go │ ├── algoutil_test.go │ ├── crypt.go │ ├── password.go │ ├── params_test.go │ └── params.go ├── shape │ ├── rect.go │ └── util.go ├── set │ └── set.go ├── mtm │ └── mysql.go ├── mysqlx │ └── json.go ├── whitelist │ ├── white_list.go │ └── white_list_test.go ├── coord │ └── vector3.go ├── env │ └── env.go └── astar │ └── astar_test.go ├── internal ├── web │ ├── static │ │ ├── client │ │ │ ├── javascript-astar │ │ │ │ ├── .npmignore │ │ │ │ ├── .gitignore │ │ │ │ ├── .travis.yml │ │ │ │ ├── test │ │ │ │ │ └── index.html │ │ │ │ ├── Gruntfile.js │ │ │ │ ├── package.json │ │ │ │ ├── LICENSE │ │ │ │ ├── benchmark │ │ │ │ │ ├── benchmark.js │ │ │ │ │ └── index.html │ │ │ │ ├── index.html │ │ │ │ └── README.md │ │ │ ├── statemachine.js │ │ │ ├── assets │ │ │ │ └── map │ │ │ │ │ └── xinshoucun │ │ │ │ │ ├── xinshoucun.block │ │ │ │ │ ├── xinshoucun.config │ │ │ │ │ ├── pic │ │ │ │ │ ├── xinshoucun.jpg │ │ │ │ │ ├── xinshoucun_0_0.jpg │ │ │ │ │ ├── xinshoucun_0_1.jpg │ │ │ │ │ ├── xinshoucun_0_2.jpg │ │ │ │ │ ├── xinshoucun_0_3.jpg │ │ │ │ │ ├── xinshoucun_0_4.jpg │ │ │ │ │ ├── xinshoucun_0_5.jpg │ │ │ │ │ ├── xinshoucun_0_6.jpg │ │ │ │ │ ├── xinshoucun_0_7.jpg │ │ │ │ │ ├── xinshoucun_0_8.jpg │ │ │ │ │ ├── xinshoucun_0_9.jpg │ │ │ │ │ ├── xinshoucun_1_0.jpg │ │ │ │ │ ├── xinshoucun_1_1.jpg │ │ │ │ │ ├── xinshoucun_1_2.jpg │ │ │ │ │ ├── xinshoucun_1_3.jpg │ │ │ │ │ ├── xinshoucun_1_4.jpg │ │ │ │ │ ├── xinshoucun_1_5.jpg │ │ │ │ │ ├── xinshoucun_1_6.jpg │ │ │ │ │ ├── xinshoucun_1_7.jpg │ │ │ │ │ ├── xinshoucun_1_8.jpg │ │ │ │ │ ├── xinshoucun_1_9.jpg │ │ │ │ │ ├── xinshoucun_2_0.jpg │ │ │ │ │ ├── xinshoucun_2_1.jpg │ │ │ │ │ ├── xinshoucun_2_2.jpg │ │ │ │ │ ├── xinshoucun_2_3.jpg │ │ │ │ │ ├── xinshoucun_2_4.jpg │ │ │ │ │ ├── xinshoucun_2_5.jpg │ │ │ │ │ ├── xinshoucun_2_6.jpg │ │ │ │ │ ├── xinshoucun_2_7.jpg │ │ │ │ │ ├── xinshoucun_2_8.jpg │ │ │ │ │ ├── xinshoucun_2_9.jpg │ │ │ │ │ ├── xinshoucun_3_0.jpg │ │ │ │ │ ├── xinshoucun_3_1.jpg │ │ │ │ │ ├── xinshoucun_3_2.jpg │ │ │ │ │ ├── xinshoucun_3_3.jpg │ │ │ │ │ ├── xinshoucun_3_4.jpg │ │ │ │ │ ├── xinshoucun_3_5.jpg │ │ │ │ │ ├── xinshoucun_3_6.jpg │ │ │ │ │ ├── xinshoucun_3_7.jpg │ │ │ │ │ ├── xinshoucun_3_8.jpg │ │ │ │ │ ├── xinshoucun_3_9.jpg │ │ │ │ │ ├── xinshoucun_4_0.jpg │ │ │ │ │ ├── xinshoucun_4_1.jpg │ │ │ │ │ ├── xinshoucun_4_2.jpg │ │ │ │ │ ├── xinshoucun_4_3.jpg │ │ │ │ │ ├── xinshoucun_4_4.jpg │ │ │ │ │ ├── xinshoucun_4_5.jpg │ │ │ │ │ ├── xinshoucun_4_6.jpg │ │ │ │ │ ├── xinshoucun_4_7.jpg │ │ │ │ │ ├── xinshoucun_4_8.jpg │ │ │ │ │ ├── xinshoucun_4_9.jpg │ │ │ │ │ ├── xinshoucun_5_0.jpg │ │ │ │ │ ├── xinshoucun_5_1.jpg │ │ │ │ │ ├── xinshoucun_5_2.jpg │ │ │ │ │ ├── xinshoucun_5_3.jpg │ │ │ │ │ ├── xinshoucun_5_4.jpg │ │ │ │ │ ├── xinshoucun_5_5.jpg │ │ │ │ │ ├── xinshoucun_5_6.jpg │ │ │ │ │ ├── xinshoucun_5_7.jpg │ │ │ │ │ ├── xinshoucun_5_8.jpg │ │ │ │ │ ├── xinshoucun_5_9.jpg │ │ │ │ │ ├── xinshoucun_6_0.jpg │ │ │ │ │ ├── xinshoucun_6_1.jpg │ │ │ │ │ ├── xinshoucun_6_2.jpg │ │ │ │ │ ├── xinshoucun_6_3.jpg │ │ │ │ │ ├── xinshoucun_6_4.jpg │ │ │ │ │ ├── xinshoucun_6_5.jpg │ │ │ │ │ ├── xinshoucun_6_6.jpg │ │ │ │ │ ├── xinshoucun_6_7.jpg │ │ │ │ │ ├── xinshoucun_6_8.jpg │ │ │ │ │ ├── xinshoucun_6_9.jpg │ │ │ │ │ ├── xinshoucun_7_0.jpg │ │ │ │ │ ├── xinshoucun_7_1.jpg │ │ │ │ │ ├── xinshoucun_7_2.jpg │ │ │ │ │ ├── xinshoucun_7_3.jpg │ │ │ │ │ ├── xinshoucun_7_4.jpg │ │ │ │ │ ├── xinshoucun_7_5.jpg │ │ │ │ │ ├── xinshoucun_7_6.jpg │ │ │ │ │ ├── xinshoucun_7_7.jpg │ │ │ │ │ ├── xinshoucun_7_8.jpg │ │ │ │ │ ├── xinshoucun_7_9.jpg │ │ │ │ │ ├── xinshoucun_8_0.jpg │ │ │ │ │ ├── xinshoucun_8_1.jpg │ │ │ │ │ ├── xinshoucun_8_2.jpg │ │ │ │ │ ├── xinshoucun_8_3.jpg │ │ │ │ │ ├── xinshoucun_8_4.jpg │ │ │ │ │ ├── xinshoucun_8_5.jpg │ │ │ │ │ ├── xinshoucun_8_6.jpg │ │ │ │ │ ├── xinshoucun_8_7.jpg │ │ │ │ │ ├── xinshoucun_8_8.jpg │ │ │ │ │ ├── xinshoucun_8_9.jpg │ │ │ │ │ ├── xinshoucun_9_0.jpg │ │ │ │ │ ├── xinshoucun_9_1.jpg │ │ │ │ │ ├── xinshoucun_9_2.jpg │ │ │ │ │ ├── xinshoucun_9_3.jpg │ │ │ │ │ ├── xinshoucun_9_4.jpg │ │ │ │ │ ├── xinshoucun_9_5.jpg │ │ │ │ │ ├── xinshoucun_9_6.jpg │ │ │ │ │ ├── xinshoucun_9_7.jpg │ │ │ │ │ ├── xinshoucun_9_8.jpg │ │ │ │ │ ├── xinshoucun_9_9.jpg │ │ │ │ │ ├── xinshoucun_0_10.jpg │ │ │ │ │ ├── xinshoucun_0_11.jpg │ │ │ │ │ ├── xinshoucun_0_12.jpg │ │ │ │ │ ├── xinshoucun_0_13.jpg │ │ │ │ │ ├── xinshoucun_0_14.jpg │ │ │ │ │ ├── xinshoucun_10_0.jpg │ │ │ │ │ ├── xinshoucun_10_1.jpg │ │ │ │ │ ├── xinshoucun_10_10.jpg │ │ │ │ │ ├── xinshoucun_10_11.jpg │ │ │ │ │ ├── xinshoucun_10_12.jpg │ │ │ │ │ ├── xinshoucun_10_13.jpg │ │ │ │ │ ├── xinshoucun_10_14.jpg │ │ │ │ │ ├── xinshoucun_10_2.jpg │ │ │ │ │ ├── xinshoucun_10_3.jpg │ │ │ │ │ ├── xinshoucun_10_4.jpg │ │ │ │ │ ├── xinshoucun_10_5.jpg │ │ │ │ │ ├── xinshoucun_10_6.jpg │ │ │ │ │ ├── xinshoucun_10_7.jpg │ │ │ │ │ ├── xinshoucun_10_8.jpg │ │ │ │ │ ├── xinshoucun_10_9.jpg │ │ │ │ │ ├── xinshoucun_11_0.jpg │ │ │ │ │ ├── xinshoucun_11_1.jpg │ │ │ │ │ ├── xinshoucun_11_10.jpg │ │ │ │ │ ├── xinshoucun_11_11.jpg │ │ │ │ │ ├── xinshoucun_11_12.jpg │ │ │ │ │ ├── xinshoucun_11_13.jpg │ │ │ │ │ ├── xinshoucun_11_14.jpg │ │ │ │ │ ├── xinshoucun_11_2.jpg │ │ │ │ │ ├── xinshoucun_11_3.jpg │ │ │ │ │ ├── xinshoucun_11_4.jpg │ │ │ │ │ ├── xinshoucun_11_5.jpg │ │ │ │ │ ├── xinshoucun_11_6.jpg │ │ │ │ │ ├── xinshoucun_11_7.jpg │ │ │ │ │ ├── xinshoucun_11_8.jpg │ │ │ │ │ ├── xinshoucun_11_9.jpg │ │ │ │ │ ├── xinshoucun_12_0.jpg │ │ │ │ │ ├── xinshoucun_12_1.jpg │ │ │ │ │ ├── xinshoucun_12_10.jpg │ │ │ │ │ ├── xinshoucun_12_11.jpg │ │ │ │ │ ├── xinshoucun_12_12.jpg │ │ │ │ │ ├── xinshoucun_12_13.jpg │ │ │ │ │ ├── xinshoucun_12_14.jpg │ │ │ │ │ ├── xinshoucun_12_2.jpg │ │ │ │ │ ├── xinshoucun_12_3.jpg │ │ │ │ │ ├── xinshoucun_12_4.jpg │ │ │ │ │ ├── xinshoucun_12_5.jpg │ │ │ │ │ ├── xinshoucun_12_6.jpg │ │ │ │ │ ├── xinshoucun_12_7.jpg │ │ │ │ │ ├── xinshoucun_12_8.jpg │ │ │ │ │ ├── xinshoucun_12_9.jpg │ │ │ │ │ ├── xinshoucun_13_0.jpg │ │ │ │ │ ├── xinshoucun_13_1.jpg │ │ │ │ │ ├── xinshoucun_13_10.jpg │ │ │ │ │ ├── xinshoucun_13_11.jpg │ │ │ │ │ ├── xinshoucun_13_12.jpg │ │ │ │ │ ├── xinshoucun_13_13.jpg │ │ │ │ │ ├── xinshoucun_13_14.jpg │ │ │ │ │ ├── xinshoucun_13_2.jpg │ │ │ │ │ ├── xinshoucun_13_3.jpg │ │ │ │ │ ├── xinshoucun_13_4.jpg │ │ │ │ │ ├── xinshoucun_13_5.jpg │ │ │ │ │ ├── xinshoucun_13_6.jpg │ │ │ │ │ ├── xinshoucun_13_7.jpg │ │ │ │ │ ├── xinshoucun_13_8.jpg │ │ │ │ │ ├── xinshoucun_13_9.jpg │ │ │ │ │ ├── xinshoucun_14_0.jpg │ │ │ │ │ ├── xinshoucun_14_1.jpg │ │ │ │ │ ├── xinshoucun_14_10.jpg │ │ │ │ │ ├── xinshoucun_14_11.jpg │ │ │ │ │ ├── xinshoucun_14_12.jpg │ │ │ │ │ ├── xinshoucun_14_13.jpg │ │ │ │ │ ├── xinshoucun_14_14.jpg │ │ │ │ │ ├── xinshoucun_14_2.jpg │ │ │ │ │ ├── xinshoucun_14_3.jpg │ │ │ │ │ ├── xinshoucun_14_4.jpg │ │ │ │ │ ├── xinshoucun_14_5.jpg │ │ │ │ │ ├── xinshoucun_14_6.jpg │ │ │ │ │ ├── xinshoucun_14_7.jpg │ │ │ │ │ ├── xinshoucun_14_8.jpg │ │ │ │ │ ├── xinshoucun_14_9.jpg │ │ │ │ │ ├── xinshoucun_15_0.jpg │ │ │ │ │ ├── xinshoucun_15_1.jpg │ │ │ │ │ ├── xinshoucun_15_10.jpg │ │ │ │ │ ├── xinshoucun_15_11.jpg │ │ │ │ │ ├── xinshoucun_15_12.jpg │ │ │ │ │ ├── xinshoucun_15_13.jpg │ │ │ │ │ ├── xinshoucun_15_14.jpg │ │ │ │ │ ├── xinshoucun_15_2.jpg │ │ │ │ │ ├── xinshoucun_15_3.jpg │ │ │ │ │ ├── xinshoucun_15_4.jpg │ │ │ │ │ ├── xinshoucun_15_5.jpg │ │ │ │ │ ├── xinshoucun_15_6.jpg │ │ │ │ │ ├── xinshoucun_15_7.jpg │ │ │ │ │ ├── xinshoucun_15_8.jpg │ │ │ │ │ ├── xinshoucun_15_9.jpg │ │ │ │ │ ├── xinshoucun_16_0.jpg │ │ │ │ │ ├── xinshoucun_16_1.jpg │ │ │ │ │ ├── xinshoucun_16_10.jpg │ │ │ │ │ ├── xinshoucun_16_11.jpg │ │ │ │ │ ├── xinshoucun_16_12.jpg │ │ │ │ │ ├── xinshoucun_16_13.jpg │ │ │ │ │ ├── xinshoucun_16_14.jpg │ │ │ │ │ ├── xinshoucun_16_2.jpg │ │ │ │ │ ├── xinshoucun_16_3.jpg │ │ │ │ │ ├── xinshoucun_16_4.jpg │ │ │ │ │ ├── xinshoucun_16_5.jpg │ │ │ │ │ ├── xinshoucun_16_6.jpg │ │ │ │ │ ├── xinshoucun_16_7.jpg │ │ │ │ │ ├── xinshoucun_16_8.jpg │ │ │ │ │ ├── xinshoucun_16_9.jpg │ │ │ │ │ ├── xinshoucun_17_0.jpg │ │ │ │ │ ├── xinshoucun_17_1.jpg │ │ │ │ │ ├── xinshoucun_17_10.jpg │ │ │ │ │ ├── xinshoucun_17_11.jpg │ │ │ │ │ ├── xinshoucun_17_12.jpg │ │ │ │ │ ├── xinshoucun_17_13.jpg │ │ │ │ │ ├── xinshoucun_17_14.jpg │ │ │ │ │ ├── xinshoucun_17_2.jpg │ │ │ │ │ ├── xinshoucun_17_3.jpg │ │ │ │ │ ├── xinshoucun_17_4.jpg │ │ │ │ │ ├── xinshoucun_17_5.jpg │ │ │ │ │ ├── xinshoucun_17_6.jpg │ │ │ │ │ ├── xinshoucun_17_7.jpg │ │ │ │ │ ├── xinshoucun_17_8.jpg │ │ │ │ │ ├── xinshoucun_17_9.jpg │ │ │ │ │ ├── xinshoucun_18_0.jpg │ │ │ │ │ ├── xinshoucun_18_1.jpg │ │ │ │ │ ├── xinshoucun_18_10.jpg │ │ │ │ │ ├── xinshoucun_18_11.jpg │ │ │ │ │ ├── xinshoucun_18_12.jpg │ │ │ │ │ ├── xinshoucun_18_13.jpg │ │ │ │ │ ├── xinshoucun_18_14.jpg │ │ │ │ │ ├── xinshoucun_18_2.jpg │ │ │ │ │ ├── xinshoucun_18_3.jpg │ │ │ │ │ ├── xinshoucun_18_4.jpg │ │ │ │ │ ├── xinshoucun_18_5.jpg │ │ │ │ │ ├── xinshoucun_18_6.jpg │ │ │ │ │ ├── xinshoucun_18_7.jpg │ │ │ │ │ ├── xinshoucun_18_8.jpg │ │ │ │ │ ├── xinshoucun_18_9.jpg │ │ │ │ │ ├── xinshoucun_19_0.jpg │ │ │ │ │ ├── xinshoucun_19_1.jpg │ │ │ │ │ ├── xinshoucun_19_10.jpg │ │ │ │ │ ├── xinshoucun_19_11.jpg │ │ │ │ │ ├── xinshoucun_19_12.jpg │ │ │ │ │ ├── xinshoucun_19_13.jpg │ │ │ │ │ ├── xinshoucun_19_14.jpg │ │ │ │ │ ├── xinshoucun_19_2.jpg │ │ │ │ │ ├── xinshoucun_19_3.jpg │ │ │ │ │ ├── xinshoucun_19_4.jpg │ │ │ │ │ ├── xinshoucun_19_5.jpg │ │ │ │ │ ├── xinshoucun_19_6.jpg │ │ │ │ │ ├── xinshoucun_19_7.jpg │ │ │ │ │ ├── xinshoucun_19_8.jpg │ │ │ │ │ ├── xinshoucun_19_9.jpg │ │ │ │ │ ├── xinshoucun_1_10.jpg │ │ │ │ │ ├── xinshoucun_1_11.jpg │ │ │ │ │ ├── xinshoucun_1_12.jpg │ │ │ │ │ ├── xinshoucun_1_13.jpg │ │ │ │ │ ├── xinshoucun_1_14.jpg │ │ │ │ │ ├── xinshoucun_2_10.jpg │ │ │ │ │ ├── xinshoucun_2_11.jpg │ │ │ │ │ ├── xinshoucun_2_12.jpg │ │ │ │ │ ├── xinshoucun_2_13.jpg │ │ │ │ │ ├── xinshoucun_2_14.jpg │ │ │ │ │ ├── xinshoucun_3_10.jpg │ │ │ │ │ ├── xinshoucun_3_11.jpg │ │ │ │ │ ├── xinshoucun_3_12.jpg │ │ │ │ │ ├── xinshoucun_3_13.jpg │ │ │ │ │ ├── xinshoucun_3_14.jpg │ │ │ │ │ ├── xinshoucun_4_10.jpg │ │ │ │ │ ├── xinshoucun_4_11.jpg │ │ │ │ │ ├── xinshoucun_4_12.jpg │ │ │ │ │ ├── xinshoucun_4_13.jpg │ │ │ │ │ ├── xinshoucun_4_14.jpg │ │ │ │ │ ├── xinshoucun_5_10.jpg │ │ │ │ │ ├── xinshoucun_5_11.jpg │ │ │ │ │ ├── xinshoucun_5_12.jpg │ │ │ │ │ ├── xinshoucun_5_13.jpg │ │ │ │ │ ├── xinshoucun_5_14.jpg │ │ │ │ │ ├── xinshoucun_6_10.jpg │ │ │ │ │ ├── xinshoucun_6_11.jpg │ │ │ │ │ ├── xinshoucun_6_12.jpg │ │ │ │ │ ├── xinshoucun_6_13.jpg │ │ │ │ │ ├── xinshoucun_6_14.jpg │ │ │ │ │ ├── xinshoucun_7_10.jpg │ │ │ │ │ ├── xinshoucun_7_11.jpg │ │ │ │ │ ├── xinshoucun_7_12.jpg │ │ │ │ │ ├── xinshoucun_7_13.jpg │ │ │ │ │ ├── xinshoucun_7_14.jpg │ │ │ │ │ ├── xinshoucun_8_10.jpg │ │ │ │ │ ├── xinshoucun_8_11.jpg │ │ │ │ │ ├── xinshoucun_8_12.jpg │ │ │ │ │ ├── xinshoucun_8_13.jpg │ │ │ │ │ ├── xinshoucun_8_14.jpg │ │ │ │ │ ├── xinshoucun_9_10.jpg │ │ │ │ │ ├── xinshoucun_9_11.jpg │ │ │ │ │ ├── xinshoucun_9_12.jpg │ │ │ │ │ ├── xinshoucun_9_13.jpg │ │ │ │ │ └── xinshoucun_9_14.jpg │ │ │ │ │ └── xinshoucun.xml │ │ │ ├── monster.js │ │ │ ├── urls.js │ │ │ ├── block.js │ │ │ ├── grid_show.js │ │ │ ├── spell_entity.js │ │ │ └── httpclient.js │ │ └── update │ │ │ ├── v1.9.3.kl.6.patch │ │ │ └── version.json │ ├── api │ │ └── scene.go │ └── stats.go ├── master │ ├── service.go │ ├── user.go │ ├── func.go │ └── master.go ├── game │ ├── func.go │ ├── object │ │ ├── object_test.go │ │ └── util.go │ ├── path_finder.go │ ├── crypto │ │ ├── crypto_test.go │ │ └── crypto.go │ ├── aoimgr.go │ ├── igame.go │ └── game.go └── gate │ ├── service.go │ └── gate.go ├── .gitignore ├── protocol ├── web.go ├── test.go ├── route.go ├── agent.go ├── apps.go └── users.go ├── db ├── types.go ├── logger.go ├── startup.go ├── spell.go ├── monster.go ├── online.go ├── third_account.go ├── const.go ├── scene.go ├── views.go ├── hero.go ├── trade.go └── common.go ├── constants └── constants.go ├── .vscode └── launch.json ├── README.md ├── configs └── config.toml └── go.mod /docs/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cmd/game/build.sh: -------------------------------------------------------------------------------- 1 | go build -o go_gs_game main.go 2 | -------------------------------------------------------------------------------- /cmd/gate/build.sh: -------------------------------------------------------------------------------- 1 | go build -o go_gs_gate main.go 2 | -------------------------------------------------------------------------------- /cmd/web/build.sh: -------------------------------------------------------------------------------- 1 | go build -o go_gs_web main.go 2 | -------------------------------------------------------------------------------- /cmd/master/build.sh: -------------------------------------------------------------------------------- 1 | go build -o go_gs_master main.go 2 | -------------------------------------------------------------------------------- /pkg/aoi/Makefile: -------------------------------------------------------------------------------- 1 | bench: 2 | go test -bench=. -benchmem -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/.npmignore: -------------------------------------------------------------------------------- 1 | benchmark -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /*.iml 2 | .idea 3 | *.exe 4 | dist/ 5 | config2.toml 6 | cmd/kwxd/configs/config.local.toml 7 | -------------------------------------------------------------------------------- /tools/sql2struct/dbr.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/tools/sql2struct/dbr.exe -------------------------------------------------------------------------------- /internal/web/static/client/statemachine.js: -------------------------------------------------------------------------------- 1 | 2 | class StateMachine { 3 | constructor() { 4 | 5 | } 6 | } -------------------------------------------------------------------------------- /cmd/game/blocks/xinshoucun.block: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/cmd/game/blocks/xinshoucun.block -------------------------------------------------------------------------------- /cmd/web/start_server.sh: -------------------------------------------------------------------------------- 1 | go build -o go_gs_web main.go 2 | nohup ./go_gs_web -c ../../configs/config.toml > data.log 2>&1 & 3 | -------------------------------------------------------------------------------- /cmd/gate/start_server.sh: -------------------------------------------------------------------------------- 1 | go build -o go_gs_gate main.go 2 | nohup ./go_gs_gate -c ../../configs/config.toml > data.log 2>&1 & 3 | -------------------------------------------------------------------------------- /pkg/security/sql.go: -------------------------------------------------------------------------------- 1 | package security 2 | 3 | // TODO: 验证SQL语句是否合法 4 | func ValidateSQL(sql string) bool { 5 | return true 6 | } 7 | -------------------------------------------------------------------------------- /cmd/master/start_server.sh: -------------------------------------------------------------------------------- 1 | go build -o go_gs_master main.go 2 | nohup ./go_gs_master -c ../../configs/config.toml > data.log 2>&1 & 3 | -------------------------------------------------------------------------------- /internal/web/static/update/v1.9.3.kl.6.patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/update/v1.9.3.kl.6.patch -------------------------------------------------------------------------------- /cmd/game/start_server.sh: -------------------------------------------------------------------------------- 1 | go build -o go_gs_game main.go 2 | export GODEBUG=gctrace=1 3 | nohup ./go_gs_game -c ../../configs/config.toml > data.log 2>&1 & 4 | -------------------------------------------------------------------------------- /pkg/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import "github.com/DanPlayer/randomname" 4 | 5 | func GetRandomHeroName() string { 6 | return randomname.GenerateName() 7 | } 8 | -------------------------------------------------------------------------------- /docs/SQL.md: -------------------------------------------------------------------------------- 1 | # 按照时间统计局数 2 | 3 | ``` 4 | select uid as `ID`, name as `昵称`, count(*) as `局数` from rank where `record_at` > 1505480400 and uid > 0 group by uid order by `局数` desc; 5 | ``` -------------------------------------------------------------------------------- /protocol/web.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | type Version struct { 4 | Version int `json:"version"` 5 | Android string `json:"android"` 6 | IOS string `json:"ios"` 7 | } 8 | -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/xinshoucun.block: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/xinshoucun.block -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/xinshoucun.config: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/xinshoucun.config -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.11" 4 | before_script: 5 | - npm install -g grunt-cli 6 | script: 7 | - grunt default --verbose -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_0_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_10_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_11_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_12_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_13_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_14_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_15_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_16_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_17_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_18_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_0.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_1.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_2.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_3.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_4.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_5.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_6.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_7.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_8.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_19_9.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_1_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_2_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_3_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_4_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_5_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_6_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_7_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_8_14.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_10.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_11.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_12.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_13.jpg -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouyangzhongmin/gameserver/HEAD/internal/web/static/client/assets/map/xinshoucun/pic/xinshoucun_9_14.jpg -------------------------------------------------------------------------------- /tools/sql2struct/sql2struct.bat: -------------------------------------------------------------------------------- 1 | %~dp0dbr --driver mysql --source root:88888888@tcp(10.10.30.52:3306)/broker --destination ../../internal/model --template struct.xorm.kwx.tpl --single --file struct_kwx.go 2 | -------------------------------------------------------------------------------- /internal/web/static/update/version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.9.3", 3 | "patch": 6, 4 | "android": "https://fir.im/tand", 5 | "ios": "https://fir.im/tios", 6 | "download": "http://39.108.135.229:12307/static/update/v1.9.3.kl.6.patch" 7 | } -------------------------------------------------------------------------------- /internal/master/service.go: -------------------------------------------------------------------------------- 1 | package master 2 | 3 | import ( 4 | "github.com/lonng/nano/component" 5 | ) 6 | 7 | var ( 8 | // All services in master server 9 | Services = &component.Components{} 10 | ) 11 | 12 | func init() { 13 | Services.Register(defaultManager) 14 | } 15 | -------------------------------------------------------------------------------- /protocol/test.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | type TestRequest struct { 4 | IntField int `json:"int_field"` 5 | StringField string `json:"string_field"` 6 | } 7 | 8 | type TestMessage struct { 9 | Code int `json:"code"` 10 | Message string `json:"message"` 11 | } 12 | -------------------------------------------------------------------------------- /internal/master/user.go: -------------------------------------------------------------------------------- 1 | package master 2 | 3 | import ( 4 | "github.com/lonng/nano/session" 5 | "github.com/ouyangzhongmin/gameserver/db/model" 6 | ) 7 | 8 | type User struct { 9 | session *session.Session 10 | data *model.User 11 | Uid int64 12 | heroData *model.Hero 13 | } 14 | -------------------------------------------------------------------------------- /pkg/async/async.go: -------------------------------------------------------------------------------- 1 | package async 2 | 3 | import "github.com/sirupsen/logrus" 4 | 5 | func pcall(fn func()) { 6 | defer func() { 7 | if err := recover(); err != nil { 8 | logrus.Errorf("aync/pcall: Error=%v", err) 9 | } 10 | }() 11 | 12 | fn() 13 | } 14 | 15 | func Run(fn func()) { 16 | go pcall(fn) 17 | } 18 | -------------------------------------------------------------------------------- /internal/web/static/client/monster.js: -------------------------------------------------------------------------------- 1 | 2 | // Monster class definition 3 | class Monster extends Role{ 4 | constructor(monsterData) { 5 | super(monsterData, "red") 6 | } 7 | 8 | update(deltaTime, camera){ 9 | super.update(deltaTime, camera) 10 | } 11 | 12 | draw(ctx) { 13 | super.draw(ctx) 14 | } 15 | } -------------------------------------------------------------------------------- /pkg/path/path.go: -------------------------------------------------------------------------------- 1 | package path 2 | 3 | // 预生成的路径 4 | type SerialPaths struct { 5 | Id int `json:"id"` 6 | Paths []PointPath `json:"paths"` 7 | } 8 | 9 | type PointPath struct { 10 | Sx int32 `json:"sx"` 11 | Sy int32 `json:"sy"` 12 | Ex int32 `json:"ex"` 13 | Ey int32 `json:"ey"` 14 | Paths [][]int32 `json:"paths"` 15 | } 16 | -------------------------------------------------------------------------------- /db/types.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | //KeyPair rsa's public & private key pair 4 | type KeyPair struct { 5 | PrivateKey string 6 | PublicKey string 7 | } 8 | 9 | type retentionStats struct { 10 | date int64 11 | register int64 //注册人数 12 | loginDay1 int64 //1,2,3,7,14,30登录 13 | loginDay2 int64 14 | loginDay3 int64 15 | loginDay7 int64 16 | loginDay14 int64 17 | loginDay30 int64 18 | } 19 | -------------------------------------------------------------------------------- /internal/game/func.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "github.com/lonng/nano/session" 5 | "github.com/ouyangzhongmin/gameserver/constants" 6 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 7 | ) 8 | 9 | func heroWithSession(s *session.Session) (*Hero, error) { 10 | p, ok := s.Value(constants.KCurHero).(*Hero) 11 | if !ok { 12 | return nil, errutil.ErrHeroNotFound 13 | } 14 | return p, nil 15 | } 16 | -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit Example 6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /pkg/algoutil/password_test.go: -------------------------------------------------------------------------------- 1 | package algoutil 2 | 3 | import "testing" 4 | 5 | func TestPasswordHash(t *testing.T) { 6 | pwds := []string{ 7 | "hsdlfjsdlfjsldkjfsldj", 8 | "你好!!!", 9 | "superadmin", 10 | } 11 | 12 | for _, pwd := range pwds { 13 | hash, salt := PasswordHash(pwd) 14 | t.Logf("hash: %s\nsalt: %s\n pwd: %s\n", hash, salt, pwd) 15 | if !VerifyPassword(pwd, salt, hash) { 16 | t.Fail() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /db/logger.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "github.com/go-xorm/core" 5 | log "github.com/sirupsen/logrus" 6 | ) 7 | 8 | type Logger struct { 9 | *log.Entry 10 | level core.LogLevel 11 | } 12 | 13 | func (l *Logger) SetLevel(level core.LogLevel) { 14 | l.level = level 15 | } 16 | 17 | func (l *Logger) Level() core.LogLevel { 18 | return l.level 19 | } 20 | 21 | func (l *Logger) ShowSQL(show ...bool) {} 22 | func (l *Logger) IsShowSQL() bool { return false } 23 | -------------------------------------------------------------------------------- /internal/web/static/client/urls.js: -------------------------------------------------------------------------------- 1 | 2 | if (isPrdEnv()) { 3 | //改成自己的地址 4 | Global.WSAddr = "47.99.**.**" 5 | Global.HttpBaseUrl = "http://47.99.**.**:12307" 6 | } 7 | 8 | function isPrdEnv(){ 9 | // let test = true 10 | // if(test){ 11 | // return true 12 | // } 13 | var path = window.location.host; 14 | if (path.includes('47.99.**.**') || path.includes('**.**.com')) { 15 | return true 16 | } 17 | return false 18 | } 19 | -------------------------------------------------------------------------------- /pkg/shape/rect.go: -------------------------------------------------------------------------------- 1 | package shape 2 | 3 | // 左上角坐标系 4 | type Rect struct { 5 | X, Y, Width, Height int64 6 | } 7 | 8 | // Contains 判断点是否在矩形内 9 | func (r Rect) Contains(x, y int64) bool { 10 | return x >= r.X && x <= r.X+r.Width && 11 | y >= r.Y && y <= r.Y+r.Height 12 | } 13 | 14 | // Contains 判断点是否在矩形内 15 | func (r Rect) ContainsRect(rect2 Rect) bool { 16 | return rect2.X >= r.X && rect2.X+rect2.Width <= r.X+r.Width && 17 | rect2.Y >= r.Y && rect2.Y+rect2.Height <= r.Y+r.Height 18 | } 19 | -------------------------------------------------------------------------------- /tools/sql2struct/struct.xorm.kwx.tpl: -------------------------------------------------------------------------------- 1 | {{if not .IsAppend}}package {{.Model}}{{end}} 2 | 3 | {{$ilen := len .Imports}}{{if gt $ilen 0}} 4 | import ( 5 | {{range .Imports}}"{{.}}"{{end}} 6 | ){{end}} 7 | 8 | {{range .Tables}} 9 | type {{Mapper .Name}} struct { 10 | {{$table := .}} 11 | {{range .ColumnsSeq}}{{$col := $table.GetColumn .}} {{Mapper $col.Name}} {{Type $col}} {{Tag $table $col}} 12 | {{end}} 13 | } 14 | {{end}} 15 | 16 | func syncSchema() { 17 | DB.StoreEngine("InnoDB").Sync2({{range .Tables}} 18 | new({{Mapper .Name}}),{{end}} 19 | ) 20 | } -------------------------------------------------------------------------------- /pkg/security/validity.go: -------------------------------------------------------------------------------- 1 | package security 2 | 3 | import ( 4 | "regexp" 5 | ) 6 | 7 | var ( 8 | phoneRE *regexp.Regexp 9 | nameRE *regexp.Regexp 10 | ) 11 | 12 | func init() { 13 | r, err := regexp.Compile("^1[0-9]{10}$") 14 | if err != nil { 15 | panic(err.Error()) 16 | } 17 | phoneRE = r 18 | 19 | r, err = regexp.Compile("^[0-9a-zA-Z.@]{6,32}$") 20 | if err != nil { 21 | panic(err.Error()) 22 | } 23 | nameRE = r 24 | } 25 | 26 | func ValidateName(name string) bool { 27 | return nameRE.MatchString(name) 28 | } 29 | 30 | // 验证电话号码 31 | func ValidatePhone(phone string) bool { 32 | return phoneRE.MatchString(phone) 33 | } 34 | -------------------------------------------------------------------------------- /db/startup.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "fmt" 5 | "github.com/spf13/viper" 6 | ) 7 | 8 | func Startup() func() { 9 | dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s", 10 | viper.GetString("database.username"), 11 | viper.GetString("database.password"), 12 | viper.GetString("database.host"), 13 | viper.GetString("database.port"), 14 | viper.GetString("database.dbname"), 15 | viper.GetString("database.args")) 16 | 17 | return MustStartup( 18 | dsn, 19 | MaxIdleConns(viper.GetInt("database.max_idle_conns")), 20 | MaxIdleConns(viper.GetInt("database.max_open_conns")), 21 | ShowSQL(viper.GetBool("database.show_sql"))) 22 | } 23 | -------------------------------------------------------------------------------- /pkg/security/validity_test.go: -------------------------------------------------------------------------------- 1 | package security 2 | 3 | import "testing" 4 | 5 | var testdata = []string{ 6 | "123123kj123", 7 | "sdflsjsdfsdf", 8 | "SDdko300df", 9 | } 10 | 11 | var testdata2 = []string{ 12 | "skdfd", 13 | " sdkfjf", 14 | "23409.sdf0#", 15 | "!sdlkfj,/ lksjf", 16 | } 17 | 18 | func TestValidateName(t *testing.T) { 19 | for _, name := range testdata { 20 | if !ValidateName(name) { 21 | t.Errorf("should pass name: %s", name) 22 | t.Fail() 23 | } 24 | } 25 | 26 | for _, name := range testdata2 { 27 | if ValidateName(name) { 28 | t.Errorf("should not pass name: %s", name) 29 | t.Fail() 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/Gruntfile.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function(grunt) { 3 | 4 | grunt.initConfig({ 5 | pkg: grunt.file.readJSON('package.json'), 6 | 7 | qunit: { 8 | all: ['test/index.html'] 9 | }, 10 | 11 | 12 | jshint: { 13 | options: { 14 | browser: true, 15 | sub: true, 16 | undef: true, 17 | unused: true 18 | }, 19 | all: ['astar.js', 'test/tests.js', 'demo/demo.js'] 20 | } 21 | }); 22 | 23 | 24 | grunt.loadNpmTasks('grunt-contrib-jshint'); 25 | grunt.loadNpmTasks('grunt-contrib-qunit'); 26 | 27 | grunt.registerTask('default', ['jshint', 'qunit']); 28 | 29 | }; 30 | -------------------------------------------------------------------------------- /db/spell.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "github.com/ouyangzhongmin/gameserver/db/model" 5 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 6 | ) 7 | 8 | func QuerySpell(id int) (*model.Spell, error) { 9 | h := &model.Spell{Id: id} 10 | has, err := database.Get(h) 11 | if err != nil { 12 | return nil, err 13 | } 14 | if !has { 15 | return nil, errutil.ErrNotFound 16 | } 17 | return h, nil 18 | } 19 | 20 | func QueryBufferState(id int) (*model.BufferState, error) { 21 | h := &model.BufferState{Id: id} 22 | has, err := database.Get(h) 23 | if err != nil { 24 | return nil, err 25 | } 26 | if !has { 27 | return nil, errutil.ErrNotFound 28 | } 29 | return h, nil 30 | } 31 | -------------------------------------------------------------------------------- /pkg/set/set.go: -------------------------------------------------------------------------------- 1 | package set 2 | 3 | import "sync" 4 | 5 | type Set struct { 6 | mu sync.Mutex 7 | m map[string]struct{} 8 | } 9 | 10 | func (s *Set) Contains(val string) bool { 11 | if val == "" { 12 | return true 13 | } 14 | s.mu.Lock() 15 | defer s.mu.Unlock() 16 | 17 | if _, ok := s.m[val]; ok { 18 | return true 19 | } 20 | return false 21 | } 22 | 23 | func (s *Set) Add(val string) { 24 | s.mu.Lock() 25 | defer s.mu.Unlock() 26 | s.m[val] = struct{}{} 27 | } 28 | 29 | func (s *Set) Remove(val string) { 30 | s.mu.Lock() 31 | defer s.mu.Unlock() 32 | delete(s.m, val) 33 | } 34 | 35 | func New() *Set { 36 | return &Set{ 37 | m: make(map[string]struct{}), 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /db/monster.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "github.com/ouyangzhongmin/gameserver/db/model" 5 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 6 | ) 7 | 8 | func QueryMonster(id int64) (*model.Monster, error) { 9 | m := &model.Monster{Id: id} 10 | has, err := database.Get(m) 11 | if err != nil { 12 | return nil, err 13 | } 14 | if !has { 15 | return nil, errutil.ErrNotFound 16 | } 17 | return m, nil 18 | } 19 | 20 | func QueryAiConfig(mid int64) (*model.Aiconfig, error) { 21 | m := &model.Aiconfig{MonsterId: mid} 22 | has, err := database.Get(m) 23 | if err != nil { 24 | return nil, err 25 | } 26 | if !has { 27 | return nil, errutil.ErrNotFound 28 | } 29 | return m, nil 30 | } 31 | -------------------------------------------------------------------------------- /internal/game/object/object_test.go: -------------------------------------------------------------------------------- 1 | package object 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestMonsterIdGen(t *testing.T) { 9 | 10 | for oid := 1; oid < 100; oid += 5 { 11 | //注意这里的oid 不能超过10万,否则offsetId会被截取为0 12 | offsetId := (oid * 10000) & 0xFFFFFFFF 13 | offsetTs := int64(time.Now().Unix() % 1000000) 14 | var id int64 = int64(offsetId) + offsetTs + int64(1) 15 | t.Log("mmid:", oid, offsetId, offsetTs, id) 16 | } 17 | 18 | for oid := 10000; oid < 100000; oid += 1000 { 19 | offsetId := (oid * 10000) & 0xFFFFFFFF 20 | offsetTs := int64(time.Now().Unix() % 1000000) 21 | var id int64 = int64(offsetId) + offsetTs + int64(1) 22 | t.Log("nnid:", oid, offsetId, offsetTs, id) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "javascript-astar", 3 | "version": "0.4.1", 4 | "description": "astar search algorithm in JavaScript", 5 | "main": "astar.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/bgrins/javascript-astar.git" 9 | }, 10 | "keywords": [ 11 | ], 12 | "author": "Brian Grinstead", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/bgrins/javascript-astar/issues" 16 | }, 17 | "main": "./astar.js", 18 | "homepage": "http://bgrins.github.io/javascript-astar", 19 | "devDependencies": { 20 | "grunt": "~0.4.5", 21 | "grunt-contrib-qunit": "~0.5.0", 22 | "grunt-contrib-jshint": "~0.10.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /internal/gate/service.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | import ( 4 | "github.com/lonng/nano/component" 5 | "github.com/lonng/nano/session" 6 | "github.com/ouyangzhongmin/gameserver/protocol" 7 | ) 8 | 9 | var ( 10 | // All services in master server 11 | Services = &component.Components{} 12 | 13 | bindService = newGateService() 14 | ) 15 | 16 | func init() { 17 | Services.Register(bindService) 18 | } 19 | 20 | type GateService struct { 21 | component.Base 22 | nextGateUid int64 23 | } 24 | 25 | func newGateService() *GateService { 26 | return &GateService{} 27 | } 28 | 29 | // 在进入场景的时候需要记录session和对应的sceneId, 在调用SceneManager时需要查找对应的node服务器 30 | func (ts *GateService) RecordScene(s *session.Session, msg *protocol.UserSceneId) error { 31 | s.Bind(msg.Uid) 32 | s.Set("sceneId", msg.SceneId) 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /protocol/route.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | const ( 4 | // 服务器将多条消息合并进入一条数据发给前端, 需要前端做特殊处理 5 | OnMergeMessages = "OnMergeMessages" 6 | 7 | //client用的 8 | OnEnterScene = "OnEnterScene" 9 | OnEnterView = "OnEnterView" 10 | OnExitView = "OnExitView" 11 | OnHeroMoveTrace = "OnHeroMoveTrace" 12 | OnHeroMoveStopped = "OnHeroMoveStopped" 13 | OnMonsterMoveTrace = "OnMonsterMoveTrace" 14 | OnMonsterMoveStopped = "OnMonsterMoveStopped" 15 | OnMonsterCommonAttack = "OnMonsterCommonAttack" 16 | OnReleaseSpell = "OnReleaseSpell" 17 | OnLifeChanged = "OnLifeChanged" 18 | OnManaChanged = "OnManaChanged" 19 | OnEntityDie = "OnEntityDie" 20 | OnBufferAdd = "OnBufferAdd" 21 | OnBufferRemove = "OnBufferRemove" 22 | 23 | OnTextMessage = "OnTextMessage" 24 | ) 25 | -------------------------------------------------------------------------------- /internal/game/path_finder.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "fmt" 5 | "github.com/ouyangzhongmin/gameserver/pkg/astar" 6 | ) 7 | 8 | // 这个非线程安全,需要单线程一个执行 9 | type PathFinder struct { 10 | cachedPaths map[string][][]int32 11 | a *astar.AStar 12 | } 13 | 14 | func NewPathFinder(grids [][]int32) *PathFinder { 15 | f := &PathFinder{} 16 | f.cachedPaths = make(map[string][][]int32) 17 | f.a = astar.NewAstar(grids) 18 | return f 19 | } 20 | 21 | func (f *PathFinder) FindPath(sx, sy, ex, ey int) ([][]int32, error) { 22 | key := fmt.Sprintf("%d_%d_%d_%d", sy, sx, ey, ex) 23 | if path, ok := f.cachedPaths[key]; ok && path != nil { 24 | return path, nil 25 | } else { 26 | path, _, _, err := f.a.FindPath([]int32{int32(sy), int32(sx)}, []int32{int32(ey), int32(ex)}) 27 | if path != nil { 28 | f.cachedPaths[key] = path 29 | } 30 | return path, err 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /internal/game/object/util.go: -------------------------------------------------------------------------------- 1 | package object 2 | 3 | const ( 4 | LIFE_STRENGTH_PERM = 15 5 | MANA_INTELLIGENCE_PERM = 10 6 | ATTACK_ATTR_PERM = 2 7 | DEFENSE_AGILITY_PERM = 2 8 | ) 9 | 10 | func CaculateLife(baseLife, strength int64) int64 { 11 | return baseLife + strength*LIFE_STRENGTH_PERM 12 | } 13 | 14 | func CaculateMana(baseMana, intelligence int64) int64 { 15 | return baseMana + intelligence*MANA_INTELLIGENCE_PERM 16 | } 17 | 18 | func CaculateAttack(attrType int, baseAttack, strength, agility, intelligence int64) int64 { 19 | if attrType == 1 { 20 | return baseAttack + agility*ATTACK_ATTR_PERM 21 | } else if attrType == 2 { 22 | return baseAttack + intelligence*ATTACK_ATTR_PERM 23 | } 24 | return baseAttack + strength*ATTACK_ATTR_PERM 25 | } 26 | 27 | func CaculateDefense(baseDefense, agility int64) int64 { 28 | return baseDefense + agility*DEFENSE_AGILITY_PERM 29 | } 30 | -------------------------------------------------------------------------------- /db/online.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/ouyangzhongmin/gameserver/db/model" 6 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 7 | log "github.com/sirupsen/logrus" 8 | ) 9 | 10 | func InsertOnline(count int, scenes map[int]interface{}, ts int64) { 11 | jsonstr, err := json.Marshal(scenes) 12 | if err != nil { 13 | log.Errorf("统计在线人数失败: %s", err.Error()) 14 | return 15 | } 16 | _, err = database.Exec("insert into online(user_count,scenes,time) values (?,?,?)", count, string(jsonstr), ts) 17 | if err != nil { 18 | log.Errorf("统计在线人数失败: %s", err.Error()) 19 | } 20 | } 21 | 22 | func OnlineStats(begin, end int64) ([]model.Online, error) { 23 | if begin > end { 24 | return nil, errutil.ErrIllegalParameter 25 | } 26 | 27 | list := make([]model.Online, 0) 28 | 29 | return list, database.Where("`time` BETWEEN ? AND ?", begin, end).Find(&list) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/algoutil/algoutil_test.go: -------------------------------------------------------------------------------- 1 | package algoutil 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGenRSAKey(t *testing.T) { 8 | ts := []string{"hello world", "miss right"} 9 | priv, pub, err := GenRSAKey() 10 | if err != nil { 11 | t.Fatal(err) 12 | } 13 | 14 | for _, tstr := range ts { 15 | c, err := RSAEncrypt([]byte(tstr), pub) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | d, err := RSADecrypt(c, priv) 20 | if string(d) != tstr { 21 | t.Fail() 22 | } 23 | } 24 | } 25 | 26 | func BenchmarkGenRSAKey(b *testing.B) { 27 | for i := 0; i < b.N; i++ { 28 | GenRSAKey() 29 | } 30 | } 31 | 32 | func TestMaskPhone(t *testing.T) { 33 | _, err := MaskPhone("128888888888") 34 | if err == nil { 35 | t.Fail() 36 | } 37 | 38 | _, err = MaskPhone("12888888888") 39 | if err != nil { 40 | t.Fail() 41 | } 42 | 43 | _, err = MaskPhone("15222544") 44 | if err == nil { 45 | t.Fail() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pkg/mtm/mysql.go: -------------------------------------------------------------------------------- 1 | //参考 https://yq.aliyun.com/articles/178898?utm_content=m_29337 2 | package mtm 3 | 4 | import ( 5 | "database/sql" 6 | 7 | _ "github.com/go-sql-driver/mysql" 8 | ) 9 | 10 | var Db *sql.DB = nil 11 | 12 | //sql.DB的设计就是用来作为长连接使用的。不要频繁Open, Close 13 | func CreateMysqlDb(mysqlServer string) (*sql.DB, error) { 14 | 15 | if Db != nil { 16 | return Db, nil 17 | } 18 | _db, err := sql.Open("mysql", mysqlServer) 19 | //都适用默认配置,有需要在配置 20 | //来限制连接池中空闲连接的数量,但是这并不会限制连接池的大小。连接回收(recycle)的很快,通过设置一个较大的N,可以在连接池中保留一些空闲连接,供快速复用(reuse)。但保持连接空闲时间过久可能会引发其他问题,比如超时。设置N=0则可以避免连接空闲太久。 21 | //_db.SetMaxIdleConns(0) 22 | ////来限制连接池中打开的连接数量。 23 | //_db.SetMaxOpenConns(0) 24 | ////来限制连接的生命周期。连接超时后,会在需要时惰性回收复用。 25 | //_db.SetConnMaxLifetime(60 * time.Second) 26 | if err != nil { 27 | return nil, nil 28 | } else { 29 | return _db, nil 30 | } 31 | } 32 | 33 | //sql.DB的设计就是用来作为长连接使用的。不要频繁Open, Close 34 | //func (this *MySql) Close() { 35 | // this.Db.Close() 36 | //} 37 | -------------------------------------------------------------------------------- /constants/constants.go: -------------------------------------------------------------------------------- 1 | package constants 2 | 3 | const ( 4 | KCurHero = "hero" 5 | ) 6 | 7 | const ( 8 | DEFAULT_SCENE = 1 9 | DEFAULT_SCENE2 = 2 10 | 11 | MONSTER_TYPE_NORMAL = 0 12 | MONSTER_TYPE_NPC = 1 13 | 14 | SCENE_AOI_GRID_SIZE = 60 15 | ) 16 | 17 | const ( 18 | ATTR_TYPE_STRENGTH = iota 19 | ATTR_TYPE_AGILITY 20 | ATTR_TYPE_INTELLIGENCE 21 | ) 22 | 23 | const ( 24 | ENTITY_TYPE_HERO int = iota 25 | ENTITY_TYPE_MONSTER 26 | ENTITY_TYPE_SPELL 27 | ) 28 | 29 | type ActionState int 30 | 31 | const ( 32 | ACTION_STATE_IDLE ActionState = iota 33 | ACTION_STATE_WALK 34 | ACTION_STATE_RUN 35 | ACTION_STATE_CHASE //追击 36 | ACTION_STATE_ESCAPE //逃跑 37 | ACTION_STATE_ATTACK 38 | ACTION_STATE_DIE 39 | ) 40 | 41 | type BEHAVIOR int 42 | 43 | // AI行为状态 44 | const ( 45 | BEHAVIOR_STATE_IDLE BEHAVIOR = iota 46 | BEHAVIOR_STATE_ATTACK 47 | BEHAVIOR_STATE_ESCAPE 48 | BEHAVIOR_STATE_RETURN 49 | BEHAVIOR_STATE_FOLLOW 50 | BEHAVIOR_STATE_LOOP_WALKER 51 | ) 52 | -------------------------------------------------------------------------------- /pkg/algoutil/crypt.go: -------------------------------------------------------------------------------- 1 | package algoutil 2 | 3 | import ( 4 | "crypto/rsa" 5 | "crypto/x509" 6 | "encoding/pem" 7 | "errors" 8 | "fmt" 9 | "io/ioutil" 10 | ) 11 | 12 | func pemParse(data []byte, pemType string) ([]byte, error) { 13 | block, _ := pem.Decode(data) 14 | if block == nil { 15 | return nil, errors.New("No PEM block found") 16 | } 17 | if pemType != "" && block.Type != pemType { 18 | return nil, fmt.Errorf("Key's type is '%s', expected '%s'", block.Type, pemType) 19 | } 20 | return block.Bytes, nil 21 | } 22 | 23 | func ParsePrivateKey(data []byte) (*rsa.PrivateKey, error) { 24 | pemData, err := pemParse(data, "RSA PRIVATE KEY") 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | return x509.ParsePKCS1PrivateKey(pemData) 30 | } 31 | 32 | func LoadPrivateKey(privKeyPath string) (*rsa.PrivateKey, error) { 33 | certPEMBlock, err := ioutil.ReadFile(privKeyPath) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | return ParsePrivateKey(certPEMBlock) 39 | } 40 | -------------------------------------------------------------------------------- /pkg/algoutil/password.go: -------------------------------------------------------------------------------- 1 | package algoutil 2 | 3 | import ( 4 | "bytes" 5 | "crypto/sha1" 6 | "encoding/base64" 7 | "fmt" 8 | "strings" 9 | 10 | "github.com/pborman/uuid" 11 | ) 12 | 13 | func passwordHash(pwd, salt string) string { 14 | buf := &bytes.Buffer{} 15 | fmt.Fprintf(buf, "%s%x%s", salt, pwd, salt) 16 | result1 := sha1.Sum(buf.Bytes()) 17 | 18 | buf.Reset() 19 | 20 | fmt.Fprintf(buf, "%s%s%x%s%s", pwd, salt, result1, salt, pwd) 21 | result2 := sha1.Sum(buf.Bytes()) 22 | 23 | buf.Reset() 24 | fmt.Fprintf(buf, "%x", result2) 25 | return base64.StdEncoding.EncodeToString(buf.Bytes()) 26 | } 27 | 28 | // PasswordHash accept password and generate with uuid as salt 29 | // FORMAT: sha1.Sum(pwd + salt + sha1.Sum(salt + pwd + salt) + salt + pwd) 30 | func PasswordHash(pwd string) (hash, salt string) { 31 | salt = strings.Replace(uuid.New(), "-", "", -1) 32 | hash = passwordHash(pwd, salt) 33 | return hash, salt 34 | } 35 | 36 | func VerifyPassword(pwd, salt, hash string) bool { 37 | return passwordHash(pwd, salt) == hash 38 | } 39 | -------------------------------------------------------------------------------- /internal/web/static/client/assets/map/xinshoucun/xinshoucun.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /internal/game/crypto/crypto_test.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import "testing" 4 | 5 | func BenchmarkCrypto_Inbound(b *testing.B) { 6 | c := &crypto{[]byte("hKKJdfskj997sdSk")} 7 | payload := []byte(`[{"name":"test","length":1.06666672229767,"segments":[{"t":0.233333334326744,"v":4.44000005722046},{"t":0.200000002980232,"v":2.62499976158142},{"t":0.266666650772095,"v":0.686249911785126},{"t":0.166666686534882,"v":1.34915959835052},{"t":0.200000047683716,"v":2.28395414352417}]}]`) 8 | test := c.outbound(nil, payload) 9 | for i := 0; i < b.N; i++ { 10 | c.inbound(nil, test) 11 | } 12 | } 13 | 14 | func BenchmarkCrypto_Outbound(b *testing.B) { 15 | c := &crypto{[]byte("hKKJdfskj997sdSk")} 16 | payload := []byte(`[{"name":"test","length":1.06666672229767,"segments":[{"t":0.233333334326744,"v":4.44000005722046},{"t":0.200000002980232,"v":2.62499976158142},{"t":0.266666650772095,"v":0.686249911785126},{"t":0.166666686534882,"v":1.34915959835052},{"t":0.200000047683716,"v":2.28395414352417}]}]`) 17 | for i := 0; i < b.N; i++ { 18 | c.outbound(nil, payload) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /internal/game/crypto/crypto.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "encoding/base64" 5 | "errors" 6 | "fmt" 7 | "github.com/lonng/nano/pipeline" 8 | "github.com/lonng/nano/session" 9 | "github.com/xxtea/xxtea-go/xxtea" 10 | ) 11 | 12 | var xxteaKey = []byte("7AEC4MA152BQE9HWQ7KB") 13 | 14 | type Crypto struct { 15 | key []byte 16 | } 17 | 18 | func NewCrypto() *Crypto { 19 | return &Crypto{xxteaKey} 20 | } 21 | 22 | func (c *Crypto) Inbound(s *session.Session, msg *pipeline.Message) error { 23 | out, err := base64.StdEncoding.DecodeString(string(msg.Data)) 24 | if err != nil { 25 | fmt.Printf("Inbound Error=%s, In=%s \n", err.Error(), string(msg.Data)) 26 | return err 27 | } 28 | 29 | out = xxtea.Decrypt(out, c.key) 30 | if out == nil { 31 | return errors.New("decrypt error: out == nil") 32 | } 33 | msg.Data = out 34 | return nil 35 | } 36 | 37 | func (c *Crypto) Outbound(s *session.Session, msg *pipeline.Message) error { 38 | out := xxtea.Encrypt(msg.Data, c.key) 39 | msg.Data = []byte(base64.StdEncoding.EncodeToString(out)) 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /pkg/mysqlx/json.go: -------------------------------------------------------------------------------- 1 | // 支持mysql json类型解析 2 | package mysqlx 3 | 4 | import ( 5 | "bytes" 6 | "database/sql/driver" 7 | "errors" 8 | ) 9 | 10 | type JSON []byte 11 | 12 | func (j JSON) Value() (driver.Value, error) { 13 | if j.IsNull() { 14 | return "{}", nil 15 | } 16 | return string(j), nil 17 | } 18 | 19 | func (j *JSON) Scan(value interface{}) error { 20 | if value == nil { 21 | *j = nil 22 | return nil 23 | } 24 | s, ok := value.([]byte) 25 | if !ok { 26 | errors.New("Invalid Scan Source") 27 | } 28 | *j = append((*j)[0:0], s...) 29 | return nil 30 | } 31 | 32 | func (m JSON) MarshalJSON() ([]byte, error) { 33 | if m == nil { 34 | return []byte("null"), nil 35 | } 36 | return m, nil 37 | } 38 | 39 | func (m *JSON) UnmarshalJSON(data []byte) error { 40 | if m == nil { 41 | return errors.New("null point exception") 42 | } 43 | *m = append((*m)[0:0], data...) 44 | return nil 45 | } 46 | 47 | func (j JSON) IsNull() bool { 48 | return len(j) == 0 || string(j) == "null" 49 | } 50 | 51 | func (j JSON) Equals(j1 JSON) bool { 52 | return bytes.Equal([]byte(j), []byte(j1)) 53 | } 54 | -------------------------------------------------------------------------------- /internal/web/static/client/block.js: -------------------------------------------------------------------------------- 1 | 2 | class Block { 3 | constructor() { 4 | this.grid = null 5 | } 6 | 7 | setGrid(grid){ 8 | this.grid = grid; 9 | } 10 | 11 | isBlock(x, y) { 12 | if (!this.grid){ 13 | return false; 14 | } 15 | return this.grid[y][x] === 0 16 | } 17 | 18 | // 返回的paths中的数据paths[i][0]为y轴, paths[i][1]为X轴 19 | findPath(start, end){ 20 | let graph = new Graph(this.grid, { diagonal: true }) 21 | const startp = graph.grid[start.y][start.x]; 22 | const endp = graph.grid[end.y][end.x]; 23 | const paths = astar.search(graph, startp, endp, { heuristic: astar.heuristics.diagonal }); 24 | let newPaths = [] 25 | if (paths){ 26 | for(let i = 0; i < paths.length; i++){ 27 | //这个Astar中返回的X为坐标系的Y轴,对应二维数组的1第一维 28 | newPaths.push([paths[i].x, paths[i].y]) 29 | } 30 | } 31 | console.log("findPath:", start, end, startp, endp, "paths:::", paths, ",newPaths:::", newPaths) 32 | return newPaths; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "master", 9 | "type": "go", 10 | "request": "launch", 11 | "mode": "debug", 12 | "program": "cmd/master/main.go" 13 | }, 14 | { 15 | "name": "gate", 16 | "type": "go", 17 | "request": "launch", 18 | "mode": "debug", 19 | "program": "cmd/gate/main.go" 20 | }, 21 | { 22 | "name": "web", 23 | "type": "go", 24 | "request": "launch", 25 | "mode": "debug", 26 | "program": "cmd/web/main.go" 27 | }, 28 | { 29 | "name": "game", 30 | "type": "go", 31 | "request": "launch", 32 | "mode": "debug", 33 | "program": "cmd/game/main.go" 34 | } 35 | 36 | ] 37 | } -------------------------------------------------------------------------------- /internal/game/aoimgr.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | // AOI管理器 4 | import ( 5 | "github.com/ouyangzhongmin/gameserver/pkg/aoi" 6 | "github.com/ouyangzhongmin/gameserver/pkg/coord" 7 | ) 8 | 9 | type aoiMgr struct { 10 | aoi aoi.AOI 11 | } 12 | 13 | func newAoiMgr(areaWidth int, gridCount int) *aoiMgr { 14 | mgr := &aoiMgr{} 15 | //基于大格子算法的AOI,找的一个基于九宫格的aoi库直接使用了,自己也可以定义二维数组的方式实现 16 | mgr.aoi = aoi.NewGridManager(0, 0, areaWidth, gridCount) 17 | return mgr 18 | } 19 | 20 | func (m *aoiMgr) Enter(entity IMovableEntity) { 21 | m.aoi.Add(float64(entity.GetPos().X), float64(entity.GetPos().Y), entity.GetUUID(), entity) 22 | } 23 | 24 | // 防止泄露 对象销毁时一定要调用Leave 25 | func (m *aoiMgr) Leave(entity IMovableEntity) { 26 | m.aoi.Delete(float64(entity.GetPos().X), float64(entity.GetPos().Y), entity.GetUUID()) 27 | } 28 | 29 | func (m *aoiMgr) Moved(entity IMovableEntity, x, y, oldX, oldY coord.Coord) { 30 | m.aoi.Moved(float64(x), float64(y), float64(oldX), float64(oldY), entity.GetUUID(), entity) 31 | } 32 | 33 | func (m *aoiMgr) Search(x, y coord.Coord) []interface{} { 34 | result := m.aoi.Search(float64(x), float64(y)) 35 | return result 36 | } 37 | -------------------------------------------------------------------------------- /pkg/aoi/aoi.go: -------------------------------------------------------------------------------- 1 | package aoi 2 | 3 | import "sync" 4 | 5 | // AOI (Area of Interest) represents an interface for managing entities within a specific area. 6 | type AOI interface { 7 | Add(x, y float64, name string, data interface{}) // Add an entity to the AOI 8 | Delete(x, y float64, name string) // Delete an entity from the AOI 9 | Search(x, y float64) (result []interface{}) // Search for entities within a specified range 10 | Moved(x, y, oldx, oldy float64, key string, data interface{}) 11 | } 12 | 13 | // Entity represents an object with coordinates and a key. 14 | type Entity struct { 15 | X, Y float64 16 | Key string 17 | Data interface{} //引用的数据指针要记录下来 18 | } 19 | 20 | var ( 21 | resultPool sync.Pool // Pool for recycling result slices 22 | entityPool sync.Pool // Pool for recycling Entity objects 23 | ) 24 | 25 | func init() { 26 | // Initialize the resultPool to recycle result slices 27 | resultPool.New = func() interface{} { 28 | return make([]interface{}, 0, 500) 29 | } 30 | 31 | // Initialize the entityPool to recycle Entity objects 32 | entityPool.New = func() interface{} { 33 | return &Entity{} 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pkg/shape/util.go: -------------------------------------------------------------------------------- 1 | package shape 2 | 3 | import "math" 4 | 5 | // 计算两点之间的距离 6 | func CalculateDistance(x1, y1, x2, y2 float64) float64 { 7 | return math.Sqrt(math.Pow(x2-x1, 2) + math.Pow(y2-y1, 2)) 8 | } 9 | 10 | // 判断点是否在圆内 11 | // (cx, cy) 是圆心的坐标,radius 是圆的半径,(x, y) 是点的坐标 12 | func IsInsideCircle(cx, cy, radius, x, y float64) bool { 13 | distance := math.Sqrt(math.Pow(x-cx, 2) + math.Pow(y-cy, 2)) 14 | return distance <= radius 15 | } 16 | 17 | /** 18 | * 获得从基准点到目标点的角度 19 | * @param baseX 20 | * @param baseY 21 | * @param targetX 22 | * @param targetY 23 | * @return 24 | */ 25 | func GetAngle(baseX, baseY, targetX, targetY float64) float64 { 26 | radians := GetRadians(baseX, baseY, targetX, targetY) 27 | return RadiansToDegrees(radians) 28 | } 29 | 30 | /** 31 | * 获得从基准点到目标点的弧度 32 | * @param baseX 33 | * @param baseY 34 | * @param targetX 35 | * @param targetY 36 | * @return 37 | */ 38 | func GetRadians(baseX, baseY, targetX, targetY float64) float64 { 39 | return math.Atan2(baseY-targetY, targetX-baseX) // flash 的坐标的y是反的 40 | } 41 | 42 | /* 43 | * 将弧度转换为度数 44 | */ 45 | func RadiansToDegrees(radians float64) float64 { 46 | return radians * (180 / math.Pi) 47 | } 48 | -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Brian Grinstead, http://briangrinstead.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gameserver 2 | ## 基于nanoserver直接改造的的mmrpg server, 小部分代码雷同 3 | * gate -- 网关服务器 4 | * master- 集群master服务器, 处理用户选择创建等 5 | * game - 游戏场景逻辑服务器, 可以多开,每个game对应1个或多个场景管理 6 | * web 登录http服务 + html client demo 7 | * aoi下载于开源:https://github.com/knight0zh/aoi 8 | * nanaserver: https://github.com/lonng/nanoserver 9 | * nano: https://github.com/lonng/nano 10 | 11 | ## 启动 12 | 导入docs/jsmx.sql到mysql,修改configs/config.toml配置,然后分别运行cmd/master、gate、game、web start_server.sh启动所有服务, 13 | 内置html demo: http://localhost:12307/static/client/ 14 | 15 | ## 目前问题: 16 | ```aiignore 17 | 1.hero 推送消息在同屏数据量大时消息会堵塞,nano作者在agent.push内会丢弃超过agentWriteBacklog(16)缓冲区的数据,我加了个消息合并发送的方式, 18 | 目前测试使用的是json序列化,生产如果是mmrpg类建议改为bytes 19 | 20 | 2.game服务器重启entity数据都丢失了,无法做到重启用户无感知,可以参考goworld方式将entity全部序列化到文件,重启时载入 21 | 22 | 3.目前实现的视野刷新问题,如果同屏1万人在线,那么服务器的视野刷新处理计算非常高, 不适合大量同屏的处理 23 | 24 | 4.目前的game主要实现的是aoi 同步等逻辑,业务功能模块可以再新加一个node进程来实现,更新重启也不会影响用户 25 | ``` 26 | 27 | ## 无缝大地图实现逻辑: 28 | 代码分支: `feature/cell` 29 | ```aiignore 30 | 动态将scene分割成 n 个 区域(cell)只做横向切割。 31 | 每个game进程内每个scene只能管理一个cell, 由master的 CellManager 服务器分配管理, 32 | 每启动一个cell, 将scene 重新按宽度均匀分布切割为多1个cell,cell内将数据重新迁移分布。 33 | cell边界通过Real->Ghost切换来实现无缝的逻辑。 34 | 建议每次启动新的cell时需要间隔小段时间等待数据迁移完成再启动下一个。 35 | ``` 36 | ![image](./cell时序图.jpg) -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/benchmark/benchmark.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | var running = false; 3 | $("#runall").click(function() { 4 | if (running) { 5 | return; 6 | } 7 | running = true; 8 | 9 | var graph = new Graph(grid), 10 | start = graph.grid[0][0], 11 | end = graph.grid[140][140], 12 | results = [], 13 | times = 0; 14 | 15 | for (var i = 0; i < 1000; i++) { 16 | var startTime = performance ? performance.now() : new Date().getTime(), 17 | result = astar.search(graph, start, end), 18 | endTime = performance ? performance.now() : new Date().getTime(); 19 | times = times + (endTime - startTime); 20 | 21 | results.push( 22 | '
  • Found path with ' + result.length + ' steps. ' + 23 | 'Took ' + (endTime - startTime).toFixed(2) + ' milliseconds.
  • ' 24 | ); 25 | } 26 | 27 | $("#graph").html(graph.toString()); 28 | $("#summary").html('Average time: ' + (times / 1000).toFixed(2) + 'ms'); 29 | $("#results").html(results.join('')); 30 | 31 | running = false; 32 | return false; 33 | }); 34 | }); -------------------------------------------------------------------------------- /db/third_account.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "github.com/ouyangzhongmin/gameserver/db/model" 5 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 6 | ) 7 | 8 | func QueryThirdAccount(account, platform string) (*model.ThirdAccount, error) { 9 | t := &model.ThirdAccount{ThirdAccount: account, Platform: platform} 10 | has, err := database.Get(t) 11 | if err != nil { 12 | return nil, err 13 | } 14 | 15 | if !has { 16 | return nil, errutil.ErrThirdAccountNotFound 17 | } 18 | 19 | return t, nil 20 | } 21 | 22 | func InsertThirdAccount(account *model.ThirdAccount, u *model.User) error { 23 | session := database.NewSession() 24 | if err := session.Begin(); err != nil { 25 | return err 26 | } 27 | defer session.Close() 28 | 29 | if _, err := session.Insert(u); err != nil { 30 | session.Rollback() 31 | return err 32 | } 33 | 34 | // update uid 35 | account.Uid = u.Id 36 | 37 | if _, err := session.Insert(account); err != nil { 38 | session.Rollback() 39 | return err 40 | } 41 | 42 | return session.Commit() 43 | } 44 | 45 | func UpdateThirdAccount(account *model.ThirdAccount) error { 46 | if account == nil { 47 | return errutil.ErrInvalidParameter 48 | } 49 | _, err := database.Where("id=?", account.Id).Update(account) 50 | return err 51 | } 52 | -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JavaScript A* Search Algorithm 6 | 7 | 8 | 9 | 10 | 23 | 24 |
    25 |

    A* Search Algorithm

    26 | 27 | 33 |
    34 | 35 | 36 | -------------------------------------------------------------------------------- /protocol/agent.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | type RegisterAgentRequest struct { 4 | Name string `json:"name"` 5 | Account string `json:"account"` 6 | Password string `json:"password"` 7 | Extra string `json:"extra"` 8 | } 9 | 10 | type AgentLoginRequest struct { 11 | Username string `json:"username"` 12 | Password string `json:"password"` 13 | } 14 | 15 | type AgentDetail struct { 16 | Id int64 `json:"id"` 17 | Name string `json:"name"` 18 | Account string `json:"account"` 19 | CardCount int64 `json:"card_count"` 20 | CreateAt int64 `json:"create_at"` 21 | } 22 | 23 | type AgentLoginResponse struct { 24 | Code int `json:"code"` 25 | Token string `json:"token"` 26 | Detail AgentDetail `json:"detail"` 27 | } 28 | 29 | type AgentListResponse struct { 30 | Code int `json:"code"` 31 | Agents []AgentDetail `json:"agents"` 32 | Total int64 `json:"total"` 33 | } 34 | 35 | type RechargeDetail struct { 36 | PlayerId int64 `json:"player_id"` 37 | Extra string `json:"extra"` 38 | CreateAt int64 `json:"create_at"` 39 | CardCount int64 `json:"card_count"` 40 | } 41 | 42 | type RechargeListResponse struct { 43 | Code int `json:"code"` 44 | Recharges []RechargeDetail `json:"recharges"` 45 | Total int64 `json:"total"` 46 | } 47 | -------------------------------------------------------------------------------- /db/const.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | const ( 4 | KWX = "broker" 5 | ) 6 | 7 | const ( 8 | defaultMaxConns = 10 9 | ) 10 | 11 | // Users表中role字段的取值 12 | const ( 13 | RoleTypeAdmin = 1 //管理员账号 14 | RoleTypeThird = 2 //三方平台账号 15 | ) 16 | 17 | const ( 18 | OpActionRegister = 1 //注册 19 | OpActionFreezen = 2 //冻结账号 20 | OpActionUnFreezen = 3 //账号解冻 21 | OpActionDelete = 4 //账号删除 22 | ) 23 | 24 | const ( 25 | UserOffline = 1 //离线 26 | UserOnline = 2 //在线 27 | ) 28 | 29 | const ( 30 | StatusNormal = 1 //正常 31 | StatusDeleted = 2 //删除 32 | StatusFreezed = 3 //冻结 33 | StatusBound = 4 //绑定 34 | ) 35 | 36 | // 订单状态 37 | const ( 38 | OrderStatusCreated = 1 //创建 39 | OrderStatusPayed = 2 //完成 40 | OrderStatusNotified = 3 //已确认订单 41 | ) 42 | 43 | const ( 44 | OrderTypeUnknown = iota 45 | OrderTypeBuyToken //购买令牌 46 | OrderTypeConsumeToken //消费代币(eg:使用令牌购买游戏中的道具,比如房卡) 47 | OrderTypeConsume3rd //第三方支付平台消费(eg:直接使用alipay, wechat等购买游戏中的道具) 48 | OrderTypeTest //支付测试 49 | ) 50 | 51 | const ( 52 | NotifyResultSuccess = 1 //通知成功 53 | NotifyResultFailed = 2 //通知失败 54 | ) 55 | 56 | const ( 57 | dayInSecond = 24 * 60 * 60 58 | 59 | day1 = dayInSecond 60 | day2 = day1 * 2 61 | day3 = day1 * 3 62 | day7 = day1 * 7 63 | day14 = day1 * 14 64 | day30 = day1 * 30 65 | ) 66 | 67 | const ( 68 | RankingNormal = 1 69 | RankingDesc = 2 70 | ) 71 | 72 | const ( 73 | DefaultTopN = 10 74 | ) 75 | -------------------------------------------------------------------------------- /db/scene.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "github.com/ouyangzhongmin/gameserver/db/model" 5 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 6 | ) 7 | 8 | func QueryScene(id int) (*model.Scene, error) { 9 | h := &model.Scene{Id: id} 10 | has, err := database.Get(h) 11 | if err != nil { 12 | return nil, err 13 | } 14 | if !has { 15 | return nil, errutil.ErrNotFound 16 | } 17 | return h, nil 18 | } 19 | 20 | func SceneList(sceneIds []int) ([]model.Scene, error) { 21 | list := []model.Scene{} 22 | if sceneIds != nil && len(sceneIds) > 0 { 23 | if err := database.In("id", sceneIds).Find(&list); err != nil { 24 | return nil, err 25 | } 26 | } else { 27 | bean := &model.Scene{} 28 | if err := database.Find(&list, bean); err != nil { 29 | return nil, err 30 | } 31 | } 32 | if len(list) < 1 { 33 | return []model.Scene{}, nil 34 | } 35 | return list, nil 36 | } 37 | 38 | func SceneDoorList(sceneId int) ([]model.SceneDoor, error) { 39 | result := make([]model.SceneDoor, 0) 40 | if err := database.Where("scene_id=?", sceneId).Find(&result); err != nil { 41 | return nil, err 42 | } 43 | return result, nil 44 | } 45 | 46 | func SceneMonsterConfigList(sceneId int) ([]model.SceneMonsterConfig, error) { 47 | result := make([]model.SceneMonsterConfig, 0) 48 | if err := database.Where("scene_id=?", sceneId).Find(&result); err != nil { 49 | return nil, err 50 | } 51 | return result, nil 52 | } 53 | -------------------------------------------------------------------------------- /db/views.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | //trade & order => views 4 | type ViewTrade struct { 5 | PayAt int64 6 | Uid int64 7 | Id int64 8 | 9 | Type int 10 | Money int 11 | RealMoney int 12 | ProductCount int 13 | Status int 14 | 15 | OrderId string 16 | ComsumerId string 17 | AppId string 18 | ChannelId string 19 | OrderPlatform string 20 | ChannelOrderId string 21 | Currency string 22 | RoleId string 23 | ServerName string 24 | ProductId string 25 | ProductName string 26 | RoleName string 27 | PayPlatform string 28 | } 29 | 30 | func (v *ViewTrade) TableName() string { 31 | return "view_trade" 32 | } 33 | 34 | // trade & register & user => views 35 | type ViewChannelApp struct { 36 | Id int64 37 | Type byte 38 | Status byte 39 | 40 | Uid int64 41 | CreatedAt int64 42 | RegisterAt int64 43 | FirstRechargeAt int64 44 | 45 | RealMoney int 46 | RegisterType int 47 | 48 | Os string 49 | Imei string 50 | OrderId string 51 | AppId string 52 | Model string 53 | ServerId string 54 | ProductId string 55 | OrderPlatform string 56 | PayPlatform string 57 | PassportChannelId string 58 | PaymentChannelId string 59 | } 60 | 61 | func (v *ViewChannelApp) TableName() string { 62 | return "view_channel_app" 63 | } 64 | -------------------------------------------------------------------------------- /pkg/whitelist/white_list.go: -------------------------------------------------------------------------------- 1 | package whitelist 2 | 3 | import ( 4 | "regexp" 5 | "sync" 6 | ) 7 | 8 | var ( 9 | lock sync.RWMutex 10 | ips = map[string]*regexp.Regexp{} 11 | ) 12 | 13 | func Setup(list []string) error { 14 | lock.Lock() 15 | defer lock.Unlock() 16 | 17 | for _, ip := range list { 18 | re, err := regexp.Compile(ip) 19 | if err != nil { 20 | return err 21 | } 22 | ips[ip] = re 23 | } 24 | 25 | return nil 26 | } 27 | 28 | //VerifyIP check the ip is a legal ip or not 29 | func VerifyIP(ip string) bool { 30 | lock.RLock() 31 | defer lock.RUnlock() 32 | 33 | for _, r := range ips { 34 | if r.MatchString(ip) { 35 | return true 36 | } 37 | } 38 | return false 39 | } 40 | 41 | func RegisterIP(ip string) error { 42 | lock.Lock() 43 | defer lock.Unlock() 44 | 45 | _, ok := ips[ip] 46 | if ok { 47 | return nil 48 | } 49 | 50 | re, err := regexp.Compile(ip) 51 | if err != nil { 52 | return err 53 | } 54 | ips[ip] = re 55 | return nil 56 | } 57 | 58 | func RemoveIP(ip string) { 59 | lock.Lock() 60 | defer lock.Unlock() 61 | 62 | delete(ips, ip) 63 | } 64 | 65 | func IPList() []string { 66 | lock.RLock() 67 | defer lock.RUnlock() 68 | 69 | list := []string{} 70 | for ip := range ips { 71 | list = append(list, ip) 72 | } 73 | 74 | return list 75 | } 76 | 77 | func ClearIPList() { 78 | lock.Lock() 79 | defer lock.Unlock() 80 | 81 | ips = map[string]*regexp.Regexp{} 82 | } 83 | -------------------------------------------------------------------------------- /internal/game/igame.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "github.com/ouyangzhongmin/gameserver/pkg/coord" 5 | "github.com/ouyangzhongmin/gameserver/pkg/shape" 6 | ) 7 | 8 | type IEntity interface { 9 | onEnterScene(s *Scene) 10 | onExitScene(s *Scene) 11 | GetScene() *Scene 12 | SetPos(x, y, z coord.Coord) 13 | GetPos() coord.Vector3 14 | GetID() int64 15 | // 不存储在数据库,只作为运行对象的唯一值 16 | GetUUID() string 17 | GetEntityType() int 18 | Destroy() 19 | IsDestroyed() bool 20 | } 21 | 22 | type IMovableEntity interface { 23 | IEntity 24 | //对象进入我的视野 25 | onEnterView(target IMovableEntity) 26 | //对象离开我的视野 27 | onExitView(target IMovableEntity) 28 | //我进入对象的视野 29 | onEnterOtherView(target IMovableEntity) 30 | //我离开对象的视野 31 | onExitOtherView(target IMovableEntity) 32 | update(curMilliSecond int64, elapsedTime int64) error 33 | GetViewList() map[string]IMovableEntity 34 | GetCanSeeMeViewList() map[string]IMovableEntity 35 | GetViewRect() shape.Rect 36 | SetViewRange(int, int) 37 | GetViewRange() (int, int) 38 | CanSee(target IEntity) bool 39 | IsInViewList(target IMovableEntity) bool 40 | } 41 | 42 | type IAiManager interface { 43 | update(curMilliSecond int64, elapsedTime int64) error 44 | onBeenAttacked(target IMovableEntity) 45 | GetAiData() interface{} 46 | GetOwner() IMovableEntity 47 | } 48 | 49 | type IAoiManager interface { 50 | Enter(entity IMovableEntity) 51 | Leave(entity IMovableEntity) 52 | Moved(entity IMovableEntity, oldX, oldY coord.Coord) 53 | } 54 | -------------------------------------------------------------------------------- /pkg/aoi/README.md: -------------------------------------------------------------------------------- 1 | # AOI (Area of Interest) Library 2 | 3 | This library provides implementations of Area of Interest algorithms for spatial partitioning. Currently, it includes implementations for the following algorithms: 4 | 5 | 1. **九宫格 (Grid Manager)** 6 | - A simple grid-based AOI algorithm dividing the area into a grid of cells and associating entities with the corresponding grid cells. 7 | 8 | 2. **四叉树 (Quadtree)** 9 | - A hierarchical spatial partitioning algorithm dividing the area into four quadrants recursively, optimizing the search for entities within a specified range. 10 | 11 | ## Usage: 12 | 13 | ### 九宫格 (Grid Manager) 14 | 15 | ```go 16 | // Example Usage: 17 | aoiManager := NewGridManager(startX, startY, areaWidth, gridCount) 18 | aoiManager.Add(x, y, "player1") 19 | aoiManager.Delete(x, y, "player1") 20 | result := aoiManager.Search(x, y) 21 | 22 | // Example Usage: 23 | quadTree := NewQuadTree(startX, startY, areaWidth) 24 | quadTree.Add(x, y, "player1") 25 | quadTree.Delete(x, y, "player1") 26 | result := quadTree.Search(x, y) 27 | ``` 28 | 29 | ## Features: 30 | - Both implementations support adding, deleting, and searching for entities within a specified area of interest. 31 | - The Grid Manager uses a simple grid-based approach, while the Quadtree provides a hierarchical and optimized solution for larger and dynamic environments. 32 | 33 | ## TODO: 34 | Implement additional commonly used AOI algorithms: 35 | - R-树 (R-tree) 36 | - 六边形网格 (Hexagonal Grid) 37 | - 基于事件的算法 (Event-driven Approaches) 38 | 39 | ## License 40 | This AOI Library is licensed under the MIT License. -------------------------------------------------------------------------------- /pkg/whitelist/white_list_test.go: -------------------------------------------------------------------------------- 1 | package whitelist 2 | 3 | import ( 4 | "os" 5 | "reflect" 6 | "testing" 7 | ) 8 | 9 | func TestVerifyIP(t *testing.T) { 10 | m := map[string]bool{ 11 | "127.0.0.1": true, 12 | "127.0.0.2": false, 13 | "192.168.1.1": true, 14 | "192.168.1.255": true, 15 | "192.168.0.1": false, 16 | } 17 | 18 | for k, v := range m { 19 | if VerifyIP(k) != v { 20 | t.Fatal(k) 21 | } 22 | } 23 | } 24 | 25 | func TestClearIPList(t *testing.T) { 26 | ClearIPList() 27 | m := map[string]bool{ 28 | "127.0.0.1": false, 29 | "127.0.0.2": false, 30 | "192.168.1.1": false, 31 | "192.168.1.255": false, 32 | "192.168.0.1": false, 33 | } 34 | 35 | for k, v := range m { 36 | if VerifyIP(k) != v { 37 | t.Fatal(k) 38 | } 39 | } 40 | } 41 | 42 | func TestRegisterIP(t *testing.T) { 43 | RegisterIP("159.56.25.14") 44 | 45 | if !VerifyIP("159.56.25.14") { 46 | t.Fail() 47 | } 48 | } 49 | 50 | func TestRemoveIP(t *testing.T) { 51 | RegisterIP("159.56.25.14") 52 | 53 | if !VerifyIP("159.56.25.14") { 54 | t.Fail() 55 | } 56 | 57 | RemoveIP("159.56.25.14") 58 | if VerifyIP("159.56.25.14") { 59 | t.Fail() 60 | } 61 | } 62 | 63 | func TestIPList(t *testing.T) { 64 | ClearIPList() 65 | m := []string{"124.4.59.24", "58.57.1.*"} 66 | 67 | for _, ip := range m { 68 | RegisterIP(ip) 69 | } 70 | 71 | if !reflect.DeepEqual(m, IPList()) { 72 | t.Fail() 73 | } 74 | } 75 | 76 | func TestMain(m *testing.M) { 77 | Setup([]string{"127.0.0.1", "192.168.1.*"}) 78 | 79 | retCode := m.Run() 80 | os.Exit(retCode) 81 | 82 | } 83 | -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/benchmark/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Benchmark - JavaScript A* Search Algorithm 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 28 | 29 |
    30 |

    Benchmark

    31 | 32 | Run benchmark 33 |
    34 |
    
    35 |         
    36 |     
    37 | 38 | 39 | -------------------------------------------------------------------------------- /internal/web/api/scene.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/gorilla/mux" 5 | "github.com/lonng/nex" 6 | "github.com/ouyangzhongmin/gameserver/db" 7 | "github.com/ouyangzhongmin/gameserver/db/model" 8 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 9 | "github.com/ouyangzhongmin/gameserver/pkg/whitelist" 10 | "net/http" 11 | "strconv" 12 | ) 13 | 14 | func MakeSceneService() http.Handler { 15 | router := mux.NewRouter() 16 | router.Handle("/v1/scene/", nex.Handler(sceneList)).Methods("GET") //获取列表(lite) 17 | router.Handle("/v1/scene/{id}", nex.Handler(sceneByID)).Methods("GET") //获取记录 18 | return router 19 | } 20 | 21 | func SceneByID(id int) (*model.Scene, error) { 22 | p, err := db.QueryScene(id) 23 | if err != nil { 24 | return nil, err 25 | } 26 | return p, nil 27 | 28 | } 29 | 30 | func sceneList(r *http.Request) ([]model.Scene, error) { 31 | if !whitelist.VerifyIP(r.RemoteAddr) { 32 | return nil, errutil.ErrPermissionDenied 33 | } 34 | list, err := db.SceneList(nil) 35 | if err != nil { 36 | return nil, err 37 | } 38 | return list, nil 39 | } 40 | 41 | func sceneByID(r *http.Request) (*model.Scene, error) { 42 | if !whitelist.VerifyIP(r.RemoteAddr) { 43 | return nil, errutil.ErrPermissionDenied 44 | } 45 | vars := mux.Vars(r) 46 | idStr, ok := vars["id"] 47 | if !ok || idStr == "" { 48 | return nil, errutil.ErrInvalidParameter 49 | } 50 | 51 | id, err := strconv.ParseInt(idStr, 10, 0) 52 | if err != nil { 53 | return nil, errutil.ErrInvalidParameter 54 | } 55 | 56 | scene, err := SceneByID(int(id)) 57 | if err != nil { 58 | return nil, err 59 | } 60 | return scene, nil 61 | } 62 | -------------------------------------------------------------------------------- /protocol/apps.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | type RegisterAppRequest struct { 4 | Name string `json:"name"` //应用名 5 | RedirectURI string `json:"redirect_uri"` //回调地址 6 | Extra string `json:"extra"` //应用描述 7 | CpID string `json:"cp_id"` //内容供应商ID 8 | ThirdProperties map[string]map[string]string `json:"third_properties"` //第三方属性 9 | } 10 | 11 | type RegisterAppResponse struct { 12 | Code int32 `json:"code"` //状态码 13 | Data AppInfo `json:"data"` //数据 14 | } 15 | 16 | type AppListRequest struct { 17 | CpID string `json:"cp_id"` 18 | Offset int `json:"offset"` 19 | Count int `json:"count"` 20 | } 21 | type AppListResponse struct { 22 | Code int `json:"code"` //状态码 23 | Data []AppInfo `json:"data"` //应用列表 24 | Total int64 `json:"total"` //总数量 25 | } 26 | 27 | type AppInfoRequest struct { 28 | AppID string `json:"appid"` //应用ID 29 | } 30 | 31 | type AppInfoResponse struct { 32 | Code int32 `json:"code"` //状态码 33 | Data AppInfo `json:"data"` //数据 34 | } 35 | 36 | type DeleteAppRequest struct { 37 | AppID string `json:"appid"` //应用ID 38 | } 39 | 40 | type UpdateAppRequest struct { 41 | Type int `json:"type"` //更新类型, 1为重新生成appkey/appsecret, 2为更新其他内容 42 | AppID string `json:"appid"` //应用ID 43 | Name string `json:"name"` //应用名 44 | RedirectURI string `json:"redirect_uri"` //回调地址 45 | Extra string `json:"extra"` //应用描述 46 | ThirdProperties map[string]map[string]string `json:"third_properties"` //第三方属性 47 | } 48 | -------------------------------------------------------------------------------- /db/hero.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "github.com/ouyangzhongmin/gameserver/db/model" 5 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 6 | ) 7 | 8 | func InsertHero(h *model.Hero) (int64, error) { 9 | if h == nil { 10 | return 0, errutil.ErrInvalidParameter 11 | } 12 | row, err := database.Exec(`insert into hero(name,avatar,attr_type,uid,experience,level,max_life,max_mana, 13 | defense,attack,base_life,base_mana,base_defense,base_attack,strength,agility, 14 | intelligence,step_time,scene_id,attack_range) 15 | values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`, 16 | h.Name, h.Avatar, h.AttrType, h.Uid, h.Experience, h.Level, h.MaxLife, h.MaxMana, 17 | h.Defense, h.Attack, h.BaseLife, h.BaseMana, h.BaseDefense, h.BaseAttack, h.Strength, h.Agility, 18 | h.Intelligence, h.StepTime, h.SceneId, h.AttackRange) 19 | if err != nil { 20 | return 0, err 21 | } 22 | return row.LastInsertId() 23 | } 24 | 25 | func UpdateHero(d *model.Hero) error { 26 | if d == nil { 27 | return nil 28 | } 29 | _, err := database.Where("id=?", d.Id).AllCols().Update(d) 30 | return err 31 | } 32 | 33 | func QueryHero(id int64) (*model.Hero, error) { 34 | h := &model.Hero{Id: id} 35 | has, err := database.Get(h) 36 | if err != nil { 37 | return nil, err 38 | } 39 | if !has { 40 | return nil, errutil.ErrNotFound 41 | } 42 | return h, nil 43 | } 44 | 45 | func DeleteHero(id int64) error { 46 | _, err := database.Exec("UPDATE `hero` SET `status` = 0 WHERE `id`= ? ", id) 47 | if err != nil { 48 | return err 49 | } 50 | return nil 51 | } 52 | 53 | func HeroList(uid int64) ([]model.Hero, error) { 54 | result := make([]model.Hero, 0) 55 | err := database.Where("uid=?", uid).Desc("id").Find(&result) 56 | 57 | if err != nil { 58 | return nil, errutil.ErrDBOperation 59 | } 60 | return result, nil 61 | } 62 | -------------------------------------------------------------------------------- /pkg/coord/vector3.go: -------------------------------------------------------------------------------- 1 | package coord 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // Coord is the of coordinations entity position (x, y, z) 9 | type Coord int 10 | 11 | // Vector3 is type of entity position 12 | type Vector3 struct { 13 | X Coord `json:"x"` 14 | Y Coord `json:"y"` 15 | Z Coord `json:"z"` 16 | } 17 | 18 | func (p Vector3) String() string { 19 | return fmt.Sprintf("(%.2f, %.2f, %.2f)", p.X, p.Y, p.Z) 20 | } 21 | 22 | // DistanceTo calculates distance between two positions 23 | func (p Vector3) DistanceTo(o Vector3) Coord { 24 | dx := p.X - o.X 25 | dy := p.Y - o.Y 26 | dz := p.Z - o.Z 27 | return Coord(math.Sqrt(float64(dx*dx + dy*dy + dz*dz))) 28 | } 29 | 30 | // Sub calculates Vector3 p - Vector3 o 31 | func (p Vector3) Sub(o Vector3) Vector3 { 32 | return Vector3{p.X - o.X, p.Y - o.Y, p.Z - o.Z} 33 | } 34 | 35 | func (p Vector3) Add(o Vector3) Vector3 { 36 | return Vector3{p.X + o.X, p.Y + o.Y, p.Z + o.Z} 37 | } 38 | 39 | func (p *Vector3) Copy(o Vector3) { 40 | p.X = o.X 41 | p.Y = o.Y 42 | p.Z = o.Z 43 | } 44 | 45 | // Mul calculates Vector3 p * m 46 | func (p Vector3) Mul(m Coord) Vector3 { 47 | return Vector3{p.X * m, p.Y * m, p.Z * m} 48 | } 49 | 50 | // DirToYaw convert direction represented by Vector3 to Yaw 51 | func (p Vector3) DirToYaw() float32 { 52 | p.Normalize() 53 | 54 | yaw := math.Acos(float64(p.X)) 55 | if p.Z < 0 { 56 | yaw = math.Pi*2 - yaw 57 | } 58 | 59 | yaw = yaw / math.Pi * 180 // convert to angle 60 | 61 | if yaw <= 90 { 62 | yaw = 90 - yaw 63 | } else { 64 | yaw = 90 + (360 - yaw) 65 | } 66 | 67 | return float32(yaw) 68 | } 69 | 70 | func (p *Vector3) Normalize() { 71 | d := Coord(math.Sqrt(float64(p.X*p.X + p.Y*p.Y + p.Z*p.Z))) 72 | if d == 0 { 73 | return 74 | } 75 | p.X /= d 76 | p.Y /= d 77 | p.Z /= d 78 | } 79 | 80 | func (p Vector3) Normalized() Vector3 { 81 | p.Normalize() 82 | return p 83 | } 84 | -------------------------------------------------------------------------------- /internal/web/static/client/grid_show.js: -------------------------------------------------------------------------------- 1 | 2 | class GridShow { 3 | constructor() { 4 | this.grid = null 5 | 6 | this.semiTransparentRed = 'rgba(255, 0, 0, 0.5)'; 7 | } 8 | 9 | update(deltaTime, camera){ 10 | if (!this.grid || this.grid.length === 0){ 11 | return 12 | } 13 | this.startX = getGridXByPixel(camera.x); 14 | this.startY = getGridYByPixel(camera.y); 15 | this.endX = this.startX + Math.ceil(camera.width/GRID_WIDTH) 16 | this.endY = this.startY + Math.ceil(camera.height/GRID_HEIGHT) 17 | if (this.endY >= this.grid.length){ 18 | this.endY = this.grid.length - 1; 19 | } 20 | if (this.endX >= this.grid[0].length){ 21 | this.endX = this.grid[0].length - 1; 22 | } 23 | } 24 | 25 | draw(ctx) { 26 | if (!this.grid || this.grid.length === 0){ 27 | return 28 | } 29 | // console.log("gridShow.draw0::", this.startY, this.endY, this.endX , this.startX) 30 | for (let row = 0; row < (this.endY - this.startY); row++) { 31 | for (let col = 0; col < (this.endX - this.startX); col++) { 32 | ctx.strokeStyle = 'black'; 33 | ctx.strokeRect(col * GRID_WIDTH, row * GRID_HEIGHT, GRID_WIDTH, GRID_HEIGHT); 34 | // console.log("gridShow.draw::", row+this.startY, col+this.startX, this.grid[row+this.startY][col+this.startX]) 35 | if (this.grid[row+this.startY][col+this.startX] === 0) { 36 | ctx.fillStyle = this.semiTransparentRed; 37 | ctx.fillRect(col * GRID_WIDTH, row * GRID_HEIGHT, GRID_WIDTH, GRID_HEIGHT); 38 | } 39 | } 40 | } 41 | } 42 | 43 | show(grid){ 44 | this.grid = grid; 45 | // console.log("gridShow.show:", grid) 46 | } 47 | 48 | isShow(){ 49 | return this.grid && this.grid.length > 0 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /pkg/algoutil/params_test.go: -------------------------------------------------------------------------------- 1 | package algoutil 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type Test struct { 8 | Foo, Bar, FooBar string 9 | } 10 | 11 | func TestParamsToStruct(t *testing.T) { 12 | test := &Test{} 13 | ParamsToStruct("foo=hello&bar=world&foobar=helloworld", test) 14 | if test.Foo != "hello" || test.Bar != "world" || test.FooBar != "helloworld" { 15 | t.Fail() 16 | } 17 | } 18 | 19 | func TestSortParams(t *testing.T) { 20 | if SortParams(ParseParams("zdf=sdff&b=c&a=c&aaaaa=cdf")) != "a=c&aaaaa=cdf&b=c&zdf=sdff" { 21 | t.Fail() 22 | } 23 | unsorted := "discount=0.00&payment_type=1&subject=金币&trade_no=2016031421001004170242826341&buyer_email=15520707860&gmt_create=2016-03-14 16:10:24¬ify_type=trade_status_sync&quantity=1&out_trade_no=426006374921535488&seller_id=2088801054724902¬ify_time=2016-03-14 16:10:25&body=500金币&trade_status=TRADE_SUCCESS&is_total_fee_adjust=N&total_fee=0.01&gmt_payment=2016-03-14 16:10:25&seller_email=854761339@qq.com&price=0.01&buyer_id=2088402810244179¬ify_id=cfdcab45ae04498a568e03357edd6cehba&use_coupon=N&sign_type=RSA&sign=e+VYyBpGyLubIdOMpQt0B/StveBZgthVcTbsNEFFmUgjJ+Bahl+3pf5g0Dim1yBZ3Sxz4C57qrozqfzjdVhWf/SEs8QWyf6+V4LgcosTTWpXBLXnVWfMvInGuxOUrufh9fG874tIISMkPPrkud+vsTn6wcqetipBh+wM+P7J9NI=" 24 | sorted := "body=500金币&buyer_email=15520707860&buyer_id=2088402810244179&discount=0.00&gmt_create=2016-03-14 16:10:24&gmt_payment=2016-03-14 16:10:25&is_total_fee_adjust=N¬ify_id=cfdcab45ae04498a568e03357edd6cehba¬ify_time=2016-03-14 16:10:25¬ify_type=trade_status_sync&out_trade_no=426006374921535488&payment_type=1&price=0.01&quantity=1&seller_email=854761339@qq.com&seller_id=2088801054724902&sign=e+VYyBpGyLubIdOMpQt0B/StveBZgthVcTbsNEFFmUgjJ+Bahl+3pf5g0Dim1yBZ3Sxz4C57qrozqfzjdVhWf/SEs8QWyf6+V4LgcosTTWpXBLXnVWfMvInGuxOUrufh9fG874tIISMkPPrkud+vsTn6wcqetipBh+wM+P7J9NI=&sign_type=RSA&subject=金币&total_fee=0.01&trade_no=2016031421001004170242826341&trade_status=TRADE_SUCCESS&use_coupon=N" 25 | if SortParams(ParseParams(unsorted)) != sorted { 26 | t.Fail() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /configs/config.toml: -------------------------------------------------------------------------------- 1 | [core] 2 | # enable debug mode 3 | debug = true 4 | heartbeat = 30 5 | 6 | #WEB服务器设置 7 | [webserver] 8 | addr = "0.0.0.0:12307" #监听地址 9 | enable_ssl = false #是否使用https, 如果为true, 则必须配置cert和key的路径 10 | static_dir = "E:\\workspace\\goProjects\\src\\gameserver\\internal\\web\\static" 11 | #"web/static" 12 | 13 | #证书设置 14 | [webserver.certificates] 15 | cert = "configs/****.crt" #证书路径 16 | key = "configs/****.key" #Key路径 17 | 18 | 19 | [gate] 20 | host = "127.0.0.1" 21 | port = 33250 22 | gate-address = ":33290" 23 | 24 | [master] 25 | host = "127.0.0.1" 26 | port = 33252 27 | 28 | [game-server] 29 | host = "127.0.0.1" 30 | port = 33251 31 | 32 | # Redis server config 33 | [redis] 34 | host = "172.16.2.23" 35 | port = 6379 36 | 37 | # Mysql server config 38 | [database] 39 | host = "172.16.2.8" 40 | port = 3306 41 | dbname = "jsmx" 42 | password = "root" 43 | username = "root" 44 | args = "charset=utf8mb4" 45 | buf_size = 1024 46 | max_idle_conns = 1024 47 | max_open_conns = 1024 48 | show_sql = true 49 | 50 | # 微信 51 | [wechat] 52 | appid = "**" 53 | appsecret = "**" 54 | callback_url = "YOUR_CALLBACK" 55 | mer_id = "**" 56 | unify_order_url = "https://api.mch.weixin.qq.com/pay/unifiedorder" 57 | 58 | #Token设置 59 | [token] 60 | expires = 21600 #token过期时间 61 | 62 | #白名单设置 63 | [whitelist] 64 | ip = ["10.10.*", "127.0.0.1", ".*"] #白名单地址, 支持golang正则表达式语法 65 | 66 | #分享信息 67 | [share] 68 | title = "一起来玩" 69 | desc = "砍爆你" 70 | 71 | #更新设置 72 | [update] 73 | force = true #是否强制更新 74 | version = "1.9.3" 75 | android = "https://fir.im/tand" 76 | ios = "https://fir.im/tios" 77 | 78 | #联系设置 79 | [contact] 80 | daili1 = "kefuweixin01" 81 | daili2 = "kefuweixin01" 82 | kefu1 = "kefuweixin01" 83 | 84 | #语音账号http://gcloud.qq.com/product/6 85 | [voice] 86 | appid = "xxx" 87 | appkey = "xxx" 88 | 89 | #广播消息 90 | [broadcast] 91 | message = ["系统消息:健康游戏,禁止沉迷", "欢迎进入游戏"] 92 | 93 | #登陆相关 94 | [login] 95 | guest = true 96 | lists = ["test"] 97 | -------------------------------------------------------------------------------- /internal/master/func.go: -------------------------------------------------------------------------------- 1 | package master 2 | 3 | import ( 4 | "github.com/ouyangzhongmin/gameserver/constants" 5 | "github.com/ouyangzhongmin/gameserver/db/model" 6 | "github.com/ouyangzhongmin/gameserver/internal/game/object" 7 | "github.com/ouyangzhongmin/gameserver/pkg/utils" 8 | "github.com/ouyangzhongmin/gameserver/protocol" 9 | ) 10 | 11 | func BroadcastSystemMessage(message string) { 12 | defaultManager.group.Broadcast("onBroadcast", &protocol.StringMessage{Message: message}) 13 | } 14 | 15 | func Kick(uid int64) error { 16 | defaultManager.chKick <- uid 17 | return nil 18 | } 19 | 20 | func Reset(uid int64) { 21 | defaultManager.chReset <- uid 22 | } 23 | 24 | func Recharge(uid, coin int64) { 25 | defaultManager.chRecharge <- RechargeInfo{uid, coin} 26 | } 27 | 28 | // 测试用的 29 | func createRandomHero(uid int64, sceneId int, name, avatar string, attrType int) *model.Hero { 30 | if name == "" { 31 | name = utils.GetRandomHeroName() 32 | } 33 | h := &model.Hero{ 34 | Name: name, 35 | Avatar: avatar, 36 | AttrType: 0, 37 | Uid: uid, 38 | Experience: 0, 39 | Level: 1, 40 | BaseLife: 100000, 41 | BaseMana: 1000, 42 | StepTime: 300, 43 | SceneId: sceneId, 44 | AttackRange: 3, 45 | } 46 | if attrType == constants.ATTR_TYPE_STRENGTH { 47 | h.BaseDefense = 5 48 | h.BaseAttack = 22 49 | h.Strength = 28 50 | h.Agility = 22 51 | h.Intelligence = 20 52 | } else if attrType == constants.ATTR_TYPE_AGILITY { 53 | h.BaseDefense = 5 54 | h.BaseAttack = 22 55 | h.Strength = 22 56 | h.Agility = 30 57 | h.Intelligence = 20 58 | } else { 59 | h.BaseDefense = 5 60 | h.BaseAttack = 22 61 | h.Strength = 18 62 | h.Agility = 18 63 | h.Intelligence = 35 64 | } 65 | h.MaxLife = object.CaculateLife(h.BaseLife, h.Strength) 66 | h.MaxMana = object.CaculateLife(h.BaseMana, h.Intelligence) 67 | h.Attack = object.CaculateAttack(h.AttrType, h.BaseAttack, h.Strength, h.Agility, h.Intelligence) 68 | h.Defense = object.CaculateDefense(h.Defense, h.Agility) 69 | return h 70 | } 71 | -------------------------------------------------------------------------------- /internal/master/master.go: -------------------------------------------------------------------------------- 1 | package master 2 | 3 | import ( 4 | "fmt" 5 | "github.com/lonng/nano" 6 | "github.com/lonng/nano/cluster/clusterpb" 7 | "github.com/lonng/nano/serialize/json" 8 | "github.com/lonng/nano/session" 9 | log "github.com/sirupsen/logrus" 10 | "github.com/spf13/viper" 11 | "strings" 12 | ) 13 | 14 | var ( 15 | logger = log.WithField("component", "master") 16 | ) 17 | 18 | // Startup 初始化master服务器 19 | func Startup() { 20 | 21 | version := viper.GetString("update.version") 22 | heartbeat := viper.GetInt("core.heartbeat") 23 | if heartbeat < 5 { 24 | heartbeat = 5 25 | } 26 | forceUpdate := viper.GetBool("update.force") 27 | // register game handler 28 | comps := Services 29 | 30 | listen := fmt.Sprintf(":%d", viper.GetInt("master.port")) 31 | logger.Infof("当前master server服务器版本: %s, 是否强制更新: %t, 当前心跳时间间隔: %d秒", version, forceUpdate, heartbeat) 32 | logger.Info("master service starup:", listen) 33 | nano.Listen(listen, 34 | nano.WithMaster(), 35 | //nano.WithPipeline(pip), 36 | nano.WithLogger(log.WithField("component", "master")), 37 | nano.WithSerializer(json.NewSerializer()), 38 | nano.WithComponents(comps), 39 | nano.WithCustomerRemoteServiceRoute(customerRemoteServiceRoute), 40 | ) 41 | } 42 | 43 | // 集群模式下,需要获取用户所在的game node调用rpc 44 | func customerRemoteServiceRoute(service string, session *session.Session, members []*clusterpb.MemberInfo) *clusterpb.MemberInfo { 45 | if strings.Contains(service, "SceneManager") { 46 | //根据用户id获取用户在哪个node上 47 | curSceneId := session.Int("sceneId") 48 | if curSceneId > 0 { 49 | for _, m := range members { 50 | label := m.Label 51 | if label != "" { 52 | label = strings.ReplaceAll(label, "scene:", "") 53 | tmpArr := strings.Split(label, ",") 54 | for _, tmp := range tmpArr { 55 | if tmp == fmt.Sprintf("%d", curSceneId) { 56 | return m 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | count := int64(len(members)) 64 | var index = session.UID() % count 65 | fmt.Printf("remote service:%s route to :%v \n", service, members[index]) 66 | return members[index] 67 | } 68 | -------------------------------------------------------------------------------- /internal/web/stats.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "github.com/lonng/nex" 5 | log "github.com/sirupsen/logrus" 6 | 7 | "time" 8 | 9 | "github.com/ouyangzhongmin/gameserver/db" 10 | "github.com/ouyangzhongmin/gameserver/protocol" 11 | 12 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 13 | ) 14 | 15 | var dayInternal = 24 * 60 * 60 16 | 17 | // 注册用户数 18 | func registerUsersHandler(query *nex.Form) (interface{}, error) { 19 | begin := query.Int64OrDefault("from", 0) 20 | end := query.Int64OrDefault("to", -1) 21 | if end < 0 { 22 | end = time.Now().Unix() 23 | } 24 | 25 | log.Infof("获取注册用户信息: begin=%s, end=%s", time.Unix(begin, 0).String(), time.Unix(end, 0).String()) 26 | c, err := db.QueryRegisterUsers(begin, end) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | return protocol.CommonResponse{ 32 | Data: c, 33 | }, nil 34 | } 35 | 36 | // 实时在线人数 37 | func onlineLiteHandler() (interface{}, error) { 38 | 39 | c, err := db.OnlineStatsLite() 40 | if err != nil { 41 | return nil, err 42 | } 43 | 44 | return protocol.CommonResponse{ 45 | Data: c, 46 | }, nil 47 | } 48 | 49 | // 某日的n日留存 50 | func retentionHandler(query *nex.Form) (interface{}, error) { 51 | from := query.IntOrDefault("from", -1) 52 | to := query.IntOrDefault("to", -1) 53 | 54 | if from < 0 || to < 0 || to < from { 55 | return nil, errutil.ErrIllegalParameter 56 | } 57 | 58 | list := []*protocol.Retention{} 59 | for i := from; i <= to; i += dayInternal { 60 | ret, err := db.RetentionList(i) 61 | if err != nil { 62 | return nil, err 63 | } 64 | list = append(list, ret) 65 | } 66 | 67 | return &protocol.RetentionResponse{Data: list}, nil 68 | 69 | } 70 | 71 | // 从指定日开始到当前的每日活跃人数 72 | func activationUsersHandler(query *nex.Form) (interface{}, error) { 73 | from := query.Int64OrDefault("from", 0) 74 | to := query.Int64OrDefault("to", 0) 75 | 76 | if to == 0 { 77 | to = time.Now().Unix() 78 | } 79 | 80 | ret, err := db.QueryActivationUser(from, to) 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | return &protocol.RetentionResponse{Data: ret}, nil 86 | 87 | } 88 | -------------------------------------------------------------------------------- /internal/game/game.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "strconv" 7 | "strings" 8 | "time" 9 | 10 | "github.com/lonng/nano" 11 | "github.com/lonng/nano/component" 12 | "github.com/lonng/nano/serialize/json" 13 | log "github.com/sirupsen/logrus" 14 | "github.com/spf13/viper" 15 | ) 16 | 17 | var ( 18 | version = "" // 游戏版本 19 | forceUpdate = false 20 | logger = log.WithField("component", "game") 21 | ) 22 | 23 | // Startup 初始化游戏服务器 24 | func Startup(scenes string) { 25 | rand.Seed(time.Now().Unix()) 26 | version = viper.GetString("update.version") 27 | 28 | heartbeat := viper.GetInt("core.heartbeat") 29 | if heartbeat < 5 { 30 | heartbeat = 5 31 | } 32 | 33 | forceUpdate = viper.GetBool("update.force") 34 | // register game handler 35 | sceneIds := parseScenes(scenes) 36 | defaultSceneManager.setSceneIds(sceneIds) 37 | comps := &component.Components{} 38 | comps.Register(defaultSceneManager) 39 | 40 | masterHost := viper.GetString("master.host") 41 | masterPort := viper.GetInt("master.port") 42 | masterAddr := fmt.Sprintf("%s:%d", masterHost, masterPort) 43 | 44 | // 加密管道 45 | //c := crypto.NewCrypto() 46 | //pip := pipeline.New() 47 | //pip.Inbound().PushBack(c.Inbound) 48 | //pip.Outbound().PushBack(c.Outbound) 49 | 50 | listen := fmt.Sprintf(":%d", viper.GetInt("game-server.port")) 51 | logger.Infof("当前游戏服务器版本: %s, 是否强制更新: %t, 当前心跳时间间隔: %d秒", version, forceUpdate, heartbeat) 52 | logger.Info("game service starup:", listen) 53 | nano.Listen(listen, 54 | nano.WithLabel("scene:"+scenes), //通过这个实现的消息对应场景服务器的处理 55 | nano.WithAdvertiseAddr(masterAddr), 56 | nano.WithDebugMode(), 57 | //nano.WithPipeline(pip), 58 | nano.WithLogger(log.WithField("component", "game")), 59 | nano.WithSerializer(json.NewSerializer()), 60 | nano.WithComponents(comps), 61 | ) 62 | } 63 | 64 | func parseScenes(scenes string) []int { 65 | sceneIds := make([]int, 0) 66 | for _, s := range strings.Split(scenes, ",") { 67 | sid, err := strconv.Atoi(s) 68 | if err != nil { 69 | panic(err) 70 | } 71 | sceneIds = append(sceneIds, sid) 72 | } 73 | return sceneIds 74 | } 75 | -------------------------------------------------------------------------------- /tools/exportmysql/main_mysql_export_go_struct.go: -------------------------------------------------------------------------------- 1 | //mysql表导出go struct工具 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | "path" 9 | "path/filepath" 10 | "runtime" 11 | 12 | "github.com/ouyangzhongmin/gameserver/pkg/mtm" 13 | ) 14 | 15 | type MysqlCnf struct { 16 | UserName string `json:"-"` 17 | Password string `json:"-"` 18 | IpAddrees string 19 | Port int 20 | DbName string 21 | } 22 | 23 | func (m *MysqlCnf) GetDsn() string { 24 | var charset = "utf8mb4" 25 | //mycat json读取报错问题:Error 1023: program err;java.lang.Index0utofBoundsException: Index: 1, Size: 1 26 | //原因是mycat prepare json处理问题,可以通过改为客户端prepare跳过mycat 预处理,方法为dsn加上:&interpolateParams=true,但是加上后写入json数据的地方要用sqlx.JSONText类型 27 | dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=Local", m.UserName, m.Password, m.IpAddrees, m.Port, m.DbName, charset) 28 | return dsn 29 | } 30 | 31 | func main() { 32 | dns := &MysqlCnf{ 33 | UserName: "root", 34 | Password: "root", 35 | IpAddrees: "172.16.2.8", 36 | Port: 3306, 37 | DbName: "jsmx", 38 | } 39 | dir := filepath.Join(GetCurrentDir(), "../../db/model") 40 | //模型转换 41 | t2s := mtm.CreateTableToStruct(&mtm.Options{ 42 | MySqlUrl: dns.GetDsn(), //数据库地址 DSN (Data Source Name) :[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN] 43 | FileName: "models.go", //文件名 当IfOneFile=true时有效 默认Models.go 44 | IfOneFile: true, //多个表是否放在同一文件 true=同一文件 默认false 45 | PackageName: "model", //自定义项目package名称 默认Models 46 | SavePath: dir, //保存文件夹 默认./Models 47 | IfToHump: true, //是否转换驼峰 true=是 默认false 48 | IfJsonTag: true, //是否包含json tag true=是 默认false 49 | IfDbTag: true, 50 | IfPluralToSingular: false, //是否复数转单数 true=是 默认false 51 | IfCapitalizeFirstLetter: true, //是否首字母转换大写 true=是 默认false 52 | }) 53 | err := t2s.Run() 54 | if err != nil { 55 | log.Fatal("模型转换:" + err.Error()) 56 | } 57 | t2s.PrintDBColumns("jsmx") 58 | } 59 | 60 | // 获取当前文件夹(此函数不建议在执行次数比较频繁地方使用,可以在启动过程或者脚本里使用) 61 | func GetCurrentDir() string { 62 | _, filename, _, _ := runtime.Caller(1) 63 | return path.Dir(filename) 64 | } 65 | -------------------------------------------------------------------------------- /protocol/users.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | type RegisterUserRequest struct { 4 | Type int `json:"type"` //注册方式: 1-手机 2-贪玩蛇 5 | Name string `json:"name"` //用户名, 可空,当非游客注册时用户名与手机号必须至少出现一项 6 | Password string `json:"password"` //MD5后的用户密码, 长度>=6 7 | VerifyID string `json:"verify_id"` //验证码ID 8 | VerifyCode string `json:"verify_code"` //验证码 9 | Phone string `json:"phone"` //手机号,可空 10 | AppID string `json:"appid"` //来自于哪一个应用的注册 11 | ChannelID string `json:"channel_id"` //来自于哪一个渠道的注册 12 | Device Device `json:"device"` //设备信息 13 | Token string `json:"token"` //Token, 游客注册并绑定时, 验证游客身份 14 | } 15 | 16 | type CheckUserInfoRequest struct { 17 | Type int `json:"type"` //注册方式: 1-手机 2-贪玩蛇 18 | Name string `json:"name"` //用户名, 可空,当非游客注册时用户名与手机号必须至少出现一项 19 | VerifyID string `json:"verify_id"` //验证码ID 20 | VerifyCode string `json:"verify_code"` //验证码 21 | Phone string `json:"phone"` //手机号,可空 22 | AppID string `json:"appid"` 23 | } 24 | 25 | type UserListRequest struct { 26 | Offset int `json:"offset"` 27 | Count int `json:"count"` 28 | } 29 | 30 | type UserListResponse struct { 31 | Code int `json:"code"` //状态码 32 | Data []UserInfo `json:"users"` //用户列表 33 | Total int `json:"total"` 34 | } 35 | 36 | type UserInfoRequest struct { 37 | UID int64 `json:"uid"` 38 | } 39 | 40 | type UserInfoResponse struct { 41 | Code int `json:"code"` //状态码 42 | Data UserInfo `json:"data"` //数据 43 | } 44 | 45 | type DeleteUserRequest struct { 46 | UID int64 `json:"uid"` 47 | } 48 | 49 | type QueryUserRequest struct { 50 | Name string `json:"name"` //用户名 51 | } 52 | 53 | //用属性查询用户 54 | type QueryUserByAttrRequest struct { 55 | Attr string `json:"attr"` //属性 56 | } 57 | 58 | //用户统计信息列表 59 | type UserStatsInfoListRequest struct { 60 | RoleTypes []uint8 `json:"role_types"` 61 | Account string `json:"account"` 62 | } 63 | 64 | type UserStatsInfoListResponse struct { 65 | Code int `json:"code"` //状态码 66 | Data []UserInfo `json:"users"` //用户列表 67 | Total int `json:"total"` 68 | } 69 | 70 | type QueryInfo struct { 71 | Name string `json:"name"` 72 | MaskedPhone string `json:"masked_phone"` 73 | } 74 | 75 | type QueryUserResponse struct { 76 | Code int `json:"code"` 77 | Data QueryInfo `json:"data"` 78 | } 79 | -------------------------------------------------------------------------------- /pkg/env/env.go: -------------------------------------------------------------------------------- 1 | package env 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strings" 7 | ) 8 | 9 | const ( 10 | ENV_PRODUCTION = "PRODUCTION" 11 | ENV_DEVELOP = "DEVELOP" 12 | ENV_TEST = "TEST" 13 | ENV_OVERSEAS = "OVERSEAS" 14 | ENV_OVERSEAS_TEST = "OVERSEAS_TEST" 15 | ENV_KEY = "ENV_GAME" 16 | ) 17 | 18 | var env = strings.TrimSpace(os.Getenv(ENV_KEY)) 19 | 20 | func init() { 21 | fmt.Println("env::::", env) 22 | LogEnv() 23 | } 24 | 25 | // 是否是开发环境 26 | func IsDevelopEnv() bool { 27 | if strings.TrimSpace(env) == "" { 28 | env = strings.TrimSpace(os.Getenv(ENV_KEY)) 29 | } 30 | return env == "" || env == ENV_DEVELOP 31 | } 32 | 33 | // 是否是测试环境 34 | func IsTestEnv() bool { 35 | return IsCNTestEnv() || IsOverseasTestEnv() 36 | } 37 | 38 | // 国内测试环境 39 | func IsCNTestEnv() bool { 40 | if strings.TrimSpace(env) == "" { 41 | env = strings.TrimSpace(os.Getenv(ENV_KEY)) 42 | } 43 | return env == ENV_TEST 44 | } 45 | 46 | // 是否是生产环境,包括国内国外 47 | func IsProductionEnv() bool { 48 | return IsCNProductionEnv() || IsOverseasEnv() 49 | } 50 | 51 | // 是否是国内生产环境 52 | func IsCNProductionEnv() bool { 53 | if strings.TrimSpace(env) == "" { 54 | env = strings.TrimSpace(os.Getenv(ENV_KEY)) 55 | } 56 | return env == ENV_PRODUCTION 57 | } 58 | 59 | // 是否是海外 60 | func IsOverseasEnv() bool { 61 | if strings.TrimSpace(env) == "" { 62 | env = strings.TrimSpace(os.Getenv(ENV_KEY)) 63 | } 64 | return env == ENV_OVERSEAS 65 | } 66 | 67 | // 是否是海外测试 68 | func IsOverseasTestEnv() bool { 69 | if strings.TrimSpace(env) == "" { 70 | env = strings.TrimSpace(os.Getenv(ENV_KEY)) 71 | } 72 | return env == ENV_OVERSEAS_TEST 73 | } 74 | 75 | // 非线上环境 76 | func IsJustTestEnv() bool { 77 | return !(IsProductionEnv() || IsOverseasEnv()) 78 | } 79 | 80 | // 指定一个环境变量值,指定后系统变更时需要重启应用才会使用新的环境变量, 81 | // 不会影响系统环境变量 82 | func SetEnv(v string) { 83 | env = v 84 | fmt.Println("指定环境变量:", env) 85 | LogEnv() 86 | } 87 | 88 | func LogEnv() { 89 | if IsCNProductionEnv() { 90 | fmt.Println("当前是国内生产环境") 91 | } else if IsOverseasEnv() { 92 | fmt.Println("当前是海外生产环境") 93 | } else if IsCNTestEnv() { 94 | fmt.Println("当前是国内TEST环境") 95 | } else if IsOverseasTestEnv() { 96 | fmt.Println("当前是海外TEST环境") 97 | } else { 98 | fmt.Println("当前是DEVELOP环境") 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /db/trade.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "github.com/ouyangzhongmin/gameserver/db/model" 5 | "github.com/ouyangzhongmin/gameserver/pkg/algoutil" 6 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 7 | ) 8 | 9 | func InsertTrade(t *model.Trade) error { 10 | logger.Info("insert trade, order id: " + t.OrderId) 11 | 12 | trade := &model.Trade{OrderId: t.OrderId} 13 | has, err := database.Get(trade) 14 | if err != nil { 15 | return err 16 | } 17 | if has { 18 | return errutil.ErrTradeExisted 19 | } 20 | order, err := QueryOrder(t.OrderId) 21 | if err != nil { 22 | return err 23 | } 24 | if order.Type == OrderTypeBuyToken { 25 | order.Status = OrderStatusNotified 26 | } else { 27 | order.Status = OrderStatusPayed 28 | } 29 | sess := database.NewSession() 30 | 31 | // 开始事务 32 | sess.Begin() 33 | defer sess.Close() 34 | if _, err := sess.Insert(t); err != nil { 35 | println(err.Error()) 36 | sess.Rollback() 37 | return err 38 | } 39 | 40 | if _, err := sess.Where("order_id = ?", order.OrderId).Update(order); err != nil { 41 | println(err.Error()) 42 | sess.Rollback() 43 | return err 44 | } 45 | 46 | u := &model.User{} 47 | sess.Where("uid = ?", order.Uid).Get(u) 48 | 49 | //添加首充时间 50 | //if u.FirstRechargeAt == 0 { 51 | // u.FirstRechargeAt = order.CreatedAt 52 | // if _, err = sess.Id(u.Id).Update(u); err != nil { 53 | // sess.Rollback() 54 | // return err 55 | // } 56 | //} 57 | 58 | return sess.Commit() 59 | } 60 | 61 | func TradeList(appid, channelID, orderID string, start, end int64, offset, count int) ([]ViewTrade, int, error) { 62 | start, end = algoutil.TimeRange(start, end) 63 | 64 | trade := &ViewTrade{ 65 | AppId: appid, 66 | ChannelId: channelID, 67 | OrderId: orderID, 68 | } 69 | total, err := database.Where("pay_at BETWEEN ? AND ?", start, end).Count(trade) 70 | if err != nil { 71 | logger.Error(err) 72 | return nil, 0, errutil.ErrDBOperation 73 | } 74 | 75 | result := make([]ViewTrade, 0) 76 | if count == noLimitFlag { 77 | err = database.Where("pay_at BETWEEN ? AND ?", start, end). 78 | Desc("id").Find(&result, trade) 79 | } else { 80 | err = database.Where("pay_at BETWEEN ? AND ?", start, end). 81 | Desc("id").Limit(count, offset).Find(&result, trade) 82 | } 83 | 84 | if err != nil { 85 | logger.Error(err) 86 | return nil, 0, errutil.ErrDBOperation 87 | } 88 | 89 | return result, int(total), nil 90 | } 91 | -------------------------------------------------------------------------------- /internal/web/static/client/spell_entity.js: -------------------------------------------------------------------------------- 1 | 2 | // Monster class definition 3 | class SpellEntity{ 4 | constructor(spellData, target, parent) { 5 | this.data = spellData 6 | this.id = this.data.id; 7 | this.target = target; 8 | this.parent = parent; 9 | this.targetX = getPixelXByGrid(this.data.target_pos.x) 10 | this.targetY = getPixelYByGrid(this.data.target_pos.y); 11 | this.speed = getSpeed(this.data.fly_step_time) 12 | this.radius = 5; 13 | this.setPos(getPixelXByGrid(this.data.pos_x),getPixelYByGrid(this.data.pos_y),0) 14 | } 15 | 16 | update(deltaTime, camera){ 17 | if (this.target){ 18 | //跟随目标 19 | this.targetX = getPixelXByGrid(this.target.x) 20 | this.targetY = getPixelYByGrid(this.target.y); 21 | } 22 | this.updateMove(deltaTime); 23 | this.screenX = this.x - camera.x; 24 | this.screenY = this.y - camera.y; 25 | 26 | } 27 | 28 | draw(ctx) { 29 | ctx.beginPath(); 30 | ctx.arc(this.screenX, this.screenY, this.radius, 0, Math.PI * 2, false); 31 | ctx.fillStyle = "black"; 32 | ctx.fill(); 33 | // ���Ʊ߿� 34 | ctx.lineWidth = 1; 35 | ctx.strokeStyle = 'black'; 36 | ctx.stroke(); 37 | } 38 | 39 | updateMove(deltaTime){ 40 | const tempTargetX = this.targetX; 41 | const tempTargetY = this.targetY; 42 | const tempDist = getDistance(this.x , this.y , tempTargetX , tempTargetY); 43 | const tempAngle = getAngle(this.x , this.y , tempTargetX , tempTargetY); 44 | const tempActualSpeed = this.speed * deltaTime; 45 | if(tempDist <= Math.floor(tempActualSpeed + 0.5)) { 46 | this.setPos(tempTargetX, tempTargetY, 0) 47 | this.destroy() 48 | }else 49 | { 50 | this.speedX = cosD(tempAngle) * tempActualSpeed; 51 | this.speedY = sinD(tempAngle) * tempActualSpeed; 52 | this.setPos(this.x +this.speedX, this.y + this.speedY , 0) 53 | } 54 | } 55 | 56 | setPos(x,y,z){ 57 | // console.log(this.name, "setPos::", x, y , z) 58 | this.x = x; 59 | this.y = y; 60 | this.z = z; 61 | } 62 | 63 | destroy(){ 64 | if (this.parent){ 65 | this.parent.removeSpell(this.data.id) 66 | this.parent = null 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /db/common.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type Option func(setting *Setting) 9 | type Closer func() 10 | 11 | type Setting struct { 12 | ShowSQL bool 13 | MaxOpenConns int 14 | MaxIdleConns int 15 | } 16 | 17 | func MaxIdleConnOption(i int) Option { 18 | return func(s *Setting) { 19 | s.MaxIdleConns = i 20 | } 21 | } 22 | 23 | func MaxOpenConnOption(i int) Option { 24 | return func(s *Setting) { 25 | s.MaxOpenConns = i 26 | } 27 | } 28 | 29 | func ShowSQLOption(show bool) Option { 30 | return func(s *Setting) { 31 | s.ShowSQL = show 32 | } 33 | } 34 | 35 | // Build data source name 36 | func BuildDSN(host string, port int, username, password, dbname, args string) string { 37 | return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?%s", username, password, host, port, dbname, args) 38 | } 39 | 40 | //// 根据一个大区信息, 返回大区的SQL条件语句 41 | //// 例如: area: {AreaID: 100, ServerIDs: []int{1, 2, 3, 5}} 42 | //// 返回: (`area_id`=100 AND `server_id` IN(1,2,3,5)) 43 | //func AreaCondition(area *protocol.Area) string { 44 | // if len(area.ServerIDs) > 0 { 45 | // servers := []string{} 46 | // for _, id := range area.ServerIDs { 47 | // servers = append(servers, strconv.Itoa(id)) 48 | // } 49 | // return fmt.Sprintf("(`area_id`=%d AND `server_id` IN(%s))", area.AreaID, strings.Join(servers, ",")) 50 | // } else { 51 | // return fmt.Sprintf("`area_id`=%d", area.AreaID) 52 | // } 53 | //} 54 | // 55 | //func AreaVectorCondition(areas []*protocol.Area) string { 56 | // conditions := []string{} 57 | // for _, area := range areas { 58 | // conditions = append(conditions, AreaCondition(area)) 59 | // } 60 | // return fmt.Sprintf("(%s)", strings.Join(conditions, " OR ")) 61 | //} 62 | 63 | // 给定列, 返回起始时间条件SQL语句, [begin, end) 64 | func RangeCondition(column string, begin, end int64) string { 65 | return fmt.Sprintf("(`%s` BETWEEN %d AND %d)", column, begin, end) 66 | } 67 | 68 | func ChannelCondition(c []string) string { 69 | return fmt.Sprintf("`channel` IN('%s')", strings.Join(c, "','")) 70 | } 71 | 72 | func EqIntCondition(col string, v int) string { 73 | return fmt.Sprintf("`%s`=%d", col, v) 74 | } 75 | 76 | func EqInt64Condition(col string, v int64) string { 77 | return fmt.Sprintf("`%s`=%d", col, v) 78 | } 79 | 80 | func LtInt64Condition(col string, v int64) string { 81 | return fmt.Sprintf("`%s`<%d", col, v) 82 | } 83 | 84 | func Combined(cond ...string) string { 85 | return strings.Join(cond, " AND ") 86 | } 87 | 88 | func Insert(bean interface{}) error { 89 | _, err := database.Insert(bean) 90 | return err 91 | } 92 | -------------------------------------------------------------------------------- /internal/web/static/client/httpclient.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * // 使用示例 5 | * const apiClient = new HttpClient('https://api.example.com'); 6 | * 7 | * // 发起GET请求 8 | * apiClient.get('/users') 9 | * .then(data => console.log(data)) 10 | * .catch(error => console.error('Error fetching users:', error)); 11 | * 12 | * // 发起POST请求 13 | * apiClient.post('/users', { name: 'John Doe', age: 30 }) 14 | * .then(data => console.log(data)) 15 | * .catch(error => console.error('Error creating user:', error)); 16 | */ 17 | class HttpClient { 18 | constructor(baseUrl = '') { 19 | this.baseUrl = baseUrl; 20 | } 21 | 22 | async get(endpoint, params = {}) { 23 | const queryString = this._buildQueryString(params); 24 | const url = `${this.baseUrl}${endpoint}${queryString ? '?' + queryString : ''}`; 25 | const response = await fetch(url); 26 | return this._handleResponse(response); 27 | } 28 | 29 | async post(endpoint, data = {}) { 30 | const url = `${this.baseUrl}${endpoint}`; 31 | const response = await fetch(url, { 32 | method: 'POST', 33 | headers: { 34 | 'Content-Type': 'application/json' 35 | }, 36 | body: JSON.stringify(data) 37 | }); 38 | return this._handleResponse(response); 39 | } 40 | 41 | // 可以根据需要添加其他HTTP方法,如put, delete等 42 | 43 | _buildQueryString(params) { 44 | return Object.keys(params) 45 | .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`) 46 | .join('&'); 47 | } 48 | 49 | async _handleResponse(response) { 50 | if (!response.ok) { 51 | throw new Error(`HTTP error! status: ${response.status}`); 52 | } 53 | const data = await response.json(); 54 | return data; 55 | } 56 | 57 | async fetchFileAsByteArray(url) { 58 | try { 59 | // ʹ�� fetch API ��ȡ�ļ����� 60 | const response = await fetch(url); 61 | 62 | // �����Ӧ�Ƿ�ɹ� 63 | if (!response.ok) { 64 | throw new Error(`Failed to fetch file: ${response.statusText}`); 65 | } 66 | 67 | // ʹ�� ArrayBuffer �� Uint8Array ����ȡ�ֽ����� 68 | const arrayBuffer = await response.arrayBuffer(); 69 | const byteArray = new Uint8Array(arrayBuffer); 70 | 71 | // �����ֽ����� 72 | return byteArray; 73 | } catch (error) { 74 | console.error('Error fetching and parsing file:', error); 75 | } 76 | } 77 | } 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /pkg/astar/astar_test.go: -------------------------------------------------------------------------------- 1 | package astar 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | var grids [][]int32 9 | 10 | func init() { 11 | grids = [][]int32{ 12 | {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 13 | {1, 1, 0, 2, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 14 | {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 15 | {0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 16 | {0, 2, 1, 2, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 17 | {0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 18 | {2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 19 | {0, 0, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 20 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 21 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 22 | {0, 0, 0, 1, 2, 1, 0, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 23 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 24 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 25 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 26 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 27 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 28 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 29 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 30 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 31 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 32 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 33 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 34 | {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, 35 | } 36 | } 37 | 38 | func Test_FindPath(t *testing.T) { 39 | fmt.Println("----init:", len(grids[0]), len(grids), NODE_OPEN, NODE_BARRIER, NODE_NO_PASS) 40 | astar := NewAstar(grids) 41 | path, block, turn, err := astar.FindPath([]int32{3, 2}, []int32{5, 3}) 42 | if err != nil { 43 | t.Fatal(err) 44 | } 45 | fmt.Println(path, block, turn) 46 | } 47 | 48 | func Test_FindPathIgnoreBlock(t *testing.T) { 49 | astar := NewAstar(grids) 50 | path, block, turn, err := astar.FindPathIgnoreBlock([]int32{3, 2}, [][]int32{{5, 3}}) 51 | if err != nil { 52 | t.Fatal(err) 53 | } 54 | fmt.Println(path, block, turn) 55 | } 56 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ouyangzhongmin/gameserver 2 | 3 | go 1.20 4 | 5 | replace ( 6 | golang.org/x/crypto => github.com/golang/crypto v0.0.0-20181001203147-e3636079e1a4 7 | golang.org/x/net => github.com/golang/net v0.0.0-20180926154720-4dfa2610cdf3 8 | golang.org/x/sys => github.com/golang/sys v0.0.0-20180928133829-e4b3c5e90611 9 | golang.org/x/text => github.com/golang/text v0.3.0 10 | ) 11 | 12 | require ( 13 | github.com/DanPlayer/randomname v1.0.1 14 | github.com/go-sql-driver/mysql v1.4.0 15 | github.com/go-xorm/core v0.6.0 16 | github.com/go-xorm/xorm v0.7.0 17 | github.com/google/gops v0.3.28 18 | github.com/google/uuid v1.2.0 19 | github.com/gorilla/mux v1.6.2 20 | github.com/lonng/nano v0.5.1 21 | github.com/lonng/nex v1.4.1 22 | github.com/pborman/uuid v1.2.0 23 | github.com/sirupsen/logrus v1.6.0 24 | github.com/spf13/viper v1.2.1 25 | github.com/urfave/cli v1.22.5 26 | github.com/xxtea/xxtea-go v0.0.0-20170828040851-35c4b17eecf6 27 | golang.org/x/crypto v0.23.0 28 | golang.org/x/net v0.25.0 29 | golang.org/x/text v0.15.0 30 | gopkg.in/chanxuehong/wechat.v2 v2.0.0-20180924084534-7e0579cb5377 31 | ) 32 | 33 | require ( 34 | github.com/bwmarrin/snowflake v0.3.0 // indirect 35 | github.com/chanxuehong/rand v0.0.0-20180830053958-4b3aff17f488 // indirect 36 | github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect 37 | github.com/denisenkom/go-mssqldb v0.12.3 // indirect 38 | github.com/fsnotify/fsnotify v1.4.7 // indirect 39 | github.com/go-xorm/builder v0.0.0-20180322150003-a9b7ffcca3f0 // indirect 40 | github.com/golang/protobuf v1.5.2 // indirect 41 | github.com/gorilla/context v1.1.2 // indirect 42 | github.com/gorilla/websocket v1.4.2 // indirect 43 | github.com/hashicorp/hcl v1.0.0 // indirect 44 | github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect 45 | github.com/lib/pq v1.10.9 // indirect 46 | github.com/magiconair/properties v1.8.0 // indirect 47 | github.com/mattn/go-sqlite3 v1.14.24 // indirect 48 | github.com/mitchellh/mapstructure v1.0.0 // indirect 49 | github.com/pelletier/go-toml v1.2.0 // indirect 50 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 51 | github.com/spf13/afero v1.1.2 // indirect 52 | github.com/spf13/cast v1.2.0 // indirect 53 | github.com/spf13/jwalterweatherman v1.0.0 // indirect 54 | github.com/spf13/pflag v1.0.5 // indirect 55 | github.com/stretchr/testify v1.9.0 // indirect 56 | github.com/ziutek/mymysql v1.5.4 // indirect 57 | golang.org/x/sys v0.20.0 // indirect 58 | google.golang.org/appengine v1.5.0 // indirect 59 | google.golang.org/genproto v0.0.0-20210630183607-d20f26d13c79 // indirect 60 | google.golang.org/grpc v1.39.0 // indirect 61 | google.golang.org/protobuf v1.34.1 // indirect 62 | gopkg.in/yaml.v2 v2.4.0 // indirect 63 | ) 64 | -------------------------------------------------------------------------------- /internal/gate/gate.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | import ( 4 | "fmt" 5 | "github.com/lonng/nano" 6 | "github.com/lonng/nano/cluster/clusterpb" 7 | "github.com/lonng/nano/serialize/json" 8 | "github.com/lonng/nano/session" 9 | log "github.com/sirupsen/logrus" 10 | "github.com/spf13/viper" 11 | "net/http" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | var ( 17 | logger = log.WithField("component", "gate") 18 | ) 19 | 20 | // Startup 初始化gate服务器 21 | func Startup() { 22 | 23 | version := viper.GetString("update.version") 24 | heartbeat := viper.GetInt("core.heartbeat") 25 | if heartbeat < 5 { 26 | heartbeat = 5 27 | } 28 | forceUpdate := viper.GetBool("update.force") 29 | // register game handler 30 | comps := Services 31 | 32 | // 加密管道 33 | //c := crypto.NewCrypto() 34 | //pip := pipeline.New() 35 | //pip.Inbound().PushBack(c.Inbound) 36 | //pip.Outbound().PushBack(c.Outbound) 37 | masterHost := viper.GetString("master.host") 38 | masterPort := viper.GetInt("master.port") 39 | masterAddr := fmt.Sprintf("%s:%d", masterHost, masterPort) 40 | gateAddress := viper.GetString("gate.gate-address") 41 | 42 | listen := fmt.Sprintf(":%d", viper.GetInt("gate.port")) 43 | logger.Infof("当前gate server服务器版本: %s, 是否强制更新: %t, 当前心跳时间间隔: %d秒", version, forceUpdate, heartbeat) 44 | logger.Info("gate service starup: ", listen, ",,,gateAddress: ", gateAddress) 45 | nano.Listen(listen, 46 | nano.WithAdvertiseAddr(masterAddr), 47 | nano.WithClientAddr(gateAddress), 48 | nano.WithIsWebsocket(true), 49 | nano.WithCheckOriginFunc(func(_ *http.Request) bool { return true }), 50 | //nano.WithPipeline(pip), 51 | nano.WithHeartbeatInterval(time.Duration(heartbeat)*time.Second), 52 | nano.WithLogger(log.WithField("component", "gate")), 53 | nano.WithSerializer(json.NewSerializer()), 54 | nano.WithComponents(comps), 55 | nano.WithCustomerRemoteServiceRoute(customerRemoteServiceRoute), 56 | ) 57 | } 58 | 59 | // 集群模式下,需要获取用户所在的game node调用rpc 60 | func customerRemoteServiceRoute(service string, session *session.Session, members []*clusterpb.MemberInfo) *clusterpb.MemberInfo { 61 | if strings.Contains(service, "SceneManager") { 62 | //根据用户id获取用户在哪个node上 63 | curSceneId := session.Int("sceneId") 64 | if curSceneId > 0 { 65 | for _, m := range members { 66 | label := m.Label 67 | if label != "" { 68 | label = strings.ReplaceAll(label, "scene:", "") 69 | tmpArr := strings.Split(label, ",") 70 | for _, tmp := range tmpArr { 71 | if tmp == fmt.Sprintf("%d", curSceneId) { 72 | return m 73 | } 74 | } 75 | } 76 | } 77 | } 78 | } 79 | count := int64(len(members)) 80 | var index = session.UID() % count 81 | fmt.Printf("remote service:%s route to :%v \n", service, members[index]) 82 | return members[index] 83 | } 84 | -------------------------------------------------------------------------------- /internal/web/static/client/javascript-astar/README.md: -------------------------------------------------------------------------------- 1 | # javascript-astar 2 | 3 | ## An implementation of the A* Search Algorithm in JavaScript 4 | 5 | See a demo at http://www.briangrinstead.com/files/astar/ 6 | 7 | ## Sample Usage 8 | 9 | If you want just the A* search code (not the demo visualization), use code like this http://gist.github.com/581352 10 | ```js 11 | 12 | 42 | ``` 43 | A few notes about weight values: 44 | 45 | 1. A weight of 0 denotes a wall. 46 | 2. A weight cannot be negative. 47 | 3. A weight cannot be between 0 and 1 (exclusive). 48 | 4. A weight can contain decimal values (greater than 1). 49 | 50 | ### Original (slower) implementation 51 | 52 | The original version of the algorithm used a list, and was a bit clearer but much slower. It was based off the [original blog post](http://www.briangrinstead.com/blog/astar-search-algorithm-in-javascript). The code is available at: https://github.com/bgrins/javascript-astar/tree/0.0.1/original-implementation. 53 | 54 | The newest version of the algorithm using a Binary Heap. It is quite faster than the original. 55 | http://www.briangrinstead.com/blog/astar-search-algorithm-in-javascript-updated 56 | Binary Heap taken from http://eloquentjavascript.net/appendix2.html (license: http://creativecommons.org/licenses/by/3.0/) 57 | 58 | 59 | ## Running the test suite 60 | 61 | [![Build Status](https://travis-ci.org/bgrins/javascript-astar.png?branch=master)](https://travis-ci.org/bgrins/javascript-astar) 62 | 63 | If you don't have grunt installed, follow the [grunt getting started guide](http://gruntjs.com/getting-started) first. 64 | 65 | Pull down the project, then run: 66 | 67 | npm install 68 | grunt 69 | -------------------------------------------------------------------------------- /pkg/algoutil/params.go: -------------------------------------------------------------------------------- 1 | package algoutil 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "net/url" 8 | "sort" 9 | "strings" 10 | 11 | "github.com/ouyangzhongmin/gameserver/pkg/errutil" 12 | ) 13 | 14 | const ( 15 | argSep = "&" 16 | kvSep = "=" 17 | ) 18 | 19 | func ParseParams(params string) map[string]string { 20 | m := map[string]string{} 21 | parts := strings.Split(params, argSep) 22 | for _, arg := range parts { 23 | // strings.Split(s, "=") will cause error when signature has 24 | // padding(that is something like "==") 25 | i := strings.IndexAny(arg, kvSep) 26 | if i < 0 { 27 | continue 28 | } 29 | k := arg[:i] 30 | v := arg[i+1:] 31 | m[k] = v 32 | } 33 | return m 34 | } 35 | 36 | // TODO: WARNING!!!!!!! 37 | // All struct field must be string type 38 | func ParamsToStruct(params string, v interface{}) error { 39 | if params == "" || len(strings.TrimSpace(params)) < 1 { 40 | return errutil.ErrIllegalParameter 41 | } 42 | m := ParseParams(params) 43 | bytes, err := json.Marshal(m) 44 | if err != nil { 45 | return err 46 | } 47 | return json.Unmarshal(bytes, v) 48 | } 49 | 50 | func SortParams(m map[string]string) string { 51 | if len(m) == 0 { 52 | return "" 53 | } 54 | var ( 55 | i = 0 56 | keys = make([]string, len(m)) 57 | buf = &bytes.Buffer{} 58 | ) 59 | for k := range m { 60 | keys[i] = k 61 | i++ 62 | } 63 | sort.Strings(keys) 64 | 65 | for _, k := range keys { 66 | buf.WriteString(k) 67 | buf.WriteString("=") 68 | buf.WriteString(m[k]) 69 | buf.WriteString("&") 70 | } 71 | buf.Truncate(buf.Len() - 1) 72 | return buf.String() 73 | } 74 | 75 | func ConcatWithURLEncode(params map[string]string) *bytes.Buffer { 76 | if params == nil || len(params) == 0 { 77 | return nil 78 | } 79 | 80 | buf := &bytes.Buffer{} 81 | for k, v := range params { 82 | buf.WriteString(k) 83 | buf.WriteString("=") 84 | buf.WriteString(url.QueryEscape(v)) 85 | buf.WriteString("&") 86 | } 87 | 88 | buf.Truncate(buf.Len() - 1) 89 | 90 | return buf 91 | } 92 | 93 | // SortAndConcat sort the map by key in ASCII order, 94 | // and concat it in form of "k1=v1&k2=v2" 95 | func SortAndConcat(params map[string]string, extras ...bool) []byte { 96 | if params == nil || len(params) == 0 { 97 | return nil 98 | } 99 | 100 | var trimSpace bool = true 101 | if len(extras) > 0 { 102 | trimSpace = extras[0] 103 | } 104 | 105 | keys := make([]string, len(params)) 106 | i := 0 107 | for k := range params { 108 | keys[i] = k 109 | i++ 110 | } 111 | sort.Strings(keys) 112 | buf := &bytes.Buffer{} 113 | for _, k := range keys { 114 | if trimSpace && params[k] == "" { 115 | continue 116 | } 117 | buf.WriteString(fmt.Sprintf("%s=%s&", k, params[k])) 118 | 119 | } 120 | buf.Truncate(buf.Len() - 1) 121 | return buf.Bytes() 122 | } 123 | -------------------------------------------------------------------------------- /cmd/gate/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/ouyangzhongmin/gameserver/db" 6 | "github.com/ouyangzhongmin/gameserver/internal/gate" 7 | "github.com/ouyangzhongmin/gameserver/pkg/env" 8 | "github.com/ouyangzhongmin/gameserver/pkg/fileutil" 9 | "os" 10 | "path" 11 | "path/filepath" 12 | "runtime" 13 | "runtime/pprof" 14 | "strings" 15 | "sync" 16 | "time" 17 | 18 | _ "github.com/go-sql-driver/mysql" 19 | log "github.com/sirupsen/logrus" 20 | "github.com/spf13/viper" 21 | "github.com/urfave/cli" 22 | ) 23 | 24 | func main() { 25 | app := cli.NewApp() 26 | 27 | // base application info 28 | app.Name = "gate server" 29 | app.Author = "Oyzm" 30 | app.Version = "0.0.1" 31 | app.Copyright = "oyzm team reserved" 32 | app.Usage = "gate server" 33 | 34 | // flags 35 | app.Flags = []cli.Flag{ 36 | cli.StringFlag{ 37 | Name: "config, c", 38 | Value: "", 39 | Usage: "load configuration from `FILE`", 40 | }, 41 | cli.BoolFlag{ 42 | Name: "cpuprofile", 43 | Usage: "enable cpu profile", 44 | }, 45 | } 46 | 47 | app.Action = serve 48 | app.Run(os.Args) 49 | } 50 | 51 | func serve(c *cli.Context) error { 52 | cfgpth := c.String("config") 53 | appPath, err := filepath.Abs(filepath.Dir(os.Args[0])) 54 | if err != nil { 55 | panic(err) 56 | } 57 | workPath, err := os.Getwd() 58 | if err != nil { 59 | panic(err) 60 | } 61 | 62 | if strings.TrimSpace(cfgpth) == "" { 63 | if !env.IsDevelopEnv() { 64 | panic("需要指定配置文件路径....") 65 | } 66 | tomlName := "configs/config.toml" 67 | cfgpth = filepath.Join(appPath, tomlName) 68 | if !fileutil.FileExists(cfgpth) { 69 | cfgpth = filepath.Join(workPath, tomlName) 70 | if !fileutil.FileExists(cfgpth) { 71 | cfgpth = filepath.Join(getCurrentPath(), tomlName) 72 | } 73 | } 74 | log.Println("使用工程配置:", cfgpth) 75 | } else { 76 | log.Println("使用指定配置:", cfgpth) 77 | } 78 | if !fileutil.FileExists(cfgpth) { 79 | panic(fmt.Sprintf("%s配置不存在", cfgpth)) 80 | } 81 | viper.SetConfigType("toml") 82 | viper.SetConfigFile(cfgpth) 83 | viper.ReadInConfig() 84 | 85 | log.SetFormatter(&log.TextFormatter{DisableColors: true}) 86 | if viper.GetBool("core.debug") { 87 | log.SetLevel(log.DebugLevel) 88 | } 89 | 90 | if c.Bool("cpuprofile") { 91 | filename := fmt.Sprintf("cpuprofile-%d.pprof", time.Now().Unix()) 92 | f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, os.ModePerm) 93 | if err != nil { 94 | panic(err) 95 | } 96 | pprof.StartCPUProfile(f) 97 | defer pprof.StopCPUProfile() 98 | } 99 | 100 | wg := sync.WaitGroup{} 101 | wg.Add(1) 102 | go func() { 103 | defer wg.Done() 104 | // setup database 105 | closer := db.Startup() 106 | defer closer() 107 | gate.Startup() 108 | }() // 开启gate 109 | 110 | wg.Wait() 111 | return nil 112 | } 113 | 114 | func getCurrentPath() string { 115 | _, filename, _, _ := runtime.Caller(1) 116 | return path.Dir(filename) 117 | } 118 | -------------------------------------------------------------------------------- /cmd/master/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/ouyangzhongmin/gameserver/db" 6 | "github.com/ouyangzhongmin/gameserver/internal/master" 7 | "github.com/ouyangzhongmin/gameserver/pkg/env" 8 | "github.com/ouyangzhongmin/gameserver/pkg/fileutil" 9 | "os" 10 | "path" 11 | "path/filepath" 12 | "runtime" 13 | "runtime/pprof" 14 | "strings" 15 | "sync" 16 | "time" 17 | 18 | _ "github.com/go-sql-driver/mysql" 19 | log "github.com/sirupsen/logrus" 20 | "github.com/spf13/viper" 21 | "github.com/urfave/cli" 22 | ) 23 | 24 | func main() { 25 | app := cli.NewApp() 26 | 27 | // base application info 28 | app.Name = "master server" 29 | app.Author = "Oyzm" 30 | app.Version = "0.0.1" 31 | app.Copyright = "oyzm team reserved" 32 | app.Usage = "master server" 33 | 34 | // flags 35 | app.Flags = []cli.Flag{ 36 | cli.StringFlag{ 37 | Name: "config, c", 38 | Value: "", 39 | Usage: "load configuration from `FILE`", 40 | }, 41 | cli.BoolFlag{ 42 | Name: "cpuprofile", 43 | Usage: "enable cpu profile", 44 | }, 45 | } 46 | 47 | app.Action = serve 48 | app.Run(os.Args) 49 | } 50 | 51 | func serve(c *cli.Context) error { 52 | cfgpth := c.String("config") 53 | appPath, err := filepath.Abs(filepath.Dir(os.Args[0])) 54 | if err != nil { 55 | panic(err) 56 | } 57 | workPath, err := os.Getwd() 58 | if err != nil { 59 | panic(err) 60 | } 61 | 62 | if strings.TrimSpace(cfgpth) == "" { 63 | if !env.IsDevelopEnv() { 64 | panic("需要指定配置文件路径....") 65 | } 66 | tomlName := "configs/config.toml" 67 | cfgpth = filepath.Join(appPath, tomlName) 68 | if !fileutil.FileExists(cfgpth) { 69 | cfgpth = filepath.Join(workPath, tomlName) 70 | if !fileutil.FileExists(cfgpth) { 71 | cfgpth = filepath.Join(getCurrentPath(), tomlName) 72 | } 73 | } 74 | log.Println("使用工程配置:", cfgpth) 75 | } else { 76 | log.Println("使用指定配置:", cfgpth) 77 | } 78 | if !fileutil.FileExists(cfgpth) { 79 | panic(fmt.Sprintf("%s配置不存在", cfgpth)) 80 | } 81 | viper.SetConfigType("toml") 82 | viper.SetConfigFile(cfgpth) 83 | viper.ReadInConfig() 84 | 85 | log.SetFormatter(&log.TextFormatter{DisableColors: true}) 86 | if viper.GetBool("core.debug") { 87 | log.SetLevel(log.DebugLevel) 88 | } 89 | 90 | if c.Bool("cpuprofile") { 91 | filename := fmt.Sprintf("cpuprofile-%d.pprof", time.Now().Unix()) 92 | f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, os.ModePerm) 93 | if err != nil { 94 | panic(err) 95 | } 96 | pprof.StartCPUProfile(f) 97 | defer pprof.StopCPUProfile() 98 | } 99 | 100 | wg := sync.WaitGroup{} 101 | wg.Add(1) 102 | go func() { 103 | defer wg.Done() 104 | // setup database 105 | closer := db.Startup() 106 | defer closer() 107 | master.Startup() 108 | }() // 开启master 109 | 110 | wg.Wait() 111 | return nil 112 | } 113 | 114 | func getCurrentPath() string { 115 | _, filename, _, _ := runtime.Caller(1) 116 | return path.Dir(filename) 117 | } 118 | --------------------------------------------------------------------------------