source-server
This commit is contained in:
parent
a00b9a88eb
commit
9ead72db4a
22
source-server/.gitattributes
vendored
Normal file
22
source-server/.gitattributes
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
### default behavior
|
||||
* text=auto eol=lf
|
||||
## note: eol in text auto is fixed since git 2.10 (31 aug 2016)
|
||||
|
||||
### windows (always crlf)
|
||||
*.bat eol=crlf
|
||||
*.sln eol=crlf
|
||||
*.filters eol=crlf
|
||||
*.users eol=crlf
|
||||
*.vcxproj eol=crlf
|
||||
*.vssscc eol=crlf
|
||||
|
||||
### unix (always lf)
|
||||
*.sh eol=lf
|
||||
*.bash eol=lf
|
||||
*.py eol=lf
|
||||
|
||||
### binaries
|
||||
*.suo binary
|
||||
|
||||
### others
|
||||
*.txt eol=crlf
|
||||
69
source-server/.gitignore
vendored
Normal file
69
source-server/.gitignore
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
Extern
|
||||
__test
|
||||
__trash
|
||||
|
||||
.vs
|
||||
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
#+easy with .suo
|
||||
#*.suo
|
||||
|
||||
*.bsc
|
||||
*.exe
|
||||
*.ilk
|
||||
*.map
|
||||
*.pdb
|
||||
*.idb
|
||||
|
||||
obj
|
||||
ipch
|
||||
Debug
|
||||
Release
|
||||
MfcRelease
|
||||
*___Win32_MfcRelease
|
||||
MfcDebug
|
||||
*___Win32_MfcDebug
|
||||
Distribute
|
||||
|
||||
bin
|
||||
|
||||
OBJDIR
|
||||
.obj
|
||||
|
||||
Depend
|
||||
Depend.bak
|
||||
|
||||
*.a
|
||||
*.dll
|
||||
*.lib
|
||||
*.o
|
||||
*.so
|
||||
*.iobj
|
||||
*.ipdb
|
||||
|
||||
db_r*
|
||||
game_r*
|
||||
|
||||
db_symlink
|
||||
game_symlink
|
||||
|
||||
pre_qc
|
||||
*.pyc
|
||||
|
||||
*.bak
|
||||
/.project
|
||||
|
||||
### archives
|
||||
*.rar
|
||||
*.7z
|
||||
*.zip
|
||||
!server-Extern.zip
|
||||
*.gz
|
||||
*.bz
|
||||
*.xz
|
||||
*.tar
|
||||
*.tgz
|
||||
*.tbz
|
||||
*.txz
|
||||
448
source-server/README-SERVER.txt
Normal file
448
source-server/README-SERVER.txt
Normal file
@ -0,0 +1,448 @@
|
||||
# README #
|
||||
|
||||
### What is this repository for? ###
|
||||
|
||||
* Quick summary
|
||||
* Version
|
||||
* [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
|
||||
####
|
||||
# git config --global http.sslVerify false
|
||||
# git config --global credential.helper "cache --timeout=3600"
|
||||
###
|
||||
# git add -A
|
||||
# git commit -m "base added"
|
||||
### or
|
||||
# git commit -am "files updated"
|
||||
###
|
||||
# git push
|
||||
###
|
||||
# git pull
|
||||
####
|
||||
|
||||
### How do I get set up? ###
|
||||
|
||||
* Summary of set up
|
||||
// mysql dep
|
||||
# cd /usr/ports/databases/mysql56-client
|
||||
# make WITH_XCHARSET=all install clean
|
||||
## OR
|
||||
# pkg install mysql56-client
|
||||
|
||||
// extern extract
|
||||
# cd ./Srcs
|
||||
# tar -xzf Extern.tgz
|
||||
|
||||
// cryptopp dep
|
||||
# cd ./Srcs/Extern/cryptopp
|
||||
# gmake libcryptopp.a -j4
|
||||
|
||||
//how to compile all-the-server (db+game+dep)
|
||||
# cd ./Srcs/Server
|
||||
# gmake all -j4
|
||||
|
||||
//how to compile just game (not necessary)
|
||||
# cd ./Srcs/Server/game/src
|
||||
# gmake -j4
|
||||
|
||||
//how to compile just db (not necessary)
|
||||
# cd ./Srcs/Server/db/src
|
||||
# gmake -j4
|
||||
|
||||
* Configuration
|
||||
@#GENERAL MACROS
|
||||
#define __OBSOLETE__ //useless and pointless code removed
|
||||
#define __UNIMPLEMENTED__ //drafts of new things to be implemented
|
||||
|
||||
@/Src/Server/common/CommonDefines.h
|
||||
>>default
|
||||
#define _IMPROVED_PACKET_ENCRYPTION_ //enable cryptopp mixed encryption for client<>server comunication
|
||||
#define USE_IMPROVED_PACKET_DECRYPTED_BUFFER //enable a buffer for decrypting incoming packets sent at different times (for IMPROVED_PACKET_ENCRYPTION only)
|
||||
#define __UDP_BLOCK__
|
||||
#define ENABLE_QUEST_CATEGORY //enable quest category+new packet types (unimplemented)
|
||||
>>systems
|
||||
#define ENABLE_D_NJGUILD //enable d.new_jump_all_guild+cpp relative functions (untested)
|
||||
#define ENABLE_NEWSTUFF //enable new stuff (new lua funcs, new CONFIG options, ecc)
|
||||
#define ENABLE_FULL_NOTICE //enable new big notice features
|
||||
#define ENABLE_PORT_SECURITY // block db_port, p2p_port, and remote adminpage exploits
|
||||
#define ENABLE_BELT_INVENTORY_EX // move the belt items into the BELT_INVENTORY window and prevents unknown belt positions if you de/increase wear/inventory slots
|
||||
#define ENABLE_CMD_WARP_IN_DUNGEON // /warp <player> will warp successfully even if the player is inside a dungeon (be sure a .quest login event won't still warp you out)
|
||||
#define ENABLE_USE_COSTUME_ATTR // enable the items reset costume and enchant costume
|
||||
#define ENABLE_ITEM_ATTR_COSTUME // enable costume_hair, costume_body, costume_weapon item_attr/_rare parts
|
||||
#define ENABLE_SEQUENCE_SYSTEM // enable sequence system
|
||||
#define MAP_ALLOW_LIMIT <int> // define how many maps are allowed per game core (default 32)
|
||||
#define ENABLE_PLAYER_PER_ACCOUNT5 // enable 5 characters (per account) in the select phase (instead of 4)
|
||||
#define ENABLE_DICE_SYSTEM // enable dice system: if the mob is king or boss and you're in party, the dropped item is randomly rolled
|
||||
#define ENABLE_EXTEND_INVEN_SYSTEM //enable 4 inventory pages
|
||||
#define ENABLE_MOUNT_COSTUME_SYSTEM // enable mount costume slot
|
||||
#define ENABLE_WEAPON_COSTUME_SYSTEM //enable weapon costume slot
|
||||
#define ENABLE_PET_SYSTEM_EX // enable item pet without quest [@warme666]
|
||||
#define ENABLE_SKILL_FLAG_PARTY //enable skill flag party (separated from lycan define)
|
||||
#define ENABLE_NO_DSS_QUALIFICATION //disable dragon soul qualification [@warme666]
|
||||
#define ENABLE_NO_SELL_PRICE_DIVIDED_BY_5 // disable dividing the sell price by 5 [@warme666]
|
||||
#define ENABLE_CHECK_SELL_PRICE // it checks if the sell price is higher than the buy price; if yes, sell price will be equal to the buy price
|
||||
#define ENABLE_GOTO_LAG_FIX // it force-clears the entities when switching sectree
|
||||
#define ENABLE_MOUNT_COSTUME_EX_SYSTEM //mount load via item_proto with APPLY_MOUNT (118) bonus like official
|
||||
#define ENABLE_PENDANT_SYSTEM // pendant equip implementation
|
||||
#define ENABLE_GLOVE_SYSTEM // glove equip implementation
|
||||
#define ENABLE_MOVE_CHANNEL // enable channel switch
|
||||
#define ENABLE_REDUCED_ENTITY_VIEW // it reduces the complexity of the entity view
|
||||
>>lycan
|
||||
#define ENABLE_WOLFMAN_CHARACTER // enable wolfman character and the relative new features (claws, bleeding and so on) [@warme666]
|
||||
#define DISABLE_WOLFMAN_ON_CREATE // disable wolfman on create phase [@warme666]
|
||||
#define USE_MOB_BLEEDING_AS_POISON // if enabled, the mob_proto structure won't change and the bleeding % will be get from the poison field
|
||||
#define USE_MOB_CLAW_AS_DAGGER // if enabled, the mob_proto structure won't change and the claw % will be get from the dagger field
|
||||
#define USE_ITEM_BLEEDING_AS_POISON // if enabled, the poison reduce bonus can also reduce the bleeding damage as if it's bleeding reduce itself
|
||||
#define USE_ITEM_CLAW_AS_DAGGER // if enabled, the resist dagger bonus can also reduce the claw damage as if it's resist claw itself
|
||||
#define USE_WOLFMAN_STONES // if enabled, lycan stones can be dropped from the metin stones
|
||||
#define USE_WOLFMAN_BOOKS // if enabled, lycan skill books can be dropped
|
||||
>>magic reduction stone
|
||||
#define ENABLE_MAGIC_REDUCTION_SYSTEM // enable resist magic reduction bonus
|
||||
#define USE_MAGIC_REDUCTION_STONES // enable resist magic reduction stone drops from metins
|
||||
>>pet system
|
||||
#define __PET_SYSTEM__ // enable traditional pet system
|
||||
#define USE_ACTIVE_PET_SEAL_EFFECT // it will activate the pet slot if it's active
|
||||
#define USE_PET_SEAL_ON_LOGIN // it will automatically spawn the pet after a rewarp
|
||||
|
||||
@/Src/Server/db/src/ClientManager.h
|
||||
#define ENABLE_PROTO_FROM_DB //read protos from db if "PROTO_FROM_DB = 1" is specified inside conf.txt
|
||||
//mirror protos to db if "MIRROR2DB = 1" is specified inside conf.txt
|
||||
|
||||
@/Src/Server/db/src/ClientManager.cpp
|
||||
#define ENABLE_DEFAULT_PRIV //enable default priv loading from common.priv_settings
|
||||
#define ENABLE_ITEMAWARD_REFRESH //enable a select query every 5 seconds into player.item_award
|
||||
|
||||
@/Src/Server/db/src/ClientManagerBoot.cpp
|
||||
#define ENABLE_AUTODETECT_VNUMRANGE //if protos are loaded from db, it will automatically detect the vnum range for ds items
|
||||
|
||||
@/Src/Server/db/src/ProtoReader.cpp
|
||||
#define ENABLE_NUMERIC_FIELD //txt protos now can read numbers instead of tags as well
|
||||
|
||||
@/Srcs/Server/game/src/stdafx.h
|
||||
>moved to CommonDefines.h
|
||||
|
||||
@/Srcs/Server/game/src/stdafx.h
|
||||
#define ENABLE_LIMIT_TIME //enable game timestamp expiration
|
||||
|
||||
@/Srcs/Server/game/src/guild.h
|
||||
#define ENABLE_NEWGUILDMAKE //enable pc.make_guild0 and disable CInputMain::AnswerMakeGuild
|
||||
|
||||
@/Srcs/Server/game/src/horse_rider.h
|
||||
#define ENABLE_INFINITE_HORSE_HEALTH_STAMINA // full horse health and stamina all the times
|
||||
|
||||
@/Srcs/Server/game/src/quest.h
|
||||
#define ENABLE_QUEST_DIE_EVENT //add quest event "die"
|
||||
#define ENABLE_QUEST_BOOT_EVENT //add quest event "boot"
|
||||
#define ENABLE_QUEST_DND_EVENT //add quest event "dnd"
|
||||
|
||||
@/Srcs/Server/game/src/config.cpp
|
||||
#define ENABLE_CMD_PLAYER //enable PLAYER grade inside CMD
|
||||
#define ENABLE_EXPTABLE_FROMDB //read the exp table from the db
|
||||
#define ENABLE_AUTODETECT_INTERNAL_IP //autodetect internal ip if the public one is missing
|
||||
#define ENABLE_GENERAL_CMD //if enabled, it reads a general CMD from "locale/%s/conf/GENERAL_CMD", "locale/%s/conf/GENERAL_CMD_CHANNEL_%d", and/or "locale/%s/conf/GENERAL_CMD_CHANNEL_%d_HOSTNAME_%s"
|
||||
#define ENABLE_GENERAL_CONFIG //if enabled, it reads a general CONFIG from "locale/%s/conf/GENERAL_CONFIG", "locale/%s/conf/GENERAL_CONFIG_CHANNEL_%d", and/or "locale/%s/conf/GENERAL_CONFIG_CHANNEL_%d_HOSTNAME_%s"
|
||||
//in the GENERAL_CONFIG, all the options are valid except: HOSTNAME, CHANNEL, PLAYER_SQL, COMMON_SQL, LOG_SQL, PORT, P2P_PORT, MAP_ALLOW, AUTH_SERVER, TEEN_ADDR, TEEN_PORT
|
||||
|
||||
@/Srcs/Server/game/src/char_resist.cpp
|
||||
#define ENABLE_IMMUNE_PERC //enable 90% of success instead of 100% regarding immunes (antistun/slow/fall)
|
||||
|
||||
@/Srcs/Server/game/src/item.cpp
|
||||
#define ENABLE_IMMUNE_FIX //fix immune bug where you need to equip shield at last (or refresh compute e.g. un/riding horse)
|
||||
|
||||
@/Srcs/Server/game/src/item_manager.h
|
||||
#define ENABLE_ITEM_PROTO_MAP //improves GetTable load by O(1)
|
||||
|
||||
@/Srcs/Server/game/src/db.cpp
|
||||
#define ENABLE_SPAMDB_REFRESH //enable a select query every 10 minutes into common.spam_db
|
||||
|
||||
@/Srcs/Server/game/src/questlua.cpp
|
||||
#define ENABLE_TRANSLATE_LUA //enable translate.lua loading
|
||||
#define ENABLE_QUESTLIB_EXTRA_LUA //enable questlib_extra.lua loading
|
||||
|
||||
@/Srcs/Server/game/src/questlua_dungeon.cpp
|
||||
#define D_JOIN_AS_JUMP_PARTY //d.join will internally work as d.new_jump_party
|
||||
|
||||
@/Srcs/Server/game/src/questlua_pc.cpp
|
||||
#define ENABLE_LOCALECHECK_CHANGENAME //enable check that unable change name on Europe Locales
|
||||
#define ENABLE_PC_OPENSHOP //enable pc.open_shop0(idshop) but buy/sell not work yet
|
||||
|
||||
@/Srcs/Server/game/src/shop.cpp
|
||||
#define ENABLE_SHOP_BLACKLIST //enable ignore 70024 (Blessing Marble) and 70035 (Magic Copper Ore)
|
||||
|
||||
@/Srcs/Server/game/src/cmd.cpp
|
||||
#define ENABLE_BLOCK_CMD_SHORTCUT //if enabled, people won't be able to shorten commands
|
||||
|
||||
@/Srcs/Server/game/src/cmd_gm.cpp
|
||||
#define ENABLE_STATPLUS_NOLIMIT //disable only 90 points for con+/int+/str+/dex+ commands
|
||||
#define ENABLE_SET_STATE_WITH_TARGET // enable set_state target as 3rd arg
|
||||
#define ENABLE_CMD_IPURGE_EX // /ipurge 2nd arg can remove items from a specific window (inv/equip/ds/belt/all)
|
||||
|
||||
@/Srcs/Server/game/src/char_skill.cpp
|
||||
#define ENABLE_FORCE2MASTERSKILL //skill always pass to m1 when b17 instead of b(number(17-20))
|
||||
#define ENABLE_NO_MOUNT_CHECK //check whether horse mount vnum should be checked when skilling
|
||||
#define ENABLE_NULLIFYAFFECT_LIMIT //sura skill 66 won't nullify players with level < or > of yours by 9
|
||||
#define ENABLE_MASTER_SKILLBOOK_NO_STEPS //if enabled, you will only need a book to increase a master skill, and not as many as the level-20
|
||||
|
||||
@/Srcs/Server/game/src/char_item.cpp
|
||||
#define ENABLE_FIREWORK_STUN //enable stun affect when using firework items
|
||||
#define ENABLE_ADDSTONE_FAILURE //enable add stone failure
|
||||
#define ENABLE_EFFECT_EXTRAPOT //enable extrapot effects when using green/purple potions
|
||||
#define ENABLE_BOOKS_STACKFIX //enable stackable books instead of remove all the pile
|
||||
#define ENABLE_ITEM_RARE_ATTR_LEVEL_PCT //enable 1-5 level pct for item rare attr add/change
|
||||
#define ENABLE_UNIQUE_ITEM_AUTOSPLIT //enable autosplit when equipping stacked unique items
|
||||
|
||||
@/Srcs/Server/game/src/char_battle.cpp
|
||||
#define ENABLE_NEWEXP_CALCULATION //recalculate exp rate so you won't get random negative exp/marriage points
|
||||
#define ENABLE_EFFECT_PENETRATE //enable penetrate effect when performing a penetration
|
||||
#define ENABLE_NO_DAMAGE_QUEST_RUNNING //if enabled, no damage will be dealt to monsters while running quests (otherwise the quest kill event wouldn't be triggered)
|
||||
|
||||
@/Srcs/Server/game/src/char.h
|
||||
#define NEW_ICEDAMAGE_SYSTEM //add new system for nemere dungeon and so on
|
||||
#define ENABLE_ANTI_CMD_FLOOD //limit player's command execution to 10 commands per second, otherwise it'll be disconnected!
|
||||
#define ENABLE_OPEN_SHOP_WITH_ARMOR //if enabled, people can open a personal shop with the armor equipped
|
||||
#define ENABLE_SKILL_COOLDOWN_CHECK //if enabled, it will add a check on the skill usage to prevent some damage hacks
|
||||
|
||||
@/Srcs/Server/game/src/char.cpp
|
||||
#define ENABLE_SHOWNPCLEVEL //show Lv %d level even for NPCs (not applicable on mob/stone/warp)
|
||||
#define ENABLE_GOHOME_IF_MAP_NOT_ALLOWED //you'll go back to your village if you're not allowed to go in that map
|
||||
#define ENABLE_GM_FLAG_IF_TEST_SERVER //show the gm flag if it's on test server mode
|
||||
#define ENABLE_GM_FLAG_FOR_LOW_WIZARD //show the gm flag for low wizard too
|
||||
#define ENABLE_MOUNT_ENTITY_REFRESH //it will refresh entities when riding/unriding (it's also a quick work-around when the client desyncs)
|
||||
|
||||
@/Srcs/Server/game/src/input_db.cpp
|
||||
#define ENABLE_GOHOME_IF_MAP_NOT_EXIST //you'll go back to your village if the map doesn't exist
|
||||
|
||||
@/Srcs/Server/game/src/guild.cpp
|
||||
#define ENABLE_GUILD_COMMENT_ANTIFLOOD //prevent flood in guild comments
|
||||
|
||||
@/Srcs/Server/game/src/mining.cpp
|
||||
#define ENABLE_PICKAXE_RENEWAL //if the upgrading of the pickaxe will fail, it won't turn back of 1 grade, but just lose 10% mastering points.
|
||||
|
||||
@/Srcs/Server/game/src/fishing.cpp
|
||||
#define ENABLE_FISHINGROD_RENEWAL //if the upgrading of the fishing rod will fail, it won't turn back of 1 grade, but just lose 10% mastering points.
|
||||
|
||||
@/Srcs/Server/game/src/questmanager.cpp
|
||||
#define ENABLE_PARTYKILL //re-enable PartyKill
|
||||
|
||||
@/Srcs/Server/game/src/input_auth.cpp
|
||||
#define ENABLE_ACCOUNT_W_SPECIALCHARS //enable special characters in account names (account.account.login)
|
||||
|
||||
@/Srcs/Server/game/src/input_main.cpp
|
||||
#define ENABLE_CHAT_COLOR_SYSTEM //enable chat colors based on IsGm or GetEmpire (+colored empire name)
|
||||
#define ENABLE_CHAT_SPAMLIMIT //limit chat spam to 4 messages for 5 seconds, if you spam it for 10 times, you'll be disconnected!
|
||||
#define ENABLE_WHISPER_CHAT_SPAMLIMIT //limit whisper chat to 10 messages per 5 seconds, otherwise you'll be disconnected!
|
||||
#define ENABLE_CHAT_LOGGING //enable chat logging (which saves all the gm chats)
|
||||
#define ENABLE_CHECK_GHOSTMODE //enable check that blocks the movements if the character is dead
|
||||
#define ENABLE_TP_SPEED_CHECK //enable speed check teleport back
|
||||
|
||||
@/Srcs/Server/game/src/input_login.cpp
|
||||
#define USE_LYCAN_CREATE_POSITION // if enabled, the lycan will be warped to his own village at character creation
|
||||
|
||||
|
||||
@/Src/Server/game/src/quest/qc.cc
|
||||
#define ENABLE_WHEN_PARENTHESIS //it enables () [] usage in the when cause for the quest file
|
||||
|
||||
|
||||
* Dependencies
|
||||
@/Srcs/Extern/include/boost
|
||||
@/Srcs/Extern/include/cryptopp
|
||||
@/Srcs/Extern/include/IL
|
||||
@/Srcs/Extern/lib:
|
||||
libIL.a //from DevIL
|
||||
libcryptopp.a //from cryptopp
|
||||
libjasper.a
|
||||
libpng.a
|
||||
libtiff.a
|
||||
libjbig.a
|
||||
libmng.a
|
||||
liblcms.a
|
||||
libjpeg.a
|
||||
@/usr/lib/liblzma.a //or lib32
|
||||
|
||||
* Database configuration
|
||||
* How to run tests
|
||||
* Deployment instructions
|
||||
|
||||
### Contribution guidelines ###
|
||||
|
||||
* Writing tests
|
||||
* Code review
|
||||
#@general
|
||||
@warme001: be aware about PLAYER_MAX_LEVEL_CONST (common/length.h) and gPlayerMaxLevel (game/config.h)
|
||||
@warme002: be aware about ITEM_MAX_COUNT (common/item_length.h) and g_bItemCountLimit (game/config.h)
|
||||
@warme003: do_click_safebox can be used by PLAYER in every map!
|
||||
@warme004: `when vnum.kill begin` and `when kill begin` are both triggered
|
||||
@warme005: different locale stuff
|
||||
@warme006: not implemented stuff from another locale
|
||||
@warme007: on db/src/ClientManager.cpp; commented locale set from common.locale due to its uselessness and bugginess (./close && ./start)
|
||||
it processes a NULL mysql connection (dat ymir threading) if there was a bit of overload before starting the process up again
|
||||
@warme008: on char_item.cpp; now 27996 (poison bottle) can inflict poison
|
||||
@warme009: on char_resist.cpp; if bleeding is used as poison, the bleeding enchantment is poison enchantment/50 (so mobs can bleed players)
|
||||
@warme010: on char_state.cpp; test_server is used as "BOOL g_test_server"
|
||||
@warme011: on dungeon.cpp; you should never use d.join instead of d.new_jump_party since it causes random crashes due to a wrong implementation of the party hash check
|
||||
@warme012: trivial errors are now considered as simple logs
|
||||
@warme013: unneccessary errors are now simply commented
|
||||
@warme014: wrong lua return arguments number
|
||||
@warme015: increased buffer size for prevention
|
||||
@warme016: improved info in the relative print
|
||||
|
||||
#@common
|
||||
@fixme400: on tables.h; TPlayerTable hp/mp from short to int (hp/mp >32767 should be fixed)
|
||||
|
||||
#@db/src
|
||||
@fixme201: on ProtoReader.cpp; changed 'SAMLL' into 'SMALL'
|
||||
@fixme202: on ClientManagerGuild.cpp; fixed the guild remove member time issue if the player was offline
|
||||
(withdraw_time -> new_withdraw_time)
|
||||
@fixme203: on ClientManagerPlayer.cpp; dandling pointer for "command"
|
||||
@fixme204: on Cache.cpp; myshop_pricelist primary key duplication error if there are many items of the same vnum in the personal shop
|
||||
@fixme205: on Cache.cpp, ClientManager.cpp; "replace into item" was deleting any foreign keys pointed to player.item
|
||||
|
||||
#@game/src
|
||||
@fixme101: on log.cpp; fixed '%s' for invalid_server_log
|
||||
@fixme102: on cmd_general.cpp; inside ACMD(do_war) fixed the unsigned bug
|
||||
@fixme103: on config, input_login, input_main.cpp; fixed clientcheckversion (version > date) to (version != date) and delay from 10 to 0
|
||||
@fixme104: on char.cpp, questlua_pc.cpp; fixed get status point after lv90 changing 90 with gPlayerMaxLevel
|
||||
@fixme105: on cmd.cpp; disabled every korean command
|
||||
@fixme106: on input_main.cpp; if a full-speeded player is on a mount (es. lion), he'll be brought back due to the distance range
|
||||
@fixme107: on char_battle.cpp; if character (player|mob) has negative hp on dead, sura&co will absorb hp/mp losing 'em themselves
|
||||
@fixme108: on char.cpp; if you change a mount but the previous is not 0, all the entities (npcs&co) in the player client
|
||||
(not others) are vanished until another refresh (not exists mounts still bug you after second mount call)
|
||||
@fixme109: on questmanager.cpp; if you kill a player (war m), `when kill begin` will be triggered twice
|
||||
@fixme110: on char_affect.cpp; if you attack when semi-transparent (revived or ninja skill or white flag) you'll still be transparent
|
||||
@fixme111: on test.cpp; ConvertAttribute2 has x and y inverted (before y->x after x->y)
|
||||
@fixme112: on char_item.cpp; you can change bonuses in equipped items too (until re-login)
|
||||
bonus values will not be refreshed by ChangePoint and unequipping it will remove back only the new bonuses set on
|
||||
e.g. you had a 2500hp bonus shoes, you changed it to 50mp when equipped and you'll unequipped
|
||||
what will it happen? instead of remove 2500hp, you won't receive 50mp and you also lose 50mp when unequipped
|
||||
@fixme113: on char_item.cpp; same thing of #112
|
||||
you can remove stones from equipped items w/o losing bonuses
|
||||
e.g. have an item with antiwar+4 equipped:
|
||||
1) remove all the stones 2) unequip it 3) re-add stone 4) re-equip it 5) repeat it thrice
|
||||
result? an item with no stones but you'll have 75% of antiwar
|
||||
@fixme114: on char_item.cpp; gathering of #111, #112 and few others.
|
||||
@fixme115: on char_item.cpp; you can retrieve all the item on the ground if you're in a party and the owner is not in yours.
|
||||
@fixme116: on char_skill.cpp; normal horse mount skills cannot inflict damage
|
||||
@fixme117: on char_item.cpp; you can't swap equipment from inventory if full, and also prevent unmotivated belt swap if its inventory is not empty
|
||||
@fixme118: on char.cpp; when ComputePoints is called:
|
||||
you'll gain as many hp/mp as many you have in your equipment bonuses
|
||||
affect hp/mp will be lost when login or updating
|
||||
@fixme119: on input_main.cpp; you can put items from safebox/mall to belt inventory w/o checking the type (items with size>1 are not placeable anyway)
|
||||
@fixme120: on input_login.cpp; few packet IDs not checked
|
||||
@fixme121: on char_item.cpp; the refine scroll item value 1 from the magic stone was generating useless syserrs
|
||||
@fixme122: on arena.cpp; few other potions were not checked on arena map
|
||||
@fixme123: on char_item.cpp; USE_CHANGE_ATTRIBUTE2 (24) sub type check bug (the condition could never be true)
|
||||
@fixme124: on char_item.cpp; no check on 6-7 add/change items about costume stuff
|
||||
@fixme125: on char.cpp; dungeon regen pointing to a dangling pointer (not required -> removed)
|
||||
@fixme126: on marriage.cpp; fix lovepoints overflow
|
||||
@fixme127: on cube.cpp; /cube r_info exploit fix; it can cause a crash due to an unchecked cube npc masters vnums
|
||||
e.g. 1) you open the Baek-Go cube's console 2) click on an npc/kill a mob without close the cube console
|
||||
3) digit /cube r_info 4) crash core
|
||||
@fixme128: on char.cpp; mining hack fix; you can mine a vein anywhere in the map because there's no check on the character
|
||||
which means, you can stay at 0x0y and mining a vein in 666x999y and get the stuff beside him or in the pc's inventory
|
||||
@fixme129: on PetSystem.cpp; the azrael pets (53005->34004 normal/53006->34009 gold) don't give the buff if not in dungeon at summon up and remove them anyway when unsummoned
|
||||
@fixme130: on messenger_manager.cpp; and cmd_general.cpp if you do /messenger_auth n XXX, the player with the name XXX will receive a "refused friend invite" print from you
|
||||
which means, if you flood this packet, the "victim" will be disconnected or at maximum could get lag
|
||||
@fixme131: on char.cpp; fix annoying sync packets sendable even on unfightable pc/npc entities
|
||||
e.g. wallhack against players' shops inside the village's squares (where the NOPK attr is set) to move them out and kill them
|
||||
@fixme132: on shop.cpp; if two people buy the same item at the same time from a pc's shop, the slower one will receive a wrong return packet (crash client)
|
||||
@fixme133: on input_main.cpp; banword check and hyper text feature were processing the final chat string instead of the raw one
|
||||
@fixme134: on questlua_pc.cpp; the pc.mount_bonus was addable even if the mount wasn't spawn (only /unmount pc.unmount can remove it)
|
||||
@fixme135: on char.cpp; if the Sync is made before a move packet and the sectree differs of few x/y coordinates, the sectree will be changed without update (crash character) (troublesome -> removed)
|
||||
@fixme136: on char.cpp; there are no checks about the zero division exception: e.g. if you set a mob's max hp to 0 in the mob proto, you'll get random crashes.
|
||||
@fixme137: on char_battle.cpp; when a player dies, the HP could have a negative value. Now it's 0 like the official.
|
||||
@fixme138: on db.cpp, input_auth.cpp; the account's password was shown in the mysql history queries as clear text at every login attempt (mysql full granted user required -> now hashed)
|
||||
@fixme139: on shop.h; CShop class destructor wasn't virtual. If a derived class like CShopEx was deleted, a memory leak would have been generated.
|
||||
@fixme140: on input_main.cpp; the belt could be put into the safebox even though the belt inventory isn't empty.
|
||||
@fixme141: on char_item.cpp; the items in the belt inventory could be used even if their slot were not available
|
||||
@fixme142: on messenger_manager.cpp; sql injection fix about net.SendMessengerRemovePacket
|
||||
@fixme143: on guild_manager.cpp; sql injection fix about net.SendAnswerMakeGuildPacket
|
||||
@fixme144: on sectree_manager.cpp; if map/index doesn't end with a newline, the game will crash (before refactory)
|
||||
@fixme145: on input_main.cpp; guild_add_member can add any vid as guild's member even if it's a mob or an npc
|
||||
@fixme147: on char_item.cpp; ramadan candy item can be used even if the relative affect is still up
|
||||
@fixme148: on item_manager_read_tables.cpp; type quest, special, attr not handled in ConvSpecialDropItemFile
|
||||
@fixme149: on char.cpp; refine material skip exploit if items are swapped
|
||||
@fixme150: on exchange.cpp; char_item.cpp; prevent item module swapping if the quest is suspended
|
||||
@fixme152: on questlua_pc.cpp; pc.get_special_ride_vnum was checking socket2 instead of socket0
|
||||
@fixme153: on threeway_war.cpp; kills made of people over lvl99 weren't counted
|
||||
@fixme154: on cmd_gm.cpp; the /all_skill_master command will now set the right amount of points to the sub skills
|
||||
@fixme156: on char_affect.cpp; prevent doubling the affect values before they are loaded (such as pc.mount_bonus at login; because the quest is loaded before the quests)
|
||||
@fixme157: on OxEvent.cpp; the attender list wasn't cleared after stopping the ox event
|
||||
@fixme158: on input_main.cpp; the deviltower refiner won't set the flag to 0 anymore if you have no money, and it will decrease it by 1 for allowing multiple refine attempts
|
||||
@fixme159: on exchange.cpp; when exchanging, a wrong check in the ds items was not allowing the exchange due to "not enough space in ds inventory" if the first sub ds inventory slot was not empty
|
||||
@fixme160: on DragonSoul.cpp; when removing a ds stone, if the destination slot wasn't empty, the ds item in there would have been replaced and lost
|
||||
@fixme168: on questevent.cpp; if the quest info name is already null, the std::string constructor will throw an exception
|
||||
@fixme169: on char_item.cpp; missing checks for mythical peach like a second vnum and nullptr
|
||||
@fixme170: on item.cpp; missing condition on special mineral slots for just 2 bonuses
|
||||
@fixme171: on dungeon.cpp; FCountMonster was also counting horses and pets
|
||||
@fixme172: on dungeon.cpp; FNotice was sending ChatPackets to even non-player characters
|
||||
@fixme173: on item.cpp; by pressing \\z to pick up items, sometimes, it would fail due to far distance
|
||||
@fixme174: on questmanager.cpp; in case of quest error in server_timer, it would try to print the error to the current player causing a core crash
|
||||
@fixme177: on cmd_gm.cpp; /priv_guild snprintf had an empty format
|
||||
@fixme179: on ClientManagerBoot.cpp, ProtoReader.cpp; the item size with 0 length will cause game cores
|
||||
@fixme180: on cmd_general.cpp; /costume will cause game core crashes if the relative costume bonus ids aren't present inside fn_string or have no %d
|
||||
@fixme182: on input_login.cpp; you'd get no horse level if you relogged in with no job set
|
||||
@fixme183: on input_main.cpp, messenger_manager.cpp; player rename wasn't clearing the previous nickname from the friendlist
|
||||
@fixme184: on length.h; some slots of the dragon soul inventory weren't working properly
|
||||
@fixme185: on ClientManagerBoot.cpp; the material count var isn't initialized and cause crashes on certain circumstances
|
||||
@fixme186: on item.cpp; the ClearMountAttributeAndAffect without owner would trigger a core crash
|
||||
@fixme187: on input.cpp; the input buffer will keep increasing until it saturates the ram if people keep sending broken packets
|
||||
@fixme188: on char.h, questlua_npc|dungeon|global.cpp, dungeon.cpp; the scripted npc->Dead() was triggering player rewards if the mob was previously damaged
|
||||
@fixme189: on item_manager.cpp; the Stones array had an out of range error
|
||||
@fixme190: on input_login.cpp; exploit by accessing non-existing players
|
||||
@fixme191: on safebox.cpp; switching safebox size level was causing a memory leak
|
||||
@fixme192: on char_battle.cpp; the deathblow wasn't affecting warrior and wolfman races
|
||||
@fixme193: on guild_manager.cpp; observer players can be killed to increment the guild war kills
|
||||
@fixme194: on char_battle.cpp; mobs killed in non attackable zones weren't dropping yangs/items
|
||||
@fixme195: on regen.cpp; missing 'ma' 'ra' 'sa' handling regen type
|
||||
@fixme196: on char_item.cpp; possible item duplication bug while moving splitted items onto the same slot
|
||||
@fixme197: on cmd_general.cpp; stucked connections while fully quitting from game would leave the character online
|
||||
@fixme198: on char_battle.cpp; karma drop duplication bug: the dropped item gets duplicated after warping to another game core
|
||||
@fixme199: on char.h, char.cpp, char_item.cpp, char_quickslot.cpp; the mobs were allocating unused memory
|
||||
@fixme300: on cmd_gm.cpp; /full and /ipurge were causing a glitch in the status page by having negative status
|
||||
@fixme301: on input_main.cpp, char.cpp; leaders and party members can leave the party while being on other channels
|
||||
@fixme302: on questpc.cpp; HEADER_GC_QUEST_INFO had a wrong calculated size
|
||||
@fixme303: on item_manager_read_tables.cpp; the load of items had O(n) complexity for each vnum of any Group
|
||||
@fixme304: on char.h, char.cpp; yielded quest states were pointing to dangling item pointers
|
||||
@fixme305: on char_skill.cpp; skill affects were not cleared after a skill reset
|
||||
@fixme306: on char.cpp; real time items were not expired if inside the safebox
|
||||
@fixme307: on cmd_general.cpp; crash core if the item for feeding the horse didn't exist in the item proto
|
||||
@fixme308: on sectree_manager.cpp; when loading map/index, if the map is already loaded, the regen will duplicate
|
||||
@fixme309: on questlua_pc.cpp; flushing the cache after changing the player name was causing item duplication
|
||||
@fixme310: on ClientManager.cpp; only the first 3 players of the account had a full empire select check
|
||||
@fixme311: on questmanager.cpp; CancelServerTimers not properly erasing the element from the container
|
||||
@fixme312: on char_skill.cpp; mobs could ran away on death instead of playing the death animation
|
||||
@fixme313: on char.cpp; very fast mounts would reach coordinates like -2147483648 and being unable to sync
|
||||
@fixme314: on char_item.cpp; unique items can now be be stackable without issues
|
||||
@fixme315: on building.cpp; skip guild land load from other maps
|
||||
@fixme316: on char_item.cpp; items with sockets set at runtime weren't automatically stacked properly
|
||||
|
||||
|
||||
#@/Server (general)
|
||||
@fixme401: fixed the guild disband time issue
|
||||
on db/src/ClientManagerGuild.cpp
|
||||
(withdraw_time -> new_disband_time)
|
||||
on game/src/guild.cpp
|
||||
(new_withdraw_time -> new_disband_time)
|
||||
@fixme402: fixed the usage of the affect system before its loading
|
||||
on game/src/char_item.cpp
|
||||
added an IsAffectLoaded check when using an item
|
||||
@fixme403: fixed player.myshop_pricelist corrupted data
|
||||
on db/src/ClientManager.cpp; db/src/ClientManager.h; game/src/char.cpp
|
||||
TPacketMyshopPricelistHeader to TItemPriceListTable
|
||||
|
||||
#@/General
|
||||
@fixme501: on game/src/char.h, game/src/char.cpp, game/src/packet.h; mob race word to dword
|
||||
@fixme502: on common/tables.h, game/src/packet.h; character part word to dword
|
||||
|
||||
|
||||
* Other guidelines
|
||||
|
||||
## Trick to replace ALUA macro (notepad++) for all questlua*.cpp files (CTRL+F)
|
||||
# Find (Search Type -> Regular Expression)
|
||||
int[ \t]*([A-Za-z0-9\_]+)[ \t]*\([ \t]*lua_State[ \t]*\*[ \t]*[\/\*]*L[\*\/]*[ \t]*\)
|
||||
# Replace with (File -> Save all) [26 files, 621 replaces]
|
||||
ALUA\($1\)
|
||||
|
||||
### Who do I talk to? ###
|
||||
|
||||
* Repo owner or admin
|
||||
martysama0134
|
||||
149
source-server/Srcs/Server/Makefile
Normal file
149
source-server/Srcs/Server/Makefile
Normal file
@ -0,0 +1,149 @@
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
|
||||
PLATFORM = $(shell file /bin/ls | cut -d' ' -f3 | cut -d'-' -f1)
|
||||
BSD_VERSION = $(shell uname -v 2>&1 | cut -d' ' -f2 | cut -d'.' -f1)
|
||||
SVR_VERSION = $(shell cat __REVISION__)
|
||||
|
||||
.PHONY: liblua libsql libgame libpoly libthecore game db
|
||||
|
||||
default: liblua libsql libgame libpoly libthecore game db
|
||||
@echo "--------------------------------------"
|
||||
@echo "Build Done"
|
||||
@echo "--------------------------------------"
|
||||
|
||||
quick: .
|
||||
$(MAKE) -C liblua/5.0
|
||||
$(MAKE) -C libsql
|
||||
$(MAKE) -C libgame/src
|
||||
$(MAKE) -C libpoly
|
||||
$(MAKE) -C libthecore/src
|
||||
touch game/src/main.cpp
|
||||
$(MAKE) -C game/src
|
||||
$(MAKE) -C game/src symlink
|
||||
touch db/src/Main.cpp
|
||||
$(MAKE) -C db/src
|
||||
$(MAKE) -C db/src symlink
|
||||
|
||||
liblua: .
|
||||
$(MAKE) -C $@/5.0 clean
|
||||
$(MAKE) -C $@/5.0
|
||||
|
||||
libsql: .
|
||||
@touch $@/Depend
|
||||
$(MAKE) -C $@ dep
|
||||
$(MAKE) -C $@ clean
|
||||
$(MAKE) -C $@
|
||||
|
||||
libgame: .
|
||||
@touch $@/src/Depend
|
||||
$(MAKE) -C $@/src dep
|
||||
$(MAKE) -C $@/src clean
|
||||
$(MAKE) -C $@/src
|
||||
|
||||
libpoly: .
|
||||
@touch $@/Depend
|
||||
$(MAKE) -C $@ dep
|
||||
$(MAKE) -C $@ clean
|
||||
$(MAKE) -C $@
|
||||
|
||||
libthecore: .
|
||||
@touch $@/src/Depend
|
||||
$(MAKE) -C $@/src dep
|
||||
$(MAKE) -C $@/src clean
|
||||
$(MAKE) -C $@/src
|
||||
|
||||
game: .
|
||||
@touch $@/src/Depend
|
||||
$(MAKE) -C $@/src dep
|
||||
$(MAKE) -C $@/src clean
|
||||
# $(MAKE) -C $@/src limit_time
|
||||
$(MAKE) -C $@/src
|
||||
$(MAKE) -C $@/src symlink
|
||||
|
||||
db: .
|
||||
@touch $@/src/Depend
|
||||
$(MAKE) -C $@/src dep
|
||||
$(MAKE) -C $@/src clean
|
||||
$(MAKE) -C $@/src
|
||||
$(MAKE) -C $@/src symlink
|
||||
|
||||
ver:
|
||||
@$(CC) -v
|
||||
|
||||
ver2:
|
||||
@$(CC) -v
|
||||
$(MAKE) -C game/src ver
|
||||
|
||||
symlink:
|
||||
$(MAKE) -C game/src symlink
|
||||
$(MAKE) -C db/src symlink
|
||||
|
||||
strip:
|
||||
$(MAKE) -C game/src strip
|
||||
$(MAKE) -C db/src strip
|
||||
|
||||
clean:
|
||||
$(MAKE) -C liblua/5.0 clean
|
||||
$(MAKE) -C libsql clean
|
||||
$(MAKE) -C libgame/src clean
|
||||
$(MAKE) -C libpoly clean
|
||||
$(MAKE) -C libthecore/src clean
|
||||
$(MAKE) -C game/src clean
|
||||
$(MAKE) -C db/src clean
|
||||
|
||||
all:
|
||||
@echo "--------------------------------------"
|
||||
@echo "Update Revision"
|
||||
@echo "--------------------------------------"
|
||||
@expr $(SVR_VERSION) + 1 > __REVISION__
|
||||
@cat __REVISION__
|
||||
|
||||
@echo "--------------------------------------"
|
||||
@echo "Full Build Start"
|
||||
@echo "--------------------------------------"
|
||||
|
||||
$(MAKE) -C liblua/5.0 clean
|
||||
$(MAKE) -C liblua/5.0
|
||||
|
||||
# $(MAKE) -C liblua/5.2 clean
|
||||
# $(MAKE) -C liblua/5.2 freebsd
|
||||
# $(MAKE) -C liblua/5.2 local
|
||||
|
||||
@touch libsql/Depend
|
||||
$(MAKE) -C libsql dep
|
||||
$(MAKE) -C libsql clean
|
||||
$(MAKE) -C libsql
|
||||
|
||||
@touch libgame/src/Depend
|
||||
$(MAKE) -C libgame/src dep
|
||||
$(MAKE) -C libgame/src clean
|
||||
$(MAKE) -C libgame/src
|
||||
|
||||
@touch libpoly/Depend
|
||||
$(MAKE) -C libpoly dep
|
||||
$(MAKE) -C libpoly clean
|
||||
$(MAKE) -C libpoly
|
||||
|
||||
@touch libthecore/src/Depend
|
||||
$(MAKE) -C libthecore/src dep
|
||||
$(MAKE) -C libthecore/src clean
|
||||
$(MAKE) -C libthecore/src
|
||||
|
||||
@touch game/src/Depend
|
||||
$(MAKE) -C game/src dep
|
||||
$(MAKE) -C game/src clean
|
||||
# $(MAKE) -C game/src limit_time
|
||||
$(MAKE) -C game/src
|
||||
$(MAKE) -C game/src symlink
|
||||
# $(MAKE) -C game/src strip
|
||||
|
||||
@touch db/src/Depend
|
||||
$(MAKE) -C db/src dep
|
||||
$(MAKE) -C db/src clean
|
||||
$(MAKE) -C db/src
|
||||
$(MAKE) -C db/src symlink
|
||||
# $(MAKE) -C db/src strip
|
||||
@echo "--------------------------------------"
|
||||
@echo "Full Build End"
|
||||
@echo "--------------------------------------"
|
||||
1
source-server/Srcs/Server/__REVISION__
Normal file
1
source-server/Srcs/Server/__REVISION__
Normal file
@ -0,0 +1 @@
|
||||
41023
|
||||
105
source-server/Srcs/Server/common/CommonDefines.h
Normal file
105
source-server/Srcs/Server/common/CommonDefines.h
Normal file
@ -0,0 +1,105 @@
|
||||
#ifndef __INC_METIN2_COMMON_DEFINES_H__
|
||||
#define __INC_METIN2_COMMON_DEFINES_H__
|
||||
#pragma once
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ### Standard Features ###
|
||||
#define _IMPROVED_PACKET_ENCRYPTION_
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
#define USE_IMPROVED_PACKET_DECRYPTED_BUFFER
|
||||
#endif
|
||||
#define __UDP_BLOCK__
|
||||
//#define ENABLE_QUEST_CATEGORY
|
||||
|
||||
// ### END Standard Features ###
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ### New Features ###
|
||||
#define ENABLE_NO_MOUNT_CHECK
|
||||
#define ENABLE_D_NJGUILD
|
||||
#define ENABLE_FULL_NOTICE
|
||||
#define ENABLE_NEWSTUFF
|
||||
#define ENABLE_PORT_SECURITY
|
||||
#define ENABLE_BELT_INVENTORY_EX
|
||||
#define ENABLE_CMD_WARP_IN_DUNGEON
|
||||
// #define ENABLE_ITEM_ATTR_COSTUME
|
||||
// #define ENABLE_SEQUENCE_SYSTEM
|
||||
#define ENABLE_PLAYER_PER_ACCOUNT5
|
||||
#define ENABLE_DICE_SYSTEM
|
||||
#define ENABLE_EXTEND_INVEN_SYSTEM
|
||||
#define ENABLE_MOUNT_COSTUME_SYSTEM
|
||||
#define ENABLE_WEAPON_COSTUME_SYSTEM
|
||||
#define ENABLE_QUEST_DIE_EVENT
|
||||
#define ENABLE_QUEST_BOOT_EVENT
|
||||
#define ENABLE_QUEST_DND_EVENT
|
||||
#define ENABLE_PET_SYSTEM_EX
|
||||
#define ENABLE_SKILL_FLAG_PARTY
|
||||
#define ENABLE_NO_DSS_QUALIFICATION
|
||||
// #define ENABLE_NO_SELL_PRICE_DIVIDED_BY_5
|
||||
#define ENABLE_CHECK_SELL_PRICE
|
||||
#define ENABLE_GOTO_LAG_FIX
|
||||
#define ENABLE_MOUNT_COSTUME_EX_SYSTEM
|
||||
#define ENABLE_PENDANT_SYSTEM
|
||||
#define ENABLE_GLOVE_SYSTEM
|
||||
#define ENABLE_MOVE_CHANNEL
|
||||
#define ENABLE_QUIVER_SYSTEM
|
||||
#define ENABLE_REDUCED_ENTITY_VIEW
|
||||
#define ENABLE_GUILD_TOKEN_AUTH
|
||||
#define ENABLE_DS_GRADE_MYTH
|
||||
#define ENABLE_DB_SQL_LOG
|
||||
|
||||
#define __PET_SYSTEM__
|
||||
#ifdef __PET_SYSTEM__
|
||||
#define USE_ACTIVE_PET_SEAL_EFFECT
|
||||
#define PET_SEAL_ACTIVE_SOCKET_IDX 2
|
||||
#define USE_PET_SEAL_ON_LOGIN
|
||||
#endif
|
||||
|
||||
enum eCommonDefines {
|
||||
MAP_ALLOW_LIMIT = 32, // 32 default
|
||||
};
|
||||
|
||||
#define ENABLE_WOLFMAN_CHARACTER
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
// #define DISABLE_WOLFMAN_ON_CREATE
|
||||
#define USE_MOB_BLEEDING_AS_POISON
|
||||
#define USE_MOB_CLAW_AS_DAGGER
|
||||
// #define USE_ITEM_BLEEDING_AS_POISON
|
||||
// #define USE_ITEM_CLAW_AS_DAGGER
|
||||
#define USE_WOLFMAN_STONES
|
||||
#define USE_WOLFMAN_BOOKS
|
||||
#endif
|
||||
|
||||
// #define ENABLE_MAGIC_REDUCTION_SYSTEM
|
||||
#ifdef ENABLE_MAGIC_REDUCTION_SYSTEM
|
||||
// #define USE_MAGIC_REDUCTION_STONES
|
||||
#endif
|
||||
|
||||
// ### END New Features ###
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ### Ex Features ###
|
||||
#define DISABLE_STOP_RIDING_WHEN_DIE // if DISABLE_TOP_RIDING_WHEN_DIE is defined, the player doesn't lose the horse after dying
|
||||
#define ENABLE_ACCE_COSTUME_SYSTEM //fixed version
|
||||
// #define USE_ACCE_ABSORB_WITH_NO_NEGATIVE_BONUS //enable only positive bonus in acce absorb
|
||||
#define ENABLE_HIGHLIGHT_NEW_ITEM //if you want to see highlighted a new item when dropped or when exchanged
|
||||
#define ENABLE_KILL_EVENT_FIX //if you want to fix the 0 exp problem about the when kill lua event (recommended)
|
||||
// #define ENABLE_SYSLOG_PACKET_SENT // debug purposes
|
||||
|
||||
#define ENABLE_EXTEND_ITEM_AWARD //slight adjustement
|
||||
#ifdef ENABLE_EXTEND_ITEM_AWARD
|
||||
// #define USE_ITEM_AWARD_CHECK_ATTRIBUTES //it prevents bonuses higher than item_attr lvl1-lvl5 min-max range limit
|
||||
#endif
|
||||
|
||||
#define ENABLE_CHEQUE_SYSTEM
|
||||
#ifdef ENABLE_CHEQUE_SYSTEM
|
||||
#define ENABLE_SHOP_USE_CHEQUE
|
||||
#define DISABLE_CHEQUE_DROP
|
||||
#define ENABLE_WON_EXCHANGE_WINDOW
|
||||
#endif
|
||||
// ### END Ex Features ###
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
266
source-server/Srcs/Server/common/PulseManager.h
Normal file
266
source-server/Srcs/Server/common/PulseManager.h
Normal file
@ -0,0 +1,266 @@
|
||||
// martysama0134's PulseManager class for quick anti-flood code implementation
|
||||
#ifndef __COMMON__PULSEMANAGER_H__
|
||||
#define __COMMON__PULSEMANAGER_H__
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <unordered_map>
|
||||
#include <chrono>
|
||||
|
||||
enum class ePulse {
|
||||
GuildComment,
|
||||
CommandRequest,
|
||||
ItemDrop,
|
||||
BoxOpening,
|
||||
BuySell,
|
||||
SafeboxMove,
|
||||
ChannelStatus,
|
||||
RideMount,
|
||||
SharedRequest,
|
||||
};
|
||||
|
||||
// #define __PULSEMANAGER__SECOND_SUPPORT__
|
||||
#define __PULSEMANAGER__CLOCK_SUPPORT__
|
||||
// #define __PULSEMANAGER__M2_SUPPORT__
|
||||
|
||||
#ifdef __PULSEMANAGER__M2_SUPPORT__
|
||||
#include "../libthecore/include/stdafx.h"
|
||||
#endif
|
||||
|
||||
#define PULSEMANAGER_CLOCK_TO_SEC(diff) (std::chrono::duration_cast<std::chrono::milliseconds>(diff).count()/1000.0)
|
||||
#define PULSEMANAGER_CLOCK_TO_SEC2(key1, key2) (PULSEMANAGER_CLOCK_TO_SEC(PulseManager::Instance().DiffClock(key1, key2)))
|
||||
|
||||
class PulseManager
|
||||
{
|
||||
public:
|
||||
using SubKeyT = ePulse;
|
||||
using MainKeyT = uint32_t;
|
||||
|
||||
#ifdef __PULSEMANAGER__M2_SUPPORT__
|
||||
using PulseT = int;
|
||||
using PulseMapT = std::unordered_map<SubKeyT, PulseT>;
|
||||
using MainPulseMapT = std::unordered_map<MainKeyT, PulseMapT>;
|
||||
PulseT passesPerSec{ 25 };
|
||||
MainPulseMapT pulseMap;
|
||||
#endif
|
||||
|
||||
#ifdef __PULSEMANAGER__SECOND_SUPPORT__
|
||||
using SecondT = time_t;//uint32_t;
|
||||
using SecondMapT = std::unordered_map<SubKeyT, SecondT>;
|
||||
using MainSecondMapT = std::unordered_map<MainKeyT, SecondMapT>;
|
||||
MainSecondMapT secondMap;
|
||||
#endif
|
||||
|
||||
#ifdef __PULSEMANAGER__CLOCK_SUPPORT__
|
||||
using TypeClock = std::chrono::high_resolution_clock;
|
||||
using ClockT = TypeClock::time_point;
|
||||
using DurationT = TypeClock::duration;
|
||||
using CountT = int64_t;
|
||||
using PairValueT = std::pair<DurationT, CountT>;
|
||||
using ClockMapT = std::unordered_map<SubKeyT, PairValueT>;
|
||||
using MainClockMapT = std::unordered_map<MainKeyT, ClockMapT>;
|
||||
MainClockMapT clockMap;
|
||||
#endif
|
||||
|
||||
static PulseManager& Instance() {
|
||||
thread_local PulseManager _this;
|
||||
return _this;
|
||||
}
|
||||
|
||||
#ifdef __PULSEMANAGER__SECOND_SUPPORT__
|
||||
inline static SecondT GetTime() {
|
||||
return time(0); //get_global_time();//get_dword_time();
|
||||
}
|
||||
|
||||
/* SECOND BLOCK */
|
||||
SecondT GetSecond(MainKeyT key1, SubKeyT key2) {
|
||||
auto it1 = secondMap.find(key1);
|
||||
if (it1 == secondMap.end())
|
||||
return 0;
|
||||
auto it2 = it1->second.find(key2);
|
||||
if (it2 == it1->second.end())
|
||||
return 0;
|
||||
|
||||
return it2->second;
|
||||
}
|
||||
|
||||
void SetSecond(MainKeyT key1, SubKeyT key2, SecondT value, bool appendCurrent = true) {
|
||||
if (appendCurrent)
|
||||
value += GetTime();
|
||||
secondMap[key1][key2] = value;
|
||||
}
|
||||
|
||||
bool CheckSecond(MainKeyT key1, SubKeyT key2, SecondT nextLapse) {
|
||||
if (GetSecond(key1, key2) > GetTime())
|
||||
return false;
|
||||
SetSecond(key1, key2, nextLapse, true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __PULSEMANAGER__CLOCK_SUPPORT__
|
||||
inline static DurationT GetChrono() {
|
||||
return std::chrono::high_resolution_clock::now().time_since_epoch();
|
||||
}
|
||||
|
||||
/* CLOCK BLOCK */
|
||||
PairValueT GetPair(MainKeyT key1, SubKeyT key2) const {
|
||||
const auto it1 = clockMap.find(key1);
|
||||
if (it1 == clockMap.end())
|
||||
return {TypeClock::duration::zero(), 0};
|
||||
|
||||
const auto it2 = it1->second.find(key2);
|
||||
if (it2 == it1->second.end())
|
||||
return {TypeClock::duration::zero(), 0};
|
||||
|
||||
return it2->second;
|
||||
}
|
||||
|
||||
DurationT GetClock(MainKeyT key1, SubKeyT key2) const {
|
||||
return GetPair(key1, key2).first;
|
||||
}
|
||||
|
||||
CountT GetCount(MainKeyT key1, SubKeyT key2) const {
|
||||
return GetPair(key1, key2).second;
|
||||
}
|
||||
|
||||
void SetPair(MainKeyT key1, SubKeyT key2, PairValueT pair, bool appendCurrent = true) {
|
||||
if (appendCurrent)
|
||||
pair.first += GetChrono();
|
||||
clockMap[key1][key2] = pair;
|
||||
}
|
||||
|
||||
void SetClock(MainKeyT key1, SubKeyT key2, DurationT value, bool appendCurrent = true) {
|
||||
if (appendCurrent)
|
||||
value += GetChrono();
|
||||
clockMap[key1][key2].first = value;
|
||||
}
|
||||
|
||||
void SetCount(MainKeyT key1, SubKeyT key2, CountT count, bool decreaseValue = true) {
|
||||
if (decreaseValue)
|
||||
clockMap[key1][key2].second -= count;
|
||||
else
|
||||
clockMap[key1][key2].second = count;
|
||||
}
|
||||
|
||||
bool CheckClock(MainKeyT key1, SubKeyT key2) {
|
||||
if (GetClock(key1, key2) > GetChrono())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IncreaseClock(MainKeyT key1, SubKeyT key2, DurationT nextLapse) {
|
||||
if (!CheckClock(key1, key2))
|
||||
return false;
|
||||
SetClock(key1, key2, nextLapse, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckCount(MainKeyT key1, SubKeyT key2) {
|
||||
//std::cout << "CHECK COUNT " << GetCount(key1, key2) << std::endl;
|
||||
SetCount(key1, key2, 1, true);
|
||||
if (GetCount(key1, key2) <= 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IncreaseCount(MainKeyT key1, SubKeyT key2, DurationT nextLapse, CountT maxCount) {
|
||||
if (!CheckClock(key1, key2)) { // if clock fails, check if max count is reached
|
||||
if (!CheckCount(key1, key2))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
SetPair(key1, key2, { nextLapse, maxCount }, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
DurationT DiffClock(MainKeyT key1, SubKeyT key2) {
|
||||
return GetClock(key1, key2) - GetChrono();
|
||||
}
|
||||
|
||||
void ClearClock(MainKeyT key1) {
|
||||
auto it1 = clockMap.find(key1);
|
||||
if (it1 == clockMap.end())
|
||||
return;
|
||||
clockMap.erase(it1);
|
||||
}
|
||||
|
||||
void ClearClock(MainKeyT key1, SubKeyT key2) {
|
||||
auto it1 = clockMap.find(key1);
|
||||
if (it1 == clockMap.end())
|
||||
return;
|
||||
auto it2 = it1->second.find(key2);
|
||||
if (it2 == it1->second.end())
|
||||
return;
|
||||
it1->second.erase(it2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __PULSEMANAGER__M2_SUPPORT__
|
||||
void SetPassesPerSec(PulseT v) {
|
||||
passesPerSec = v;
|
||||
}
|
||||
|
||||
PulseT Sec2Pulse(SecondT v) {
|
||||
return v * passesPerSec;
|
||||
}
|
||||
|
||||
SecondT Pulse2Sec(PulseT v) {
|
||||
return v / passesPerSec;
|
||||
}
|
||||
|
||||
inline static PulseT GetCorePulse() {
|
||||
return thecore_pulse();
|
||||
}
|
||||
|
||||
/* CLOCK BLOCK */
|
||||
bool HasPulse(MainKeyT key1, SubKeyT key2) {
|
||||
auto it1 = pulseMap.find(key1);
|
||||
if (it1 == pulseMap.end())
|
||||
return false;
|
||||
auto it2 = it1->second.find(key2);
|
||||
if (it2 == it1->second.end())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
PulseT GetPulse(MainKeyT key1, SubKeyT key2) {
|
||||
auto it1 = pulseMap.find(key1);
|
||||
if (it1 == pulseMap.end())
|
||||
return 0;
|
||||
auto it2 = it1->second.find(key2);
|
||||
if (it2 == it1->second.end())
|
||||
return 0;
|
||||
return it2->second;
|
||||
}
|
||||
|
||||
void SetPulse(MainKeyT key1, SubKeyT key2, PulseT value, bool appendCurrent = true) {
|
||||
if (appendCurrent)
|
||||
value += GetCorePulse();
|
||||
pulseMap[key1][key2] = value;
|
||||
}
|
||||
|
||||
bool CheckPulse(MainKeyT key1, SubKeyT key2, PulseT nextLapse) {
|
||||
if (GetPulse(key1, key2) > GetCorePulse())
|
||||
return false;
|
||||
SetPulse(key1, key2, nextLapse, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
SecondT GetPSecond(MainKeyT key1, SubKeyT key2) {
|
||||
auto v = GetPulse(key1, key2);
|
||||
return Pulse2Sec(v);
|
||||
}
|
||||
|
||||
void SetPSecond(MainKeyT key1, SubKeyT key2, SecondT value, bool appendCurrent = true) {
|
||||
auto pulses = Sec2Pulse(value);
|
||||
// if (appendCurrent)
|
||||
// pulses += GetTime();
|
||||
SetPulse(key1, key2, pulses, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
#endif // __COMMON__PULSEMANAGER_H__
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
38
source-server/Srcs/Server/common/VnumHelper.h
Normal file
38
source-server/Srcs/Server/common/VnumHelper.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef __HEADER_VNUM_HELPER__
|
||||
#define __HEADER_VNUM_HELPER__
|
||||
|
||||
class CItemVnumHelper
|
||||
{
|
||||
public:
|
||||
|
||||
static const bool IsPhoenix(DWORD vnum) { return 53001 == vnum; }
|
||||
|
||||
static const bool IsRamadanMoonRing(DWORD vnum) { return 71135 == vnum; }
|
||||
|
||||
static const bool IsHalloweenCandy(DWORD vnum) { return 71136 == vnum; }
|
||||
|
||||
static const bool IsHappinessRing(DWORD vnum) { return 71143 == vnum; }
|
||||
|
||||
static const bool IsLovePendant(DWORD vnum) { return 71145 == vnum; }
|
||||
};
|
||||
|
||||
class CMobVnumHelper
|
||||
{
|
||||
public:
|
||||
|
||||
static bool IsPhoenix(DWORD vnum) { return 34001 == vnum; }
|
||||
static bool IsIcePhoenix(DWORD vnum) { return 34003 == vnum; }
|
||||
|
||||
static bool IsPetUsingPetSystem(DWORD vnum) { return (IsPhoenix(vnum) || IsReindeerYoung(vnum)) || IsIcePhoenix(vnum); }
|
||||
|
||||
static bool IsReindeerYoung(DWORD vnum) { return 34002 == vnum; }
|
||||
|
||||
static bool IsRamadanBlackHorse(DWORD vnum) { return 20119 == vnum || 20219 == vnum || 22022 == vnum; }
|
||||
};
|
||||
|
||||
class CVnumHelper
|
||||
{
|
||||
};
|
||||
|
||||
#endif //__HEADER_VNUM_HELPER__
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
16
source-server/Srcs/Server/common/billing.h
Normal file
16
source-server/Srcs/Server/common/billing.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __INC_METIN_II_COMMON_BILLING_H__
|
||||
#define __INC_METIN_II_COMMON_BILLING_H__
|
||||
|
||||
enum EBillingTypes
|
||||
{
|
||||
BILLING_NONE,
|
||||
BILLING_IP_FREE,
|
||||
BILLING_FREE,
|
||||
BILLING_IP_TIME,
|
||||
BILLING_IP_DAY,
|
||||
BILLING_TIME,
|
||||
BILLING_DAY,
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
64
source-server/Srcs/Server/common/building.h
Normal file
64
source-server/Srcs/Server/common/building.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef __METIN_II_COMMON_BUILDING_H__
|
||||
#define __METIN_II_COMMON_BUILDING_H__
|
||||
|
||||
namespace building
|
||||
{
|
||||
enum
|
||||
{
|
||||
OBJECT_MATERIAL_MAX_NUM = 5,
|
||||
};
|
||||
|
||||
typedef struct SLand
|
||||
{
|
||||
DWORD dwID;
|
||||
long lMapIndex;
|
||||
long x, y;
|
||||
long width, height;
|
||||
DWORD dwGuildID;
|
||||
BYTE bGuildLevelLimit;
|
||||
DWORD dwPrice;
|
||||
} TLand;
|
||||
|
||||
typedef struct SObjectMaterial
|
||||
{
|
||||
DWORD dwItemVnum;
|
||||
DWORD dwCount;
|
||||
} TObjectMaterial;
|
||||
|
||||
typedef struct SObjectProto
|
||||
{
|
||||
DWORD dwVnum;
|
||||
DWORD dwPrice;
|
||||
|
||||
TObjectMaterial kMaterials[OBJECT_MATERIAL_MAX_NUM];
|
||||
|
||||
DWORD dwUpgradeVnum;
|
||||
DWORD dwUpgradeLimitTime;
|
||||
long lLife;
|
||||
long lRegion[4];
|
||||
|
||||
DWORD dwNPCVnum;
|
||||
long lNPCX;
|
||||
long lNPCY;
|
||||
|
||||
DWORD dwGroupVnum;
|
||||
DWORD dwDependOnGroupVnum;
|
||||
} TObjectProto;
|
||||
|
||||
typedef struct SObject
|
||||
{
|
||||
DWORD dwID;
|
||||
DWORD dwLandID;
|
||||
DWORD dwVnum;
|
||||
long lMapIndex;
|
||||
long x, y;
|
||||
|
||||
float xRot;
|
||||
float yRot;
|
||||
float zRot;
|
||||
long lLife;
|
||||
} TObject;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
69
source-server/Srcs/Server/common/cache.h
Normal file
69
source-server/Srcs/Server/common/cache.h
Normal file
@ -0,0 +1,69 @@
|
||||
#ifndef __INC_COMMON_CACHE_H__
|
||||
#define __INC_COMMON_CACHE_H__
|
||||
|
||||
template <typename T> class cache
|
||||
{
|
||||
public:
|
||||
cache()
|
||||
: m_bNeedQuery(false), m_expireTime(600), m_lastUpdateTime(0)
|
||||
{
|
||||
m_lastFlushTime = time(0);
|
||||
|
||||
memset( &m_data, 0, sizeof(m_data) );
|
||||
}
|
||||
|
||||
T * Get(bool bUpdateTime = true)
|
||||
{
|
||||
if (bUpdateTime)
|
||||
m_lastUpdateTime = time(0);
|
||||
|
||||
return &m_data;
|
||||
}
|
||||
|
||||
void Put(T * pNew, bool bSkipQuery = false)
|
||||
{
|
||||
thecore_memcpy(&m_data, pNew, sizeof(T));
|
||||
m_lastUpdateTime = time(0);
|
||||
|
||||
if (!bSkipQuery)
|
||||
m_bNeedQuery = true;
|
||||
}
|
||||
|
||||
bool CheckFlushTimeout()
|
||||
{
|
||||
if (m_bNeedQuery && time(0) - m_lastFlushTime > m_expireTime)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckTimeout()
|
||||
{
|
||||
if (time(0) - m_lastUpdateTime > m_expireTime)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
if (!m_bNeedQuery)
|
||||
return;
|
||||
|
||||
OnFlush();
|
||||
m_bNeedQuery = false;
|
||||
m_lastFlushTime = time(0);
|
||||
}
|
||||
|
||||
virtual void OnFlush() = 0;
|
||||
|
||||
protected:
|
||||
T m_data;
|
||||
bool m_bNeedQuery;
|
||||
time_t m_expireTime;
|
||||
time_t m_lastUpdateTime;
|
||||
time_t m_lastFlushTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
40
source-server/Srcs/Server/common/d3dtype.h
Normal file
40
source-server/Srcs/Server/common/d3dtype.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef __INC_METIN_II_D3DTYPE_H__
|
||||
#define __INC_METIN_II_D3DTYPE_H__
|
||||
|
||||
typedef struct D3DXVECTOR2
|
||||
{
|
||||
float x, y;
|
||||
} D3DXVECTOR2, *LPD3DXVECTOR2;
|
||||
|
||||
typedef struct D3DXVECTOR3
|
||||
{
|
||||
float x, y, z;
|
||||
} D3DXVECTOR3, *LPD3DXVECTOR3;
|
||||
|
||||
typedef struct D3DXVECTOR4
|
||||
{
|
||||
float x, y, z, w;
|
||||
} D3DXVECTOR4, *LPD3DXVECTOR4;
|
||||
|
||||
typedef struct D3DXQUATERNION
|
||||
{
|
||||
float x, y, z, w;
|
||||
} D3DXQUATERNION, *LPD3DXQUATERNION;
|
||||
|
||||
typedef struct D3DXCOLOR
|
||||
{
|
||||
float r, g, b, a;
|
||||
} D3DXCOLOR, *LPD3DXCOLOR;
|
||||
|
||||
typedef struct _D3DCOLORVALUE
|
||||
{
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
} D3DCOLORVALUE;
|
||||
|
||||
typedef D3DXVECTOR3 D3DVECTOR;
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
447
source-server/Srcs/Server/common/item_length.h
Normal file
447
source-server/Srcs/Server/common/item_length.h
Normal file
@ -0,0 +1,447 @@
|
||||
#ifndef __INC_METIN2_ITEM_LENGTH_H__
|
||||
#define __INC_METIN2_ITEM_LENGTH_H__
|
||||
|
||||
#include "CommonDefines.h"
|
||||
|
||||
enum EItemMisc
|
||||
{
|
||||
ITEM_NAME_MAX_LEN = 24,
|
||||
ITEM_VALUES_MAX_NUM = 6,
|
||||
ITEM_SMALL_DESCR_MAX_LEN = 256,
|
||||
ITEM_LIMIT_MAX_NUM = 2,
|
||||
ITEM_APPLY_MAX_NUM = 3,
|
||||
ITEM_SOCKET_MAX_NUM = 3,
|
||||
ITEM_MAX_COUNT = 200,
|
||||
|
||||
ITEM_ATTRIBUTE_NORM_NUM = 5,
|
||||
ITEM_ATTRIBUTE_RARE_NUM = 2,
|
||||
|
||||
ITEM_ATTRIBUTE_NORM_START = 0,
|
||||
ITEM_ATTRIBUTE_NORM_END = ITEM_ATTRIBUTE_NORM_START + ITEM_ATTRIBUTE_NORM_NUM,
|
||||
|
||||
ITEM_ATTRIBUTE_RARE_START = ITEM_ATTRIBUTE_NORM_END,
|
||||
ITEM_ATTRIBUTE_RARE_END = ITEM_ATTRIBUTE_RARE_START + ITEM_ATTRIBUTE_RARE_NUM,
|
||||
|
||||
ITEM_ATTRIBUTE_MAX_NUM = ITEM_ATTRIBUTE_RARE_END, // 7
|
||||
ITEM_ATTRIBUTE_MAX_LEVEL = 5,
|
||||
ITEM_AWARD_WHY_MAX_LEN = 50,
|
||||
|
||||
REFINE_MATERIAL_MAX_NUM = 5,
|
||||
|
||||
ITEM_ELK_VNUM = 50026,
|
||||
};
|
||||
|
||||
const BYTE ITEM_SOCKET_REMAIN_SEC = 0;
|
||||
enum EItemValueIdice
|
||||
{
|
||||
ITEM_VALUE_DRAGON_SOUL_POLL_OUT_BONUS_IDX = 0,
|
||||
ITEM_VALUE_CHARGING_AMOUNT_IDX = 0,
|
||||
ITEM_VALUE_SECONDARY_COIN_UNIT_IDX = 0,
|
||||
};
|
||||
enum EItemDragonSoulSockets
|
||||
{
|
||||
ITEM_SOCKET_DRAGON_SOUL_ACTIVE_IDX = 2,
|
||||
ITEM_SOCKET_CHARGING_AMOUNT_IDX = 2,
|
||||
};
|
||||
|
||||
enum EItemUniqueSockets
|
||||
{
|
||||
ITEM_SOCKET_UNIQUE_SAVE_TIME = ITEM_SOCKET_MAX_NUM - 2,
|
||||
ITEM_SOCKET_UNIQUE_REMAIN_TIME = ITEM_SOCKET_MAX_NUM - 1
|
||||
};
|
||||
|
||||
enum EItemTypes
|
||||
{
|
||||
ITEM_NONE, //0
|
||||
ITEM_WEAPON,
|
||||
ITEM_ARMOR,
|
||||
ITEM_USE,
|
||||
ITEM_AUTOUSE, //4
|
||||
ITEM_MATERIAL, //5
|
||||
ITEM_SPECIAL,
|
||||
ITEM_TOOL, //7
|
||||
ITEM_LOTTERY,
|
||||
ITEM_ELK,
|
||||
ITEM_METIN, //10
|
||||
ITEM_CONTAINER, //11
|
||||
ITEM_FISH,
|
||||
ITEM_ROD, //13
|
||||
ITEM_RESOURCE, //14
|
||||
ITEM_CAMPFIRE, //15
|
||||
ITEM_UNIQUE, //16
|
||||
ITEM_SKILLBOOK, //17
|
||||
ITEM_QUEST, //18
|
||||
ITEM_POLYMORPH, //19
|
||||
ITEM_TREASURE_BOX,
|
||||
ITEM_TREASURE_KEY,
|
||||
ITEM_SKILLFORGET, //22
|
||||
ITEM_GIFTBOX, //23
|
||||
ITEM_PICK, //24
|
||||
ITEM_HAIR,
|
||||
ITEM_TOTEM,
|
||||
ITEM_BLEND,
|
||||
ITEM_COSTUME,
|
||||
ITEM_DS,
|
||||
ITEM_SPECIAL_DS,
|
||||
ITEM_EXTRACT,
|
||||
ITEM_SECONDARY_COIN,
|
||||
ITEM_RING,
|
||||
ITEM_BELT,
|
||||
ITEM_PET,
|
||||
};
|
||||
|
||||
enum EMetinSubTypes
|
||||
{
|
||||
METIN_NORMAL,
|
||||
METIN_GOLD,
|
||||
};
|
||||
|
||||
enum EWeaponSubTypes
|
||||
{
|
||||
WEAPON_SWORD,
|
||||
WEAPON_DAGGER,
|
||||
WEAPON_BOW,
|
||||
WEAPON_TWO_HANDED,
|
||||
WEAPON_BELL,
|
||||
WEAPON_FAN,
|
||||
WEAPON_ARROW,
|
||||
WEAPON_MOUNT_SPEAR,
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
WEAPON_CLAW = 8,
|
||||
#endif
|
||||
#ifdef ENABLE_QUIVER_SYSTEM
|
||||
WEAPON_QUIVER = 9,
|
||||
#endif
|
||||
WEAPON_NUM_TYPES,
|
||||
};
|
||||
|
||||
enum EArmorSubTypes
|
||||
{
|
||||
ARMOR_BODY,
|
||||
ARMOR_HEAD,
|
||||
ARMOR_SHIELD,
|
||||
ARMOR_WRIST,
|
||||
ARMOR_FOOTS,
|
||||
ARMOR_NECK,
|
||||
ARMOR_EAR,
|
||||
ARMOR_PENDANT, //7
|
||||
ARMOR_GLOVE, //8
|
||||
ARMOR_NUM_TYPES
|
||||
};
|
||||
|
||||
enum ECostumeSubTypes
|
||||
{
|
||||
COSTUME_BODY = ARMOR_BODY,
|
||||
COSTUME_HAIR = ARMOR_HEAD,
|
||||
#ifdef ENABLE_MOUNT_COSTUME_SYSTEM
|
||||
COSTUME_MOUNT = 2,
|
||||
#endif
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
COSTUME_ACCE = 3,
|
||||
#endif
|
||||
#ifdef ENABLE_WEAPON_COSTUME_SYSTEM
|
||||
COSTUME_WEAPON = 4,
|
||||
#endif
|
||||
COSTUME_NUM_TYPES,
|
||||
};
|
||||
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
enum EAcceInfo
|
||||
{
|
||||
ACCE_GRADE_VALUE_FIELD = 0,
|
||||
ACCE_ABSORPTION_SOCKET = 0,
|
||||
ACCE_ABSORBED_SOCKET = 1,
|
||||
ACCE_GRADE_1_ABS = 1,
|
||||
ACCE_GRADE_2_ABS = 5,
|
||||
ACCE_GRADE_3_ABS = 10,
|
||||
ACCE_GRADE_4_ABS_MIN = 11,
|
||||
ACCE_GRADE_4_ABS_MAX = 25,
|
||||
ACCE_GRADE_4_ABS_MAX_COMB = 19,
|
||||
ACCE_GRADE_4_ABS_RANGE = 5,
|
||||
ACCE_EFFECT_FROM_ABS = 19,
|
||||
ACCE_CLEAN_ATTR_VALUE0 = 7,
|
||||
ACCE_WINDOW_MAX_MATERIALS = 2,
|
||||
ACCE_GRADE_1_PRICE = 100000,
|
||||
ACCE_GRADE_2_PRICE = 200000,
|
||||
ACCE_GRADE_3_PRICE = 300000,
|
||||
ACCE_GRADE_4_PRICE = 500000,
|
||||
ACCE_COMBINE_GRADE_1 = 80,
|
||||
ACCE_COMBINE_GRADE_2 = 70,
|
||||
ACCE_COMBINE_GRADE_3 = 50,
|
||||
ACCE_COMBINE_GRADE_4 = 30,
|
||||
ACCE_REVERSAL_VNUM_1 = 39046,
|
||||
ACCE_REVERSAL_VNUM_2 = 90000,
|
||||
ACCE_BASE_VNUM = 85000,
|
||||
ACCE_EFFECT_VNUM = 500,
|
||||
};
|
||||
#endif
|
||||
|
||||
enum EDragonSoulSubType
|
||||
{
|
||||
DS_SLOT1,
|
||||
DS_SLOT2,
|
||||
DS_SLOT3,
|
||||
DS_SLOT4,
|
||||
DS_SLOT5,
|
||||
DS_SLOT6,
|
||||
DS_SLOT_MAX,
|
||||
};
|
||||
|
||||
enum EDragonSoulGradeTypes
|
||||
{
|
||||
DRAGON_SOUL_GRADE_NORMAL,
|
||||
DRAGON_SOUL_GRADE_BRILLIANT,
|
||||
DRAGON_SOUL_GRADE_RARE,
|
||||
DRAGON_SOUL_GRADE_ANCIENT,
|
||||
DRAGON_SOUL_GRADE_LEGENDARY,
|
||||
#ifdef ENABLE_DS_GRADE_MYTH
|
||||
DRAGON_SOUL_GRADE_MYTH,
|
||||
#endif
|
||||
DRAGON_SOUL_GRADE_MAX,
|
||||
};
|
||||
|
||||
enum EDragonSoulStepTypes
|
||||
{
|
||||
DRAGON_SOUL_STEP_LOWEST,
|
||||
DRAGON_SOUL_STEP_LOW,
|
||||
DRAGON_SOUL_STEP_MID,
|
||||
DRAGON_SOUL_STEP_HIGH,
|
||||
DRAGON_SOUL_STEP_HIGHEST,
|
||||
DRAGON_SOUL_STEP_MAX,
|
||||
};
|
||||
#define DRAGON_SOUL_STRENGTH_MAX 7
|
||||
|
||||
enum EDSInventoryMaxNum
|
||||
{
|
||||
DRAGON_SOUL_INVENTORY_MAX_NUM = DS_SLOT_MAX * DRAGON_SOUL_GRADE_MAX * DRAGON_SOUL_BOX_SIZE,
|
||||
};
|
||||
|
||||
enum EFishSubTypes
|
||||
{
|
||||
FISH_ALIVE,
|
||||
FISH_DEAD,
|
||||
};
|
||||
|
||||
enum EResourceSubTypes
|
||||
{
|
||||
RESOURCE_FISHBONE,
|
||||
RESOURCE_WATERSTONEPIECE,
|
||||
RESOURCE_WATERSTONE,
|
||||
RESOURCE_BLOOD_PEARL,
|
||||
RESOURCE_BLUE_PEARL,
|
||||
RESOURCE_WHITE_PEARL,
|
||||
RESOURCE_BUCKET,
|
||||
RESOURCE_CRYSTAL,
|
||||
RESOURCE_GEM,
|
||||
RESOURCE_STONE,
|
||||
RESOURCE_METIN,
|
||||
RESOURCE_ORE,
|
||||
};
|
||||
|
||||
enum EUniqueSubTypes
|
||||
{
|
||||
UNIQUE_NONE,
|
||||
UNIQUE_BOOK,
|
||||
UNIQUE_SPECIAL_RIDE,
|
||||
UNIQUE_SPECIAL_MOUNT_RIDE,
|
||||
};
|
||||
|
||||
enum EUseSubTypes
|
||||
{
|
||||
USE_POTION, // 0
|
||||
USE_TALISMAN,
|
||||
USE_TUNING,
|
||||
USE_MOVE,
|
||||
USE_TREASURE_BOX,
|
||||
USE_MONEYBAG,
|
||||
USE_BAIT,
|
||||
USE_ABILITY_UP,
|
||||
USE_AFFECT,
|
||||
USE_CREATE_STONE,
|
||||
USE_SPECIAL, // 10
|
||||
USE_POTION_NODELAY,
|
||||
USE_CLEAR,
|
||||
USE_INVISIBILITY,
|
||||
USE_DETACHMENT,
|
||||
USE_BUCKET,
|
||||
USE_POTION_CONTINUE,
|
||||
USE_CLEAN_SOCKET,
|
||||
USE_CHANGE_ATTRIBUTE,
|
||||
USE_ADD_ATTRIBUTE,
|
||||
USE_ADD_ACCESSORY_SOCKET, // 20
|
||||
USE_PUT_INTO_ACCESSORY_SOCKET,
|
||||
USE_ADD_ATTRIBUTE2,
|
||||
USE_RECIPE,
|
||||
USE_CHANGE_ATTRIBUTE2,
|
||||
USE_BIND,
|
||||
USE_UNBIND,
|
||||
USE_TIME_CHARGE_PER,
|
||||
USE_TIME_CHARGE_FIX, // 28
|
||||
USE_PUT_INTO_BELT_SOCKET,
|
||||
USE_PUT_INTO_RING_SOCKET,
|
||||
USE_CHANGE_COSTUME_ATTR, // 31
|
||||
USE_RESET_COSTUME_ATTR, // 32
|
||||
};
|
||||
|
||||
enum EExtractSubTypes
|
||||
{
|
||||
EXTRACT_DRAGON_SOUL,
|
||||
EXTRACT_DRAGON_HEART,
|
||||
};
|
||||
|
||||
enum EAutoUseSubTypes
|
||||
{
|
||||
AUTOUSE_POTION,
|
||||
AUTOUSE_ABILITY_UP,
|
||||
AUTOUSE_BOMB,
|
||||
AUTOUSE_GOLD,
|
||||
AUTOUSE_MONEYBAG,
|
||||
AUTOUSE_TREASURE_BOX
|
||||
};
|
||||
|
||||
enum EMaterialSubTypes
|
||||
{
|
||||
MATERIAL_LEATHER,
|
||||
MATERIAL_BLOOD,
|
||||
MATERIAL_ROOT,
|
||||
MATERIAL_NEEDLE,
|
||||
MATERIAL_JEWEL,
|
||||
MATERIAL_DS_REFINE_NORMAL,
|
||||
MATERIAL_DS_REFINE_BLESSED,
|
||||
MATERIAL_DS_REFINE_HOLLY,
|
||||
};
|
||||
|
||||
enum ESpecialSubTypes
|
||||
{
|
||||
SPECIAL_MAP,
|
||||
SPECIAL_KEY,
|
||||
SPECIAL_DOC,
|
||||
SPECIAL_SPIRIT,
|
||||
};
|
||||
|
||||
enum EToolSubTypes
|
||||
{
|
||||
TOOL_FISHING_ROD
|
||||
};
|
||||
|
||||
enum ELotterySubTypes
|
||||
{
|
||||
LOTTERY_TICKET,
|
||||
LOTTERY_INSTANT
|
||||
};
|
||||
|
||||
enum EItemFlag
|
||||
{
|
||||
ITEM_FLAG_REFINEABLE = (1 << 0),
|
||||
ITEM_FLAG_SAVE = (1 << 1),
|
||||
ITEM_FLAG_STACKABLE = (1 << 2),
|
||||
ITEM_FLAG_COUNT_PER_1GOLD = (1 << 3),
|
||||
ITEM_FLAG_SLOW_QUERY = (1 << 4),
|
||||
ITEM_FLAG_UNUSED01 = (1 << 5), // UNUSED
|
||||
ITEM_FLAG_UNIQUE = (1 << 6),
|
||||
ITEM_FLAG_MAKECOUNT = (1 << 7),
|
||||
ITEM_FLAG_IRREMOVABLE = (1 << 8),
|
||||
ITEM_FLAG_CONFIRM_WHEN_USE = (1 << 9),
|
||||
ITEM_FLAG_QUEST_USE = (1 << 10),
|
||||
ITEM_FLAG_QUEST_USE_MULTIPLE = (1 << 11),
|
||||
ITEM_FLAG_QUEST_GIVE = (1 << 12),
|
||||
ITEM_FLAG_LOG = (1 << 13),
|
||||
ITEM_FLAG_APPLICABLE = (1 << 14),
|
||||
};
|
||||
|
||||
enum EItemAntiFlag
|
||||
{
|
||||
ITEM_ANTIFLAG_FEMALE = (1 << 0),
|
||||
ITEM_ANTIFLAG_MALE = (1 << 1),
|
||||
ITEM_ANTIFLAG_WARRIOR = (1 << 2),
|
||||
ITEM_ANTIFLAG_ASSASSIN = (1 << 3),
|
||||
ITEM_ANTIFLAG_SURA = (1 << 4),
|
||||
ITEM_ANTIFLAG_SHAMAN = (1 << 5),
|
||||
ITEM_ANTIFLAG_GET = (1 << 6),
|
||||
ITEM_ANTIFLAG_DROP = (1 << 7),
|
||||
ITEM_ANTIFLAG_SELL = (1 << 8),
|
||||
ITEM_ANTIFLAG_EMPIRE_A = (1 << 9),
|
||||
ITEM_ANTIFLAG_EMPIRE_B = (1 << 10),
|
||||
ITEM_ANTIFLAG_EMPIRE_C = (1 << 11),
|
||||
ITEM_ANTIFLAG_SAVE = (1 << 12),
|
||||
ITEM_ANTIFLAG_GIVE = (1 << 13),
|
||||
ITEM_ANTIFLAG_PKDROP = (1 << 14),
|
||||
ITEM_ANTIFLAG_STACK = (1 << 15),
|
||||
ITEM_ANTIFLAG_MYSHOP = (1 << 16),
|
||||
ITEM_ANTIFLAG_SAFEBOX = (1 << 17),
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
ITEM_ANTIFLAG_WOLFMAN = (1 << 18),
|
||||
#endif
|
||||
};
|
||||
|
||||
enum EItemWearableFlag
|
||||
{
|
||||
WEARABLE_BODY = (1 << 0),
|
||||
WEARABLE_HEAD = (1 << 1),
|
||||
WEARABLE_FOOTS = (1 << 2),
|
||||
WEARABLE_WRIST = (1 << 3),
|
||||
WEARABLE_WEAPON = (1 << 4),
|
||||
WEARABLE_NECK = (1 << 5),
|
||||
WEARABLE_EAR = (1 << 6),
|
||||
WEARABLE_UNIQUE = (1 << 7),
|
||||
WEARABLE_SHIELD = (1 << 8),
|
||||
WEARABLE_ARROW = (1 << 9),
|
||||
WEARABLE_HAIR = (1 << 10),
|
||||
WEARABLE_ABILITY = (1 << 11),
|
||||
WEARABLE_PENDANT = (1 << 12),
|
||||
WEARABLE_GLOVE = (1 << 13),
|
||||
};
|
||||
|
||||
enum ELimitTypes
|
||||
{
|
||||
LIMIT_NONE,
|
||||
LIMIT_LEVEL,
|
||||
LIMIT_STR,
|
||||
LIMIT_DEX,
|
||||
LIMIT_INT,
|
||||
LIMIT_CON,
|
||||
LIMIT_PCBANG, //reserved for backwards compatibility
|
||||
LIMIT_REAL_TIME,
|
||||
LIMIT_REAL_TIME_START_FIRST_USE,
|
||||
LIMIT_TIMER_BASED_ON_WEAR,
|
||||
LIMIT_MAX_NUM,
|
||||
};
|
||||
|
||||
enum EAttrAddonTypes
|
||||
{
|
||||
ATTR_ADDON_NONE,
|
||||
// positive values are reserved for set
|
||||
ATTR_DAMAGE_ADDON = -1,
|
||||
};
|
||||
|
||||
enum ERefineType
|
||||
{
|
||||
REFINE_TYPE_NORMAL,
|
||||
REFINE_TYPE_NOT_USED1,
|
||||
REFINE_TYPE_SCROLL,
|
||||
REFINE_TYPE_HYUNIRON,
|
||||
REFINE_TYPE_MONEY_ONLY,
|
||||
REFINE_TYPE_MUSIN,
|
||||
REFINE_TYPE_BDRAGON,
|
||||
};
|
||||
|
||||
enum EPetType
|
||||
{
|
||||
PET_EGG, //0
|
||||
PET_UPBRINGING, //1
|
||||
PET_BAG, //2
|
||||
PET_FEEDSTUFF, //3
|
||||
PET_SKILL, //4
|
||||
PET_SKILL_DEL_BOOK, //5
|
||||
PET_NAME_CHANGE, //6
|
||||
PET_EXPFOOD, //7
|
||||
PET_SKILL_ALL_DEL_BOOK, //8
|
||||
PET_EXPFOOD_PER, //9
|
||||
PET_ATTR_DETERMINE, //10
|
||||
PET_ATTR_CHANGE, //11
|
||||
PET_PAY, //12
|
||||
PET_PRIMIUM_FEEDSTUFF, //13
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
873
source-server/Srcs/Server/common/length.h
Normal file
873
source-server/Srcs/Server/common/length.h
Normal file
@ -0,0 +1,873 @@
|
||||
#ifndef __INC_METIN_II_LENGTH_H__
|
||||
#define __INC_METIN_II_LENGTH_H__
|
||||
|
||||
#include "CommonDefines.h"
|
||||
|
||||
#define WORD_MAX 0xffff
|
||||
enum EMisc
|
||||
{
|
||||
MAX_HOST_LENGTH = 15,
|
||||
IP_ADDRESS_LENGTH = 15,
|
||||
LOGIN_MAX_LEN = 30,
|
||||
PASSWD_MAX_LEN = 16,
|
||||
#ifdef ENABLE_PLAYER_PER_ACCOUNT5
|
||||
PLAYER_PER_ACCOUNT = 5,
|
||||
#else
|
||||
PLAYER_PER_ACCOUNT = 4,
|
||||
#endif
|
||||
ACCOUNT_STATUS_MAX_LEN = 8,
|
||||
CHARACTER_NAME_MAX_LEN = 24,
|
||||
SHOP_SIGN_MAX_LEN = 32,
|
||||
INVENTORY_PAGE_COLUMN = 5, // 5 (default)
|
||||
INVENTORY_PAGE_ROW = 9, // 9 (default)
|
||||
INVENTORY_PAGE_SIZE = INVENTORY_PAGE_COLUMN*INVENTORY_PAGE_ROW,
|
||||
#ifdef ENABLE_EXTEND_INVEN_SYSTEM
|
||||
INVENTORY_PAGE_COUNT = 4, // 2 (default)
|
||||
#else
|
||||
INVENTORY_PAGE_COUNT = 2, // 2 (default)
|
||||
#endif
|
||||
INVENTORY_MAX_NUM = INVENTORY_PAGE_SIZE*INVENTORY_PAGE_COUNT, // 90 (default)
|
||||
ABILITY_MAX_NUM = 50,
|
||||
EMPIRE_MAX_NUM = 4,
|
||||
BANWORD_MAX_LEN = 24,
|
||||
SOCIAL_ID_MAX_LEN = 18,
|
||||
|
||||
GUILD_NAME_MAX_LEN = 12,
|
||||
|
||||
SHOP_HOST_ITEM_MAX_NUM = 40,
|
||||
SHOP_GUEST_ITEM_MAX_NUM = 18,
|
||||
|
||||
SHOP_PRICELIST_MAX_NUM = 40,
|
||||
|
||||
CHAT_MAX_LEN = 512,
|
||||
|
||||
QUICKSLOT_MAX_NUM = 36,
|
||||
|
||||
JOURNAL_MAX_NUM = 2,
|
||||
|
||||
QUERY_MAX_LEN = 8192,
|
||||
|
||||
FILE_MAX_LEN = 128,
|
||||
|
||||
PLAYER_EXP_TABLE_MAX = 120,
|
||||
PLAYER_MAX_LEVEL_CONST = 250,
|
||||
|
||||
GUILD_MAX_LEVEL = 20,
|
||||
MOB_MAX_LEVEL = 100,
|
||||
|
||||
ATTRIBUTE_MAX_VALUE = 20,
|
||||
CHARACTER_PATH_MAX_NUM = 64,
|
||||
SKILL_MAX_NUM = 255,
|
||||
SKILLBOOK_DELAY_MIN = 64800,
|
||||
SKILLBOOK_DELAY_MAX = 108000,
|
||||
SKILL_MAX_LEVEL = 40,
|
||||
|
||||
APPLY_NAME_MAX_LEN = 32,
|
||||
EVENT_FLAG_NAME_MAX_LEN = 32,
|
||||
|
||||
MOB_SKILL_MAX_NUM = 5,
|
||||
|
||||
POINT_MAX_NUM = 255,
|
||||
DRAGON_SOUL_BOX_SIZE = 32,
|
||||
DRAGON_SOUL_BOX_COLUMN_NUM = 8,
|
||||
DRAGON_SOUL_BOX_ROW_NUM = DRAGON_SOUL_BOX_SIZE / DRAGON_SOUL_BOX_COLUMN_NUM,
|
||||
DRAGON_SOUL_REFINE_GRID_SIZE = 15,
|
||||
MAX_AMOUNT_OF_MALL_BONUS = 20,
|
||||
|
||||
WEAR_MAX_NUM = 32,
|
||||
|
||||
//LIMIT_GOLD
|
||||
GOLD_MAX = 2000000000,
|
||||
#ifdef ENABLE_CHEQUE_SYSTEM
|
||||
CHEQUE_MAX = 1000,
|
||||
CHEQUE_VNUM = 2,
|
||||
#ifndef ENABLE_IKASHOP_RENEWAL
|
||||
YANG_PER_CHEQUE = 100000000,
|
||||
#endif
|
||||
#endif
|
||||
//END_LIMIT_GOLD
|
||||
|
||||
SHOP_TAB_NAME_MAX = 32,
|
||||
SHOP_TAB_COUNT_MAX = 3,
|
||||
|
||||
BELT_INVENTORY_SLOT_WIDTH = 4,
|
||||
BELT_INVENTORY_SLOT_HEIGHT= 4,
|
||||
|
||||
BELT_INVENTORY_SLOT_COUNT = BELT_INVENTORY_SLOT_WIDTH * BELT_INVENTORY_SLOT_HEIGHT,
|
||||
};
|
||||
|
||||
enum EWearPositions
|
||||
{
|
||||
WEAR_BODY, // 0
|
||||
WEAR_HEAD, // 1
|
||||
WEAR_FOOTS, // 2
|
||||
WEAR_WRIST, // 3
|
||||
WEAR_WEAPON, // 4
|
||||
WEAR_NECK, // 5
|
||||
WEAR_EAR, // 6
|
||||
WEAR_UNIQUE1, // 7
|
||||
WEAR_UNIQUE2, // 8
|
||||
WEAR_ARROW, // 9
|
||||
WEAR_SHIELD, // 10
|
||||
WEAR_ABILITY1, // 11
|
||||
WEAR_ABILITY2, // 12
|
||||
WEAR_ABILITY3, // 13
|
||||
WEAR_ABILITY4, // 14
|
||||
WEAR_ABILITY5, // 15
|
||||
WEAR_ABILITY6, // 16
|
||||
WEAR_ABILITY7, // 17
|
||||
WEAR_ABILITY8, // 18
|
||||
WEAR_COSTUME_BODY, // 19
|
||||
WEAR_COSTUME_HAIR, // 20
|
||||
|
||||
#ifdef ENABLE_MOUNT_COSTUME_SYSTEM
|
||||
WEAR_COSTUME_MOUNT, // 21
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
WEAR_COSTUME_ACCE, // 22
|
||||
#endif
|
||||
|
||||
WEAR_BELT, // 23
|
||||
|
||||
#ifdef ENABLE_WEAPON_COSTUME_SYSTEM
|
||||
WEAR_COSTUME_WEAPON,// 24
|
||||
#endif
|
||||
|
||||
WEAR_PENDANT, // 25
|
||||
WEAR_GLOVE, // 26
|
||||
|
||||
WEAR_MAX = 32
|
||||
};
|
||||
|
||||
enum EDragonSoulDeckType
|
||||
{
|
||||
DRAGON_SOUL_DECK_0,
|
||||
DRAGON_SOUL_DECK_1,
|
||||
DRAGON_SOUL_DECK_MAX_NUM = 2,
|
||||
|
||||
DRAGON_SOUL_DECK_RESERVED_MAX_NUM = 3,
|
||||
};
|
||||
|
||||
enum ESex
|
||||
{
|
||||
SEX_MALE,
|
||||
SEX_FEMALE
|
||||
};
|
||||
|
||||
enum EDirection
|
||||
{
|
||||
DIR_NORTH,
|
||||
DIR_NORTHEAST,
|
||||
DIR_EAST,
|
||||
DIR_SOUTHEAST,
|
||||
DIR_SOUTH,
|
||||
DIR_SOUTHWEST,
|
||||
DIR_WEST,
|
||||
DIR_NORTHWEST,
|
||||
DIR_MAX_NUM
|
||||
};
|
||||
|
||||
#define ABILITY_MAX_LEVEL 10
|
||||
|
||||
enum EAbilityDifficulty
|
||||
{
|
||||
DIFFICULTY_EASY,
|
||||
DIFFICULTY_NORMAL,
|
||||
DIFFICULTY_HARD,
|
||||
DIFFICULTY_VERY_HARD,
|
||||
DIFFICULTY_NUM_TYPES
|
||||
};
|
||||
|
||||
enum EAbilityCategory
|
||||
{
|
||||
CATEGORY_PHYSICAL,
|
||||
CATEGORY_MENTAL,
|
||||
CATEGORY_ATTRIBUTE,
|
||||
CATEGORY_NUM_TYPES
|
||||
};
|
||||
|
||||
enum EJobs
|
||||
{
|
||||
JOB_WARRIOR,
|
||||
JOB_ASSASSIN,
|
||||
JOB_SURA,
|
||||
JOB_SHAMAN,
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
JOB_WOLFMAN,
|
||||
#endif
|
||||
JOB_MAX_NUM
|
||||
};
|
||||
|
||||
enum ESkillGroups
|
||||
{
|
||||
SKILL_GROUP_MAX_NUM = 2,
|
||||
};
|
||||
|
||||
enum ERaceFlags
|
||||
{
|
||||
RACE_FLAG_ANIMAL = (1 << 0),
|
||||
RACE_FLAG_UNDEAD = (1 << 1),
|
||||
RACE_FLAG_DEVIL = (1 << 2),
|
||||
RACE_FLAG_HUMAN = (1 << 3),
|
||||
RACE_FLAG_ORC = (1 << 4),
|
||||
RACE_FLAG_MILGYO = (1 << 5),
|
||||
RACE_FLAG_INSECT = (1 << 6),
|
||||
RACE_FLAG_FIRE = (1 << 7),
|
||||
RACE_FLAG_ICE = (1 << 8),
|
||||
RACE_FLAG_DESERT = (1 << 9),
|
||||
RACE_FLAG_TREE = (1 << 10),
|
||||
RACE_FLAG_ATT_ELEC = (1 << 11),
|
||||
RACE_FLAG_ATT_FIRE = (1 << 12),
|
||||
RACE_FLAG_ATT_ICE = (1 << 13),
|
||||
RACE_FLAG_ATT_WIND = (1 << 14),
|
||||
RACE_FLAG_ATT_EARTH = (1 << 15),
|
||||
RACE_FLAG_ATT_DARK = (1 << 16),
|
||||
RACE_FLAG_CZ = (1 << 17), // 1<<11 official
|
||||
};
|
||||
|
||||
enum ELoads
|
||||
{
|
||||
LOAD_NONE,
|
||||
LOAD_LIGHT,
|
||||
LOAD_NORMAL,
|
||||
LOAD_HEAVY,
|
||||
LOAD_MASSIVE
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
QUICKSLOT_TYPE_NONE,
|
||||
QUICKSLOT_TYPE_ITEM,
|
||||
QUICKSLOT_TYPE_SKILL,
|
||||
QUICKSLOT_TYPE_COMMAND,
|
||||
QUICKSLOT_TYPE_MAX_NUM,
|
||||
};
|
||||
|
||||
enum EParts
|
||||
{
|
||||
PART_MAIN,
|
||||
PART_WEAPON,
|
||||
PART_HEAD,
|
||||
PART_HAIR,
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
PART_ACCE,
|
||||
#endif
|
||||
PART_MAX_NUM,
|
||||
PART_WEAPON_SUB,
|
||||
};
|
||||
|
||||
enum EChatType
|
||||
{
|
||||
CHAT_TYPE_TALKING,
|
||||
CHAT_TYPE_INFO,
|
||||
CHAT_TYPE_NOTICE,
|
||||
CHAT_TYPE_PARTY,
|
||||
CHAT_TYPE_GUILD,
|
||||
CHAT_TYPE_COMMAND,
|
||||
CHAT_TYPE_SHOUT,
|
||||
CHAT_TYPE_WHISPER,
|
||||
CHAT_TYPE_BIG_NOTICE,
|
||||
CHAT_TYPE_MONARCH_NOTICE,
|
||||
#ifdef ENABLE_DICE_SYSTEM
|
||||
CHAT_TYPE_DICE_INFO, //11
|
||||
#endif
|
||||
CHAT_TYPE_MAX_NUM
|
||||
};
|
||||
|
||||
enum EWhisperType
|
||||
{
|
||||
WHISPER_TYPE_NORMAL = 0,
|
||||
WHISPER_TYPE_NOT_EXIST = 1,
|
||||
WHISPER_TYPE_TARGET_BLOCKED = 2,
|
||||
WHISPER_TYPE_SENDER_BLOCKED = 3,
|
||||
WHISPER_TYPE_ERROR = 4,
|
||||
WHISPER_TYPE_GM = 5,
|
||||
WHISPER_TYPE_SYSTEM = 0xFF
|
||||
};
|
||||
|
||||
enum ECharacterPosition
|
||||
{
|
||||
POSITION_GENERAL,
|
||||
POSITION_BATTLE,
|
||||
POSITION_DYING,
|
||||
POSITION_SITTING_CHAIR,
|
||||
POSITION_SITTING_GROUND,
|
||||
POSITION_INTRO,
|
||||
POSITION_MAX_NUM
|
||||
};
|
||||
|
||||
enum EGMLevels
|
||||
{
|
||||
GM_PLAYER,
|
||||
GM_LOW_WIZARD,
|
||||
GM_WIZARD,
|
||||
GM_HIGH_WIZARD,
|
||||
GM_GOD,
|
||||
GM_IMPLEMENTOR,
|
||||
GM_DISABLE,
|
||||
};
|
||||
|
||||
enum EMobRank
|
||||
{
|
||||
MOB_RANK_PAWN,
|
||||
MOB_RANK_S_PAWN,
|
||||
MOB_RANK_KNIGHT,
|
||||
MOB_RANK_S_KNIGHT,
|
||||
MOB_RANK_BOSS,
|
||||
MOB_RANK_KING,
|
||||
MOB_RANK_MAX_NUM
|
||||
};
|
||||
|
||||
enum ECharType
|
||||
{
|
||||
CHAR_TYPE_MONSTER,
|
||||
CHAR_TYPE_NPC,
|
||||
CHAR_TYPE_STONE,
|
||||
CHAR_TYPE_WARP,
|
||||
CHAR_TYPE_DOOR,
|
||||
CHAR_TYPE_BUILDING,
|
||||
CHAR_TYPE_PC,
|
||||
CHAR_TYPE_POLYMORPH_PC,
|
||||
CHAR_TYPE_HORSE,
|
||||
CHAR_TYPE_GOTO
|
||||
};
|
||||
|
||||
enum EBattleType
|
||||
{
|
||||
BATTLE_TYPE_MELEE,
|
||||
BATTLE_TYPE_RANGE,
|
||||
BATTLE_TYPE_MAGIC,
|
||||
BATTLE_TYPE_SPECIAL,
|
||||
BATTLE_TYPE_POWER,
|
||||
BATTLE_TYPE_TANKER,
|
||||
BATTLE_TYPE_SUPER_POWER,
|
||||
BATTLE_TYPE_SUPER_TANKER,
|
||||
BATTLE_TYPE_MAX_NUM
|
||||
};
|
||||
|
||||
enum EApplyTypes
|
||||
{
|
||||
APPLY_NONE, // 0
|
||||
APPLY_MAX_HP, // 1
|
||||
APPLY_MAX_SP, // 2
|
||||
APPLY_CON, // 3
|
||||
APPLY_INT, // 4
|
||||
APPLY_STR, // 5
|
||||
APPLY_DEX, // 6
|
||||
APPLY_ATT_SPEED, // 7
|
||||
APPLY_MOV_SPEED, // 8
|
||||
APPLY_CAST_SPEED, // 9
|
||||
APPLY_HP_REGEN, // 10
|
||||
APPLY_SP_REGEN, // 11
|
||||
APPLY_POISON_PCT, // 12
|
||||
APPLY_STUN_PCT, // 13
|
||||
APPLY_SLOW_PCT, // 14
|
||||
APPLY_CRITICAL_PCT, // 15
|
||||
APPLY_PENETRATE_PCT, // 16
|
||||
APPLY_ATTBONUS_HUMAN, // 17
|
||||
APPLY_ATTBONUS_ANIMAL, // 18
|
||||
APPLY_ATTBONUS_ORC, // 19
|
||||
APPLY_ATTBONUS_MILGYO, // 20
|
||||
APPLY_ATTBONUS_UNDEAD, // 21
|
||||
APPLY_ATTBONUS_DEVIL, // 22
|
||||
APPLY_STEAL_HP, // 23
|
||||
APPLY_STEAL_SP, // 24
|
||||
APPLY_MANA_BURN_PCT, // 25
|
||||
APPLY_DAMAGE_SP_RECOVER, // 26
|
||||
APPLY_BLOCK, // 27
|
||||
APPLY_DODGE, // 28
|
||||
APPLY_RESIST_SWORD, // 29
|
||||
APPLY_RESIST_TWOHAND, // 30
|
||||
APPLY_RESIST_DAGGER, // 31
|
||||
APPLY_RESIST_BELL, // 32
|
||||
APPLY_RESIST_FAN, // 33
|
||||
APPLY_RESIST_BOW, // 34
|
||||
APPLY_RESIST_FIRE, // 35
|
||||
APPLY_RESIST_ELEC, // 36
|
||||
APPLY_RESIST_MAGIC, // 37
|
||||
APPLY_RESIST_WIND, // 38
|
||||
APPLY_REFLECT_MELEE, // 39
|
||||
APPLY_REFLECT_CURSE, // 40
|
||||
APPLY_POISON_REDUCE, // 41
|
||||
APPLY_KILL_SP_RECOVER, // 42
|
||||
APPLY_EXP_DOUBLE_BONUS, // 43
|
||||
APPLY_GOLD_DOUBLE_BONUS, // 44
|
||||
APPLY_ITEM_DROP_BONUS, // 45
|
||||
APPLY_POTION_BONUS, // 46
|
||||
APPLY_KILL_HP_RECOVER, // 47
|
||||
APPLY_IMMUNE_STUN, // 48
|
||||
APPLY_IMMUNE_SLOW, // 49
|
||||
APPLY_IMMUNE_FALL, // 50
|
||||
APPLY_SKILL, // 51
|
||||
APPLY_BOW_DISTANCE, // 52
|
||||
APPLY_ATT_GRADE_BONUS, // 53
|
||||
APPLY_DEF_GRADE_BONUS, // 54
|
||||
APPLY_MAGIC_ATT_GRADE, // 55
|
||||
APPLY_MAGIC_DEF_GRADE, // 56
|
||||
APPLY_CURSE_PCT, // 57
|
||||
APPLY_MAX_STAMINA, // 58
|
||||
APPLY_ATTBONUS_WARRIOR, // 59
|
||||
APPLY_ATTBONUS_ASSASSIN, // 60
|
||||
APPLY_ATTBONUS_SURA, // 61
|
||||
APPLY_ATTBONUS_SHAMAN, // 62
|
||||
APPLY_ATTBONUS_MONSTER, // 63
|
||||
APPLY_MALL_ATTBONUS,
|
||||
APPLY_MALL_DEFBONUS,
|
||||
APPLY_MALL_EXPBONUS,
|
||||
APPLY_MALL_ITEMBONUS,
|
||||
APPLY_MALL_GOLDBONUS,
|
||||
APPLY_MAX_HP_PCT,
|
||||
APPLY_MAX_SP_PCT,
|
||||
APPLY_SKILL_DAMAGE_BONUS,
|
||||
APPLY_NORMAL_HIT_DAMAGE_BONUS,
|
||||
APPLY_SKILL_DEFEND_BONUS,
|
||||
APPLY_NORMAL_HIT_DEFEND_BONUS,
|
||||
APPLY_PC_BANG_EXP_BONUS, //reserved for backwards compatibility
|
||||
APPLY_PC_BANG_DROP_BONUS, //reserved for backwards compatibility
|
||||
|
||||
APPLY_EXTRACT_HP_PCT,
|
||||
|
||||
APPLY_RESIST_WARRIOR,
|
||||
APPLY_RESIST_ASSASSIN,
|
||||
APPLY_RESIST_SURA,
|
||||
APPLY_RESIST_SHAMAN,
|
||||
APPLY_ENERGY,
|
||||
APPLY_DEF_GRADE,
|
||||
APPLY_COSTUME_ATTR_BONUS,
|
||||
APPLY_MAGIC_ATTBONUS_PER,
|
||||
APPLY_MELEE_MAGIC_ATTBONUS_PER,
|
||||
|
||||
APPLY_RESIST_ICE,
|
||||
APPLY_RESIST_EARTH,
|
||||
APPLY_RESIST_DARK,
|
||||
|
||||
APPLY_ANTI_CRITICAL_PCT,
|
||||
APPLY_ANTI_PENETRATE_PCT,
|
||||
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
APPLY_BLEEDING_REDUCE = 92, //92
|
||||
APPLY_BLEEDING_PCT = 93, //93
|
||||
APPLY_ATTBONUS_WOLFMAN = 94,
|
||||
APPLY_RESIST_WOLFMAN = 95,
|
||||
APPLY_RESIST_CLAW = 96,
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
APPLY_ACCEDRAIN_RATE = 97, //97
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MAGIC_REDUCTION_SYSTEM
|
||||
APPLY_RESIST_MAGIC_REDUCTION = 98, //98
|
||||
#endif
|
||||
|
||||
APPLY_ENCHANT_ELECT = 99,
|
||||
APPLY_ENCHANT_FIRE = 100,
|
||||
APPLY_ENCHANT_ICE = 101,
|
||||
APPLY_ENCHANT_WIND = 102,
|
||||
APPLY_ENCHANT_EARTH = 103,
|
||||
APPLY_ENCHANT_DARK = 104,
|
||||
|
||||
APPLY_ATTBONUS_CZ = 105,
|
||||
APPLY_ATTBONUS_INSECT = 106,
|
||||
APPLY_ATTBONUS_DESERT = 107,
|
||||
APPLY_ATTBONUS_SWORD = 108,
|
||||
APPLY_ATTBONUS_TWOHAND = 109,
|
||||
APPLY_ATTBONUS_DAGGER = 110,
|
||||
APPLY_ATTBONUS_BELL = 111,
|
||||
APPLY_ATTBONUS_FAN = 112,
|
||||
APPLY_ATTBONUS_BOW = 113,
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
APPLY_ATTBONUS_CLAW = 114,
|
||||
#endif
|
||||
|
||||
APPLY_RESIST_HUMAN = 115,
|
||||
APPLY_RESIST_MOUNT_FALL = 116,
|
||||
APPLY_MOUNT = 118,
|
||||
|
||||
MAX_APPLY_NUM = 127,
|
||||
};
|
||||
|
||||
enum EOnClickEvents
|
||||
{
|
||||
ON_CLICK_NONE,
|
||||
ON_CLICK_SHOP,
|
||||
ON_CLICK_TALK,
|
||||
ON_CLICK_MAX_NUM
|
||||
};
|
||||
|
||||
enum EOnIdleEvents
|
||||
{
|
||||
ON_IDLE_NONE,
|
||||
ON_IDLE_GENERAL,
|
||||
ON_IDLE_MAX_NUM
|
||||
};
|
||||
|
||||
enum EWindows
|
||||
{
|
||||
RESERVED_WINDOW,
|
||||
INVENTORY,
|
||||
EQUIPMENT,
|
||||
SAFEBOX,
|
||||
MALL,
|
||||
DRAGON_SOUL_INVENTORY,
|
||||
BELT_INVENTORY,
|
||||
GROUND,
|
||||
WINDOW_TYPE_MAX,
|
||||
};
|
||||
|
||||
enum EMobSizes
|
||||
{
|
||||
MOBSIZE_RESERVED,
|
||||
MOBSIZE_SMALL,
|
||||
MOBSIZE_MEDIUM,
|
||||
MOBSIZE_BIG
|
||||
};
|
||||
|
||||
enum EAIFlags
|
||||
{
|
||||
AIFLAG_AGGRESSIVE = (1 << 0),
|
||||
AIFLAG_NOMOVE = (1 << 1),
|
||||
AIFLAG_COWARD = (1 << 2),
|
||||
AIFLAG_NOATTACKSHINSU = (1 << 3),
|
||||
AIFLAG_NOATTACKJINNO = (1 << 4),
|
||||
AIFLAG_NOATTACKCHUNJO = (1 << 5),
|
||||
AIFLAG_ATTACKMOB = (1 << 6),
|
||||
AIFLAG_BERSERK = (1 << 7),
|
||||
AIFLAG_STONESKIN = (1 << 8),
|
||||
AIFLAG_GODSPEED = (1 << 9),
|
||||
AIFLAG_DEATHBLOW = (1 << 10),
|
||||
AIFLAG_REVIVE = (1 << 11),
|
||||
AIFLAG_HEALER = (1 << 12),
|
||||
AIFLAG_COUNT = (1 << 13),
|
||||
AIFLAG_NORECOVERY = (1 << 14),
|
||||
AIFLAG_REFLECT = (1 << 15),
|
||||
AIFLAG_FALL = (1 << 16),
|
||||
AIFLAG_VIT = (1 << 17),
|
||||
AIFLAG_RATTSPEED = (1 << 18),
|
||||
AIFLAG_RCASTSPEED = (1 << 19),
|
||||
AIFLAG_RHP_REGEN = (1 << 20),
|
||||
AIFLAG_TIMEVIT = (1 << 21),
|
||||
};
|
||||
|
||||
enum EMobStatType
|
||||
{
|
||||
MOB_STATTYPE_POWER,
|
||||
MOB_STATTYPE_TANKER,
|
||||
MOB_STATTYPE_SUPER_POWER,
|
||||
MOB_STATTYPE_SUPER_TANKER,
|
||||
MOB_STATTYPE_RANGE,
|
||||
MOB_STATTYPE_MAGIC,
|
||||
MOB_STATTYPE_MAX_NUM
|
||||
};
|
||||
|
||||
enum EImmuneFlags
|
||||
{
|
||||
IMMUNE_STUN = (1 << 0),
|
||||
IMMUNE_SLOW = (1 << 1),
|
||||
IMMUNE_FALL = (1 << 2),
|
||||
IMMUNE_CURSE = (1 << 3),
|
||||
IMMUNE_POISON = (1 << 4),
|
||||
IMMUNE_TERROR = (1 << 5),
|
||||
IMMUNE_REFLECT = (1 << 6),
|
||||
};
|
||||
|
||||
enum EMobEnchants
|
||||
{
|
||||
MOB_ENCHANT_CURSE,
|
||||
MOB_ENCHANT_SLOW,
|
||||
MOB_ENCHANT_POISON,
|
||||
MOB_ENCHANT_STUN,
|
||||
MOB_ENCHANT_CRITICAL,
|
||||
MOB_ENCHANT_PENETRATE,
|
||||
#if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON)
|
||||
MOB_ENCHANT_BLEEDING,
|
||||
#endif
|
||||
MOB_ENCHANTS_MAX_NUM
|
||||
};
|
||||
|
||||
enum EMobResists
|
||||
{
|
||||
MOB_RESIST_SWORD,
|
||||
MOB_RESIST_TWOHAND,
|
||||
MOB_RESIST_DAGGER,
|
||||
MOB_RESIST_BELL,
|
||||
MOB_RESIST_FAN,
|
||||
MOB_RESIST_BOW,
|
||||
MOB_RESIST_FIRE,
|
||||
MOB_RESIST_ELECT,
|
||||
MOB_RESIST_MAGIC,
|
||||
MOB_RESIST_WIND,
|
||||
MOB_RESIST_POISON,
|
||||
#if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_CLAW_AS_DAGGER)
|
||||
MOB_RESIST_CLAW,
|
||||
#endif
|
||||
#if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON)
|
||||
MOB_RESIST_BLEEDING,
|
||||
#endif
|
||||
MOB_RESISTS_MAX_NUM
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SKILL_ATTR_TYPE_NORMAL = 1,
|
||||
SKILL_ATTR_TYPE_MELEE,
|
||||
SKILL_ATTR_TYPE_RANGE,
|
||||
SKILL_ATTR_TYPE_MAGIC
|
||||
/*
|
||||
SKILL_ATTR_TYPE_FIRE,
|
||||
SKILL_ATTR_TYPE_ICE,
|
||||
SKILL_ATTR_TYPE_ELEC,
|
||||
SKILL_ATTR_TYPE_DARK,
|
||||
*/
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SKILL_NORMAL,
|
||||
SKILL_MASTER,
|
||||
SKILL_GRAND_MASTER,
|
||||
SKILL_PERFECT_MASTER,
|
||||
};
|
||||
|
||||
enum EGuildWarType
|
||||
{
|
||||
GUILD_WAR_TYPE_FIELD,
|
||||
GUILD_WAR_TYPE_BATTLE,
|
||||
GUILD_WAR_TYPE_FLAG,
|
||||
GUILD_WAR_TYPE_MAX_NUM
|
||||
};
|
||||
|
||||
enum EGuildWarState
|
||||
{
|
||||
GUILD_WAR_NONE,
|
||||
GUILD_WAR_SEND_DECLARE,
|
||||
GUILD_WAR_REFUSE,
|
||||
GUILD_WAR_RECV_DECLARE,
|
||||
GUILD_WAR_WAIT_START,
|
||||
GUILD_WAR_CANCEL,
|
||||
GUILD_WAR_ON_WAR,
|
||||
GUILD_WAR_END,
|
||||
GUILD_WAR_OVER,
|
||||
GUILD_WAR_RESERVE,
|
||||
|
||||
GUILD_WAR_DURATION = 30*60,
|
||||
GUILD_WAR_WIN_POINT = 1000,
|
||||
GUILD_WAR_LADDER_HALF_PENALTY_TIME = 12*60*60,
|
||||
};
|
||||
|
||||
enum EAttributeSet
|
||||
{
|
||||
ATTRIBUTE_SET_WEAPON,
|
||||
ATTRIBUTE_SET_BODY,
|
||||
ATTRIBUTE_SET_WRIST,
|
||||
ATTRIBUTE_SET_FOOTS,
|
||||
ATTRIBUTE_SET_NECK,
|
||||
ATTRIBUTE_SET_HEAD,
|
||||
ATTRIBUTE_SET_SHIELD,
|
||||
ATTRIBUTE_SET_EAR,
|
||||
#ifdef ENABLE_ITEM_ATTR_COSTUME
|
||||
ATTRIBUTE_SET_COSTUME_BODY,
|
||||
ATTRIBUTE_SET_COSTUME_HAIR,
|
||||
#if defined(ENABLE_ITEM_ATTR_COSTUME) && defined(ENABLE_WEAPON_COSTUME_SYSTEM)
|
||||
ATTRIBUTE_SET_COSTUME_WEAPON,
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENABLE_PENDANT_SYSTEM
|
||||
ATTRIBUTE_SET_PENDANT,
|
||||
#endif
|
||||
#ifdef ENABLE_GLOVE_SYSTEM
|
||||
ATTRIBUTE_SET_GLOVE,
|
||||
#endif
|
||||
ATTRIBUTE_SET_MAX_NUM
|
||||
};
|
||||
|
||||
enum EPrivType
|
||||
{
|
||||
PRIV_NONE,
|
||||
PRIV_ITEM_DROP,
|
||||
PRIV_GOLD_DROP,
|
||||
PRIV_GOLD10_DROP,
|
||||
PRIV_EXP_PCT,
|
||||
MAX_PRIV_NUM,
|
||||
};
|
||||
|
||||
enum EMoneyLogType
|
||||
{
|
||||
MONEY_LOG_RESERVED,
|
||||
MONEY_LOG_MONSTER,
|
||||
MONEY_LOG_SHOP,
|
||||
MONEY_LOG_REFINE,
|
||||
MONEY_LOG_QUEST,
|
||||
MONEY_LOG_GUILD,
|
||||
MONEY_LOG_MISC,
|
||||
MONEY_LOG_MONSTER_KILL,
|
||||
MONEY_LOG_DROP,
|
||||
MONEY_LOG_TYPE_MAX_NUM,
|
||||
};
|
||||
|
||||
enum EPremiumTypes
|
||||
{
|
||||
PREMIUM_EXP,
|
||||
PREMIUM_ITEM,
|
||||
PREMIUM_SAFEBOX,
|
||||
PREMIUM_AUTOLOOT,
|
||||
PREMIUM_FISH_MIND,
|
||||
PREMIUM_MARRIAGE_FAST,
|
||||
PREMIUM_GOLD,
|
||||
PREMIUM_MAX_NUM = 9
|
||||
};
|
||||
|
||||
enum SPECIAL_EFFECT
|
||||
{
|
||||
SE_NONE,
|
||||
|
||||
SE_HPUP_RED,
|
||||
SE_SPUP_BLUE,
|
||||
SE_SPEEDUP_GREEN,
|
||||
SE_DXUP_PURPLE,
|
||||
SE_CRITICAL,
|
||||
SE_PENETRATE,
|
||||
SE_BLOCK,
|
||||
SE_DODGE,
|
||||
SE_CHINA_FIREWORK,
|
||||
SE_SPIN_TOP,
|
||||
SE_SUCCESS,
|
||||
SE_FAIL,
|
||||
SE_FR_SUCCESS,
|
||||
SE_LEVELUP_ON_14_FOR_GERMANY,
|
||||
SE_LEVELUP_UNDER_15_FOR_GERMANY,
|
||||
SE_PERCENT_DAMAGE1,
|
||||
SE_PERCENT_DAMAGE2,
|
||||
SE_PERCENT_DAMAGE3,
|
||||
|
||||
SE_AUTO_HPUP,
|
||||
SE_AUTO_SPUP,
|
||||
|
||||
SE_EQUIP_RAMADAN_RING,
|
||||
SE_EQUIP_HALLOWEEN_CANDY,
|
||||
SE_EQUIP_HAPPINESS_RING,
|
||||
SE_EQUIP_LOVE_PENDANT,
|
||||
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
SE_EFFECT_ACCE_SUCESS_ABSORB,
|
||||
SE_EFFECT_ACCE_EQUIP,
|
||||
#endif
|
||||
};
|
||||
|
||||
#include "item_length.h"
|
||||
|
||||
enum EDragonSoulRefineWindowSize
|
||||
{
|
||||
DRAGON_SOUL_REFINE_GRID_MAX = 15,
|
||||
};
|
||||
|
||||
enum EMisc2
|
||||
{
|
||||
DRAGON_SOUL_EQUIP_SLOT_START = INVENTORY_MAX_NUM + WEAR_MAX_NUM,
|
||||
DRAGON_SOUL_EQUIP_SLOT_END = DRAGON_SOUL_EQUIP_SLOT_START + (DS_SLOT_MAX * DRAGON_SOUL_DECK_MAX_NUM),
|
||||
DRAGON_SOUL_EQUIP_RESERVED_SLOT_END = DRAGON_SOUL_EQUIP_SLOT_END + (DS_SLOT_MAX * DRAGON_SOUL_DECK_RESERVED_MAX_NUM),
|
||||
|
||||
BELT_INVENTORY_SLOT_START = DRAGON_SOUL_EQUIP_RESERVED_SLOT_END,
|
||||
BELT_INVENTORY_SLOT_END = BELT_INVENTORY_SLOT_START + BELT_INVENTORY_SLOT_COUNT,
|
||||
|
||||
INVENTORY_AND_EQUIP_SLOT_MAX = BELT_INVENTORY_SLOT_END,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct SItemPos
|
||||
{
|
||||
BYTE window_type;
|
||||
WORD cell;
|
||||
SItemPos ()
|
||||
{
|
||||
window_type = INVENTORY;
|
||||
cell = WORD_MAX;
|
||||
}
|
||||
|
||||
SItemPos (BYTE _window_type, WORD _cell)
|
||||
{
|
||||
window_type = _window_type;
|
||||
cell = _cell;
|
||||
}
|
||||
|
||||
bool IsValidItemPosition() const
|
||||
{
|
||||
switch (window_type)
|
||||
{
|
||||
case RESERVED_WINDOW:
|
||||
return false;
|
||||
case INVENTORY:
|
||||
case EQUIPMENT:
|
||||
case BELT_INVENTORY:
|
||||
return cell < INVENTORY_AND_EQUIP_SLOT_MAX;
|
||||
case DRAGON_SOUL_INVENTORY:
|
||||
return cell < (DRAGON_SOUL_INVENTORY_MAX_NUM);
|
||||
|
||||
case SAFEBOX:
|
||||
case MALL:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsSamePosition(const SItemPos & other) const
|
||||
{
|
||||
return *this==other
|
||||
|| ((INVENTORY == window_type || EQUIPMENT == window_type)
|
||||
&& (INVENTORY == other.window_type || EQUIPMENT == other.window_type)
|
||||
&& cell == other.cell);
|
||||
}
|
||||
|
||||
bool IsEquipPosition() const
|
||||
{
|
||||
return ((INVENTORY == window_type || EQUIPMENT == window_type) && cell >= INVENTORY_MAX_NUM && cell < INVENTORY_MAX_NUM + WEAR_MAX_NUM)
|
||||
|| IsDragonSoulEquipPosition();
|
||||
}
|
||||
|
||||
bool IsDragonSoulEquipPosition() const
|
||||
{
|
||||
return (window_type == INVENTORY) && (DRAGON_SOUL_EQUIP_SLOT_START <= cell) && (DRAGON_SOUL_EQUIP_SLOT_END > cell); // @fixme184
|
||||
}
|
||||
|
||||
bool IsBeltInventoryPosition() const // @fixme324 (INVENTORY n EQUIPMENT)
|
||||
{
|
||||
return (window_type == INVENTORY || window_type == EQUIPMENT) && (BELT_INVENTORY_SLOT_START <= cell) && (BELT_INVENTORY_SLOT_END > cell);
|
||||
}
|
||||
|
||||
bool IsDefaultInventoryPosition() const
|
||||
{
|
||||
return INVENTORY == window_type && cell < INVENTORY_MAX_NUM;
|
||||
}
|
||||
|
||||
bool operator==(const struct SItemPos& rhs) const
|
||||
{
|
||||
return (window_type == rhs.window_type) && (cell == rhs.cell);
|
||||
}
|
||||
bool operator<(const struct SItemPos& rhs) const
|
||||
{
|
||||
return (window_type < rhs.window_type) || ((window_type == rhs.window_type) && (cell < rhs.cell));
|
||||
}
|
||||
} TItemPos;
|
||||
|
||||
const TItemPos NPOS (RESERVED_WINDOW, WORD_MAX);
|
||||
|
||||
typedef struct SItemPosEx
|
||||
{
|
||||
TItemPos pos;
|
||||
int id{ 0 };
|
||||
} TItemPosEx;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SHOP_COIN_TYPE_GOLD, // DEFAULT VALUE
|
||||
SHOP_COIN_TYPE_SECONDARY_COIN,
|
||||
} EShopCoinType;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
16
source-server/Srcs/Server/common/noncopyable.h
Normal file
16
source-server/Srcs/Server/common/noncopyable.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef INC_METIN_II_COMMON_NONCOPYABLE_TEMPLATE
|
||||
#define INC_METIN_II_COMMON_NONCOPYABLE_TEMPLATE
|
||||
|
||||
class noncopyable
|
||||
{
|
||||
protected:
|
||||
noncopyable() {}
|
||||
~noncopyable() {}
|
||||
|
||||
private:
|
||||
noncopyable(const noncopyable &);
|
||||
noncopyable& operator = (const noncopyable &);
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
186
source-server/Srcs/Server/common/pool.h
Normal file
186
source-server/Srcs/Server/common/pool.h
Normal file
@ -0,0 +1,186 @@
|
||||
#ifndef __INC_METIN_II_COMMON_POOL_H__
|
||||
#define __INC_METIN_II_COMMON_POOL_H__
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
||||
template<typename T>
|
||||
class CPoolNode : public T
|
||||
{
|
||||
public:
|
||||
CPoolNode()
|
||||
{
|
||||
m_pNext = NULL;
|
||||
m_pPrev = NULL;
|
||||
}
|
||||
|
||||
virtual ~CPoolNode()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
CPoolNode<T> * m_pNext;
|
||||
CPoolNode<T> * m_pPrev;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class CDynamicPool
|
||||
{
|
||||
public:
|
||||
typedef CPoolNode<T> TNode;
|
||||
|
||||
public:
|
||||
CDynamicPool()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
virtual ~CDynamicPool()
|
||||
{
|
||||
assert(m_pFreeList==NULL && "CDynamicPool::~CDynamicPool() - NOT Clear");
|
||||
assert(m_pUsedList==NULL && "CDynamicPool::~CDynamicPool() - NOT Clear");
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
m_nodes = NULL;
|
||||
m_nodeCount = 0;
|
||||
|
||||
m_pFreeList = NULL;
|
||||
m_pUsedList = NULL;
|
||||
}
|
||||
|
||||
void SetName(const char* c_szName)
|
||||
{
|
||||
m_stName = c_szName;
|
||||
}
|
||||
|
||||
DWORD GetCapacity()
|
||||
{
|
||||
return m_nodeCount;
|
||||
}
|
||||
|
||||
T* Alloc()
|
||||
{
|
||||
TNode* pnewNode;
|
||||
|
||||
if (m_pFreeList)
|
||||
{
|
||||
pnewNode = m_pFreeList;
|
||||
m_pFreeList = m_pFreeList->m_pNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
pnewNode = AllocNode();
|
||||
}
|
||||
|
||||
if (!pnewNode)
|
||||
return NULL;
|
||||
|
||||
if (!m_pUsedList)
|
||||
{
|
||||
m_pUsedList = pnewNode;
|
||||
m_pUsedList->m_pPrev = m_pUsedList->m_pNext = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pUsedList->m_pPrev = pnewNode;
|
||||
pnewNode->m_pNext = m_pUsedList;
|
||||
pnewNode->m_pPrev = NULL;
|
||||
m_pUsedList = pnewNode;
|
||||
}
|
||||
//Tracef("%s Pool Alloc %p\n", m_stName.c_str(), pnewNode);
|
||||
return (T*) pnewNode;
|
||||
}
|
||||
|
||||
void Free(T * pdata)
|
||||
{
|
||||
TNode* pfreeNode = (TNode*) pdata;
|
||||
|
||||
if (pfreeNode == m_pUsedList)
|
||||
{
|
||||
if (NULL != (m_pUsedList = m_pUsedList->m_pNext))
|
||||
m_pUsedList->m_pPrev = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pfreeNode->m_pNext)
|
||||
pfreeNode->m_pNext->m_pPrev = pfreeNode->m_pPrev;
|
||||
|
||||
if (pfreeNode->m_pPrev)
|
||||
pfreeNode->m_pPrev->m_pNext = pfreeNode->m_pNext;
|
||||
}
|
||||
|
||||
pfreeNode->m_pPrev = NULL;
|
||||
pfreeNode->m_pNext = m_pFreeList;
|
||||
m_pFreeList = pfreeNode;
|
||||
//Tracef("%s Pool Free\n", m_stName.c_str());
|
||||
}
|
||||
|
||||
void FreeAll()
|
||||
{
|
||||
TNode * pcurNode;
|
||||
TNode * pnextNode;
|
||||
|
||||
pcurNode = m_pUsedList;
|
||||
|
||||
while (pcurNode)
|
||||
{
|
||||
pnextNode = pcurNode->m_pNext;
|
||||
Free(pcurNode);
|
||||
pcurNode = pnextNode;
|
||||
}
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
TNode* pcurNode;
|
||||
TNode* pnextNode;
|
||||
|
||||
[[maybe_unused]] DWORD count = 0;
|
||||
|
||||
pcurNode = m_pFreeList;
|
||||
while (pcurNode)
|
||||
{
|
||||
pnextNode = pcurNode->m_pNext;
|
||||
delete pcurNode;
|
||||
pcurNode = pnextNode;
|
||||
++count;
|
||||
}
|
||||
m_pFreeList = NULL;
|
||||
|
||||
pcurNode = m_pUsedList;
|
||||
while (pcurNode)
|
||||
{
|
||||
pnextNode = pcurNode->m_pNext;
|
||||
delete pcurNode;
|
||||
pcurNode = pnextNode;
|
||||
++count;
|
||||
}
|
||||
|
||||
m_pUsedList = NULL;
|
||||
|
||||
assert(count==m_nodeCount && "CDynamicPool::Clear()");
|
||||
|
||||
m_nodeCount=0;
|
||||
}
|
||||
|
||||
protected:
|
||||
TNode* AllocNode()
|
||||
{
|
||||
++m_nodeCount;
|
||||
return new TNode;
|
||||
}
|
||||
|
||||
protected:
|
||||
TNode * m_nodes;
|
||||
TNode * m_pFreeList;
|
||||
TNode * m_pUsedList;
|
||||
|
||||
DWORD m_nodeCount;
|
||||
std::string m_stName;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
6
source-server/Srcs/Server/common/service.h
Normal file
6
source-server/Srcs/Server/common/service.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __INC_SERVICE_H__
|
||||
#define __INC_SERVICE_H__
|
||||
#pragma once
|
||||
#include "CommonDefines.h"
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
45
source-server/Srcs/Server/common/singleton.h
Normal file
45
source-server/Srcs/Server/common/singleton.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef __INC_SINGLETON_H__
|
||||
#define __INC_SINGLETON_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
template <typename T> class singleton
|
||||
{
|
||||
public:
|
||||
static T * ms_singleton;
|
||||
|
||||
singleton()
|
||||
{
|
||||
assert(!ms_singleton);
|
||||
long offset = (long) (T*) 1 - (long) (singleton <T>*) (T*) 1;
|
||||
ms_singleton = (T*) ((long) this + offset);
|
||||
}
|
||||
|
||||
virtual ~singleton()
|
||||
{
|
||||
assert(ms_singleton);
|
||||
ms_singleton = 0;
|
||||
}
|
||||
|
||||
static T & instance()
|
||||
{
|
||||
assert(ms_singleton);
|
||||
return (*ms_singleton);
|
||||
}
|
||||
|
||||
static T & Instance()
|
||||
{
|
||||
assert(ms_singleton);
|
||||
return (*ms_singleton);
|
||||
}
|
||||
|
||||
static T * instance_ptr()
|
||||
{
|
||||
return (ms_singleton);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> T * singleton <T>::ms_singleton = NULL;
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
237
source-server/Srcs/Server/common/stl.h
Normal file
237
source-server/Srcs/Server/common/stl.h
Normal file
@ -0,0 +1,237 @@
|
||||
#ifndef __INC_METIN_II_STL_H__
|
||||
#define __INC_METIN_II_STL_H__
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <functional>
|
||||
#include <stack>
|
||||
#include <set>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifndef __clang__
|
||||
#include <ext/functional>
|
||||
#else
|
||||
#include <functional>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef itertype
|
||||
#define itertype(v) typeof((v).begin())
|
||||
#endif
|
||||
|
||||
inline void stl_lowers(std::string& rstRet)
|
||||
{
|
||||
for (size_t i = 0; i < rstRet.length(); ++i)
|
||||
rstRet[i] = tolower(rstRet[i]);
|
||||
}
|
||||
|
||||
struct stringhash
|
||||
{
|
||||
size_t operator () (const std::string & str) const
|
||||
{
|
||||
const unsigned char * s = (const unsigned char*) str.c_str();
|
||||
const unsigned char * end = s + str.size();
|
||||
size_t h = 0;
|
||||
|
||||
while (s < end)
|
||||
{
|
||||
h *= 16777619;
|
||||
h ^= *(s++);
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// code from tr1/functional_hash.h
|
||||
template<typename T>
|
||||
struct hash;
|
||||
|
||||
template<typename _Tp>
|
||||
struct hash<_Tp*>
|
||||
{
|
||||
std::size_t
|
||||
operator()(_Tp* __p) const
|
||||
{ return reinterpret_cast<std::size_t>(__p); }
|
||||
};
|
||||
|
||||
namespace utils
|
||||
{
|
||||
template <typename T> struct IsContiguous {
|
||||
static bool constexpr value = false;
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
struct IsContiguous<std::vector<Args...>> {
|
||||
static bool constexpr value = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsContiguous<std::string> {
|
||||
static bool constexpr value = true;
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
struct IsContiguous<std::array<Args...>> {
|
||||
static bool constexpr value = true;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool IsContiguousV = IsContiguous<T>::value;
|
||||
|
||||
/////////////////////
|
||||
template<typename T>
|
||||
constexpr bool IsRawV = !std::is_pointer_v<T> && std::is_trivially_copyable_v<T> && !IsContiguousV<T>;
|
||||
};
|
||||
|
||||
namespace msl
|
||||
{
|
||||
template< class F, class... Args >
|
||||
constexpr decltype(auto) bind1st( F&& f, Args&&... args )
|
||||
{
|
||||
return std::bind(f, args..., std::placeholders::_1);
|
||||
}
|
||||
|
||||
template< class F, class... Args >
|
||||
constexpr decltype(auto) bind2nd( F&& f, Args&&... args )
|
||||
{
|
||||
return std::bind(f, std::placeholders::_1, args...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void random_shuffle(T first, T last)
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 g(rd());
|
||||
std::shuffle(first, last, g);
|
||||
}
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class container, class Pred>
|
||||
void erase_if (container & a, typename container::iterator first, typename container::iterator past, Pred pred)
|
||||
{
|
||||
while (first != past)
|
||||
if (pred(*first))
|
||||
a.erase(first++);
|
||||
else
|
||||
++first;
|
||||
}
|
||||
|
||||
template <class container>
|
||||
void wipe(container & a)
|
||||
{
|
||||
typename container::iterator first, past;
|
||||
|
||||
first = a.begin();
|
||||
past = a.end();
|
||||
|
||||
while (first != past)
|
||||
delete *(first++);
|
||||
|
||||
a.clear();
|
||||
}
|
||||
|
||||
template <class container>
|
||||
void wipe_second(container & a)
|
||||
{
|
||||
typename container::iterator first, past;
|
||||
|
||||
first = a.begin();
|
||||
past = a.end();
|
||||
|
||||
while (first != past)
|
||||
{
|
||||
delete first->second;
|
||||
++first;
|
||||
}
|
||||
|
||||
a.clear();
|
||||
}
|
||||
|
||||
template <typename T> T MINMAX(T min, T value, T max)
|
||||
{
|
||||
T tv;
|
||||
|
||||
tv = (min > value ? min : value);
|
||||
return (max < tv) ? max : tv;
|
||||
}
|
||||
|
||||
template <class _Ty>
|
||||
class void_mem_fun_t
|
||||
{
|
||||
public:
|
||||
explicit void_mem_fun_t(void (_Ty::*_Pm)()) : _Ptr(_Pm)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(_Ty* p) const
|
||||
{
|
||||
((p->*_Ptr)());
|
||||
}
|
||||
|
||||
private:
|
||||
void (_Ty::*_Ptr)();
|
||||
};
|
||||
|
||||
template<class _Ty> inline
|
||||
void_mem_fun_t<_Ty> void_mem_fun(void (_Ty::*_Pm)())
|
||||
{ return (void_mem_fun_t<_Ty>(_Pm)); }
|
||||
|
||||
template<class _Ty>
|
||||
class void_mem_fun_ref_t
|
||||
{
|
||||
public:
|
||||
explicit void_mem_fun_ref_t(void (_Ty::*_Pm)()) : _Ptr(_Pm) {}
|
||||
void operator()(_Ty& x) const
|
||||
{ return ((x.*_Ptr)()); }
|
||||
private:
|
||||
void (_Ty::*_Ptr)();
|
||||
};
|
||||
|
||||
template<class _Ty> inline
|
||||
void_mem_fun_ref_t<_Ty> void_mem_fun_ref(void (_Ty::*_Pm)())
|
||||
{ return (void_mem_fun_ref_t< _Ty>(_Pm)); }
|
||||
};
|
||||
|
||||
inline std::string FormatNumberWithDots(long long number) {
|
||||
std::string result;
|
||||
bool isNegative = false;
|
||||
|
||||
// Handle the case for negative numbers
|
||||
if (number < 0) {
|
||||
isNegative = true;
|
||||
number = -number; // Make it positive for processing
|
||||
}
|
||||
|
||||
// Convert the number to a string
|
||||
std::string numStr = std::to_string(number);
|
||||
|
||||
// Insert dots from the right every three digits
|
||||
int count = 0;
|
||||
for (int i = numStr.size() - 1; i >= 0; --i) {
|
||||
result.push_back(numStr[i]);
|
||||
if (++count == 3 && i > 0) {
|
||||
result.push_back('.');
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse the result string to get the correct order
|
||||
std::reverse(result.begin(), result.end());
|
||||
|
||||
// Add the negative sign if necessary
|
||||
if (isNegative) {
|
||||
result.insert(result.begin(), '-');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
1362
source-server/Srcs/Server/common/tables.h
Normal file
1362
source-server/Srcs/Server/common/tables.h
Normal file
File diff suppressed because it is too large
Load Diff
122
source-server/Srcs/Server/common/utils.h
Normal file
122
source-server/Srcs/Server/common/utils.h
Normal file
@ -0,0 +1,122 @@
|
||||
#ifndef _INCLUDE_HEADER_COMMON_UTILS_
|
||||
#define _INCLUDE_HEADER_COMMON_UTILS_
|
||||
|
||||
#include <msl/utils.h>
|
||||
|
||||
/*----- atoi function -----*/
|
||||
inline bool str_to_number (bool& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (strtol(in, NULL, 10) != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (char& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (char) strtol(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (unsigned char& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (unsigned char) strtoul(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (short& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (short) strtol(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (unsigned short& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (unsigned short) strtoul(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (int& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (int) strtol(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (unsigned int& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (unsigned int) strtoul(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (long& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (long) strtol(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (unsigned long& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (unsigned long) strtoul(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (long long& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (long long) strtoull(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (unsigned long long& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (unsigned long long) strtoull(in, NULL, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (float& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (float) strtof(in, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_to_number (double& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (double) strtod(in, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
inline bool str_to_number (long double& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
out = (long double) strtold(in, NULL);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
204
source-server/Srcs/Server/db/src/Cache.cpp
Normal file
204
source-server/Srcs/Server/db/src/Cache.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
#include "stdafx.h"
|
||||
#include "Cache.h"
|
||||
|
||||
#include "QID.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Main.h"
|
||||
#include <fmt/fmt.h>
|
||||
|
||||
extern CPacketInfo g_item_info;
|
||||
extern int g_iPlayerCacheFlushSeconds;
|
||||
extern int g_iItemCacheFlushSeconds;
|
||||
extern int g_test_server;
|
||||
// MYSHOP_PRICE_LIST
|
||||
extern int g_iItemPriceListTableCacheFlushSeconds;
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
//
|
||||
extern int g_item_count;
|
||||
|
||||
CItemCache::CItemCache()
|
||||
{
|
||||
m_expireTime = MIN(1800, g_iItemCacheFlushSeconds);
|
||||
}
|
||||
|
||||
CItemCache::~CItemCache()
|
||||
{
|
||||
}
|
||||
|
||||
void CItemCache::Delete()
|
||||
{
|
||||
if (m_data.vnum == 0)
|
||||
return;
|
||||
|
||||
if (g_test_server)
|
||||
sys_log(0, "ItemCache::Delete : DELETE %u", m_data.id);
|
||||
|
||||
m_data.vnum = 0;
|
||||
m_bNeedQuery = true;
|
||||
m_lastUpdateTime = time(0);
|
||||
OnFlush();
|
||||
}
|
||||
|
||||
void CItemCache::OnFlush()
|
||||
{
|
||||
if (m_data.vnum == 0)
|
||||
{
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM item%s WHERE id=%u", GetTablePostfix(), m_data.id);
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_DESTROY, 0, NULL);
|
||||
|
||||
if (g_test_server)
|
||||
sys_log(0, "ItemCache::Flush : DELETE %u %s", m_data.id, szQuery);
|
||||
}
|
||||
else
|
||||
{
|
||||
TPlayerItem *p = &m_data;
|
||||
const auto setQuery = fmt::format(FMT_COMPILE("id={}, owner_id={}, `window`={}, pos={}, count={}, vnum={}, socket0={}, socket1={}, socket2={}, "
|
||||
"attrtype0={}, attrvalue0={}, "
|
||||
"attrtype1={}, attrvalue1={}, "
|
||||
"attrtype2={}, attrvalue2={}, "
|
||||
"attrtype3={}, attrvalue3={}, "
|
||||
"attrtype4={}, attrvalue4={}, "
|
||||
"attrtype5={}, attrvalue5={}, "
|
||||
"attrtype6={}, attrvalue6={} ")
|
||||
, p->id,
|
||||
p->owner,
|
||||
p->window,
|
||||
p->pos,
|
||||
p->count,
|
||||
p->vnum,
|
||||
p->alSockets[0],
|
||||
p->alSockets[1],
|
||||
p->alSockets[2],
|
||||
p->aAttr[0].bType, p->aAttr[0].sValue,
|
||||
p->aAttr[1].bType, p->aAttr[1].sValue,
|
||||
p->aAttr[2].bType, p->aAttr[2].sValue,
|
||||
p->aAttr[3].bType, p->aAttr[3].sValue,
|
||||
p->aAttr[4].bType, p->aAttr[4].sValue,
|
||||
p->aAttr[5].bType, p->aAttr[5].sValue,
|
||||
p->aAttr[6].bType, p->aAttr[6].sValue
|
||||
); // @fixme205
|
||||
|
||||
const auto itemQuery = fmt::format(FMT_COMPILE("INSERT INTO item{} SET {} ON DUPLICATE KEY UPDATE {}"),
|
||||
GetTablePostfix(), setQuery, setQuery);
|
||||
|
||||
if (g_test_server)
|
||||
sys_log(0, "ItemCache::Flush :REPLACE (%s)", itemQuery.c_str());
|
||||
|
||||
CDBManager::instance().ReturnQuery(itemQuery.c_str(), QID_ITEM_SAVE, 0, NULL);
|
||||
|
||||
++g_item_count;
|
||||
}
|
||||
|
||||
m_bNeedQuery = false;
|
||||
}
|
||||
|
||||
//
|
||||
// CPlayerTableCache
|
||||
//
|
||||
CPlayerTableCache::CPlayerTableCache()
|
||||
{
|
||||
m_expireTime = MIN(1800, g_iPlayerCacheFlushSeconds);
|
||||
}
|
||||
|
||||
CPlayerTableCache::~CPlayerTableCache()
|
||||
{
|
||||
}
|
||||
|
||||
void CPlayerTableCache::OnFlush()
|
||||
{
|
||||
if (g_test_server)
|
||||
sys_log(0, "PlayerTableCache::Flush : %s", m_data.name);
|
||||
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
CreatePlayerSaveQuery(szQuery, sizeof(szQuery), &m_data);
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_SAVE, 0, NULL);
|
||||
}
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
//
|
||||
// CItemPriceListTableCache class implementation
|
||||
//
|
||||
|
||||
const int CItemPriceListTableCache::s_nMinFlushSec = 1800;
|
||||
|
||||
CItemPriceListTableCache::CItemPriceListTableCache()
|
||||
{
|
||||
m_expireTime = MIN(s_nMinFlushSec, g_iItemPriceListTableCacheFlushSeconds);
|
||||
}
|
||||
|
||||
void CItemPriceListTableCache::UpdateList(const TItemPriceListTable* pUpdateList)
|
||||
{
|
||||
std::vector<TItemPriceInfo> tmpvec;
|
||||
|
||||
for (uint idx = 0; idx < m_data.byCount; ++idx)
|
||||
{
|
||||
const TItemPriceInfo* pos = pUpdateList->aPriceInfo;
|
||||
for (; pos != pUpdateList->aPriceInfo + pUpdateList->byCount && m_data.aPriceInfo[idx].dwVnum != pos->dwVnum; ++pos)
|
||||
;
|
||||
|
||||
if (pos == pUpdateList->aPriceInfo + pUpdateList->byCount)
|
||||
tmpvec.emplace_back(m_data.aPriceInfo[idx]);
|
||||
}
|
||||
|
||||
if (pUpdateList->byCount > SHOP_PRICELIST_MAX_NUM)
|
||||
{
|
||||
sys_err("Count overflow!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_data.byCount = pUpdateList->byCount;
|
||||
|
||||
thecore_memcpy(m_data.aPriceInfo, pUpdateList->aPriceInfo, sizeof(TItemPriceInfo) * pUpdateList->byCount);
|
||||
|
||||
int nDeletedNum;
|
||||
|
||||
if (pUpdateList->byCount < SHOP_PRICELIST_MAX_NUM)
|
||||
{
|
||||
size_t sizeAddOldDataSize = SHOP_PRICELIST_MAX_NUM - pUpdateList->byCount;
|
||||
|
||||
if (tmpvec.size() < sizeAddOldDataSize)
|
||||
sizeAddOldDataSize = tmpvec.size();
|
||||
if (tmpvec.size() != 0)
|
||||
{
|
||||
thecore_memcpy(m_data.aPriceInfo + pUpdateList->byCount, &tmpvec[0], sizeof(TItemPriceInfo) * sizeAddOldDataSize);
|
||||
m_data.byCount += sizeAddOldDataSize;
|
||||
}
|
||||
nDeletedNum = tmpvec.size() - sizeAddOldDataSize;
|
||||
}
|
||||
else
|
||||
nDeletedNum = tmpvec.size();
|
||||
|
||||
m_bNeedQuery = true;
|
||||
|
||||
sys_log(0,
|
||||
"ItemPriceListTableCache::UpdateList : OwnerID[%u] Update [%u] Items, Delete [%u] Items, Total [%u] Items",
|
||||
m_data.dwOwnerID, pUpdateList->byCount, nDeletedNum, m_data.byCount);
|
||||
}
|
||||
|
||||
void CItemPriceListTableCache::OnFlush()
|
||||
{
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM myshop_pricelist%s WHERE owner_id = %u", GetTablePostfix(), m_data.dwOwnerID);
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_ITEMPRICE_DESTROY, 0, NULL);
|
||||
|
||||
for (int idx = 0; idx < m_data.byCount; ++idx)
|
||||
{
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"REPLACE myshop_pricelist%s(owner_id, item_vnum, price) VALUES(%u, %u, %u)", // @fixme204 (INSERT INTO -> REPLACE)
|
||||
GetTablePostfix(), m_data.dwOwnerID, m_data.aPriceInfo[idx].dwVnum, m_data.aPriceInfo[idx].dwPrice);
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_ITEMPRICE_SAVE, 0, NULL);
|
||||
}
|
||||
|
||||
sys_log(0, "ItemPriceListTableCache::Flush : OwnerID[%u] Update [%u]Items", m_data.dwOwnerID, m_data.byCount);
|
||||
|
||||
m_bNeedQuery = false;
|
||||
}
|
||||
|
||||
CItemPriceListTableCache::~CItemPriceListTableCache()
|
||||
{
|
||||
}
|
||||
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
49
source-server/Srcs/Server/db/src/Cache.h
Normal file
49
source-server/Srcs/Server/db/src/Cache.h
Normal file
@ -0,0 +1,49 @@
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_DB_CACHE_H__
|
||||
#define __INC_DB_CACHE_H__
|
||||
|
||||
#include "../../common/cache.h"
|
||||
|
||||
class CItemCache : public cache<TPlayerItem>
|
||||
{
|
||||
public:
|
||||
CItemCache();
|
||||
virtual ~CItemCache();
|
||||
|
||||
void Delete();
|
||||
virtual void OnFlush();
|
||||
};
|
||||
|
||||
class CPlayerTableCache : public cache<TPlayerTable>
|
||||
{
|
||||
public:
|
||||
CPlayerTableCache();
|
||||
virtual ~CPlayerTableCache();
|
||||
|
||||
virtual void OnFlush();
|
||||
|
||||
DWORD GetLastUpdateTime() { return m_lastUpdateTime; }
|
||||
};
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
|
||||
class CItemPriceListTableCache : public cache< TItemPriceListTable >
|
||||
{
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
|
||||
CItemPriceListTableCache(void);
|
||||
virtual ~CItemPriceListTableCache();
|
||||
|
||||
void UpdateList(const TItemPriceListTable* pUpdateList);
|
||||
|
||||
virtual void OnFlush(void);
|
||||
|
||||
private:
|
||||
|
||||
static const int s_nMinFlushSec; ///< Minimum cache expire time
|
||||
};
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
4238
source-server/Srcs/Server/db/src/ClientManager.cpp
Normal file
4238
source-server/Srcs/Server/db/src/ClientManager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
513
source-server/Srcs/Server/db/src/ClientManager.h
Normal file
513
source-server/Srcs/Server/db/src/ClientManager.h
Normal file
@ -0,0 +1,513 @@
|
||||
#ifndef __INC_CLIENTMANAGER_H__
|
||||
#define __INC_CLIENTMANAGER_H__
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include "../../common/stl.h"
|
||||
#include "../../common/building.h"
|
||||
|
||||
#include "Peer.h"
|
||||
#include "DBManager.h"
|
||||
#include "LoginData.h"
|
||||
|
||||
#define ENABLE_PROTO_FROM_DB
|
||||
|
||||
class CPlayerTableCache;
|
||||
class CItemCache;
|
||||
class CItemPriceListTableCache;
|
||||
|
||||
class CPacketInfo
|
||||
{
|
||||
public:
|
||||
void Add(int header);
|
||||
void Reset();
|
||||
|
||||
std::map<int, int> m_map_info;
|
||||
};
|
||||
|
||||
size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * pkTab);
|
||||
|
||||
class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
{
|
||||
public:
|
||||
typedef std::list<CPeer *> TPeerList;
|
||||
typedef boost::unordered_map<DWORD, CPlayerTableCache *> TPlayerTableCacheMap;
|
||||
typedef boost::unordered_map<DWORD, CItemCache *> TItemCacheMap;
|
||||
typedef boost::unordered_set<CItemCache *, boost::hash<CItemCache*> > TItemCacheSet;
|
||||
typedef boost::unordered_map<DWORD, TItemCacheSet *> TItemCacheSetPtrMap;
|
||||
typedef boost::unordered_map<DWORD, CItemPriceListTableCache*> TItemPriceListCacheMap;
|
||||
typedef boost::unordered_map<short, BYTE> TChannelStatusMap;
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
|
||||
typedef std::pair< DWORD, DWORD > TItemPricelistReqInfo;
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
|
||||
class ClientHandleInfo
|
||||
{
|
||||
public:
|
||||
DWORD dwHandle;
|
||||
DWORD account_id;
|
||||
DWORD player_id;
|
||||
BYTE account_index;
|
||||
char login[LOGIN_MAX_LEN + 1];
|
||||
char safebox_password[SAFEBOX_PASSWORD_MAX_LEN + 1];
|
||||
char ip[MAX_HOST_LENGTH + 1];
|
||||
|
||||
TAccountTable * pAccountTable;
|
||||
TSafeboxTable * pSafebox;
|
||||
|
||||
ClientHandleInfo(DWORD argHandle, DWORD dwPID = 0)
|
||||
{
|
||||
dwHandle = argHandle;
|
||||
pSafebox = NULL;
|
||||
pAccountTable = NULL;
|
||||
player_id = dwPID;
|
||||
};
|
||||
|
||||
ClientHandleInfo(DWORD argHandle, DWORD dwPID, DWORD accountId)
|
||||
{
|
||||
dwHandle = argHandle;
|
||||
pSafebox = NULL;
|
||||
pAccountTable = NULL;
|
||||
player_id = dwPID;
|
||||
account_id = accountId;
|
||||
};
|
||||
|
||||
~ClientHandleInfo()
|
||||
{
|
||||
if (pSafebox)
|
||||
{
|
||||
delete pSafebox;
|
||||
pSafebox = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
CClientManager();
|
||||
~CClientManager();
|
||||
|
||||
bool Initialize();
|
||||
time_t GetCurrentTime();
|
||||
|
||||
void MainLoop();
|
||||
void Quit();
|
||||
|
||||
void GetPeerP2PHostNames(std::string& peerHostNames);
|
||||
void SetTablePostfix(const char* c_pszTablePostfix);
|
||||
void SetPlayerIDStart(int iIDStart);
|
||||
int GetPlayerIDStart() { return m_iPlayerIDStart; }
|
||||
|
||||
int GetPlayerDeleteLevelLimit() { return m_iPlayerDeleteLevelLimit; }
|
||||
|
||||
void SetChinaEventServer(bool flag) { m_bChinaEventServer = flag; }
|
||||
bool IsChinaEventServer() { return m_bChinaEventServer; }
|
||||
|
||||
DWORD GetUserCount();
|
||||
|
||||
void SendAllGuildSkillRechargePacket();
|
||||
void SendTime();
|
||||
|
||||
CPlayerTableCache * GetPlayerCache(DWORD id);
|
||||
void PutPlayerCache(TPlayerTable * pNew);
|
||||
|
||||
void CreateItemCacheSet(DWORD dwID);
|
||||
TItemCacheSet * GetItemCacheSet(DWORD dwID);
|
||||
void FlushItemCacheSet(DWORD dwID);
|
||||
|
||||
CItemCache * GetItemCache(DWORD id);
|
||||
void PutItemCache(TPlayerItem * pNew, bool bSkipQuery = false);
|
||||
bool DeleteItemCache(DWORD id);
|
||||
|
||||
void UpdatePlayerCache();
|
||||
void UpdateItemCache();
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
|
||||
CItemPriceListTableCache* GetItemPriceListCache(DWORD dwID);
|
||||
|
||||
void PutItemPriceListCache(const TItemPriceListTable* pItemPriceList);
|
||||
|
||||
void UpdateItemPriceListCache(void);
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
|
||||
void SendGuildSkillUsable(DWORD guild_id, DWORD dwSkillVnum, bool bUsable);
|
||||
|
||||
void SetCacheFlushCountLimit(int iLimit);
|
||||
|
||||
template <class Func>
|
||||
Func for_each_peer(Func f);
|
||||
|
||||
CPeer * GetAnyPeer();
|
||||
|
||||
void ForwardPacket(BYTE header, const void* data, int size, BYTE bChannel = 0, CPeer * except = NULL);
|
||||
|
||||
void SendNotice(const char * c_pszFormat, ...);
|
||||
|
||||
// @fixme203 directly GetCommand instead of strcpy
|
||||
char* GetCommand(char* str, char* command);
|
||||
void ItemAward(CPeer * peer, char* login);
|
||||
|
||||
protected:
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
bool InitializeTables();
|
||||
bool InitializeShopTable();
|
||||
bool InitializeMobTable();
|
||||
bool InitializeItemTable();
|
||||
bool InitializeQuestItemTable();
|
||||
bool InitializeSkillTable();
|
||||
bool InitializeRefineTable();
|
||||
bool InitializeBanwordTable();
|
||||
bool InitializeItemAttrTable();
|
||||
bool InitializeItemRareTable();
|
||||
bool InitializeLandTable();
|
||||
bool InitializeObjectProto();
|
||||
bool InitializeObjectTable();
|
||||
bool InitializeMonarch();
|
||||
|
||||
bool MirrorMobTableIntoDB();
|
||||
bool MirrorItemTableIntoDB();
|
||||
|
||||
void AddPeer(socket_t fd);
|
||||
void RemovePeer(CPeer * pPeer);
|
||||
CPeer * GetPeer(IDENT ident);
|
||||
|
||||
int AnalyzeQueryResult(SQLMsg * msg);
|
||||
int AnalyzeErrorMsg(CPeer * peer, SQLMsg * msg);
|
||||
|
||||
int Process();
|
||||
|
||||
void ProcessPackets(CPeer * peer);
|
||||
|
||||
CLoginData * GetLoginData(DWORD dwKey);
|
||||
CLoginData * GetLoginDataByLogin(const char * c_pszLogin);
|
||||
CLoginData * GetLoginDataByAID(DWORD dwAID);
|
||||
|
||||
void InsertLoginData(CLoginData * pkLD);
|
||||
void DeleteLoginData(CLoginData * pkLD);
|
||||
|
||||
bool InsertLogonAccount(const char * c_pszLogin, DWORD dwHandle, const char * c_pszIP);
|
||||
bool DeleteLogonAccount(const char * c_pszLogin, DWORD dwHandle);
|
||||
bool FindLogonAccount(const char * c_pszLogin);
|
||||
|
||||
void GuildCreate(CPeer * peer, DWORD dwGuildID);
|
||||
void GuildSkillUpdate(CPeer * peer, TPacketGuildSkillUpdate* p);
|
||||
void GuildExpUpdate(CPeer * peer, TPacketGuildExpUpdate* p);
|
||||
void GuildAddMember(CPeer * peer, TPacketGDGuildAddMember* p);
|
||||
void GuildChangeGrade(CPeer * peer, TPacketGuild* p);
|
||||
void GuildRemoveMember(CPeer * peer, TPacketGuild* p);
|
||||
void GuildChangeMemberData(CPeer * peer, TPacketGuildChangeMemberData* p);
|
||||
void GuildDisband(CPeer * peer, TPacketGuild * p);
|
||||
void GuildWar(CPeer * peer, TPacketGuildWar * p);
|
||||
void GuildWarScore(CPeer * peer, TPacketGuildWarScore * p);
|
||||
void GuildChangeLadderPoint(TPacketGuildLadderPoint* p);
|
||||
void GuildUseSkill(TPacketGuildUseSkill* p);
|
||||
void GuildDepositMoney(TPacketGDGuildMoney* p);
|
||||
void GuildWithdrawMoney(CPeer* peer, TPacketGDGuildMoney* p);
|
||||
void GuildWithdrawMoneyGiveReply(TPacketGDGuildMoneyWithdrawGiveReply* p);
|
||||
void GuildWarBet(TPacketGDGuildWarBet * p);
|
||||
void GuildChangeMaster(TPacketChangeGuildMaster* p);
|
||||
|
||||
void SetGuildWarEndTime(DWORD guild_id1, DWORD guild_id2, time_t tEndTime);
|
||||
|
||||
void QUERY_BOOT(CPeer * peer, TPacketGDBoot * p);
|
||||
|
||||
void QUERY_LOGIN(CPeer * peer, DWORD dwHandle, SLoginPacket* data);
|
||||
void QUERY_LOGOUT(CPeer * peer, DWORD dwHandle, const char *);
|
||||
|
||||
void RESULT_LOGIN(CPeer * peer, SQLMsg *msg);
|
||||
|
||||
void QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoadPacket*);
|
||||
void RESULT_COMPOSITE_PLAYER(CPeer * peer, SQLMsg * pMsg, DWORD dwQID);
|
||||
void RESULT_PLAYER_LOAD(CPeer * peer, MYSQL_RES * pRes, ClientHandleInfo * pkInfo);
|
||||
void RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID);
|
||||
void RESULT_QUEST_LOAD(CPeer * pkPeer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID);
|
||||
// @fixme402 (RESULT_AFFECT_LOAD +dwRealPID)
|
||||
void RESULT_AFFECT_LOAD(CPeer * pkPeer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwRealPID);
|
||||
|
||||
// PLAYER_INDEX_CREATE_BUG_FIX
|
||||
void RESULT_PLAYER_INDEX_CREATE(CPeer *pkPeer, SQLMsg *msg);
|
||||
// END_PLAYER_INDEX_CREATE_BUG_FIX
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
|
||||
void RESULT_PRICELIST_LOAD(CPeer* peer, SQLMsg* pMsg);
|
||||
|
||||
void RESULT_PRICELIST_LOAD_FOR_UPDATE(SQLMsg* pMsg);
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
|
||||
void QUERY_PLAYER_SAVE(CPeer * peer, DWORD dwHandle, TPlayerTable*);
|
||||
|
||||
void __QUERY_PLAYER_CREATE(CPeer * peer, DWORD dwHandle, TPlayerCreatePacket *);
|
||||
void __QUERY_PLAYER_DELETE(CPeer * peer, DWORD dwHandle, TPlayerDeletePacket *);
|
||||
void __RESULT_PLAYER_DELETE(CPeer * peer, SQLMsg* msg);
|
||||
|
||||
void QUERY_PLAYER_COUNT(CPeer * pkPeer, TPlayerCountPacket *);
|
||||
|
||||
void QUERY_ITEM_SAVE(CPeer * pkPeer, const char * c_pData);
|
||||
void QUERY_ITEM_DESTROY(CPeer * pkPeer, const char * c_pData);
|
||||
void QUERY_ITEM_FLUSH(CPeer * pkPeer, const char * c_pData);
|
||||
|
||||
void QUERY_QUEST_SAVE(CPeer * pkPeer, TQuestTable *, DWORD dwLen);
|
||||
void QUERY_ADD_AFFECT(CPeer * pkPeer, TPacketGDAddAffect * p);
|
||||
void QUERY_REMOVE_AFFECT(CPeer * pkPeer, TPacketGDRemoveAffect * p);
|
||||
|
||||
void QUERY_SAFEBOX_LOAD(CPeer * pkPeer, DWORD dwHandle, TSafeboxLoadPacket *, bool bMall);
|
||||
void QUERY_SAFEBOX_SAVE(CPeer * pkPeer, TSafeboxTable * pTable);
|
||||
void QUERY_SAFEBOX_CHANGE_SIZE(CPeer * pkPeer, DWORD dwHandle, TSafeboxChangeSizePacket * p);
|
||||
void QUERY_SAFEBOX_CHANGE_PASSWORD(CPeer * pkPeer, DWORD dwHandle, TSafeboxChangePasswordPacket * p);
|
||||
|
||||
void RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg);
|
||||
void RESULT_SAFEBOX_CHANGE_SIZE(CPeer * pkPeer, SQLMsg * msg);
|
||||
void RESULT_SAFEBOX_CHANGE_PASSWORD(CPeer * pkPeer, SQLMsg * msg);
|
||||
void RESULT_SAFEBOX_CHANGE_PASSWORD_SECOND(CPeer * pkPeer, SQLMsg * msg);
|
||||
|
||||
void QUERY_EMPIRE_SELECT(CPeer * pkPeer, DWORD dwHandle, TEmpireSelectPacket * p);
|
||||
void QUERY_SETUP(CPeer * pkPeer, DWORD dwHandle, const char * c_pData);
|
||||
|
||||
void SendPartyOnSetup(CPeer * peer);
|
||||
|
||||
void QUERY_FLUSH_CACHE(CPeer * pkPeer, const char * c_pData);
|
||||
|
||||
void QUERY_PARTY_CREATE(CPeer * peer, TPacketPartyCreate* p);
|
||||
void QUERY_PARTY_DELETE(CPeer * peer, TPacketPartyDelete* p);
|
||||
void QUERY_PARTY_ADD(CPeer * peer, TPacketPartyAdd* p);
|
||||
void QUERY_PARTY_REMOVE(CPeer * peer, TPacketPartyRemove* p);
|
||||
void QUERY_PARTY_STATE_CHANGE(CPeer * peer, TPacketPartyStateChange* p);
|
||||
void QUERY_PARTY_SET_MEMBER_LEVEL(CPeer * peer, TPacketPartySetMemberLevel* p);
|
||||
|
||||
void QUERY_RELOAD_PROTO();
|
||||
|
||||
void QUERY_CHANGE_NAME(CPeer * peer, DWORD dwHandle, TPacketGDChangeName * p);
|
||||
void GetPlayerFromRes(TPlayerTable * player_table, MYSQL_RES* res);
|
||||
|
||||
void QUERY_LOGIN_KEY(CPeer * pkPeer, TPacketGDLoginKey * p);
|
||||
|
||||
void AddGuildPriv(TPacketGiveGuildPriv* p);
|
||||
void AddEmpirePriv(TPacketGiveEmpirePriv* p);
|
||||
void AddCharacterPriv(TPacketGiveCharacterPriv* p);
|
||||
|
||||
void MoneyLog(TPacketMoneyLog* p);
|
||||
|
||||
void QUERY_AUTH_LOGIN(CPeer * pkPeer, DWORD dwHandle, TPacketGDAuthLogin * p);
|
||||
|
||||
void QUERY_LOGIN_BY_KEY(CPeer * pkPeer, DWORD dwHandle, TPacketGDLoginByKey * p);
|
||||
void RESULT_LOGIN_BY_KEY(CPeer * peer, SQLMsg * msg);
|
||||
|
||||
void ChargeCash(const TRequestChargeCash * p);
|
||||
|
||||
void LoadEventFlag();
|
||||
void SetEventFlag(TPacketSetEventFlag* p);
|
||||
void SendEventFlagsOnSetup(CPeer* peer);
|
||||
|
||||
void BillingExpire(TPacketBillingExpire * p);
|
||||
void BillingCheck(const char * data);
|
||||
|
||||
void SendAllLoginToBilling();
|
||||
void SendLoginToBilling(CLoginData * pkLD, bool bLogin);
|
||||
|
||||
void MarriageAdd(TPacketMarriageAdd * p);
|
||||
void MarriageUpdate(TPacketMarriageUpdate * p);
|
||||
void MarriageRemove(TPacketMarriageRemove * p);
|
||||
|
||||
void WeddingRequest(TPacketWeddingRequest * p);
|
||||
void WeddingReady(TPacketWeddingReady * p);
|
||||
void WeddingEnd(TPacketWeddingEnd * p);
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
|
||||
void MyshopPricelistUpdate(const TItemPriceListTable* pPacket); // @fixme403 (TPacketMyshopPricelistHeader to TItemPriceListTable)
|
||||
|
||||
void MyshopPricelistRequest(CPeer* peer, DWORD dwHandle, DWORD dwPlayerID);
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
|
||||
// Building
|
||||
void CreateObject(TPacketGDCreateObject * p);
|
||||
void DeleteObject(DWORD dwID);
|
||||
void UpdateLand(DWORD * pdw);
|
||||
|
||||
// BLOCK_CHAT
|
||||
void BlockChat(TPacketBlockChat * p);
|
||||
// END_OF_BLOCK_CHAT
|
||||
|
||||
private:
|
||||
int m_looping;
|
||||
socket_t m_fdAccept;
|
||||
TPeerList m_peerList;
|
||||
|
||||
CPeer * m_pkAuthPeer;
|
||||
|
||||
// LoginKey, LoginData pair
|
||||
typedef boost::unordered_map<DWORD, CLoginData *> TLoginDataByLoginKey;
|
||||
TLoginDataByLoginKey m_map_pkLoginData;
|
||||
|
||||
// Login LoginData pair
|
||||
typedef boost::unordered_map<std::string, CLoginData *> TLoginDataByLogin;
|
||||
TLoginDataByLogin m_map_pkLoginDataByLogin;
|
||||
|
||||
// AccountID LoginData pair
|
||||
typedef boost::unordered_map<DWORD, CLoginData *> TLoginDataByAID;
|
||||
TLoginDataByAID m_map_pkLoginDataByAID;
|
||||
|
||||
typedef boost::unordered_map<std::string, CLoginData *> TLogonAccountMap;
|
||||
TLogonAccountMap m_map_kLogonAccount;
|
||||
|
||||
int m_iPlayerIDStart;
|
||||
int m_iPlayerDeleteLevelLimit;
|
||||
int m_iPlayerDeleteLevelLimitLower;
|
||||
bool m_bChinaEventServer;
|
||||
|
||||
std::vector<TMobTable> m_vec_mobTable;
|
||||
std::vector<TItemTable> m_vec_itemTable;
|
||||
std::map<DWORD, TItemTable *> m_map_itemTableByVnum;
|
||||
|
||||
int m_iShopTableSize;
|
||||
TShopTable * m_pShopTable;
|
||||
|
||||
int m_iRefineTableSize;
|
||||
TRefineTable* m_pRefineTable;
|
||||
|
||||
std::vector<TSkillTable> m_vec_skillTable;
|
||||
std::vector<TBanwordTable> m_vec_banwordTable;
|
||||
std::vector<TItemAttrTable> m_vec_itemAttrTable;
|
||||
std::vector<TItemAttrTable> m_vec_itemRareTable;
|
||||
|
||||
std::vector<building::TLand> m_vec_kLandTable;
|
||||
std::vector<building::TObjectProto> m_vec_kObjectProto;
|
||||
std::map<DWORD, building::TObject *> m_map_pkObjectTable;
|
||||
|
||||
bool m_bShutdowned;
|
||||
|
||||
TPlayerTableCacheMap m_map_playerCache;
|
||||
|
||||
TItemCacheMap m_map_itemCache;
|
||||
TItemCacheSetPtrMap m_map_pkItemCacheSetPtr;
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
|
||||
TItemPriceListCacheMap m_mapItemPriceListCache;
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
|
||||
TChannelStatusMap m_mChannelStatus;
|
||||
|
||||
struct TPartyInfo
|
||||
{
|
||||
BYTE bRole;
|
||||
BYTE bLevel;
|
||||
|
||||
TPartyInfo() :bRole(0), bLevel(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<DWORD, TPartyInfo> TPartyMember;
|
||||
typedef std::map<DWORD, TPartyMember> TPartyMap;
|
||||
typedef std::map<BYTE, TPartyMap> TPartyChannelMap;
|
||||
TPartyChannelMap m_map_pkChannelParty;
|
||||
|
||||
typedef std::map<std::string, long> TEventFlagMap;
|
||||
TEventFlagMap m_map_lEventFlag;
|
||||
|
||||
BYTE m_bLastHeader;
|
||||
int m_iCacheFlushCount;
|
||||
int m_iCacheFlushCountLimit;
|
||||
|
||||
private :
|
||||
TItemIDRangeTable m_itemRange;
|
||||
|
||||
public :
|
||||
bool InitializeNowItemID();
|
||||
DWORD GetItemID();
|
||||
DWORD GainItemID();
|
||||
TItemIDRangeTable GetItemRange() { return m_itemRange; }
|
||||
|
||||
//BOOT_LOCALIZATION
|
||||
public:
|
||||
|
||||
bool InitializeLocalization();
|
||||
|
||||
private:
|
||||
std::vector<tLocale> m_vec_Locale;
|
||||
//END_BOOT_LOCALIZATION
|
||||
//ADMIN_MANAGER
|
||||
|
||||
bool __GetAdminInfo(const char *szIP, std::vector<tAdminInfo> & rAdminVec);
|
||||
bool __GetHostInfo(std::vector<std::string> & rIPVec);
|
||||
//END_ADMIN_MANAGER
|
||||
|
||||
//RELOAD_ADMIN
|
||||
void ReloadAdmin(CPeer * peer, TPacketReloadAdmin * p);
|
||||
//END_RELOAD_ADMIN
|
||||
void BreakMarriage(CPeer * peer, const char * data);
|
||||
|
||||
struct TLogoutPlayer
|
||||
{
|
||||
DWORD pid;
|
||||
time_t time;
|
||||
|
||||
bool operator < (const TLogoutPlayer & r)
|
||||
{
|
||||
return (pid < r.pid);
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::unordered_map<DWORD, TLogoutPlayer*> TLogoutPlayerMap;
|
||||
TLogoutPlayerMap m_map_logout;
|
||||
|
||||
void InsertLogoutPlayer(DWORD pid);
|
||||
void DeleteLogoutPlayer(DWORD pid);
|
||||
void UpdateLogoutPlayer();
|
||||
void UpdateItemCacheSet(DWORD pid);
|
||||
|
||||
void FlushPlayerCacheSet(DWORD pid);
|
||||
|
||||
//MONARCH
|
||||
void Election(CPeer * peer, DWORD dwHandle, const char * p);
|
||||
void Candidacy(CPeer * peer, DWORD dwHandle, const char * p);
|
||||
void AddMonarchMoney(CPeer * peer, DWORD dwHandle, const char * p);
|
||||
void TakeMonarchMoney(CPeer * peer, DWORD dwHandle, const char * p);
|
||||
void ComeToVote(CPeer * peer, DWORD dwHandle, const char * p);
|
||||
void RMCandidacy(CPeer * peer, DWORD dwHandle, const char * p);
|
||||
void SetMonarch(CPeer * peer, DWORD dwHandle, const char * p);
|
||||
void RMMonarch(CPeer * peer, DWORD dwHandle, const char * p);
|
||||
|
||||
void DecMonarchMoney(CPeer * peer, DWORD dwHandle, const char * p);
|
||||
//END_MONARCH
|
||||
|
||||
void ChangeMonarchLord(CPeer* peer, DWORD dwHandle, TPacketChangeMonarchLord* info);
|
||||
|
||||
void SendSpareItemIDRange(CPeer* peer);
|
||||
|
||||
void UpdateHorseName(TPacketUpdateHorseName* data, CPeer* peer);
|
||||
void AckHorseName(DWORD dwPID, CPeer* peer);
|
||||
void DeleteLoginKey(TPacketDC *data);
|
||||
void ResetLastPlayerID(const TPacketNeedLoginLogInfo* data);
|
||||
//delete gift notify icon
|
||||
void DeleteAwardId(TPacketDeleteAwardID* data);
|
||||
void UpdateChannelStatus(TChannelStatus* pData);
|
||||
void RequestChannelStatus(CPeer* peer, DWORD dwHandle);
|
||||
#ifdef ENABLE_PROTO_FROM_DB
|
||||
public:
|
||||
bool InitializeMobTableFromDB();
|
||||
bool InitializeItemTableFromDB();
|
||||
protected:
|
||||
bool bIsProtoReadFromDB;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<class Func>
|
||||
Func CClientManager::for_each_peer(Func f)
|
||||
{
|
||||
TPeerList::iterator it;
|
||||
for (it = m_peerList.begin(); it!=m_peerList.end();++it)
|
||||
{
|
||||
f(*it);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
1606
source-server/Srcs/Server/db/src/ClientManagerBoot.cpp
Normal file
1606
source-server/Srcs/Server/db/src/ClientManagerBoot.cpp
Normal file
File diff suppressed because it is too large
Load Diff
77
source-server/Srcs/Server/db/src/ClientManagerEventFlag.cpp
Normal file
77
source-server/Srcs/Server/db/src/ClientManagerEventFlag.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
// vim:ts=4 sw=4
|
||||
#include "stdafx.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Main.h"
|
||||
#include "Config.h"
|
||||
#include "DBManager.h"
|
||||
#include "QID.h"
|
||||
|
||||
void CClientManager::LoadEventFlag()
|
||||
{
|
||||
char szQuery[1024];
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT szName, lValue FROM quest%s WHERE dwPID = 0", GetTablePostfix());
|
||||
|
||||
auto pmsg(CDBManager::instance().DirectQuery(szQuery));
|
||||
SQLResult* pRes = pmsg->Get();
|
||||
if (pRes->uiNumRows)
|
||||
{
|
||||
MYSQL_ROW row;
|
||||
while ((row = mysql_fetch_row(pRes->pSQLResult)))
|
||||
{
|
||||
TPacketSetEventFlag p;
|
||||
strlcpy(p.szFlagName, row[0], sizeof(p.szFlagName));
|
||||
str_to_number(p.lValue, row[1]);
|
||||
sys_log(0, "EventFlag Load %s %d", p.szFlagName, p.lValue);
|
||||
m_map_lEventFlag.emplace(p.szFlagName, p.lValue);
|
||||
ForwardPacket(HEADER_DG_SET_EVENT_FLAG, &p, sizeof(TPacketSetEventFlag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CClientManager::SetEventFlag(TPacketSetEventFlag* p)
|
||||
{
|
||||
ForwardPacket(HEADER_DG_SET_EVENT_FLAG, p, sizeof(TPacketSetEventFlag));
|
||||
|
||||
bool bChanged = false;
|
||||
|
||||
typeof(m_map_lEventFlag.begin()) it = m_map_lEventFlag.find(p->szFlagName);
|
||||
if (it == m_map_lEventFlag.end())
|
||||
{
|
||||
bChanged = true;
|
||||
m_map_lEventFlag.emplace(p->szFlagName, p->lValue);
|
||||
}
|
||||
else if (it->second != p->lValue)
|
||||
{
|
||||
bChanged = true;
|
||||
it->second = p->lValue;
|
||||
}
|
||||
|
||||
if (bChanged)
|
||||
{
|
||||
char szQuery[1024];
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"REPLACE INTO quest%s (dwPID, szName, szState, lValue) VALUES(0, '%s', '', %ld)",
|
||||
GetTablePostfix(), p->szFlagName, p->lValue);
|
||||
szQuery[1023] = '\0';
|
||||
|
||||
//CDBManager::instance().ReturnQuery(szQuery, QID_QUEST_SAVE, 0, NULL);
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
sys_log(0, "HEADER_GD_SET_EVENT_FLAG : Changed CClientmanager::SetEventFlag(%s %d) ", p->szFlagName, p->lValue);
|
||||
return;
|
||||
}
|
||||
sys_log(0, "HEADER_GD_SET_EVENT_FLAG : No Changed CClientmanager::SetEventFlag(%s %d) ", p->szFlagName, p->lValue);
|
||||
}
|
||||
|
||||
void CClientManager::SendEventFlagsOnSetup(CPeer* peer)
|
||||
{
|
||||
typeof(m_map_lEventFlag.begin()) it;
|
||||
for (it = m_map_lEventFlag.begin(); it != m_map_lEventFlag.end(); ++it)
|
||||
{
|
||||
TPacketSetEventFlag p;
|
||||
strlcpy(p.szFlagName, it->first.c_str(), sizeof(p.szFlagName));
|
||||
p.lValue = it->second;
|
||||
peer->EncodeHeader(HEADER_DG_SET_EVENT_FLAG, 0, sizeof(TPacketSetEventFlag));
|
||||
peer->Encode(&p, sizeof(TPacketSetEventFlag));
|
||||
}
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
244
source-server/Srcs/Server/db/src/ClientManagerGuild.cpp
Normal file
244
source-server/Srcs/Server/db/src/ClientManagerGuild.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
// vim:ts=4 sw=4
|
||||
#include "stdafx.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Main.h"
|
||||
#include "Config.h"
|
||||
#include "DBManager.h"
|
||||
#include "QID.h"
|
||||
#include "GuildManager.h"
|
||||
|
||||
void CClientManager::GuildCreate(CPeer * peer, DWORD dwGuildID)
|
||||
{
|
||||
sys_log(0, "GuildCreate %u", dwGuildID);
|
||||
ForwardPacket(HEADER_DG_GUILD_LOAD, &dwGuildID, sizeof(DWORD));
|
||||
|
||||
CGuildManager::instance().Load(dwGuildID);
|
||||
}
|
||||
|
||||
void CClientManager::GuildChangeGrade(CPeer* peer, TPacketGuild* p)
|
||||
{
|
||||
sys_log(0, "GuildChangeGrade %u %u", p->dwGuild, p->dwInfo);
|
||||
ForwardPacket(HEADER_DG_GUILD_CHANGE_GRADE, p, sizeof(TPacketGuild));
|
||||
}
|
||||
|
||||
void CClientManager::GuildAddMember(CPeer* peer, TPacketGDGuildAddMember * p)
|
||||
{
|
||||
CGuildManager::instance().TouchGuild(p->dwGuild);
|
||||
sys_log(0, "GuildAddMember %u %u", p->dwGuild, p->dwPID);
|
||||
|
||||
char szQuery[512];
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"INSERT INTO guild_member%s VALUES(%u, %u, %d, 0, 0)",
|
||||
GetTablePostfix(), p->dwPID, p->dwGuild, p->bGrade);
|
||||
|
||||
auto pmsg_insert(CDBManager::instance().DirectQuery(szQuery));
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"SELECT pid, grade, is_general, offer, level, job, name FROM guild_member%s, player%s WHERE guild_id = %u and pid = id and pid = %u", GetTablePostfix(), GetTablePostfix(), p->dwGuild, p->dwPID);
|
||||
|
||||
auto pmsg(CDBManager::instance().DirectQuery(szQuery));
|
||||
if (pmsg->Get()->uiNumRows == 0)
|
||||
{
|
||||
sys_err("Query failed when getting guild member data %s", pmsg->stQuery.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);
|
||||
|
||||
if (!row[0] || !row[1])
|
||||
return;
|
||||
|
||||
TPacketDGGuildMember dg;
|
||||
|
||||
dg.dwGuild = p->dwGuild;
|
||||
str_to_number(dg.dwPID, row[0]);
|
||||
str_to_number(dg.bGrade, row[1]);
|
||||
str_to_number(dg.isGeneral, row[2]);
|
||||
str_to_number(dg.dwOffer, row[3]);
|
||||
str_to_number(dg.bLevel, row[4]);
|
||||
str_to_number(dg.bJob, row[5]);
|
||||
strlcpy(dg.szName, row[6], sizeof(dg.szName));
|
||||
|
||||
ForwardPacket(HEADER_DG_GUILD_ADD_MEMBER, &dg, sizeof(TPacketDGGuildMember));
|
||||
}
|
||||
|
||||
void CClientManager::GuildRemoveMember(CPeer* peer, TPacketGuild* p)
|
||||
{
|
||||
sys_log(0, "GuildRemoveMember %u %u", p->dwGuild, p->dwInfo);
|
||||
|
||||
char szQuery[512];
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_member%s WHERE pid=%u and guild_id=%u", GetTablePostfix(), p->dwInfo, p->dwGuild);
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
// @fixme202 new_+withdraw_time
|
||||
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO quest%s (dwPID, szName, szState, lValue) VALUES(%u, 'guild_manage', 'new_withdraw_time', %u)", GetTablePostfix(), p->dwInfo, (DWORD) GetCurrentTime());
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
ForwardPacket(HEADER_DG_GUILD_REMOVE_MEMBER, p, sizeof(TPacketGuild));
|
||||
}
|
||||
|
||||
void CClientManager::GuildSkillUpdate(CPeer* peer, TPacketGuildSkillUpdate* p)
|
||||
{
|
||||
sys_log(0, "GuildSkillUpdate %d", p->amount);
|
||||
ForwardPacket(HEADER_DG_GUILD_SKILL_UPDATE, p, sizeof(TPacketGuildSkillUpdate));
|
||||
}
|
||||
|
||||
void CClientManager::GuildExpUpdate(CPeer* peer, TPacketGuildExpUpdate* p)
|
||||
{
|
||||
sys_log(0, "GuildExpUpdate %d", p->amount);
|
||||
ForwardPacket(HEADER_DG_GUILD_EXP_UPDATE, p, sizeof(TPacketGuildExpUpdate), 0, peer);
|
||||
}
|
||||
|
||||
void CClientManager::GuildChangeMemberData(CPeer* peer, TPacketGuildChangeMemberData* p)
|
||||
{
|
||||
sys_log(0, "GuildChangeMemberData %u %u %d %d", p->pid, p->offer, p->level, p->grade);
|
||||
ForwardPacket(HEADER_DG_GUILD_CHANGE_MEMBER_DATA, p, sizeof(TPacketGuildChangeMemberData), 0, peer);
|
||||
}
|
||||
|
||||
void CClientManager::GuildDisband(CPeer* peer, TPacketGuild* p)
|
||||
{
|
||||
sys_log(0, "GuildDisband %u", p->dwGuild);
|
||||
|
||||
char szQuery[512];
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild%s WHERE id=%u", GetTablePostfix(), p->dwGuild);
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_grade%s WHERE guild_id=%u", GetTablePostfix(), p->dwGuild);
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
// @fixme401 (withdraw -> new_disband)_time
|
||||
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO quest%s (dwPID, szName, szState, lValue) SELECT pid, 'guild_manage', 'new_disband_time', %u FROM guild_member%s WHERE guild_id = %u", GetTablePostfix(), (DWORD) GetCurrentTime(), GetTablePostfix(), p->dwGuild);
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_member%s WHERE guild_id=%u", GetTablePostfix(), p->dwGuild);
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_comment%s WHERE guild_id=%u", GetTablePostfix(), p->dwGuild);
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
ForwardPacket(HEADER_DG_GUILD_DISBAND, p, sizeof(TPacketGuild));
|
||||
}
|
||||
|
||||
const char* __GetWarType(int n)
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 0 :
|
||||
return "Field";
|
||||
case 1 :
|
||||
return "Theater";
|
||||
case 2 :
|
||||
return "CTF"; //Capture The Flag
|
||||
default :
|
||||
return "Wrong number";
|
||||
}
|
||||
}
|
||||
|
||||
void CClientManager::GuildWar(CPeer* peer, TPacketGuildWar* p)
|
||||
{
|
||||
switch (p->bWar)
|
||||
{
|
||||
case GUILD_WAR_SEND_DECLARE:
|
||||
sys_log(0, "GuildWar: GUILD_WAR_SEND_DECLARE type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().AddDeclare(p->bType, p->dwGuildFrom, p->dwGuildTo);
|
||||
break;
|
||||
|
||||
case GUILD_WAR_REFUSE:
|
||||
sys_log(0, "GuildWar: GUILD_WAR_REFUSE type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
|
||||
break;
|
||||
/*
|
||||
case GUILD_WAR_WAIT_START:
|
||||
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
|
||||
|
||||
if (!CGuildManager::instance().WaitStart(p))
|
||||
p->bWar = GUILD_WAR_CANCEL;
|
||||
|
||||
break;
|
||||
*/
|
||||
|
||||
case GUILD_WAR_WAIT_START:
|
||||
sys_log(0, "GuildWar: GUILD_WAR_WAIT_START type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
case GUILD_WAR_RESERVE:
|
||||
if (p->bWar != GUILD_WAR_WAIT_START)
|
||||
sys_log(0, "GuildWar: GUILD_WAR_RESERVE type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
|
||||
|
||||
if (!CGuildManager::instance().ReserveWar(p))
|
||||
p->bWar = GUILD_WAR_CANCEL;
|
||||
else
|
||||
p->bWar = GUILD_WAR_RESERVE;
|
||||
|
||||
break;
|
||||
|
||||
case GUILD_WAR_ON_WAR:
|
||||
sys_log(0, "GuildWar: GUILD_WAR_ON_WAR type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().StartWar(p->bType, p->dwGuildFrom, p->dwGuildTo);
|
||||
break;
|
||||
|
||||
case GUILD_WAR_OVER:
|
||||
sys_log(0, "GuildWar: GUILD_WAR_OVER type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().RecvWarOver(p->dwGuildFrom, p->dwGuildTo, p->bType, p->lWarPrice);
|
||||
break;
|
||||
|
||||
case GUILD_WAR_END:
|
||||
sys_log(0, "GuildWar: GUILD_WAR_END type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().RecvWarEnd(p->dwGuildFrom, p->dwGuildTo);
|
||||
return;
|
||||
|
||||
case GUILD_WAR_CANCEL :
|
||||
sys_log(0, "GuildWar: GUILD_WAR_CANCEL type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().CancelWar(p->dwGuildFrom, p->dwGuildTo);
|
||||
break;
|
||||
}
|
||||
|
||||
ForwardPacket(HEADER_DG_GUILD_WAR, p, sizeof(TPacketGuildWar));
|
||||
}
|
||||
|
||||
void CClientManager::GuildWarScore(CPeer* peer, TPacketGuildWarScore * p)
|
||||
{
|
||||
CGuildManager::instance().UpdateScore(p->dwGuildGainPoint, p->dwGuildOpponent, p->lScore, p->lBetScore);
|
||||
}
|
||||
|
||||
void CClientManager::GuildChangeLadderPoint(TPacketGuildLadderPoint* p)
|
||||
{
|
||||
sys_log(0, "GuildChangeLadderPoint Recv %u %d", p->dwGuild, p->lChange);
|
||||
CGuildManager::instance().ChangeLadderPoint(p->dwGuild, p->lChange);
|
||||
}
|
||||
|
||||
void CClientManager::GuildUseSkill(TPacketGuildUseSkill* p)
|
||||
{
|
||||
sys_log(0, "GuildUseSkill Recv %u %d", p->dwGuild, p->dwSkillVnum);
|
||||
CGuildManager::instance().UseSkill(p->dwGuild, p->dwSkillVnum, p->dwCooltime);
|
||||
SendGuildSkillUsable(p->dwGuild, p->dwSkillVnum, false);
|
||||
}
|
||||
|
||||
void CClientManager::SendGuildSkillUsable(DWORD guild_id, DWORD dwSkillVnum, bool bUsable)
|
||||
{
|
||||
sys_log(0, "SendGuildSkillUsable Send %u %d %s", guild_id, dwSkillVnum, bUsable?"true":"false");
|
||||
|
||||
TPacketGuildSkillUsableChange p;
|
||||
|
||||
p.dwGuild = guild_id;
|
||||
p.dwSkillVnum = dwSkillVnum;
|
||||
p.bUsable = bUsable;
|
||||
|
||||
ForwardPacket(HEADER_DG_GUILD_SKILL_USABLE_CHANGE, &p, sizeof(TPacketGuildSkillUsableChange));
|
||||
}
|
||||
|
||||
void CClientManager::GuildChangeMaster(TPacketChangeGuildMaster* p)
|
||||
{
|
||||
if (CGuildManager::instance().ChangeMaster(p->dwGuildID, p->idFrom, p->idTo) == true)
|
||||
{
|
||||
TPacketChangeGuildMaster packet;
|
||||
packet.dwGuildID = p->dwGuildID;
|
||||
packet.idFrom = 0;
|
||||
packet.idTo = 0;
|
||||
|
||||
ForwardPacket(HEADER_DG_ACK_CHANGE_GUILD_MASTER, &packet, sizeof(packet));
|
||||
}
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
39
source-server/Srcs/Server/db/src/ClientManagerHorseName.cpp
Normal file
39
source-server/Srcs/Server/db/src/ClientManagerHorseName.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
// vim:ts=4 sw=4
|
||||
#include "stdafx.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
void CClientManager::UpdateHorseName(TPacketUpdateHorseName* data, CPeer* peer)
|
||||
{
|
||||
char szQuery[512];
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO horse_name VALUES(%u, '%s')", data->dwPlayerID, data->szHorseName);
|
||||
|
||||
auto pmsg_insert(CDBManager::instance().DirectQuery(szQuery));
|
||||
|
||||
ForwardPacket(HEADER_DG_UPDATE_HORSE_NAME, data, sizeof(TPacketUpdateHorseName), 0, peer);
|
||||
}
|
||||
|
||||
void CClientManager::AckHorseName(DWORD dwPID, CPeer* peer)
|
||||
{
|
||||
char szQuery[512];
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT name FROM horse_name WHERE id = %u", dwPID);
|
||||
|
||||
auto pmsg(CDBManager::instance().DirectQuery(szQuery));
|
||||
|
||||
TPacketUpdateHorseName packet;
|
||||
packet.dwPlayerID = dwPID;
|
||||
|
||||
if (pmsg->Get()->uiNumRows == 0)
|
||||
{
|
||||
memset(packet.szHorseName, 0, sizeof (packet.szHorseName));
|
||||
}
|
||||
else
|
||||
{
|
||||
MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);
|
||||
strlcpy(packet.szHorseName, row[0], sizeof(packet.szHorseName));
|
||||
}
|
||||
|
||||
peer->EncodeHeader(HEADER_DG_ACK_HORSE_NAME, 0, sizeof(TPacketUpdateHorseName));
|
||||
peer->Encode(&packet, sizeof(TPacketUpdateHorseName));
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
538
source-server/Srcs/Server/db/src/ClientManagerLogin.cpp
Normal file
538
source-server/Srcs/Server/db/src/ClientManagerLogin.cpp
Normal file
@ -0,0 +1,538 @@
|
||||
#include "stdafx.h"
|
||||
#include "../../common/CommonDefines.h"
|
||||
|
||||
#include "ClientManager.h"
|
||||
|
||||
#include "Main.h"
|
||||
#include "Config.h"
|
||||
#include "QID.h"
|
||||
#include "Cache.h"
|
||||
|
||||
extern std::string g_stLocale;
|
||||
extern bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab);
|
||||
extern int g_test_server;
|
||||
extern int g_log;
|
||||
|
||||
bool CClientManager::InsertLogonAccount(const char * c_pszLogin, DWORD dwHandle, const char * c_pszIP)
|
||||
{
|
||||
char szLogin[LOGIN_MAX_LEN + 1];
|
||||
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
|
||||
|
||||
itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin);
|
||||
|
||||
if (m_map_kLogonAccount.end() != it)
|
||||
return false;
|
||||
|
||||
CLoginData * pkLD = GetLoginDataByLogin(c_pszLogin);
|
||||
|
||||
if (!pkLD)
|
||||
return false;
|
||||
|
||||
pkLD->SetConnectedPeerHandle(dwHandle);
|
||||
pkLD->SetIP(c_pszIP);
|
||||
|
||||
m_map_kLogonAccount.emplace(szLogin, pkLD);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClientManager::DeleteLogonAccount(const char * c_pszLogin, DWORD dwHandle)
|
||||
{
|
||||
char szLogin[LOGIN_MAX_LEN + 1];
|
||||
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
|
||||
|
||||
itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin);
|
||||
|
||||
if (it == m_map_kLogonAccount.end())
|
||||
return false;
|
||||
|
||||
CLoginData * pkLD = it->second;
|
||||
|
||||
if (pkLD->GetConnectedPeerHandle() != dwHandle)
|
||||
{
|
||||
sys_err("%s tried to logout in other peer handle %lu, current handle %lu", szLogin, dwHandle, pkLD->GetConnectedPeerHandle());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pkLD->IsPlay())
|
||||
{
|
||||
pkLD->SetPlay(false);
|
||||
SendLoginToBilling(pkLD, false);
|
||||
}
|
||||
|
||||
if (pkLD->IsDeleted())
|
||||
{
|
||||
delete pkLD;
|
||||
}
|
||||
|
||||
m_map_kLogonAccount.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClientManager::FindLogonAccount(const char * c_pszLogin)
|
||||
{
|
||||
char szLogin[LOGIN_MAX_LEN + 1];
|
||||
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
|
||||
|
||||
if (m_map_kLogonAccount.end() == m_map_kLogonAccount.find(szLogin))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CClientManager::QUERY_LOGIN_BY_KEY(CPeer * pkPeer, DWORD dwHandle, TPacketGDLoginByKey * p)
|
||||
{
|
||||
#ifdef ENABLE_LIMIT_TIME
|
||||
static int s_updateCount = 0;
|
||||
static int s_curTime = time(0);
|
||||
if (s_updateCount > 100)
|
||||
{
|
||||
s_curTime = time(0);
|
||||
s_updateCount = 0;
|
||||
}
|
||||
++s_updateCount;
|
||||
|
||||
if (s_curTime >= GLOBAL_LIMIT_TIME)
|
||||
{
|
||||
sys_err("Server life time expired.");
|
||||
exit(0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLoginData * pkLoginData = GetLoginData(p->dwLoginKey);
|
||||
char szLogin[LOGIN_MAX_LEN + 1];
|
||||
trim_and_lower(p->szLogin, szLogin, sizeof(szLogin));
|
||||
|
||||
if (!pkLoginData)
|
||||
{
|
||||
sys_log(0, "LOGIN_BY_KEY key not exist %s %lu", szLogin, p->dwLoginKey);
|
||||
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
TAccountTable & r = pkLoginData->GetAccountRef();
|
||||
|
||||
if (FindLogonAccount(r.login))
|
||||
{
|
||||
sys_log(0, "LOGIN_BY_KEY already login %s %lu", r.login, p->dwLoginKey);
|
||||
TPacketDGLoginAlready ptog;
|
||||
strlcpy(ptog.szLogin, szLogin, sizeof(ptog.szLogin));
|
||||
pkPeer->EncodeHeader(HEADER_DG_LOGIN_ALREADY, dwHandle, sizeof(TPacketDGLoginAlready));
|
||||
pkPeer->Encode(&ptog, sizeof(TPacketDGLoginAlready));
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(r.login, szLogin))
|
||||
{
|
||||
sys_log(0, "LOGIN_BY_KEY login differ %s %lu input %s", r.login, p->dwLoginKey, szLogin);
|
||||
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(pkLoginData->GetClientKey(), p->adwClientKey, sizeof(DWORD) * 4))
|
||||
{
|
||||
const DWORD * pdwClientKey = pkLoginData->GetClientKey();
|
||||
|
||||
sys_log(0, "LOGIN_BY_KEY client key differ %s %lu %lu %lu %lu, %lu %lu %lu %lu",
|
||||
r.login,
|
||||
p->adwClientKey[0], p->adwClientKey[1], p->adwClientKey[2], p->adwClientKey[3],
|
||||
pdwClientKey[0], pdwClientKey[1], pdwClientKey[2], pdwClientKey[3]);
|
||||
|
||||
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
TAccountTable * pkTab = new TAccountTable;
|
||||
memset(pkTab, 0, sizeof(TAccountTable));
|
||||
|
||||
pkTab->id = r.id;
|
||||
trim_and_lower(r.login, pkTab->login, sizeof(pkTab->login));
|
||||
strlcpy(pkTab->passwd, r.passwd, sizeof(pkTab->passwd));
|
||||
strlcpy(pkTab->social_id, r.social_id, sizeof(pkTab->social_id));
|
||||
strlcpy(pkTab->status, "OK", sizeof(pkTab->status));
|
||||
|
||||
ClientHandleInfo * info = new ClientHandleInfo(dwHandle);
|
||||
info->pAccountTable = pkTab;
|
||||
strlcpy(info->ip, p->szIP, sizeof(info->ip));
|
||||
|
||||
sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, info->ip);
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
#ifdef ENABLE_PLAYER_PER_ACCOUNT5
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, pid5, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), r.id);
|
||||
#else
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), r.id);
|
||||
#endif
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);
|
||||
}
|
||||
|
||||
void CClientManager::RESULT_LOGIN_BY_KEY(CPeer * peer, SQLMsg * msg)
|
||||
{
|
||||
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
|
||||
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
|
||||
|
||||
if (msg->uiSQLErrno != 0)
|
||||
{
|
||||
peer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, info->dwHandle);
|
||||
delete info;
|
||||
return;
|
||||
}
|
||||
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
|
||||
if (msg->Get()->uiNumRows == 0)
|
||||
{
|
||||
DWORD account_id = info->pAccountTable->id;
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"SELECT pid1, pid2, pid3, pid4,"
|
||||
#ifdef ENABLE_PLAYER_PER_ACCOUNT5
|
||||
" pid5,"
|
||||
#endif
|
||||
" empire FROM player_index%s WHERE id=%u", GetTablePostfix(), account_id);
|
||||
auto pMsg(CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER));
|
||||
|
||||
sys_log(0, "RESULT_LOGIN_BY_KEY FAIL player_index's NULL : ID:%d", account_id);
|
||||
|
||||
if (pMsg->Get()->uiNumRows == 0)
|
||||
{
|
||||
sys_log(0, "RESULT_LOGIN_BY_KEY FAIL player_index's NULL : ID:%d", account_id);
|
||||
|
||||
// PLAYER_INDEX_CREATE_BUG_FIX
|
||||
//snprintf(szQuery, sizeof(szQuery), "INSERT IGNORE INTO player_index%s (id) VALUES(%lu)", GetTablePostfix(), info->pAccountTable->id);
|
||||
snprintf(szQuery, sizeof(szQuery), "INSERT INTO player_index%s (id) VALUES(%u)", GetTablePostfix(), info->pAccountTable->id);
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_INDEX_CREATE, peer->GetHandle(), info);
|
||||
// END_PLAYER_INDEX_CREATE_BUF_FIX
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult);
|
||||
|
||||
int col = 0;
|
||||
|
||||
for (; col < PLAYER_PER_ACCOUNT; ++col)
|
||||
str_to_number(info->pAccountTable->players[col].dwID, row[col]);
|
||||
|
||||
str_to_number(info->pAccountTable->bEmpire, row[col++]);
|
||||
info->account_index = 1;
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"SELECT id, name, job, level, playtime, st, ht, dx, iq, part_main, part_hair,"
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
"part_acce,"
|
||||
#endif
|
||||
" x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
|
||||
GetTablePostfix(), info->pAccountTable->id);
|
||||
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN, peer->GetHandle(), info);
|
||||
}
|
||||
|
||||
// PLAYER_INDEX_CREATE_BUG_FIX
|
||||
void CClientManager::RESULT_PLAYER_INDEX_CREATE(CPeer * pkPeer, SQLMsg * msg)
|
||||
{
|
||||
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
|
||||
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
|
||||
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
#ifdef ENABLE_PLAYER_PER_ACCOUNT5
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, pid5, empire FROM player_index%s WHERE id=%u", GetTablePostfix(),
|
||||
info->pAccountTable->id);
|
||||
#else
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(),
|
||||
info->pAccountTable->id);
|
||||
#endif
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);
|
||||
}
|
||||
// END_PLAYER_INDEX_CREATE_BUG_FIX
|
||||
|
||||
TAccountTable * CreateAccountTableFromRes(MYSQL_RES * res)
|
||||
{
|
||||
char input_pwd[PASSWD_MAX_LEN + 1];
|
||||
MYSQL_ROW row = NULL;
|
||||
DWORD col;
|
||||
|
||||
row = mysql_fetch_row(res);
|
||||
col = 0;
|
||||
|
||||
TAccountTable * pkTab = new TAccountTable;
|
||||
memset(pkTab, 0, sizeof(TAccountTable));
|
||||
|
||||
strlcpy(input_pwd, row[col++], sizeof(input_pwd));
|
||||
str_to_number(pkTab->id, row[col++]);
|
||||
strlcpy(pkTab->login, row[col++], sizeof(pkTab->login));
|
||||
strlcpy(pkTab->passwd, row[col++], sizeof(pkTab->passwd));
|
||||
strlcpy(pkTab->social_id, row[col++], sizeof(pkTab->social_id));
|
||||
str_to_number(pkTab->bEmpire, row[col++]);
|
||||
|
||||
for (int j = 0; j < PLAYER_PER_ACCOUNT; ++j)
|
||||
str_to_number(pkTab->players[j].dwID, row[col++]);
|
||||
|
||||
strlcpy(pkTab->status, row[col++], sizeof(pkTab->status));
|
||||
|
||||
if (strcmp(pkTab->passwd, input_pwd))
|
||||
{
|
||||
delete pkTab;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pkTab;
|
||||
}
|
||||
|
||||
void CreateAccountPlayerDataFromRes(MYSQL_RES * pRes, TAccountTable * pkTab)
|
||||
{
|
||||
if (!pRes)
|
||||
return;
|
||||
|
||||
for (DWORD i = 0; i < mysql_num_rows(pRes); ++i)
|
||||
{
|
||||
MYSQL_ROW row = mysql_fetch_row(pRes);
|
||||
int col = 0;
|
||||
|
||||
DWORD player_id = 0;
|
||||
!row[col++] ? 0 : str_to_number(player_id, row[col - 1]);
|
||||
|
||||
if (!player_id)
|
||||
continue;
|
||||
|
||||
int j;
|
||||
|
||||
for (j = 0; j < PLAYER_PER_ACCOUNT; ++j)
|
||||
{
|
||||
if (pkTab->players[j].dwID == player_id)
|
||||
{
|
||||
CPlayerTableCache * pc = CClientManager::instance().GetPlayerCache(player_id);
|
||||
TPlayerTable * pt = pc ? pc->Get(false) : NULL;
|
||||
|
||||
if (pt)
|
||||
{
|
||||
strlcpy(pkTab->players[j].szName, pt->name, sizeof(pkTab->players[j].szName));
|
||||
|
||||
pkTab->players[j].byJob = pt->job;
|
||||
pkTab->players[j].byLevel = pt->level;
|
||||
pkTab->players[j].dwPlayMinutes = pt->playtime;
|
||||
pkTab->players[j].byST = pt->st;
|
||||
pkTab->players[j].byHT = pt->ht;
|
||||
pkTab->players[j].byDX = pt->dx;
|
||||
pkTab->players[j].byIQ = pt->iq;
|
||||
pkTab->players[j].wMainPart = pt->parts[PART_MAIN];
|
||||
pkTab->players[j].wHairPart = pt->parts[PART_HAIR];
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
pkTab->players[j].wAccePart = pt->parts[PART_ACCE];
|
||||
#endif
|
||||
pkTab->players[j].x = pt->x;
|
||||
pkTab->players[j].y = pt->y;
|
||||
pkTab->players[j].skill_group = pt->skill_group;
|
||||
pkTab->players[j].bChangeName = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!row[col++])
|
||||
*pkTab->players[j].szName = '\0';
|
||||
else
|
||||
strlcpy(pkTab->players[j].szName, row[col - 1], sizeof(pkTab->players[j].szName));
|
||||
|
||||
pkTab->players[j].byJob = 0;
|
||||
pkTab->players[j].byLevel = 0;
|
||||
pkTab->players[j].dwPlayMinutes = 0;
|
||||
pkTab->players[j].byST = 0;
|
||||
pkTab->players[j].byHT = 0;
|
||||
pkTab->players[j].byDX = 0;
|
||||
pkTab->players[j].byIQ = 0;
|
||||
pkTab->players[j].wMainPart = 0;
|
||||
pkTab->players[j].wHairPart = 0;
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
pkTab->players[j].wAccePart = 0;
|
||||
#endif
|
||||
pkTab->players[j].x = 0;
|
||||
pkTab->players[j].y = 0;
|
||||
pkTab->players[j].skill_group = 0;
|
||||
pkTab->players[j].bChangeName = 0;
|
||||
|
||||
str_to_number(pkTab->players[j].byJob, row[col++]);
|
||||
str_to_number(pkTab->players[j].byLevel, row[col++]);
|
||||
str_to_number(pkTab->players[j].dwPlayMinutes, row[col++]);
|
||||
str_to_number(pkTab->players[j].byST, row[col++]);
|
||||
str_to_number(pkTab->players[j].byHT, row[col++]);
|
||||
str_to_number(pkTab->players[j].byDX, row[col++]);
|
||||
str_to_number(pkTab->players[j].byIQ, row[col++]);
|
||||
str_to_number(pkTab->players[j].wMainPart, row[col++]);
|
||||
str_to_number(pkTab->players[j].wHairPart, row[col++]);
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
str_to_number(pkTab->players[j].wAccePart, row[col++]);
|
||||
#endif
|
||||
str_to_number(pkTab->players[j].x, row[col++]);
|
||||
str_to_number(pkTab->players[j].y, row[col++]);
|
||||
str_to_number(pkTab->players[j].skill_group, row[col++]);
|
||||
str_to_number(pkTab->players[j].bChangeName, row[col++]);
|
||||
}
|
||||
|
||||
sys_log(0, "%s %lu %lu hair %u",
|
||||
pkTab->players[j].szName, pkTab->players[j].x, pkTab->players[j].y, pkTab->players[j].wHairPart);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg)
|
||||
{
|
||||
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
|
||||
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
|
||||
|
||||
if (info->account_index == 0)
|
||||
{
|
||||
if (msg->Get()->uiNumRows == 0)
|
||||
{
|
||||
sys_log(0, "RESULT_LOGIN: no account");
|
||||
peer->EncodeHeader(HEADER_DG_LOGIN_NOT_EXIST, info->dwHandle, 0);
|
||||
delete info;
|
||||
return;
|
||||
}
|
||||
|
||||
info->pAccountTable = CreateAccountTableFromRes(msg->Get()->pSQLResult);
|
||||
|
||||
if (!info->pAccountTable)
|
||||
{
|
||||
sys_log(0, "RESULT_LOGIN: no account : WRONG_PASSWD");
|
||||
peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle);
|
||||
delete info;
|
||||
}
|
||||
else
|
||||
{
|
||||
++info->account_index;
|
||||
|
||||
char queryStr[512];
|
||||
snprintf(queryStr, sizeof(queryStr),
|
||||
"SELECT id, name, job, level, playtime, st, ht, dx, iq, part_main, part_hair,"
|
||||
#ifdef ENABLE_ACCE_COSTUME_SYSTEM
|
||||
"part_acce, "
|
||||
#endif
|
||||
" x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
|
||||
GetTablePostfix(), info->pAccountTable->id);
|
||||
|
||||
CDBManager::instance().ReturnQuery(queryStr, QID_LOGIN, peer->GetHandle(), info);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!info->pAccountTable)
|
||||
{
|
||||
peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle);
|
||||
delete info;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!InsertLogonAccount(info->pAccountTable->login, peer->GetHandle(), info->ip))
|
||||
{
|
||||
sys_log(0, "RESULT_LOGIN: already logon %s", info->pAccountTable->login);
|
||||
|
||||
TPacketDGLoginAlready p;
|
||||
strlcpy(p.szLogin, info->pAccountTable->login, sizeof(p.szLogin));
|
||||
|
||||
peer->EncodeHeader(HEADER_DG_LOGIN_ALREADY, info->dwHandle, sizeof(TPacketDGLoginAlready));
|
||||
peer->Encode(&p, sizeof(p));
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_log(0, "RESULT_LOGIN: login success %s rows: %lu", info->pAccountTable->login, msg->Get()->uiNumRows);
|
||||
|
||||
if (msg->Get()->uiNumRows > 0)
|
||||
CreateAccountPlayerDataFromRes(msg->Get()->pSQLResult, info->pAccountTable);
|
||||
|
||||
//PREVENT_COPY_ITEM
|
||||
CLoginData * p = GetLoginDataByLogin(info->pAccountTable->login);
|
||||
memcpy(&p->GetAccountRef(), info->pAccountTable, sizeof(TAccountTable));
|
||||
|
||||
//END_PREVENT_COPY_ITEM
|
||||
peer->EncodeHeader(HEADER_DG_LOGIN_SUCCESS, info->dwHandle, sizeof(TAccountTable));
|
||||
peer->Encode(info->pAccountTable, sizeof(TAccountTable));
|
||||
|
||||
}
|
||||
|
||||
delete info->pAccountTable;
|
||||
info->pAccountTable = NULL;
|
||||
delete info;
|
||||
}
|
||||
}
|
||||
|
||||
void CClientManager::QUERY_LOGOUT(CPeer * peer, DWORD dwHandle,const char * data)
|
||||
{
|
||||
TLogoutPacket* packet = (TLogoutPacket*)data;
|
||||
|
||||
if (!*packet->login)
|
||||
return;
|
||||
|
||||
CLoginData * pLoginData = GetLoginDataByLogin(packet->login);
|
||||
|
||||
if (pLoginData == NULL)
|
||||
return;
|
||||
|
||||
int pid[PLAYER_PER_ACCOUNT];
|
||||
|
||||
for (int n = 0; n < PLAYER_PER_ACCOUNT; ++n)
|
||||
{
|
||||
if (pLoginData->GetAccountRef().players[n].dwID == 0)
|
||||
{
|
||||
if (g_test_server)
|
||||
sys_log(0, "LOGOUT %s %d", packet->login, pLoginData->GetAccountRef().players[n].dwID);
|
||||
continue;
|
||||
}
|
||||
|
||||
pid[n] = pLoginData->GetAccountRef().players[n].dwID;
|
||||
|
||||
if (g_log)
|
||||
sys_log(0, "LOGOUT InsertLogoutPlayer %s %d", packet->login, pid[n]);
|
||||
|
||||
InsertLogoutPlayer(pid[n]);
|
||||
}
|
||||
|
||||
if (DeleteLogonAccount(packet->login, peer->GetHandle()))
|
||||
{
|
||||
if (g_log)
|
||||
sys_log(0, "LOGOUT %s ", packet->login);
|
||||
}
|
||||
}
|
||||
|
||||
void CClientManager::QUERY_CHANGE_NAME(CPeer * peer, DWORD dwHandle, TPacketGDChangeName * p)
|
||||
{
|
||||
char queryStr[QUERY_MAX_LEN];
|
||||
snprintf(queryStr, sizeof(queryStr),
|
||||
"SELECT COUNT(*) as count FROM player%s WHERE name='%s' AND id <> %u", GetTablePostfix(), p->name, p->pid);
|
||||
|
||||
auto pMsg(CDBManager::instance().DirectQuery(queryStr, SQL_PLAYER));
|
||||
|
||||
if (pMsg->Get()->uiNumRows)
|
||||
{
|
||||
if (!pMsg->Get()->pSQLResult)
|
||||
{
|
||||
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
|
||||
|
||||
if (*row[0] != '0')
|
||||
{
|
||||
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(queryStr, sizeof(queryStr),
|
||||
"UPDATE player%s SET name='%s',change_name=0 WHERE id=%u", GetTablePostfix(), p->name, p->pid);
|
||||
|
||||
auto pMsg0(CDBManager::instance().DirectQuery(queryStr, SQL_PLAYER));
|
||||
|
||||
TPacketDGChangeName pdg;
|
||||
peer->EncodeHeader(HEADER_DG_CHANGE_NAME, dwHandle, sizeof(TPacketDGChangeName));
|
||||
pdg.pid = p->pid;
|
||||
strlcpy(pdg.name, p->name, sizeof(pdg.name));
|
||||
peer->Encode(&pdg, sizeof(TPacketDGChangeName));
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
136
source-server/Srcs/Server/db/src/ClientManagerParty.cpp
Normal file
136
source-server/Srcs/Server/db/src/ClientManagerParty.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
// vim:ts=4 sw=4
|
||||
#include "stdafx.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Config.h"
|
||||
#include "DBManager.h"
|
||||
#include "QID.h"
|
||||
|
||||
void CClientManager::QUERY_PARTY_CREATE(CPeer* peer, TPacketPartyCreate* p)
|
||||
{
|
||||
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
|
||||
|
||||
if (pm.find(p->dwLeaderPID) == pm.end())
|
||||
{
|
||||
pm.emplace(p->dwLeaderPID, TPartyMember());
|
||||
ForwardPacket(HEADER_DG_PARTY_CREATE, p, sizeof(TPacketPartyCreate), peer->GetChannel(), peer);
|
||||
sys_log(0, "PARTY Create [%lu]", p->dwLeaderPID);
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_err("PARTY Create - Already exists [%lu]", p->dwLeaderPID);
|
||||
}
|
||||
}
|
||||
|
||||
void CClientManager::QUERY_PARTY_DELETE(CPeer* peer, TPacketPartyDelete* p)
|
||||
{
|
||||
TPartyMap& pm = m_map_pkChannelParty[peer->GetChannel()];
|
||||
itertype(pm) it = pm.find(p->dwLeaderPID);
|
||||
|
||||
if (it == pm.end())
|
||||
{
|
||||
sys_err("PARTY Delete - Non exists [%lu]", p->dwLeaderPID);
|
||||
return;
|
||||
}
|
||||
|
||||
pm.erase(it);
|
||||
ForwardPacket(HEADER_DG_PARTY_DELETE, p, sizeof(TPacketPartyDelete), peer->GetChannel(), peer);
|
||||
sys_log(0, "PARTY Delete [%lu]", p->dwLeaderPID);
|
||||
}
|
||||
|
||||
void CClientManager::QUERY_PARTY_ADD(CPeer* peer, TPacketPartyAdd* p)
|
||||
{
|
||||
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
|
||||
itertype(pm) it = pm.find(p->dwLeaderPID);
|
||||
|
||||
if (it == pm.end())
|
||||
{
|
||||
sys_err("PARTY Add - Non exists [%lu]", p->dwLeaderPID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (it->second.find(p->dwPID) == it->second.end())
|
||||
{
|
||||
it->second.emplace(p->dwPID, TPartyInfo());
|
||||
ForwardPacket(HEADER_DG_PARTY_ADD, p, sizeof(TPacketPartyAdd), peer->GetChannel(), peer);
|
||||
sys_log(0, "PARTY Add [%lu] to [%lu]", p->dwPID, p->dwLeaderPID);
|
||||
}
|
||||
else
|
||||
sys_err("PARTY Add - Already [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID);
|
||||
}
|
||||
|
||||
void CClientManager::QUERY_PARTY_REMOVE(CPeer* peer, TPacketPartyRemove* p)
|
||||
{
|
||||
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
|
||||
itertype(pm) it = pm.find(p->dwLeaderPID);
|
||||
|
||||
if (it == pm.end())
|
||||
{
|
||||
sys_err("PARTY Remove - Non exists [%lu] cannot remove [%lu]",p->dwLeaderPID, p->dwPID);
|
||||
return;
|
||||
}
|
||||
|
||||
itertype(it->second) pit = it->second.find(p->dwPID);
|
||||
|
||||
if (pit != it->second.end())
|
||||
{
|
||||
it->second.erase(pit);
|
||||
ForwardPacket(HEADER_DG_PARTY_REMOVE, p, sizeof(TPacketPartyRemove), peer->GetChannel(), peer);
|
||||
sys_log(0, "PARTY Remove [%lu] to [%lu]", p->dwPID, p->dwLeaderPID);
|
||||
}
|
||||
else
|
||||
sys_err("PARTY Remove - Cannot find [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID);
|
||||
}
|
||||
|
||||
void CClientManager::QUERY_PARTY_STATE_CHANGE(CPeer* peer, TPacketPartyStateChange* p)
|
||||
{
|
||||
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
|
||||
itertype(pm) it = pm.find(p->dwLeaderPID);
|
||||
|
||||
if (it == pm.end())
|
||||
{
|
||||
sys_err("PARTY StateChange - Non exists [%lu] cannot state change [%lu]",p->dwLeaderPID, p->dwPID);
|
||||
return;
|
||||
}
|
||||
|
||||
itertype(it->second) pit = it->second.find(p->dwPID);
|
||||
|
||||
if (pit == it->second.end())
|
||||
{
|
||||
sys_err("PARTY StateChange - Cannot find [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->bFlag)
|
||||
pit->second.bRole = p->bRole;
|
||||
else
|
||||
pit->second.bRole = 0;
|
||||
|
||||
ForwardPacket(HEADER_DG_PARTY_STATE_CHANGE, p, sizeof(TPacketPartyStateChange), peer->GetChannel(), peer);
|
||||
sys_log(0, "PARTY StateChange [%lu] at [%lu] from %d %d",p->dwPID, p->dwLeaderPID, p->bRole, p->bFlag);
|
||||
}
|
||||
|
||||
void CClientManager::QUERY_PARTY_SET_MEMBER_LEVEL(CPeer* peer, TPacketPartySetMemberLevel* p)
|
||||
{
|
||||
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
|
||||
itertype(pm) it = pm.find(p->dwLeaderPID);
|
||||
|
||||
if (it == pm.end())
|
||||
{
|
||||
sys_err("PARTY SetMemberLevel - Non exists [%lu] cannot level change [%lu]",p->dwLeaderPID, p->dwPID);
|
||||
return;
|
||||
}
|
||||
|
||||
itertype(it->second) pit = it->second.find(p->dwPID);
|
||||
|
||||
if (pit == it->second.end())
|
||||
{
|
||||
sys_err("PARTY SetMemberLevel - Cannot find [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID);
|
||||
return;
|
||||
}
|
||||
|
||||
pit->second.bLevel = p->bLevel;
|
||||
|
||||
ForwardPacket(HEADER_DG_PARTY_SET_MEMBER_LEVEL, p, sizeof(TPacketPartySetMemberLevel), peer->GetChannel());
|
||||
sys_log(0, "PARTY SetMemberLevel pid [%lu] level %d",p->dwPID, p->bLevel);
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
1307
source-server/Srcs/Server/db/src/ClientManagerPlayer.cpp
Normal file
1307
source-server/Srcs/Server/db/src/ClientManagerPlayer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
246
source-server/Srcs/Server/db/src/Config.cpp
Normal file
246
source-server/Srcs/Server/db/src/Config.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
#include "stdafx.h"
|
||||
#include "Config.h"
|
||||
|
||||
CConfig::CConfig()
|
||||
{
|
||||
}
|
||||
|
||||
CConfig::~CConfig()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void CConfig::Destroy()
|
||||
{
|
||||
m_valueMap.clear();
|
||||
}
|
||||
|
||||
void CConfig::NextLine(FILE *fp)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = fgetc(fp)) != EOF)
|
||||
{
|
||||
if (c == '\n')
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool CConfig::GetWord(FILE *fp, char *tar)
|
||||
{
|
||||
int i = 0;
|
||||
int c;
|
||||
|
||||
int semicolon_mode = 0;
|
||||
|
||||
while ((c = fgetc(fp)) != EOF)
|
||||
{
|
||||
if (c == 13)
|
||||
continue;
|
||||
|
||||
if (semicolon_mode)
|
||||
{
|
||||
if (c == '"')
|
||||
{
|
||||
tar[i] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
tar[i++] = c;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
if (c == '"')
|
||||
{
|
||||
semicolon_mode = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == ' ' || c == '\t' || c == '\n')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((c == ' ' || c == '\t' || c == '\n'))
|
||||
{
|
||||
tar[i] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
tar[i] = c;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return (i != 0);
|
||||
}
|
||||
|
||||
bool CConfig::GetLine(FILE* fp, char*dest)
|
||||
{
|
||||
int c;
|
||||
int i = 0;
|
||||
while ((c = fgetc(fp)) != EOF)
|
||||
{
|
||||
if (c == '\n')
|
||||
return true;
|
||||
dest[i] = c;
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfig::LoadFile(const char* filename)
|
||||
{
|
||||
char szTmp[256];
|
||||
char comment[256];
|
||||
|
||||
FILE * fp = fopen(filename, "rb");
|
||||
|
||||
if (fp == NULL)
|
||||
return false;
|
||||
|
||||
int mode = 0;
|
||||
|
||||
while (GetWord(fp, szTmp))
|
||||
{
|
||||
if (strcmp(szTmp, "//") == 0)
|
||||
{
|
||||
NextLine(fp);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case 0:
|
||||
strlcpy(comment, szTmp, sizeof(comment));
|
||||
++mode;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (*szTmp == '=')
|
||||
++mode;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
mode = 0;
|
||||
m_valueMap.emplace(comment, szTmp);
|
||||
break;
|
||||
}
|
||||
|
||||
// ITEM_ID_RANGE
|
||||
if (mode == 2 && strcmp(comment, "ITEM_ID_RANGE") == 0)
|
||||
{
|
||||
GetLine(fp, szTmp);
|
||||
m_valueMap.emplace(comment, szTmp);
|
||||
mode = 0;
|
||||
|
||||
}
|
||||
// ITEM_ID_RANGE_END
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string * CConfig::Search(const char* key)
|
||||
{
|
||||
itertype(m_valueMap) i = m_valueMap.find(key);
|
||||
|
||||
if (i == m_valueMap.end())
|
||||
return NULL;
|
||||
else
|
||||
return (&i->second);
|
||||
}
|
||||
|
||||
bool CConfig::GetParam(const char*key, int index, DWORD *Param)
|
||||
{
|
||||
std::string * pstStr = Search(key);
|
||||
if (!pstStr)
|
||||
return false;
|
||||
|
||||
char szParam[5][32];
|
||||
|
||||
sscanf(pstStr->c_str(), "%s %s %s %s %s", szParam[0],szParam[1],szParam[2],szParam[3],szParam[4]);
|
||||
|
||||
str_to_number(*Param, szParam[index]);
|
||||
|
||||
sys_log(0, "GetParam %d", *Param);
|
||||
return true;
|
||||
}
|
||||
const char * CConfig::Get(const char* key)
|
||||
{
|
||||
std::string * pstStr = Search(key);
|
||||
|
||||
if (!pstStr)
|
||||
{
|
||||
static std::string stTemp = "";
|
||||
return stTemp.c_str();
|
||||
}
|
||||
|
||||
return pstStr->c_str();
|
||||
}
|
||||
|
||||
bool CConfig::GetValue(const char * key, int* dest)
|
||||
{
|
||||
if (!Search(key))
|
||||
return false;
|
||||
|
||||
str_to_number(*dest, Get(key));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfig::GetValue(const char * key, float *dest)
|
||||
{
|
||||
if (!Search(key))
|
||||
return false;
|
||||
|
||||
str_to_number(*dest, Get(key));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfig::GetValue(const char * key, DWORD *dest)
|
||||
{
|
||||
if (!Search(key))
|
||||
return false;
|
||||
|
||||
str_to_number(*dest, Get(key));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfig::GetValue(const char * key, BYTE *dest)
|
||||
{
|
||||
if (!Search(key))
|
||||
return false;
|
||||
|
||||
*dest = *(BYTE *) Get(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfig::GetValue(const char * key, char *dest, size_t destSize)
|
||||
{
|
||||
if (!Search(key))
|
||||
return false;
|
||||
|
||||
strlcpy(dest, Get(key), destSize);
|
||||
|
||||
if (!*dest)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfig::GetTwoValue(const char* key, DWORD * dest1, DWORD *dest2)
|
||||
{
|
||||
if (!GetParam(key, 0, dest1))
|
||||
return false;
|
||||
|
||||
if (!GetParam(key, 1, dest2))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
35
source-server/Srcs/Server/db/src/Config.h
Normal file
35
source-server/Srcs/Server/db/src/Config.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef __INC_CONFIG_H__
|
||||
#define __INC_CONFIG_H__
|
||||
|
||||
typedef std::map<std::string, std::string> TValueMap;
|
||||
|
||||
class CConfig : public singleton<CConfig>
|
||||
{
|
||||
public:
|
||||
CConfig();
|
||||
~CConfig();
|
||||
|
||||
bool LoadFile(const char* filename);
|
||||
bool GetValue(const char* key, int* dest);
|
||||
bool GetValue(const char* key, float* dest);
|
||||
bool GetValue(const char* key, DWORD* dest);
|
||||
bool GetValue(const char* key, BYTE* dest);
|
||||
bool GetValue(const char* key, char* dest, size_t destSize);
|
||||
bool GetWord(FILE* fp, char* dest);
|
||||
bool GetLine(FILE* fp, char* dest);
|
||||
bool GetTwoValue(const char* key, DWORD * dest1, DWORD *dest2);
|
||||
void NextLine(FILE* fp);
|
||||
|
||||
private:
|
||||
void Destroy();
|
||||
bool GetParam(const char*key,int index, DWORD *Param);
|
||||
|
||||
const char * Get(const char* key);
|
||||
std::string * Search(const char* key);
|
||||
|
||||
private:
|
||||
TValueMap m_valueMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
372
source-server/Srcs/Server/db/src/CsvReader.cpp
Normal file
372
source-server/Srcs/Server/db/src/CsvReader.cpp
Normal file
@ -0,0 +1,372 @@
|
||||
#include "stdafx.h"
|
||||
#include "CsvReader.h"
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef Assert
|
||||
#include <assert.h>
|
||||
#define Assert assert
|
||||
#define LogToFile (void)(0);
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
enum ParseState
|
||||
{
|
||||
STATE_NORMAL = 0,
|
||||
STATE_QUOTE
|
||||
};
|
||||
|
||||
std::string Trim(std::string str)
|
||||
{
|
||||
str = str.erase(str.find_last_not_of(" \t\r\n") + 1);
|
||||
str = str.erase(0, str.find_first_not_of(" \t\r\n"));
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string Lower(std::string original)
|
||||
{
|
||||
std::transform(original.begin(), original.end(), original.begin(), tolower);
|
||||
return original;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void cCsvAlias::AddAlias(const char* name, size_t index)
|
||||
{
|
||||
std::string converted(Lower(name));
|
||||
|
||||
Assert(m_Name2Index.find(converted) == m_Name2Index.end());
|
||||
Assert(m_Index2Name.find(index) == m_Index2Name.end());
|
||||
|
||||
m_Name2Index.emplace(converted, index);
|
||||
m_Index2Name.emplace(index, name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void cCsvAlias::Destroy()
|
||||
{
|
||||
m_Name2Index.clear();
|
||||
m_Index2Name.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const char* cCsvAlias::operator [] (size_t index) const
|
||||
{
|
||||
INDEX2NAME_MAP::const_iterator itr(m_Index2Name.find(index));
|
||||
if (itr == m_Index2Name.end())
|
||||
{
|
||||
//LogToFile(NULL, "cannot find suitable conversion for %d", index);
|
||||
Assert(false && "cannot find suitable conversion");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return itr->second.c_str();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
size_t cCsvAlias::operator [] (const char* name) const
|
||||
{
|
||||
NAME2INDEX_MAP::const_iterator itr(m_Name2Index.find(Lower(name)));
|
||||
if (itr == m_Name2Index.end())
|
||||
{
|
||||
//LogToFile(NULL, "cannot find suitable conversion for %s", name);
|
||||
Assert(false && "cannot find suitable conversion");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool cCsvFile::Load(const char* fileName, const char seperator, const char quote)
|
||||
{
|
||||
Assert(seperator != quote);
|
||||
|
||||
std::ifstream file(fileName, std::ios::in);
|
||||
if (!file) return false;
|
||||
|
||||
Destroy();
|
||||
|
||||
cCsvRow* row = NULL;
|
||||
ParseState state = STATE_NORMAL;
|
||||
std::string token = "";
|
||||
char buf[2048+1] = {0,};
|
||||
|
||||
while (file.good())
|
||||
{
|
||||
file.getline(buf, 2048);
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
|
||||
std::string line(Trim(buf));
|
||||
if (line.empty() || (state == STATE_NORMAL && line[0] == '#')) continue;
|
||||
|
||||
std::string text = std::string(line) + " ";
|
||||
size_t cur = 0;
|
||||
|
||||
while (cur < text.size())
|
||||
{
|
||||
if (state == STATE_QUOTE)
|
||||
{
|
||||
if (text[cur] == quote)
|
||||
{
|
||||
if (text[cur+1] == quote)
|
||||
{
|
||||
token += quote;
|
||||
++cur;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
state = STATE_NORMAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
token += text[cur];
|
||||
}
|
||||
}
|
||||
|
||||
else if (state == STATE_NORMAL)
|
||||
{
|
||||
if (row == NULL)
|
||||
row = new cCsvRow();
|
||||
|
||||
if (text[cur] == seperator)
|
||||
{
|
||||
row->emplace_back(token);
|
||||
token.clear();
|
||||
}
|
||||
|
||||
else if (text[cur] == quote)
|
||||
{
|
||||
state = STATE_QUOTE;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
token += text[cur];
|
||||
}
|
||||
}
|
||||
|
||||
++cur;
|
||||
}
|
||||
|
||||
if (state == STATE_NORMAL)
|
||||
{
|
||||
Assert(row != NULL);
|
||||
row->emplace_back(token.substr(0, token.size()-2));
|
||||
m_Rows.emplace_back(row);
|
||||
token.clear();
|
||||
row = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
token = token.substr(0, token.size()-2) + "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quote) const
|
||||
{
|
||||
Assert(seperator != quote);
|
||||
|
||||
std::ofstream file;
|
||||
if (append) { file.open(fileName, std::ios::out | std::ios::app); }
|
||||
else { file.open(fileName, std::ios::out | std::ios::trunc); }
|
||||
|
||||
if (!file) return false;
|
||||
|
||||
char special_chars[5] = { seperator, quote, '\r', '\n', 0 };
|
||||
char quote_escape_string[3] = { quote, quote, 0 };
|
||||
|
||||
for (size_t i=0; i<m_Rows.size(); i++)
|
||||
{
|
||||
const cCsvRow& row = *((*this)[i]);
|
||||
|
||||
std::string line;
|
||||
|
||||
for (size_t j=0; j<row.size(); j++)
|
||||
{
|
||||
const std::string& token = row[j];
|
||||
|
||||
if (token.find_first_of(special_chars) == std::string::npos)
|
||||
{
|
||||
line += token;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
line += quote;
|
||||
|
||||
for (size_t k=0; k<token.size(); k++)
|
||||
{
|
||||
if (token[k] == quote) line += quote_escape_string;
|
||||
else line += token[k];
|
||||
}
|
||||
|
||||
line += quote;
|
||||
}
|
||||
|
||||
if (j != row.size() - 1) { line += seperator; }
|
||||
}
|
||||
|
||||
file << line << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void cCsvFile::Destroy()
|
||||
{
|
||||
for (ROWS::iterator itr(m_Rows.begin()); itr != m_Rows.end(); ++itr)
|
||||
delete *itr;
|
||||
|
||||
m_Rows.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cCsvRow* cCsvFile::operator [] (size_t index)
|
||||
{
|
||||
Assert(index < m_Rows.size());
|
||||
return m_Rows[index];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const cCsvRow* cCsvFile::operator [] (size_t index) const
|
||||
{
|
||||
Assert(index < m_Rows.size());
|
||||
return m_Rows[index];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cCsvTable::cCsvTable()
|
||||
: m_CurRow(-1)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cCsvTable::~cCsvTable()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool cCsvTable::Load(const char* fileName, const char seperator, const char quote)
|
||||
{
|
||||
Destroy();
|
||||
m_fileName = fileName;
|
||||
return m_File.Load(fileName, seperator, quote);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool cCsvTable::Next()
|
||||
{
|
||||
return ++m_CurRow < (int)m_File.GetRowCount() ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
size_t cCsvTable::ColCount() const
|
||||
{
|
||||
return CurRow()->size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int cCsvTable::AsInt(size_t index) const
|
||||
{
|
||||
const cCsvRow* const row = CurRow();
|
||||
Assert(row);
|
||||
if (index >= row->size())
|
||||
sys_err("file %s index %d >= row size %d of row %s", m_fileName.c_str(), index, row->size(), row->AsString(0));
|
||||
Assert(index < row->size());
|
||||
return row->AsInt(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
double cCsvTable::AsDouble(size_t index) const
|
||||
{
|
||||
const cCsvRow* const row = CurRow();
|
||||
Assert(row);
|
||||
if (index >= row->size())
|
||||
sys_err("file %s index %d >= row size %d of row %s", m_fileName.c_str(), index, row->size(), row->AsString(0));
|
||||
Assert(index < row->size());
|
||||
return row->AsDouble(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const char* cCsvTable::AsStringByIndex(size_t index) const
|
||||
{
|
||||
const cCsvRow* const row = CurRow();
|
||||
Assert(row);
|
||||
if (index >= row->size())
|
||||
sys_err("file %s index %d >= row size %d of row %s", m_fileName.c_str(), index, row->size(), row->AsString(0));
|
||||
Assert(index < row->size());
|
||||
return row->AsString(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void cCsvTable::Destroy()
|
||||
{
|
||||
m_File.Destroy();
|
||||
m_Alias.Destroy();
|
||||
m_CurRow = -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const cCsvRow* const cCsvTable::CurRow() const
|
||||
{
|
||||
if (m_CurRow < 0)
|
||||
{
|
||||
Assert(false && "call Next() first!");
|
||||
return NULL;
|
||||
}
|
||||
else if (m_CurRow >= (int)m_File.GetRowCount())
|
||||
{
|
||||
Assert(false && "no more rows!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_File[m_CurRow];
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
253
source-server/Srcs/Server/db/src/CsvReader.h
Normal file
253
source-server/Srcs/Server/db/src/CsvReader.h
Normal file
@ -0,0 +1,253 @@
|
||||
#ifndef __CSVFILE_H__
|
||||
#define __CSVFILE_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class cCsvAlias
|
||||
|
||||
///
|
||||
|
||||
///
|
||||
/// <pre>
|
||||
/// int a = row.AsInt(0);
|
||||
/// int b = row.AsInt(1);
|
||||
/// </pre>
|
||||
///
|
||||
|
||||
///
|
||||
/// <pre>
|
||||
/// int a = row.AsInt(0);
|
||||
/// int c = row.AsInt(1);
|
||||
|
||||
/// </pre>
|
||||
///
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class cCsvAlias
|
||||
{
|
||||
private:
|
||||
typedef std::map<std::string, size_t> NAME2INDEX_MAP;
|
||||
typedef std::map<size_t, std::string> INDEX2NAME_MAP;
|
||||
|
||||
NAME2INDEX_MAP m_Name2Index;
|
||||
INDEX2NAME_MAP m_Index2Name;
|
||||
|
||||
public:
|
||||
|
||||
cCsvAlias() {}
|
||||
|
||||
virtual ~cCsvAlias() {}
|
||||
|
||||
public:
|
||||
|
||||
void AddAlias(const char* name, size_t index);
|
||||
|
||||
void Destroy();
|
||||
|
||||
const char* operator [] (size_t index) const;
|
||||
|
||||
size_t operator [] (const char* name) const;
|
||||
|
||||
private:
|
||||
|
||||
cCsvAlias(const cCsvAlias&) {}
|
||||
|
||||
const cCsvAlias& operator = (const cCsvAlias&) { return *this; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class cCsvRow
|
||||
|
||||
///
|
||||
|
||||
///
|
||||
/// <pre>
|
||||
|
||||
/// ---------------------+----------------------------------------------------
|
||||
/// ItemPrice | ItemPrice
|
||||
/// Item,Price | "Item,Price"
|
||||
/// Item"Price | "Item""Price"
|
||||
/// "ItemPrice" | """ItemPrice"""
|
||||
/// "Item,Price" | """Item,Price"""
|
||||
/// Item",Price | "Item"",Price"
|
||||
/// </pre>
|
||||
///
|
||||
|
||||
///
|
||||
/// \sa cCsvFile
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class cCsvRow : public std::vector<std::string>
|
||||
{
|
||||
public:
|
||||
|
||||
cCsvRow() {}
|
||||
|
||||
~cCsvRow() {}
|
||||
|
||||
public:
|
||||
|
||||
int AsInt(size_t index) const { return atoi(at(index).c_str()); }
|
||||
|
||||
double AsDouble(size_t index) const { return atof(at(index).c_str()); }
|
||||
|
||||
const char* AsString(size_t index) const { return at(index).c_str(); }
|
||||
|
||||
int AsInt(const char* name, const cCsvAlias& alias) const {
|
||||
return atoi( at(alias[name]).c_str() );
|
||||
}
|
||||
|
||||
double AsDouble(const char* name, const cCsvAlias& alias) const {
|
||||
return atof( at(alias[name]).c_str() );
|
||||
}
|
||||
|
||||
const char* AsString(const char* name, const cCsvAlias& alias) const {
|
||||
return at(alias[name]).c_str();
|
||||
}
|
||||
|
||||
cCsvRow(const cCsvRow&) {}
|
||||
|
||||
private:
|
||||
|
||||
const cCsvRow& operator = (const cCsvRow&) { return *this; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class cCsvFile
|
||||
///
|
||||
/// <b>sample</b>
|
||||
/// <pre>
|
||||
/// cCsvFile file;
|
||||
///
|
||||
/// cCsvRow row1, row2, row3;
|
||||
/// row1.emplace_back("ItemPrice");
|
||||
/// row1.emplace_back("Item,Price");
|
||||
/// row1.emplace_back("Item\"Price");
|
||||
///
|
||||
/// row2.reserve(3);
|
||||
/// row2[0] = "\"ItemPrice\"";
|
||||
/// row2[1] = "\"Item,Price\"";
|
||||
/// row2[2] = "Item\",Price\"";
|
||||
///
|
||||
/// row3 = "\"ItemPrice\"\"Item,Price\"Item\",Price\"";
|
||||
///
|
||||
/// file.add(row1);
|
||||
/// file.add(row2);
|
||||
/// file.add(row3);
|
||||
/// file.save("test.csv", false);
|
||||
/// </pre>
|
||||
///
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class cCsvFile
|
||||
{
|
||||
private:
|
||||
typedef std::vector<cCsvRow*> ROWS;
|
||||
|
||||
ROWS m_Rows;
|
||||
|
||||
public:
|
||||
|
||||
cCsvFile() {}
|
||||
|
||||
virtual ~cCsvFile() { Destroy(); }
|
||||
|
||||
public:
|
||||
|
||||
bool Load(const char* fileName, const char seperator=',', const char quote='"');
|
||||
|
||||
bool Save(const char* fileName, bool append=false, char seperator=',', char quote='"') const;
|
||||
|
||||
void Destroy();
|
||||
|
||||
cCsvRow* operator [] (size_t index);
|
||||
|
||||
const cCsvRow* operator [] (size_t index) const;
|
||||
|
||||
size_t GetRowCount() const { return m_Rows.size(); }
|
||||
|
||||
private:
|
||||
|
||||
cCsvFile(const cCsvFile&) {}
|
||||
|
||||
const cCsvFile& operator = (const cCsvFile&) { return *this; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class cCsvTable
|
||||
|
||||
///
|
||||
|
||||
///
|
||||
/// <b>sample</b>
|
||||
/// <pre>
|
||||
/// cCsvTable table;
|
||||
///
|
||||
/// table.alias(0, "ItemClass");
|
||||
/// table.alias(1, "ItemType");
|
||||
///
|
||||
/// if (table.load("test.csv"))
|
||||
/// {
|
||||
/// while (table.next())
|
||||
/// {
|
||||
/// std::string item_class = table.AsString("ItemClass");
|
||||
/// int item_type = table.AsInt("ItemType");
|
||||
/// }
|
||||
/// }
|
||||
/// </pre>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class cCsvTable
|
||||
{
|
||||
public :
|
||||
cCsvFile m_File;
|
||||
std::string m_fileName;
|
||||
private:
|
||||
cCsvAlias m_Alias;
|
||||
int m_CurRow;
|
||||
|
||||
public:
|
||||
|
||||
cCsvTable();
|
||||
|
||||
virtual ~cCsvTable();
|
||||
|
||||
public:
|
||||
|
||||
bool Load(const char* fileName, const char seperator=',', const char quote='"');
|
||||
|
||||
void AddAlias(const char* name, size_t index) { m_Alias.AddAlias(name, index); }
|
||||
|
||||
bool Next();
|
||||
|
||||
size_t ColCount() const;
|
||||
|
||||
int AsInt(size_t index) const;
|
||||
|
||||
double AsDouble(size_t index) const;
|
||||
|
||||
const char* AsStringByIndex(size_t index) const;
|
||||
|
||||
int AsInt(const char* name) const { return AsInt(m_Alias[name]); }
|
||||
|
||||
double AsDouble(const char* name) const { return AsDouble(m_Alias[name]); }
|
||||
|
||||
const char* AsString(const char* name) const { return AsStringByIndex(m_Alias[name]); }
|
||||
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
|
||||
const cCsvRow* const CurRow() const;
|
||||
|
||||
cCsvTable(const cCsvTable&) {}
|
||||
|
||||
const cCsvTable& operator = (const cCsvTable&) { return *this; }
|
||||
};
|
||||
|
||||
#endif //__CSVFILE_H__
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
173
source-server/Srcs/Server/db/src/DBManager.cpp
Normal file
173
source-server/Srcs/Server/db/src/DBManager.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include "stdafx.h"
|
||||
#include "DBManager.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
extern std::string g_stLocale;
|
||||
|
||||
CDBManager::CDBManager()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
CDBManager::~CDBManager()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void CDBManager::Initialize()
|
||||
{
|
||||
for (int i = 0; i < SQL_MAX_NUM; ++i)
|
||||
{
|
||||
m_mainSQL[i].release();
|
||||
m_directSQL[i].release();
|
||||
m_asyncSQL[i].release();
|
||||
}
|
||||
}
|
||||
|
||||
void CDBManager::Destroy()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void CDBManager::Clear()
|
||||
{
|
||||
for (int i = 0; i < SQL_MAX_NUM; ++i)
|
||||
{
|
||||
m_mainSQL[i].release();
|
||||
m_directSQL[i].release();
|
||||
m_asyncSQL[i].release();
|
||||
}
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void CDBManager::Quit()
|
||||
{
|
||||
for (int i = 0; i < SQL_MAX_NUM; ++i)
|
||||
{
|
||||
if (m_mainSQL[i])
|
||||
m_mainSQL[i]->Quit();
|
||||
|
||||
if (m_asyncSQL[i])
|
||||
m_asyncSQL[i]->Quit();
|
||||
|
||||
if (m_directSQL[i])
|
||||
m_directSQL[i]->Quit();
|
||||
}
|
||||
}
|
||||
|
||||
SQLMsg * CDBManager::PopResult()
|
||||
{
|
||||
SQLMsg * p;
|
||||
|
||||
for (int i = 0; i < SQL_MAX_NUM; ++i)
|
||||
if (m_mainSQL[i] && m_mainSQL[i]->PopResult(&p))
|
||||
return p;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SQLMsg * CDBManager::PopResult(eSQL_SLOT slot)
|
||||
{
|
||||
SQLMsg * p;
|
||||
|
||||
if (m_mainSQL[slot] && m_mainSQL[slot]->PopResult(&p))
|
||||
return p;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
int CDBManager::Connect(int iSlot, const char * db_address, const int db_port, const char * db_name, const char * user, const char * pwd)
|
||||
{
|
||||
if (db_address == NULL || db_name == NULL)
|
||||
return false;
|
||||
|
||||
if (iSlot < 0 || iSlot >= SQL_MAX_NUM)
|
||||
return false;
|
||||
|
||||
sys_log(0, "CREATING DIRECT_SQL");
|
||||
m_directSQL[iSlot] = std::make_unique<CAsyncSQL2>();
|
||||
if (!m_directSQL[iSlot]->Setup(db_address, user, pwd, db_name, g_stLocale.c_str(), true, db_port))
|
||||
{
|
||||
Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
sys_log(0, "CREATING MAIN_SQL");
|
||||
m_mainSQL[iSlot] = std::make_unique<CAsyncSQL2>();
|
||||
if (!m_mainSQL[iSlot]->Setup(db_address, user, pwd, db_name, g_stLocale.c_str(), false, db_port))
|
||||
{
|
||||
Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
sys_log(0, "CREATING ASYNC_SQL");
|
||||
m_asyncSQL[iSlot] = std::make_unique<CAsyncSQL2>();
|
||||
if (!m_asyncSQL[iSlot]->Setup(db_address, user, pwd, db_name, g_stLocale.c_str(), false, db_port))
|
||||
{
|
||||
Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<SQLMsg> CDBManager::DirectQuery(const char * c_pszQuery, int iSlot)
|
||||
{
|
||||
return m_directSQL[iSlot]->DirectQuery(c_pszQuery);
|
||||
}
|
||||
|
||||
extern CPacketInfo g_query_info;
|
||||
extern int g_query_count[2];
|
||||
|
||||
void CDBManager::ReturnQuery(const char * c_pszQuery, int iType, IDENT dwIdent, void * udata, int iSlot)
|
||||
{
|
||||
assert(iSlot < SQL_MAX_NUM);
|
||||
//sys_log(0, "ReturnQuery %s", c_pszQuery);
|
||||
CQueryInfo * p = new CQueryInfo;
|
||||
|
||||
p->iType = iType;
|
||||
p->dwIdent = dwIdent;
|
||||
p->pvData = udata;
|
||||
|
||||
m_mainSQL[iSlot]->ReturnQuery(c_pszQuery, p);
|
||||
|
||||
//g_query_info.Add(iType);
|
||||
++g_query_count[0];
|
||||
}
|
||||
|
||||
void CDBManager::AsyncQuery(const char * c_pszQuery, int iSlot)
|
||||
{
|
||||
assert(iSlot < SQL_MAX_NUM);
|
||||
m_asyncSQL[iSlot]->AsyncQuery(c_pszQuery);
|
||||
++g_query_count[1];
|
||||
}
|
||||
|
||||
unsigned long CDBManager::EscapeString(void *to, const void *from, unsigned long length, int iSlot)
|
||||
{
|
||||
assert(iSlot < SQL_MAX_NUM);
|
||||
return mysql_real_escape_string(m_directSQL[iSlot]->GetSQLHandle(), (char *) to, (const char *) from, length);
|
||||
}
|
||||
|
||||
void CDBManager::SetLocale(const char * szLocale)
|
||||
{
|
||||
const std::string stLocale(szLocale);
|
||||
sys_log(0, "SetLocale start %s", szLocale);
|
||||
for (int n = 0; n < SQL_MAX_NUM; ++n)
|
||||
{
|
||||
m_mainSQL[n]->SetLocale(stLocale);
|
||||
m_directSQL[n]->SetLocale(stLocale);
|
||||
m_asyncSQL[n]->SetLocale(stLocale);
|
||||
}
|
||||
sys_log(0, "SetLocale end %s", szLocale);
|
||||
}
|
||||
|
||||
void CDBManager::QueryLocaleSet()
|
||||
{
|
||||
for (int n = 0; n < SQL_MAX_NUM; ++n)
|
||||
{
|
||||
m_mainSQL[n]->QueryLocaleSet();
|
||||
m_directSQL[n]->QueryLocaleSet();
|
||||
m_asyncSQL[n]->QueryLocaleSet();
|
||||
}
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
100
source-server/Srcs/Server/db/src/DBManager.h
Normal file
100
source-server/Srcs/Server/db/src/DBManager.h
Normal file
@ -0,0 +1,100 @@
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_METIN2_DB_DBMANAGER_H__
|
||||
#define __INC_METIN2_DB_DBMANAGER_H__
|
||||
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#include "../../libsql/AsyncSQL.h"
|
||||
#include <memory>
|
||||
|
||||
#define SQL_SAFE_LENGTH(size) (size * 2 + 1)
|
||||
#define QUERY_SAFE_LENGTH(size) (1024 + SQL_SAFE_LENGTH(size))
|
||||
|
||||
class CQueryInfo
|
||||
{
|
||||
public:
|
||||
int iType;
|
||||
DWORD dwIdent;
|
||||
void * pvData;
|
||||
};
|
||||
|
||||
enum eSQL_SLOT
|
||||
{
|
||||
SQL_PLAYER,
|
||||
SQL_ACCOUNT,
|
||||
SQL_COMMON,
|
||||
SQL_HOTBACKUP,
|
||||
#ifdef ENABLE_DB_SQL_LOG
|
||||
SQL_LOG,
|
||||
#endif
|
||||
SQL_MAX_NUM,
|
||||
};
|
||||
|
||||
class CDBManager : public singleton<CDBManager>
|
||||
{
|
||||
protected:
|
||||
void Initialize();
|
||||
void Destroy();
|
||||
|
||||
public:
|
||||
CDBManager();
|
||||
virtual ~CDBManager();
|
||||
|
||||
void Clear();
|
||||
void Quit();
|
||||
|
||||
int Connect(int iSlot, const char * host, int port, const char* dbname, const char* user, const char* pass);
|
||||
|
||||
void ReturnQuery(const char * c_pszQuery, int iType, DWORD dwIdent, void * pvData, int iSlot = SQL_PLAYER);
|
||||
void AsyncQuery(const char * c_pszQuery, int iSlot = SQL_PLAYER);
|
||||
std::unique_ptr<SQLMsg> DirectQuery(const char * c_pszQuery, int iSlot = SQL_PLAYER);
|
||||
|
||||
SQLMsg * PopResult();
|
||||
SQLMsg * PopResult(eSQL_SLOT slot );
|
||||
|
||||
unsigned long EscapeString(void * to, const void * from, unsigned long length, int iSlot = SQL_PLAYER);
|
||||
|
||||
DWORD CountReturnQuery(int i) { return m_mainSQL[i] ? m_mainSQL[i]->CountQuery() : 0; }
|
||||
DWORD CountReturnResult(int i) { return m_mainSQL[i] ? m_mainSQL[i]->CountResult() : 0; }
|
||||
DWORD CountReturnQueryFinished(int i) { return m_mainSQL[i] ? m_mainSQL[i]->CountQueryFinished() : 0; }
|
||||
DWORD CountReturnCopiedQuery(int i) { return m_mainSQL[i] ? m_mainSQL[i]->GetCopiedQueryCount() : 0; }
|
||||
|
||||
DWORD CountAsyncQuery(int i) { return m_asyncSQL[i] ? m_asyncSQL[i]->CountQuery() : 0; }
|
||||
DWORD CountAsyncResult(int i) { return m_asyncSQL[i] ? m_asyncSQL[i]->CountResult() : 0; }
|
||||
DWORD CountAsyncQueryFinished(int i) { return m_asyncSQL[i] ? m_asyncSQL[i]->CountQueryFinished() : 0; }
|
||||
DWORD CountAsyncCopiedQuery(int i) { return m_asyncSQL[i] ? m_asyncSQL[i]->GetCopiedQueryCount() : 0; }
|
||||
|
||||
void ResetCounter()
|
||||
{
|
||||
for (int i = 0; i < SQL_MAX_NUM; ++i)
|
||||
{
|
||||
if (m_mainSQL[i])
|
||||
{
|
||||
m_mainSQL[i]->ResetQueryFinished();
|
||||
m_mainSQL[i]->ResetCopiedQueryCount();
|
||||
}
|
||||
|
||||
if (m_asyncSQL[i])
|
||||
{
|
||||
m_asyncSQL[i]->ResetQueryFinished();
|
||||
m_asyncSQL[i]->ResetCopiedQueryCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<CAsyncSQL2> m_mainSQL[SQL_MAX_NUM];
|
||||
std::unique_ptr<CAsyncSQL2> m_directSQL[SQL_MAX_NUM];
|
||||
std::unique_ptr<CAsyncSQL2> m_asyncSQL[SQL_MAX_NUM];
|
||||
|
||||
//CHARSET
|
||||
public:
|
||||
void SetLocale(const char * szLocale );
|
||||
void QueryLocaleSet();
|
||||
private:
|
||||
|
||||
//END_CHARSET
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
1475
source-server/Srcs/Server/db/src/GuildManager.cpp
Normal file
1475
source-server/Srcs/Server/db/src/GuildManager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
260
source-server/Srcs/Server/db/src/GuildManager.h
Normal file
260
source-server/Srcs/Server/db/src/GuildManager.h
Normal file
@ -0,0 +1,260 @@
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_GUILD_MANAGER_H
|
||||
#define __INC_GUILD_MANAGER_H
|
||||
|
||||
#include "Peer.h"
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
#include "../../libsql/libsql.h"
|
||||
#include "../../libpoly/Poly.h"
|
||||
|
||||
enum
|
||||
{
|
||||
GUILD_WARP_WAR_CHANNEL = 99
|
||||
};
|
||||
|
||||
class CGuildWarReserve;
|
||||
|
||||
struct TGuildDeclareInfo
|
||||
{
|
||||
BYTE bType;
|
||||
DWORD dwGuildID[2];
|
||||
|
||||
TGuildDeclareInfo(BYTE _bType, DWORD _dwGuildID1, DWORD _dwGuildID2)
|
||||
: bType(_bType)
|
||||
{
|
||||
dwGuildID[0] = _dwGuildID1;
|
||||
dwGuildID[1] = _dwGuildID2;
|
||||
}
|
||||
|
||||
bool operator < (const TGuildDeclareInfo& r) const
|
||||
{
|
||||
return ((dwGuildID[0] < r.dwGuildID[0]) || ((dwGuildID[0] == r.dwGuildID[0]) && (dwGuildID[1] < r.dwGuildID[1])));
|
||||
}
|
||||
|
||||
TGuildDeclareInfo& operator = (const TGuildDeclareInfo& r)
|
||||
{
|
||||
bType = r.bType;
|
||||
dwGuildID[0] = r.dwGuildID[0];
|
||||
dwGuildID[1] = r.dwGuildID[1];
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct TGuildWaitStartInfo
|
||||
{
|
||||
BYTE bType;
|
||||
DWORD GID[2];
|
||||
long lWarPrice;
|
||||
long lInitialScore;
|
||||
CGuildWarReserve * pkReserve;
|
||||
|
||||
TGuildWaitStartInfo(BYTE _bType,
|
||||
DWORD _g1,
|
||||
DWORD _g2,
|
||||
long _lWarPrice,
|
||||
long _lInitialScore,
|
||||
CGuildWarReserve * _pkReserve)
|
||||
: bType(_bType), lWarPrice(_lWarPrice), lInitialScore(_lInitialScore), pkReserve(_pkReserve)
|
||||
{
|
||||
GID[0] = _g1;
|
||||
GID[1] = _g2;
|
||||
}
|
||||
|
||||
bool operator < (const TGuildWaitStartInfo& r) const
|
||||
{
|
||||
return ((GID[0] < r.GID[0]) || ((GID[0] == r.GID[0]) && (GID[1] < r.GID[1])));
|
||||
}
|
||||
};
|
||||
|
||||
struct TGuildWarPQElement
|
||||
{
|
||||
bool bEnd;
|
||||
BYTE bType;
|
||||
DWORD GID[2];
|
||||
DWORD iScore[2];
|
||||
DWORD iBetScore[2];
|
||||
|
||||
TGuildWarPQElement(BYTE _bType, DWORD GID1, DWORD GID2) : bEnd(false), bType(_bType)
|
||||
{
|
||||
bType = _bType;
|
||||
GID[0] = GID1;
|
||||
GID[1] = GID2;
|
||||
iScore[0] = iScore[1] = 0;
|
||||
iBetScore[0] = iBetScore[1] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct TGuildSkillUsed
|
||||
{
|
||||
DWORD GID;
|
||||
DWORD dwSkillVnum;
|
||||
|
||||
// GUILD_SKILL_COOLTIME_BUG_FIX
|
||||
TGuildSkillUsed(DWORD _GID, DWORD _dwSkillVnum) : GID(_GID), dwSkillVnum(_dwSkillVnum)
|
||||
{
|
||||
}
|
||||
// END_OF_GUILD_SKILL_COOLTIME_BUG_FIX
|
||||
};
|
||||
|
||||
inline bool operator < (const TGuildSkillUsed& a, const TGuildSkillUsed& b)
|
||||
{
|
||||
return ((a.GID < b.GID) || ((a.GID == b.GID) && (a.dwSkillVnum < b.dwSkillVnum)));
|
||||
}
|
||||
|
||||
typedef struct SGuild
|
||||
{
|
||||
SGuild() : ladder_point(0), win(0), draw(0), loss(0), gold(0), level(0)
|
||||
{
|
||||
memset(szName, 0, sizeof(szName));
|
||||
}
|
||||
|
||||
char szName[GUILD_NAME_MAX_LEN+1];
|
||||
int ladder_point;
|
||||
int win;
|
||||
int draw;
|
||||
int loss;
|
||||
int gold;
|
||||
int level;
|
||||
} TGuild;
|
||||
|
||||
typedef struct SGuildWarInfo
|
||||
{
|
||||
time_t tEndTime;
|
||||
TGuildWarPQElement * pElement;
|
||||
CGuildWarReserve * pkReserve;
|
||||
|
||||
SGuildWarInfo() : pElement(NULL)
|
||||
{
|
||||
}
|
||||
} TGuildWarInfo;
|
||||
|
||||
class CGuildWarReserve
|
||||
{
|
||||
public:
|
||||
CGuildWarReserve(const TGuildWarReserve& rTable);
|
||||
|
||||
void Initialize();
|
||||
|
||||
TGuildWarReserve & GetDataRef()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void OnSetup(CPeer * peer);
|
||||
bool Bet(const char * pszLogin, DWORD dwGold, DWORD dwGuild);
|
||||
void Draw();
|
||||
void End(int iScoreFrom, int iScoreTo);
|
||||
|
||||
int GetLastNoticeMin() { return m_iLastNoticeMin; }
|
||||
void SetLastNoticeMin(int iMin) { m_iLastNoticeMin = iMin; }
|
||||
|
||||
private:
|
||||
CGuildWarReserve();
|
||||
|
||||
TGuildWarReserve m_data;
|
||||
// <login, <guild, gold>>
|
||||
std::map<std::string, std::pair<DWORD, DWORD> > mapBet;
|
||||
int m_iLastNoticeMin;
|
||||
};
|
||||
|
||||
class CGuildManager : public singleton<CGuildManager>
|
||||
{
|
||||
public:
|
||||
CGuildManager();
|
||||
virtual ~CGuildManager();
|
||||
|
||||
void Initialize();
|
||||
|
||||
void Load(DWORD dwGuildID);
|
||||
|
||||
TGuild & TouchGuild(DWORD GID);
|
||||
|
||||
void Update();
|
||||
|
||||
void OnSetup(CPeer * peer);
|
||||
void StartWar(BYTE bType, DWORD GID1, DWORD GID2, CGuildWarReserve * pkReserve = NULL);
|
||||
|
||||
void UpdateScore(DWORD guild_gain_point, DWORD guild_opponent, int iScore, int iBetScore);
|
||||
|
||||
void AddDeclare(BYTE bType, DWORD guild_from, DWORD guild_to);
|
||||
void RemoveDeclare(DWORD guild_from, DWORD guild_to);
|
||||
|
||||
bool TakeBetPrice(DWORD dwGuildTo, DWORD dwGuildFrom, long lWarPrice);
|
||||
|
||||
bool WaitStart(TPacketGuildWar * p);
|
||||
|
||||
void RecvWarEnd(DWORD GID1, DWORD GID2);
|
||||
void RecvWarOver(DWORD dwGuildWinner, DWORD dwGuildLoser, bool bDraw, long lWarPrice);
|
||||
|
||||
void ChangeLadderPoint(DWORD GID, int change);
|
||||
|
||||
void UseSkill(DWORD dwGuild, DWORD dwSkillVnum, DWORD dwCooltime);
|
||||
|
||||
INT GetGuildGold(DWORD dwGuild);
|
||||
void DepositMoney(DWORD dwGuild, INT lGold);
|
||||
void WithdrawMoney(CPeer* peer, DWORD dwGuild, INT lGold);
|
||||
void WithdrawMoneyReply(DWORD dwGuild, BYTE bGiveSuccess, INT lGold);
|
||||
|
||||
void MoneyChange(DWORD dwGuild, DWORD dwGold);
|
||||
|
||||
void QueryRanking();
|
||||
void ResultRanking(MYSQL_RES * pRes);
|
||||
int GetRanking(DWORD dwGID);
|
||||
|
||||
// Reserve War
|
||||
|
||||
void BootReserveWar();
|
||||
bool ReserveWar(TPacketGuildWar * p);
|
||||
void ProcessReserveWar();
|
||||
bool Bet(DWORD dwID, const char * c_pszLogin, DWORD dwGold, DWORD dwGuild);
|
||||
|
||||
void CancelWar(DWORD GID1, DWORD GID2);
|
||||
|
||||
bool ChangeMaster(DWORD dwGID, DWORD dwFrom, DWORD dwTo);
|
||||
|
||||
private:
|
||||
void ParseResult(SQLResult * pRes);
|
||||
|
||||
void RemoveWar(DWORD GID1, DWORD GID2); // erase war from m_WarMap and set end on priority queue
|
||||
|
||||
void WarEnd(DWORD GID1, DWORD GID2, bool bDraw = false);
|
||||
|
||||
int GetLadderPoint(DWORD GID);
|
||||
|
||||
void GuildWarWin(DWORD GID);
|
||||
void GuildWarDraw(DWORD GID);
|
||||
void GuildWarLose(DWORD GID);
|
||||
|
||||
void ProcessDraw(DWORD dwGuildID1, DWORD dwGuildID2);
|
||||
void ProcessWinLose(DWORD dwGuildWinner, DWORD dwGuildLoser);
|
||||
|
||||
bool IsHalfWinLadderPoint(DWORD dwGuildWinner, DWORD dwGuildLoser);
|
||||
|
||||
std::map<DWORD, TGuild> m_map_kGuild;
|
||||
std::map<DWORD, std::map<DWORD, time_t> > m_mapGuildWarEndTime;
|
||||
|
||||
std::set<TGuildDeclareInfo> m_DeclareMap;
|
||||
std::map<DWORD, std::map<DWORD, TGuildWarInfo> > m_WarMap;
|
||||
|
||||
typedef std::pair<time_t, TGuildWarPQElement *> stPairGuildWar;
|
||||
typedef std::pair<time_t, TGuildSkillUsed> stPairSkillUsed;
|
||||
typedef std::pair<time_t, TGuildWaitStartInfo> stPairWaitStart;
|
||||
|
||||
std::priority_queue<stPairGuildWar, std::vector<stPairGuildWar>, std::greater<stPairGuildWar> >
|
||||
m_pqOnWar;
|
||||
std::priority_queue<stPairWaitStart, std::vector<stPairWaitStart>, std::greater<stPairWaitStart> >
|
||||
m_pqWaitStart;
|
||||
std::priority_queue<stPairSkillUsed, std::vector<stPairSkillUsed>, std::greater<stPairSkillUsed> >
|
||||
m_pqSkill;
|
||||
|
||||
std::map<DWORD, CGuildWarReserve *> m_map_kWarReserve;
|
||||
CPoly polyPower;
|
||||
CPoly polyHandicap;
|
||||
|
||||
// GID Ranking
|
||||
std::map<DWORD, int> map_kLadderPointRankingByGID;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
82
source-server/Srcs/Server/db/src/HB.cpp
Normal file
82
source-server/Srcs/Server/db/src/HB.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include "stdafx.h"
|
||||
#include "HB.h"
|
||||
#include "Main.h"
|
||||
#include "DBManager.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
PlayerHB::PlayerHB()
|
||||
{
|
||||
m_iExpireTime = 3600; // 1 hour hotbackup default.
|
||||
}
|
||||
|
||||
PlayerHB::~PlayerHB()
|
||||
{
|
||||
}
|
||||
|
||||
bool PlayerHB::Initialize()
|
||||
{
|
||||
char szQuery[128];
|
||||
snprintf(szQuery, sizeof(szQuery), "SHOW CREATE TABLE player%s", GetTablePostfix());
|
||||
|
||||
auto pMsg(CDBManager::instance().DirectQuery(szQuery));
|
||||
if (pMsg->Get()->uiNumRows == 0)
|
||||
return false;
|
||||
|
||||
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
|
||||
m_stCreateTableQuery = row[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
void PlayerHB::Put(DWORD id)
|
||||
{
|
||||
itertype(m_map_data) it = m_map_data.find(id);
|
||||
|
||||
if (it == m_map_data.end())
|
||||
{
|
||||
Query(id);
|
||||
m_map_data.emplace(id, get_dword_time());
|
||||
return;
|
||||
}
|
||||
|
||||
if (time(0) - it->second > m_iExpireTime)
|
||||
Query(id);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
bool PlayerHB::Query(DWORD id)
|
||||
{
|
||||
time_t ct = time(0);
|
||||
struct tm curr_tm = *localtime(&ct);
|
||||
char szTableName[64];
|
||||
snprintf(szTableName, sizeof(szTableName), "hb_%02d%02d%02d%02d_player%s",
|
||||
curr_tm.tm_year - 100, curr_tm.tm_mon + 1, curr_tm.tm_mday, curr_tm.tm_hour, GetTablePostfix());
|
||||
|
||||
char szQuery[4096];
|
||||
|
||||
if (m_stTableName.compare(szTableName))
|
||||
{
|
||||
char szFind[32];
|
||||
snprintf(szFind, sizeof(szFind), "CREATE TABLE `player%s`", GetTablePostfix());
|
||||
int pos = m_stCreateTableQuery.find(szFind);
|
||||
|
||||
if (pos < 0)
|
||||
{
|
||||
sys_err("cannot find %s ", szFind);
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "CREATE TABLE IF NOT EXISTS %s%s", szTableName, m_stCreateTableQuery.c_str() + strlen(szFind));
|
||||
auto pMsg(CDBManager::instance().DirectQuery(szQuery, SQL_HOTBACKUP));
|
||||
m_stTableName = szTableName;
|
||||
}
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO %s SELECT * FROM %splayer%s WHERE id=%u", m_stTableName.c_str(), GetPlayerDBName(), GetTablePostfix(), id);
|
||||
CDBManager::instance().AsyncQuery(szQuery, SQL_HOTBACKUP);
|
||||
return true;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
25
source-server/Srcs/Server/db/src/HB.h
Normal file
25
source-server/Srcs/Server/db/src/HB.h
Normal file
@ -0,0 +1,25 @@
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_METIN_II_PLAYERHB_H__
|
||||
#define __INC_METIN_II_PLAYERHB_H__
|
||||
|
||||
class PlayerHB : public singleton<PlayerHB>
|
||||
{
|
||||
public:
|
||||
PlayerHB();
|
||||
virtual ~PlayerHB();
|
||||
|
||||
bool Initialize();
|
||||
|
||||
void Put(DWORD id);
|
||||
|
||||
private:
|
||||
bool Query(DWORD id);
|
||||
|
||||
std::map<DWORD, time_t> m_map_data;
|
||||
std::string m_stCreateTableQuery;
|
||||
std::string m_stTableName;
|
||||
int m_iExpireTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
509
source-server/Srcs/Server/db/src/ItemAwardManager.cpp
Normal file
509
source-server/Srcs/Server/db/src/ItemAwardManager.cpp
Normal file
@ -0,0 +1,509 @@
|
||||
#include "stdafx.h"
|
||||
#include "QID.h"
|
||||
#include "DBManager.h"
|
||||
#include "ItemAwardManager.h"
|
||||
#include "Peer.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
#ifdef ENABLE_EXTEND_ITEM_AWARD
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include <unordered_set>
|
||||
#include <msl/random.h>
|
||||
|
||||
inline double uniform_random(const double a, const double b)
|
||||
{
|
||||
return msl::random_real(a, b);
|
||||
}
|
||||
|
||||
inline float gauss_random(const float fAverage, const float sigma)
|
||||
{
|
||||
static bool bHasNextGaussian = false;
|
||||
static float fNextGaussian = 0.0f;
|
||||
|
||||
if (bHasNextGaussian)
|
||||
{
|
||||
bHasNextGaussian = false;
|
||||
return (fNextGaussian * sigma) + fAverage;
|
||||
}
|
||||
else
|
||||
{
|
||||
double v1(0), v2(0), s(0);
|
||||
do
|
||||
{
|
||||
v1 = uniform_random(-1.f, 1.f);
|
||||
v2 = uniform_random(-1.f, 1.f);
|
||||
s = (v1 * v1) + (v2 * v2);
|
||||
} while (s >= 1.f || fabs(s) < FLT_EPSILON);
|
||||
|
||||
const double multiplier = sqrtf(-2 * logf(s) / s);
|
||||
fNextGaussian = v2 * multiplier;
|
||||
bHasNextGaussian = true;
|
||||
return (v1 * multiplier) * sigma + fAverage;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DWORD g_dwLastCachedItemAwardID = 0;
|
||||
ItemAwardManager::ItemAwardManager()
|
||||
{
|
||||
}
|
||||
|
||||
ItemAwardManager::~ItemAwardManager()
|
||||
{
|
||||
}
|
||||
|
||||
void ItemAwardManager::RequestLoad()
|
||||
{
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT id,login,vnum,count,socket0,socket1,socket2,"
|
||||
#ifdef ENABLE_EXTEND_ITEM_AWARD
|
||||
"attrtype0, attrvalue0, "
|
||||
"attrtype1, attrvalue1, "
|
||||
"attrtype2, attrvalue2, "
|
||||
"attrtype3, attrvalue3, "
|
||||
"attrtype4, attrvalue4, "
|
||||
"attrtype5, attrvalue5, "
|
||||
"attrtype6, attrvalue6, "
|
||||
#endif
|
||||
"mall,why FROM item_award WHERE taken_time IS NULL and id > %d", g_dwLastCachedItemAwardID);
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_AWARD_LOAD, 0, NULL);
|
||||
}
|
||||
|
||||
void ItemAwardManager::Load(SQLMsg * pMsg)
|
||||
{
|
||||
MYSQL_RES * pRes = pMsg->Get()->pSQLResult;
|
||||
|
||||
for (uint i = 0; i < pMsg->Get()->uiNumRows; ++i)
|
||||
{
|
||||
MYSQL_ROW row = mysql_fetch_row(pRes);
|
||||
int col = 0;
|
||||
|
||||
DWORD dwID = 0;
|
||||
str_to_number(dwID, row[col++]);
|
||||
|
||||
if (m_map_award.find(dwID) != m_map_award.end())
|
||||
continue;
|
||||
|
||||
TItemAward * kData = new TItemAward{};
|
||||
|
||||
kData->dwID = dwID;
|
||||
trim_and_lower(row[col++], kData->szLogin, sizeof(kData->szLogin));
|
||||
str_to_number(kData->dwVnum, row[col++]);
|
||||
str_to_number(kData->dwCount, row[col++]);
|
||||
str_to_number(kData->dwSocket0, row[col++]);
|
||||
str_to_number(kData->dwSocket1, row[col++]);
|
||||
str_to_number(kData->dwSocket2, row[col++]);
|
||||
#ifdef ENABLE_EXTEND_ITEM_AWARD
|
||||
for (size_t j = 0; j < ITEM_ATTRIBUTE_MAX_NUM; j++)
|
||||
{
|
||||
str_to_number(kData->aAttr[j].bType, row[col++]);
|
||||
str_to_number(kData->aAttr[j].sValue, row[col++]);
|
||||
}
|
||||
#endif
|
||||
str_to_number(kData->bMall, row[col++]);
|
||||
|
||||
if (row[col])
|
||||
{
|
||||
strlcpy(kData->szWhy, row[col], sizeof(kData->szWhy));
|
||||
|
||||
char* whyStr = kData->szWhy;
|
||||
char cmdStr[100] = "";
|
||||
strcpy(cmdStr,whyStr);
|
||||
char command[20] = "";
|
||||
// @fixme203 directly GetCommand instead of strcpy
|
||||
CClientManager::instance().GetCommand(cmdStr, command);
|
||||
//sys_err("%d, %s",pItemAward->dwID,command);
|
||||
if( !(strcmp(command,"GIFT") ))
|
||||
{
|
||||
TPacketItemAwardInfromer giftData;
|
||||
strcpy(giftData.login, kData->szLogin);
|
||||
strcpy(giftData.command, command);
|
||||
giftData.vnum = kData->dwVnum;
|
||||
CClientManager::instance().ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer));
|
||||
}
|
||||
}
|
||||
|
||||
m_map_award.emplace(dwID, kData);
|
||||
|
||||
printf("ITEM_AWARD load id %u bMall %d \n", kData->dwID, kData->bMall);
|
||||
sys_log(0, "ITEM_AWARD: load id %lu login %s vnum %lu count %u socket %lu", kData->dwID, kData->szLogin, kData->dwVnum, kData->dwCount, kData->dwSocket0);
|
||||
std::set<TItemAward *> & kSet = m_map_kSetAwardByLogin[kData->szLogin];
|
||||
kSet.emplace(kData);
|
||||
|
||||
if (dwID > g_dwLastCachedItemAwardID)
|
||||
g_dwLastCachedItemAwardID = dwID;
|
||||
}
|
||||
}
|
||||
|
||||
std::set<TItemAward *> * ItemAwardManager::GetByLogin(const char * c_pszLogin)
|
||||
{
|
||||
itertype(m_map_kSetAwardByLogin) it = m_map_kSetAwardByLogin.find(c_pszLogin);
|
||||
|
||||
if (it == m_map_kSetAwardByLogin.end())
|
||||
return NULL;
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
void ItemAwardManager::Taken(DWORD dwAwardID, DWORD dwItemID)
|
||||
{
|
||||
itertype(m_map_award) it = m_map_award.find(dwAwardID);
|
||||
|
||||
if (it == m_map_award.end())
|
||||
{
|
||||
sys_log(0, "ITEM_AWARD: Taken ID not exist %lu", dwAwardID);
|
||||
return;
|
||||
}
|
||||
|
||||
TItemAward * k = it->second;
|
||||
k->bTaken = true;
|
||||
|
||||
// Update taken_time in database to prevent not to give him again.
|
||||
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"UPDATE item_award SET taken_time=NOW(),item_id=%u WHERE id=%u AND taken_time IS NULL",
|
||||
dwItemID, dwAwardID);
|
||||
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_AWARD_TAKEN, 0, NULL);
|
||||
}
|
||||
|
||||
std::map<DWORD, TItemAward *>& ItemAwardManager::GetMapAward()
|
||||
{
|
||||
return m_map_award;
|
||||
}
|
||||
|
||||
std::map<std::string, std::set<TItemAward *> >& ItemAwardManager::GetMapkSetAwardByLogin()
|
||||
{
|
||||
return m_map_kSetAwardByLogin;
|
||||
}
|
||||
|
||||
#ifdef USE_ITEM_AWARD_CHECK_ATTRIBUTES
|
||||
/*******************************************************************\
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
||| Attribute set index, return a specific index by item type & item sub type.
|
||||
||| List initialization (since C++11)
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
\*******************************************************************/
|
||||
int8_t ItemAwardManager::GetItemAttributeSetIndex(const uint8_t bItemType, const uint8_t bItemSubType) const
|
||||
{
|
||||
using TAttributeMapT = std::map<uint8_t, std::map<uint8_t, int8_t>>;
|
||||
static const TAttributeMapT mapAttrSetFields =
|
||||
{
|
||||
{ ITEM_WEAPON,
|
||||
{
|
||||
{WEAPON_ARROW, ITEM_ATTRIBUTE_NONE},
|
||||
#ifdef ENABLE_QUIVER_SYSTEM
|
||||
{WEAPON_QUIVER, ITEM_ATTRIBUTE_NONE},
|
||||
#endif
|
||||
}
|
||||
},
|
||||
|
||||
{ ITEM_ARMOR,
|
||||
{
|
||||
{ARMOR_BODY, ATTRIBUTE_SET_BODY},
|
||||
{ARMOR_WRIST, ATTRIBUTE_SET_WRIST},
|
||||
{ARMOR_FOOTS, ATTRIBUTE_SET_FOOTS},
|
||||
{ARMOR_NECK, ATTRIBUTE_SET_NECK},
|
||||
{ARMOR_HEAD, ATTRIBUTE_SET_HEAD},
|
||||
{ARMOR_SHIELD, ATTRIBUTE_SET_SHIELD},
|
||||
{ARMOR_EAR, ATTRIBUTE_SET_EAR},
|
||||
#ifdef ENABLE_PENDANT_SYSTEM
|
||||
{ARMOR_PENDANT, ATTRIBUTE_SET_PENDANT},
|
||||
#endif
|
||||
#ifdef ENABLE_GLOVE_SYSTEM
|
||||
{ARMOR_GLOVE, ATTRIBUTE_SET_GLOVE},
|
||||
#endif
|
||||
}
|
||||
},
|
||||
|
||||
{ ITEM_COSTUME,
|
||||
{
|
||||
{COSTUME_BODY, ATTRIBUTE_SET_BODY},
|
||||
{COSTUME_HAIR, ATTRIBUTE_SET_HEAD},
|
||||
#ifdef ENABLE_MOUNT_COSTUME_SYSTEM
|
||||
{COSTUME_MOUNT, ITEM_ATTRIBUTE_NONE},
|
||||
#endif
|
||||
#ifdef ENABLE_WEAPON_COSTUME_SYSTEM
|
||||
{COSTUME_WEAPON, ATTRIBUTE_SET_WEAPON},
|
||||
#endif
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const auto c_iter_type = mapAttrSetFields.find(bItemType);
|
||||
if (c_iter_type != mapAttrSetFields.end())
|
||||
{
|
||||
const auto c_iter_sub_type = c_iter_type->second.find(bItemSubType);
|
||||
if (c_iter_sub_type != c_iter_type->second.end())
|
||||
return c_iter_sub_type->second;
|
||||
else if (c_iter_type->first == ITEM_WEAPON)
|
||||
return ATTRIBUTE_SET_WEAPON;
|
||||
}
|
||||
|
||||
return ITEM_ATTRIBUTE_NONE;
|
||||
}
|
||||
|
||||
/*******************************************************************\
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
||| 15.04.2018 - Added a check for attr types and values min - max.
|
||||
||| You can't insert wrong bonuses into a specific item.
|
||||
||| Eg. Add 2000M MAX_HP on your Sword+9, was possible, now not.
|
||||
||| Eg. Add +500 INT to your shield, now there's a check for min-max value of player.item_attr Lv.1 - Lv.5
|
||||
||| and your 500 INT value will be replaced with max value from lvl5 of bonus, like 12 (lv5), that happen with all the bonuses,
|
||||
||| same thing with the values lower than lvl1, like 5 HP_REGEN on your neck, when the minimum (lv1) is 10, the value will be replaced with 10.
|
||||
||| If the bonus type can't be added into a specific item, the bonus will be ignored > deleted. (example: critical pct to armor)
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
\*******************************************************************/
|
||||
void ItemAwardManager::CheckItemAttributes(TItemAward & rkItemAward, const TItemTable & rkItemTable, const std::vector<TItemAttrTable> & vec_itemAttrTable, const std::vector<TItemAttrTable> & vec_itemRareTable)
|
||||
{
|
||||
const auto bItemType = rkItemTable.bType;
|
||||
const auto bItemSubType = rkItemTable.bSubType;
|
||||
const auto iAttributeSet = GetItemAttributeSetIndex(bItemType, bItemSubType);
|
||||
if (iAttributeSet != ITEM_ATTRIBUTE_NONE)
|
||||
{
|
||||
// remove duplicates
|
||||
std::unordered_set<int> duplicates;
|
||||
for (size_t i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
|
||||
{
|
||||
// clear up duplicates after reached the rare ones
|
||||
if (i == ITEM_ATTRIBUTE_RARE_START)
|
||||
duplicates.clear();
|
||||
|
||||
auto bApplyType = rkItemAward.aAttr[i].bType;
|
||||
// check if already present
|
||||
if (duplicates.find(bApplyType) != duplicates.end())
|
||||
{
|
||||
rkItemAward.aAttr[i].bType = 0;
|
||||
rkItemAward.aAttr[i].sValue = 0;
|
||||
continue;
|
||||
}
|
||||
duplicates.emplace(bApplyType);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
|
||||
{
|
||||
const auto bApplyType = rkItemAward.aAttr[i].bType;
|
||||
const TItemAttrTable * pkAttrTable{nullptr};
|
||||
|
||||
// skip special bonus
|
||||
if (bApplyType == APPLY_SKILL_DAMAGE_BONUS || bApplyType == APPLY_NORMAL_HIT_DAMAGE_BONUS)
|
||||
continue;
|
||||
|
||||
// check normal bonus with item_attr
|
||||
if (i < ITEM_ATTRIBUTE_NORM_END)
|
||||
{
|
||||
for (size_t j = 0; j < vec_itemAttrTable.size() && !pkAttrTable; ++j)
|
||||
{
|
||||
const TItemAttrTable & rkAttrTable = vec_itemAttrTable.at(j);
|
||||
if (rkAttrTable.dwApplyIndex == bApplyType)
|
||||
{
|
||||
const auto bAttrLevel = rkAttrTable.bMaxLevelBySet[iAttributeSet];
|
||||
if (bAttrLevel > 0)
|
||||
pkAttrTable = &rkAttrTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
// check rare bonus with item_attr_rare
|
||||
else if (i >= ITEM_ATTRIBUTE_RARE_START)
|
||||
{
|
||||
for (size_t j = 0; j < vec_itemRareTable.size() && !pkAttrTable; ++j)
|
||||
{
|
||||
const TItemAttrTable & rkAttrTable = vec_itemRareTable.at(j);
|
||||
if (rkAttrTable.dwApplyIndex == bApplyType)
|
||||
{
|
||||
const auto bAttrLevel = rkAttrTable.bMaxLevelBySet[iAttributeSet];
|
||||
if (bAttrLevel > 0)
|
||||
pkAttrTable = &rkAttrTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pkAttrTable)
|
||||
{
|
||||
const auto sMinValue = static_cast<int16_t>(pkAttrTable->lValues[0]);
|
||||
const auto sMaxValue = static_cast<int16_t>(pkAttrTable->lValues[(sizeof(pkAttrTable->lValues) / sizeof(pkAttrTable->lValues[0])) - 1]);
|
||||
rkItemAward.aAttr[i].sValue = MINMAX(sMinValue, rkItemAward.aAttr[i].sValue, sMaxValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
rkItemAward.aAttr[i].bType = 0;
|
||||
rkItemAward.aAttr[i].sValue = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_EXTEND_ITEM_AWARD
|
||||
/*******************************************************************\
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
||| 02.04.2018 - Fixed unknown average/skill damage bonus value.
|
||||
||| player.item_proto.addon_type = -1 (Eg. 189, 199, 299, 1139, 1179, 2159, 2179, 3169, 3219, 5119, 5129, 6019, 6069, 6079, 7169)[+0 - +9]
|
||||
||| That's for the items which have addon type (-1) and you added them in item shop without bonuses like skill damage or hit damage,
|
||||
||| value x, y as default, so they'll will be without bonuses and get 'bugged'.
|
||||
||| Now when the item will be inserted there'll be a check if item doesn't have those bonuses (from query) add a random average/skill damage bonus value.
|
||||
||| INSERT INTO player.item_award(`login`, `vnum`, `count`, `mall`) VALUES ('account', 189, 1, 1);
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
\*******************************************************************/
|
||||
void ItemAwardManager::CheckItemAddonType(TItemAward & rkItemAward, const TItemTable & rkItemTable)
|
||||
{
|
||||
const bool bIsAddonTypeItem = (rkItemTable.sAddonType == -1);
|
||||
if (!bIsAddonTypeItem)
|
||||
return;
|
||||
|
||||
bool bHasBonus = false;
|
||||
for (size_t i = 0; i < ITEM_ATTRIBUTE_MAX_NUM && !bHasBonus; ++i)
|
||||
{
|
||||
const auto bType = rkItemAward.aAttr[i].bType;
|
||||
const auto sValue = rkItemAward.aAttr[i].sValue;
|
||||
|
||||
if ((bType == APPLY_SKILL_DAMAGE_BONUS || bType == APPLY_NORMAL_HIT_DAMAGE_BONUS) && sValue)
|
||||
bHasBonus = true;
|
||||
}
|
||||
|
||||
if (!bHasBonus)
|
||||
{
|
||||
const auto sApplySkillDamageValue = MINMAX(-30, static_cast<int16_t>((gauss_random(0, 5) + 0.5f)), 30);
|
||||
const auto sApplyNormalHitValue = std::abs(sApplySkillDamageValue) <= 20 ?
|
||||
(-2 * sApplySkillDamageValue) + std::abs(number(-8, 8) + number(-8, 8)) + number(1, 4) :
|
||||
(-2 * sApplySkillDamageValue) + number(1, 5);
|
||||
|
||||
rkItemAward.aAttr[0].bType = APPLY_NORMAL_HIT_DAMAGE_BONUS;
|
||||
rkItemAward.aAttr[0].sValue = sApplyNormalHitValue;
|
||||
rkItemAward.aAttr[1].bType = APPLY_SKILL_DAMAGE_BONUS;
|
||||
rkItemAward.aAttr[1].sValue = sApplySkillDamageValue;
|
||||
|
||||
// clear up possible duplicates
|
||||
for (size_t i = 2; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
|
||||
{
|
||||
const auto bType = rkItemAward.aAttr[i].bType;
|
||||
if (bType == APPLY_SKILL_DAMAGE_BONUS || bType == APPLY_NORMAL_HIT_DAMAGE_BONUS)
|
||||
{
|
||||
rkItemAward.aAttr[i].bType = 0;
|
||||
rkItemAward.aAttr[i].sValue = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************\
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
||| 12.04.2019 - Added support for books.
|
||||
||| Check skill types, unknown skill, skill vnum need to be saved into socket0,
|
||||
||| (4=Aura of the Sword < player.skill_proto), if the skill vnum is unknown, there will be a random book based on pc races,
|
||||
||| excluded skills PASSIVE, GUILD, SUPPORT.
|
||||
||| INSERT INTO player.item_award(`login`, `vnum`, `count`, `mall`) VALUES ('account', 50300, 1, 1); # Random book
|
||||
||| INSERT INTO player.item_award(`login`, `vnum`, `count`, `socket0`, `mall`) VALUES ('account', 50300, 1, 4, 1); # Specific book by skill vnum
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
\*******************************************************************/
|
||||
void ItemAwardManager::CheckItemSkillBook(TItemAward & rkItemAward, const std::vector<TSkillTable> vec_skillTable)
|
||||
{
|
||||
const bool bIsBookItem = (rkItemAward.dwVnum == ITEM_SKILL_VNUM || rkItemAward.dwVnum == ITEM_SKILLFORGET_VNUM);
|
||||
if (!bIsBookItem)
|
||||
return;
|
||||
|
||||
auto dwSocket0SkillVnum = rkItemAward.dwSocket0;
|
||||
bool bHasSkill = false;
|
||||
for (size_t i = 0; i < vec_skillTable.size(); ++i)
|
||||
{
|
||||
if (vec_skillTable[i].dwVnum == dwSocket0SkillVnum)
|
||||
{
|
||||
bHasSkill = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bHasSkill)
|
||||
{
|
||||
do
|
||||
{
|
||||
const TSkillTable * pkSkillTable = &vec_skillTable.at(number(0, vec_skillTable.size() - 1));
|
||||
if (!pkSkillTable)
|
||||
continue;
|
||||
|
||||
const auto dwSkillVnum = pkSkillTable->dwVnum;
|
||||
const auto bSkillType = pkSkillTable->bType;
|
||||
|
||||
if ((JOB_WARRIOR + 1 <= bSkillType && bSkillType <= JOB_SHAMAN + 1)
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
|| bSkillType == 7
|
||||
#endif
|
||||
)
|
||||
continue;
|
||||
|
||||
dwSocket0SkillVnum = dwSkillVnum;
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
|
||||
rkItemAward.dwSocket0 = dwSocket0SkillVnum;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************\
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
||| 11.04.2019 - Fixed unstackable items.
|
||||
||| Check if item count overflow occured, then set it to maximum.
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
\*******************************************************************/
|
||||
void ItemAwardManager::CheckItemCount(TItemAward & rkItemAward, const TItemTable & rkItemTable)
|
||||
{
|
||||
const bool bIsStackableItem = (rkItemTable.dwFlags & ITEM_FLAG_STACKABLE);
|
||||
if (rkItemAward.dwCount > 1 && !bIsStackableItem)
|
||||
rkItemAward.dwCount = 1;
|
||||
else
|
||||
rkItemAward.dwCount = MINMAX(1, rkItemAward.dwCount, ITEM_MAX_COUNT);
|
||||
}
|
||||
|
||||
/*******************************************************************\
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
||| 20.08.2021 - Fixed not slottable items.
|
||||
||| New created equipments had no available slots.
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
\*******************************************************************/
|
||||
void ItemAwardManager::CheckItemSocket(TItemAward & rkItemAward, const TItemTable & rkItemTable)
|
||||
{
|
||||
// check for limited time items
|
||||
for (const auto & limit : rkItemTable.aLimits)
|
||||
{
|
||||
if (LIMIT_REAL_TIME == limit.bType || LIMIT_REAL_TIME_START_FIRST_USE == limit.bType)
|
||||
return;
|
||||
}
|
||||
|
||||
// check slottable sockets for non limited time items
|
||||
const auto maxSockets = std::min<int>(rkItemTable.bGainSocketPct, ITEM_SOCKET_MAX_NUM);
|
||||
if (maxSockets <= 0)
|
||||
return;
|
||||
|
||||
if (maxSockets >= 1)
|
||||
rkItemAward.dwSocket0 = 1;
|
||||
if (maxSockets >= 2)
|
||||
rkItemAward.dwSocket1 = 1;
|
||||
if (maxSockets >= 3)
|
||||
rkItemAward.dwSocket2 = 1;
|
||||
}
|
||||
|
||||
/*******************************************************************\
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
||| TODO-UNFINISHED: Check if apply_type exists in bonuses.
|
||||
||| Check if apply_value, apply_duration is equal with grades (1/2/3/4/5) from settings, blend.txt
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
\*******************************************************************/
|
||||
void ItemAwardManager::CheckItemBlend(TItemAward & rkItemAward, const TItemTable & rkItemTable)
|
||||
{
|
||||
const bool bIsBlendItem = (rkItemTable.bType == ITEM_BLEND);
|
||||
if (!bIsBlendItem)
|
||||
return;
|
||||
|
||||
const auto bApplyType = rkItemAward.dwSocket0;
|
||||
const auto bApplyValue = rkItemAward.dwSocket1;
|
||||
const auto dwApplyDuration = rkItemAward.dwSocket2;
|
||||
|
||||
if (bApplyType == 0 || bApplyValue == 0 || dwApplyDuration == 0)
|
||||
sys_err("ItemAwardManager: Unknown sockets for ITEM_BLEND.");
|
||||
}
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
69
source-server/Srcs/Server/db/src/ItemAwardManager.h
Normal file
69
source-server/Srcs/Server/db/src/ItemAwardManager.h
Normal file
@ -0,0 +1,69 @@
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_ITEM_AWARD_H
|
||||
#define __INC_ITEM_AWARD_H
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include "Peer.h"
|
||||
|
||||
#ifdef ENABLE_EXTEND_ITEM_AWARD
|
||||
enum
|
||||
{
|
||||
ITEM_ATTRIBUTE_NONE = -1,
|
||||
ITEM_SKILL_VNUM = 50300,
|
||||
ITEM_SKILLFORGET_VNUM = 70037,
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct SItemAward
|
||||
{
|
||||
DWORD dwID;
|
||||
char szLogin[LOGIN_MAX_LEN+1];
|
||||
DWORD dwVnum;
|
||||
DWORD dwCount;
|
||||
DWORD dwSocket0;
|
||||
DWORD dwSocket1;
|
||||
DWORD dwSocket2;
|
||||
char szWhy[ITEM_AWARD_WHY_MAX_LEN+1];
|
||||
bool bTaken;
|
||||
bool bMall;
|
||||
#ifdef ENABLE_EXTEND_ITEM_AWARD
|
||||
TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];
|
||||
#endif
|
||||
} TItemAward;
|
||||
|
||||
class ItemAwardManager : public singleton<ItemAwardManager>
|
||||
{
|
||||
public:
|
||||
ItemAwardManager();
|
||||
virtual ~ItemAwardManager();
|
||||
|
||||
void RequestLoad();
|
||||
void Load(SQLMsg * pMsg);
|
||||
std::set<TItemAward *> * GetByLogin(const char * c_pszLogin);
|
||||
|
||||
void Taken(DWORD dwAwardID, DWORD dwItemID);
|
||||
|
||||
#ifdef ENABLE_EXTEND_ITEM_AWARD
|
||||
void CheckItemAddonType(TItemAward & pkItemAward, const TItemTable & pkItemTable);
|
||||
void CheckItemCount(TItemAward & pkItemAward, const TItemTable & pkItemTable);
|
||||
void CheckItemSocket(TItemAward & pkItemAward, const TItemTable & pkItemTable);
|
||||
void CheckItemBlend(TItemAward & pkItemAward, const TItemTable & pkItemTable);
|
||||
void CheckItemSkillBook(TItemAward & pkItemAward, const std::vector<TSkillTable> vec_skillTable);
|
||||
#endif
|
||||
#ifdef USE_ITEM_AWARD_CHECK_ATTRIBUTES
|
||||
void CheckItemAttributes(TItemAward & pkItemAward, const TItemTable & pkItemTable, const std::vector<TItemAttrTable> & vec_itemAttrTable, const std::vector<TItemAttrTable> & vec_itemRareTable);
|
||||
int8_t GetItemAttributeSetIndex(const uint8_t bItemType, const uint8_t bItemSubType) const;
|
||||
#endif
|
||||
|
||||
// gift notify
|
||||
std::map<DWORD, TItemAward *>& GetMapAward();
|
||||
std::map<std::string, std::set<TItemAward *> >& GetMapkSetAwardByLogin();
|
||||
private:
|
||||
// ID, ItemAward pair
|
||||
std::map<DWORD, TItemAward *> m_map_award;
|
||||
// PID, ItemAward pair
|
||||
std::map<std::string, std::set<TItemAward *> > m_map_kSetAwardByLogin;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
160
source-server/Srcs/Server/db/src/ItemIDRangeManager.cpp
Normal file
160
source-server/Srcs/Server/db/src/ItemIDRangeManager.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
#include "stdafx.h"
|
||||
#include "ItemIDRangeManager.h"
|
||||
#include "Main.h"
|
||||
#include "DBManager.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Peer.h"
|
||||
|
||||
CItemIDRangeManager::CItemIDRangeManager()
|
||||
{
|
||||
m_listData.clear();
|
||||
}
|
||||
|
||||
void CItemIDRangeManager::Build()
|
||||
{
|
||||
DWORD dwMin = 0;
|
||||
DWORD dwMax = 0;
|
||||
TItemIDRangeTable range;
|
||||
|
||||
for (int i = 0; ; ++i)
|
||||
{
|
||||
dwMin = cs_dwMinimumRange * (i + 1) + 1;
|
||||
dwMax = cs_dwMinimumRange * (i + 2);
|
||||
|
||||
if (dwMax == cs_dwMaxItemID)
|
||||
break;
|
||||
|
||||
if (CClientManager::instance().GetItemRange().dwMin <= dwMin &&
|
||||
CClientManager::instance().GetItemRange().dwMax >= dwMax)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BuildRange(dwMin, dwMax, range) == true)
|
||||
{
|
||||
m_listData.emplace_back(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FCheckCollision
|
||||
{
|
||||
bool hasCollision;
|
||||
TItemIDRangeTable range;
|
||||
|
||||
FCheckCollision(TItemIDRangeTable data)
|
||||
{
|
||||
hasCollision = false;
|
||||
range = data;
|
||||
}
|
||||
|
||||
void operator() (CPeer* peer)
|
||||
{
|
||||
if (hasCollision == false)
|
||||
{
|
||||
hasCollision = peer->CheckItemIDRangeCollision(range);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TItemIDRangeTable CItemIDRangeManager::GetRange()
|
||||
{
|
||||
TItemIDRangeTable ret;
|
||||
ret.dwMin = 0;
|
||||
ret.dwMax = 0;
|
||||
ret.dwUsableItemIDMin = 0;
|
||||
|
||||
if (m_listData.size() > 0)
|
||||
{
|
||||
while (m_listData.size() > 0)
|
||||
{
|
||||
ret = m_listData.front();
|
||||
m_listData.pop_front();
|
||||
|
||||
FCheckCollision f(ret);
|
||||
CClientManager::instance().for_each_peer(f);
|
||||
|
||||
if (f.hasCollision == false) return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
sys_err("ItemIDRange: NO MORE ITEM ID RANGE");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CItemIDRangeManager::BuildRange(DWORD dwMin, DWORD dwMax, TItemIDRangeTable& range)
|
||||
{
|
||||
char szQuery[1024];
|
||||
DWORD dwItemMaxID = 0;
|
||||
MYSQL_ROW row;
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT MAX(id) FROM item%s WHERE id >= %u and id <= %u", GetTablePostfix(), dwMin, dwMax);
|
||||
|
||||
auto pMsg = CDBManager::instance().DirectQuery(szQuery);
|
||||
if (pMsg != NULL)
|
||||
{
|
||||
if (pMsg->Get()->uiNumRows > 0)
|
||||
{
|
||||
row = mysql_fetch_row(pMsg->Get()->pSQLResult);
|
||||
str_to_number(dwItemMaxID, row[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (dwItemMaxID == 0)
|
||||
dwItemMaxID = dwMin;
|
||||
else
|
||||
dwItemMaxID++;
|
||||
|
||||
if ((dwMax < dwItemMaxID) || (dwMax - dwItemMaxID < cs_dwMinimumRemainCount))
|
||||
{
|
||||
sys_log(0, "ItemIDRange: Build %u ~ %u start: %u\tNOT USE remain count is below %u",
|
||||
dwMin, dwMax, dwItemMaxID, cs_dwMinimumRemainCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
range.dwMin = dwMin;
|
||||
range.dwMax = dwMax;
|
||||
range.dwUsableItemIDMin = dwItemMaxID;
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT COUNT(*) FROM item%s WHERE id >= %u AND id <= %u",
|
||||
GetTablePostfix(), range.dwUsableItemIDMin, range.dwMax);
|
||||
|
||||
pMsg = CDBManager::instance().DirectQuery(szQuery);
|
||||
|
||||
if (pMsg != NULL)
|
||||
{
|
||||
if (pMsg->Get()->uiNumRows > 0)
|
||||
{
|
||||
DWORD count = 0;
|
||||
row = mysql_fetch_row(pMsg->Get()->pSQLResult);
|
||||
str_to_number(count, row[0]);
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
sys_err("ItemIDRange: Build: %u ~ %u\thave a item", range.dwUsableItemIDMin, range.dwMax);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_log(0, "ItemIDRange: Build: %u ~ %u start:%u", range.dwMin, range.dwMax, range.dwUsableItemIDMin);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CItemIDRangeManager::UpdateRange(DWORD dwMin, DWORD dwMax)
|
||||
{
|
||||
TItemIDRangeTable range;
|
||||
|
||||
if (BuildRange(dwMin, dwMax, range) == true)
|
||||
{
|
||||
m_listData.emplace_back(range);
|
||||
}
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
25
source-server/Srcs/Server/db/src/ItemIDRangeManager.h
Normal file
25
source-server/Srcs/Server/db/src/ItemIDRangeManager.h
Normal file
@ -0,0 +1,25 @@
|
||||
// vim:ts=4 sw=4
|
||||
#ifndef __INC_METIN_II_ITEM_ID_RANGE_MANAGER_H__
|
||||
#define __INC_METIN_II_ITEM_ID_RANGE_MANAGER_H__
|
||||
|
||||
class CItemIDRangeManager : public singleton<CItemIDRangeManager>
|
||||
{
|
||||
private :
|
||||
const static DWORD cs_dwMaxItemID = 4290000000UL;
|
||||
const static DWORD cs_dwMinimumRange = 10000000UL;
|
||||
const static DWORD cs_dwMinimumRemainCount = 10000UL;
|
||||
|
||||
std::list<TItemIDRangeTable> m_listData;
|
||||
|
||||
public :
|
||||
CItemIDRangeManager();
|
||||
|
||||
void Build();
|
||||
bool BuildRange(DWORD dwMin, DWORD dwMax, TItemIDRangeTable& range);
|
||||
void UpdateRange(DWORD dwMin, DWORD dwMax);
|
||||
|
||||
TItemIDRangeTable GetRange();
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
61
source-server/Srcs/Server/db/src/Lock.cpp
Normal file
61
source-server/Srcs/Server/db/src/Lock.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include "stdafx.h"
|
||||
#include "Lock.h"
|
||||
|
||||
CLock::CLock()
|
||||
{
|
||||
}
|
||||
|
||||
CLock::~CLock()
|
||||
{
|
||||
}
|
||||
|
||||
void CLock::Initialize()
|
||||
{
|
||||
m_bLocked = false;
|
||||
#ifndef __WIN32__
|
||||
pthread_mutex_init(&m_lock, NULL);
|
||||
#else
|
||||
::InitializeCriticalSection(&m_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CLock::Destroy()
|
||||
{
|
||||
assert(!m_bLocked && "lock didn't released");
|
||||
#ifndef __WIN32__
|
||||
pthread_mutex_destroy(&m_lock);
|
||||
#else
|
||||
::DeleteCriticalSection(&m_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
int CLock::Trylock()
|
||||
{
|
||||
#ifndef __WIN32__
|
||||
return pthread_mutex_trylock(&m_lock);
|
||||
#else
|
||||
return ::TryEnterCriticalSection(&m_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CLock::Lock()
|
||||
{
|
||||
#ifndef __WIN32__
|
||||
pthread_mutex_lock(&m_lock);
|
||||
#else
|
||||
::EnterCriticalSection(&m_lock);
|
||||
#endif
|
||||
m_bLocked = true;
|
||||
}
|
||||
|
||||
void CLock::Unlock()
|
||||
{
|
||||
assert(m_bLocked && "lock didn't issued");
|
||||
m_bLocked = false;
|
||||
#ifndef __WIN32__
|
||||
pthread_mutex_unlock(&m_lock);
|
||||
#else
|
||||
::LeaveCriticalSection(&m_lock);
|
||||
#endif
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
28
source-server/Srcs/Server/db/src/Lock.h
Normal file
28
source-server/Srcs/Server/db/src/Lock.h
Normal file
@ -0,0 +1,28 @@
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_LOCK_H__
|
||||
#define __INC_LOCK_H__
|
||||
|
||||
#ifdef __WIN32__
|
||||
typedef CRITICAL_SECTION lock_t;
|
||||
#else
|
||||
typedef pthread_mutex_t lock_t;
|
||||
#endif
|
||||
|
||||
class CLock
|
||||
{
|
||||
public:
|
||||
CLock();
|
||||
~CLock();
|
||||
|
||||
void Initialize();
|
||||
void Destroy();
|
||||
int Trylock();
|
||||
void Lock();
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
lock_t m_lock;
|
||||
bool m_bLocked;
|
||||
};
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
123
source-server/Srcs/Server/db/src/LoginData.cpp
Normal file
123
source-server/Srcs/Server/db/src/LoginData.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
#include "stdafx.h"
|
||||
#include "LoginData.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
CLoginData::CLoginData()
|
||||
{
|
||||
m_dwKey = 0;
|
||||
memset(m_adwClientKey, 0, sizeof(m_adwClientKey));
|
||||
m_dwConnectedPeerHandle = 0;
|
||||
m_dwLogonTime = 0;
|
||||
memset(m_szIP, 0, sizeof(m_szIP));
|
||||
m_bPlay = false;
|
||||
m_bDeleted = false;
|
||||
m_bBillType = 0;
|
||||
m_dwBillID = 0;
|
||||
m_lastPlayTime = 0;
|
||||
m_dwLastPlayerID = 0;
|
||||
|
||||
memset(&m_data, 0, sizeof(TAccountTable));
|
||||
}
|
||||
|
||||
TAccountTable & CLoginData::GetAccountRef()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void CLoginData::SetClientKey(const DWORD * c_pdwClientKey)
|
||||
{
|
||||
thecore_memcpy(&m_adwClientKey, c_pdwClientKey, sizeof(DWORD) * 4);
|
||||
}
|
||||
|
||||
const DWORD * CLoginData::GetClientKey()
|
||||
{
|
||||
return &m_adwClientKey[0];
|
||||
}
|
||||
|
||||
void CLoginData::SetKey(DWORD dwKey)
|
||||
{
|
||||
m_dwKey = dwKey;
|
||||
}
|
||||
|
||||
DWORD CLoginData::GetKey()
|
||||
{
|
||||
return m_dwKey;
|
||||
}
|
||||
|
||||
void CLoginData::SetConnectedPeerHandle(DWORD dwHandle)
|
||||
{
|
||||
m_dwConnectedPeerHandle = dwHandle;
|
||||
}
|
||||
|
||||
DWORD CLoginData::GetConnectedPeerHandle()
|
||||
{
|
||||
return m_dwConnectedPeerHandle;
|
||||
}
|
||||
|
||||
void CLoginData::SetLogonTime()
|
||||
{
|
||||
m_dwLogonTime = get_dword_time();
|
||||
}
|
||||
|
||||
DWORD CLoginData::GetLogonTime()
|
||||
{
|
||||
return m_dwLogonTime;
|
||||
}
|
||||
|
||||
void CLoginData::SetIP(const char * c_pszIP)
|
||||
{
|
||||
strlcpy(m_szIP, c_pszIP, sizeof(m_szIP));
|
||||
}
|
||||
|
||||
const char * CLoginData::GetIP()
|
||||
{
|
||||
return m_szIP;
|
||||
}
|
||||
|
||||
void CLoginData::SetPlay(bool bOn)
|
||||
{
|
||||
if (bOn)
|
||||
{
|
||||
sys_log(0, "SetPlay on %lu %s", GetKey(), m_data.login);
|
||||
SetLogonTime();
|
||||
}
|
||||
else
|
||||
sys_log(0, "SetPlay off %lu %s", GetKey(), m_data.login);
|
||||
|
||||
m_bPlay = bOn;
|
||||
m_lastPlayTime = CClientManager::instance().GetCurrentTime();
|
||||
}
|
||||
|
||||
bool CLoginData::IsPlay()
|
||||
{
|
||||
return m_bPlay;
|
||||
}
|
||||
|
||||
void CLoginData::SetDeleted(bool bSet)
|
||||
{
|
||||
m_bDeleted = bSet;
|
||||
}
|
||||
|
||||
bool CLoginData::IsDeleted()
|
||||
{
|
||||
return m_bDeleted;
|
||||
}
|
||||
|
||||
void CLoginData::SetPremium(int * paiPremiumTimes)
|
||||
{
|
||||
thecore_memcpy(m_aiPremiumTimes, paiPremiumTimes, sizeof(m_aiPremiumTimes));
|
||||
}
|
||||
|
||||
int CLoginData::GetPremium(BYTE type)
|
||||
{
|
||||
if (type >= PREMIUM_MAX_NUM)
|
||||
return 0;
|
||||
|
||||
return m_aiPremiumTimes[type];
|
||||
}
|
||||
|
||||
int * CLoginData::GetPremiumPtr()
|
||||
{
|
||||
return &m_aiPremiumTimes[0];
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
67
source-server/Srcs/Server/db/src/LoginData.h
Normal file
67
source-server/Srcs/Server/db/src/LoginData.h
Normal file
@ -0,0 +1,67 @@
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_METIN_II_DB_LOGINDATA_H__
|
||||
#define __INC_METIN_II_DB_LOGINDATA_H__
|
||||
|
||||
class CLoginData
|
||||
{
|
||||
public:
|
||||
CLoginData();
|
||||
|
||||
TAccountTable & GetAccountRef();
|
||||
void SetClientKey(const DWORD * c_pdwClientKey);
|
||||
|
||||
const DWORD * GetClientKey();
|
||||
void SetKey(DWORD dwKey);
|
||||
DWORD GetKey();
|
||||
|
||||
void SetConnectedPeerHandle(DWORD dwHandle);
|
||||
DWORD GetConnectedPeerHandle();
|
||||
|
||||
void SetLogonTime();
|
||||
DWORD GetLogonTime();
|
||||
|
||||
void SetIP(const char * c_pszIP);
|
||||
const char * GetIP();
|
||||
|
||||
void SetPlay(bool bOn);
|
||||
bool IsPlay();
|
||||
|
||||
void SetDeleted(bool bSet);
|
||||
bool IsDeleted();
|
||||
|
||||
void SetBillID(DWORD id) { m_dwBillID = id; }
|
||||
DWORD GetBillID() { return m_dwBillID; }
|
||||
|
||||
void SetBillType(BYTE type) { m_bBillType = type; }
|
||||
BYTE GetBillType() { return m_bBillType; }
|
||||
|
||||
time_t GetLastPlayTime() { return m_lastPlayTime; }
|
||||
|
||||
void SetPremium(int * paiPremiumTimes);
|
||||
int GetPremium(BYTE type);
|
||||
int * GetPremiumPtr();
|
||||
|
||||
DWORD GetLastPlayerID() const { return m_dwLastPlayerID; }
|
||||
void SetLastPlayerID(DWORD id) { m_dwLastPlayerID = id; }
|
||||
|
||||
private:
|
||||
DWORD m_dwKey;
|
||||
DWORD m_adwClientKey[4];
|
||||
DWORD m_dwConnectedPeerHandle;
|
||||
DWORD m_dwLogonTime;
|
||||
char m_szIP[MAX_HOST_LENGTH+1];
|
||||
bool m_bPlay;
|
||||
bool m_bDeleted;
|
||||
|
||||
BYTE m_bBillType;
|
||||
DWORD m_dwBillID;
|
||||
time_t m_lastPlayTime;
|
||||
int m_aiPremiumTimes[PREMIUM_MAX_NUM];
|
||||
|
||||
DWORD m_dwLastPlayerID;
|
||||
|
||||
TAccountTable m_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
443
source-server/Srcs/Server/db/src/Main.cpp
Normal file
443
source-server/Srcs/Server/db/src/Main.cpp
Normal file
@ -0,0 +1,443 @@
|
||||
#include "stdafx.h"
|
||||
#include "Config.h"
|
||||
#include "Peer.h"
|
||||
#include "DBManager.h"
|
||||
#include "ClientManager.h"
|
||||
#include "GuildManager.h"
|
||||
#include "ItemAwardManager.h"
|
||||
#include "HB.h"
|
||||
#include "PrivManager.h"
|
||||
#include "MoneyLog.h"
|
||||
#include "Marriage.h"
|
||||
#include "Monarch.h"
|
||||
#include "ItemIDRangeManager.h"
|
||||
#include <signal.h>
|
||||
|
||||
void SetPlayerDBName(const char* c_pszPlayerDBName);
|
||||
void SetTablePostfix(const char* c_pszTablePostfix);
|
||||
int Start();
|
||||
|
||||
std::string g_stTablePostfix;
|
||||
std::string g_stLocaleNameColumn = "name";
|
||||
std::string g_stLocale = "latin1"; // default: euckr
|
||||
std::string g_stPlayerDBName = "";
|
||||
|
||||
bool g_bHotBackup = false; // default: true
|
||||
BOOL g_test_server = false;
|
||||
|
||||
int g_iPlayerCacheFlushSeconds = 60*7;
|
||||
int g_iItemCacheFlushSeconds = 60*5;
|
||||
|
||||
int g_iLogoutSeconds = 60*10;
|
||||
|
||||
int g_log = 1;
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
int g_iItemPriceListTableCacheFlushSeconds = 540;
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
|
||||
#if defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version<1000000
|
||||
extern const char * _malloc_options;
|
||||
#endif
|
||||
|
||||
extern void WriteVersion();
|
||||
|
||||
void emergency_sig(int sig)
|
||||
{
|
||||
if (sig == SIGSEGV)
|
||||
sys_log(0, "SIGNAL: SIGSEGV");
|
||||
else if (sig == SIGUSR1)
|
||||
sys_log(0, "SIGNAL: SIGUSR1");
|
||||
|
||||
if (sig == SIGSEGV)
|
||||
abort();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
WriteVersion();
|
||||
|
||||
#if defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version<1000000
|
||||
_malloc_options = "A";
|
||||
#endif
|
||||
|
||||
CConfig Config;
|
||||
CNetPoller poller;
|
||||
CDBManager DBManager;
|
||||
CClientManager ClientManager;
|
||||
PlayerHB player_hb;
|
||||
CGuildManager GuildManager;
|
||||
CPrivManager PrivManager;
|
||||
CMoneyLog MoneyLog;
|
||||
ItemAwardManager ItemAwardManager;
|
||||
marriage::CManager MarriageManager;
|
||||
CMonarch Monarch;
|
||||
CItemIDRangeManager ItemIDRangeManager;
|
||||
if (!Start())
|
||||
return 1;
|
||||
|
||||
GuildManager.Initialize();
|
||||
MarriageManager.Initialize();
|
||||
ItemIDRangeManager.Build();
|
||||
sys_log(0, "Metin2DBCacheServer Start\n");
|
||||
|
||||
CClientManager::instance().MainLoop();
|
||||
|
||||
signal_timer_disable();
|
||||
|
||||
DBManager.Quit();
|
||||
int iCount;
|
||||
|
||||
while (1)
|
||||
{
|
||||
iCount = 0;
|
||||
|
||||
iCount += CDBManager::instance().CountReturnQuery(SQL_PLAYER);
|
||||
iCount += CDBManager::instance().CountAsyncQuery(SQL_PLAYER);
|
||||
|
||||
if (iCount == 0)
|
||||
break;
|
||||
|
||||
usleep(1000);
|
||||
sys_log(0, "WAITING_QUERY_COUNT %d", iCount);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void emptybeat(LPHEART heart, int pulse)
|
||||
{
|
||||
if (!(pulse % heart->passes_per_sec))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
int Start()
|
||||
{
|
||||
if (!CConfig::instance().LoadFile("conf.txt"))
|
||||
{
|
||||
fprintf(stderr, "Loading conf.txt failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CConfig::instance().GetValue("TEST_SERVER", &g_test_server))
|
||||
{
|
||||
fprintf(stderr, "Real Server\n");
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Test Server\n");
|
||||
|
||||
if (!CConfig::instance().GetValue("LOG", &g_log))
|
||||
{
|
||||
fprintf(stderr, "Log Off");
|
||||
g_log= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_log = 1;
|
||||
fprintf(stderr, "Log On");
|
||||
}
|
||||
|
||||
int tmpValue;
|
||||
|
||||
int heart_beat = 50;
|
||||
if (!CConfig::instance().GetValue("CLIENT_HEART_FPS", &heart_beat))
|
||||
{
|
||||
fprintf(stderr, "Cannot find CLIENT_HEART_FPS configuration.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
log_set_expiration_days(3);
|
||||
|
||||
if (CConfig::instance().GetValue("LOG_KEEP_DAYS", &tmpValue))
|
||||
{
|
||||
tmpValue = MINMAX(3, tmpValue, 30);
|
||||
log_set_expiration_days(tmpValue);
|
||||
fprintf(stderr, "Setting log keeping days to %d\n", tmpValue);
|
||||
}
|
||||
|
||||
thecore_init(heart_beat, emptybeat);
|
||||
signal_timer_enable(60);
|
||||
|
||||
char szBuf[256+1];
|
||||
|
||||
if (CConfig::instance().GetValue("LOCALE", szBuf, 256))
|
||||
{
|
||||
g_stLocale = szBuf;
|
||||
sys_log(0, "LOCALE set to %s", g_stLocale.c_str());
|
||||
|
||||
// CHINA_DISABLE_HOTBACKUP
|
||||
if ("gb2312" == g_stLocale)
|
||||
{
|
||||
sys_log(0, "CIBN_LOCALE: DISABLE_HOTBACKUP");
|
||||
g_bHotBackup = false;
|
||||
}
|
||||
// END_OF_CHINA_DISABLE_HOTBACKUP
|
||||
}
|
||||
|
||||
int iDisableHotBackup;
|
||||
if (CConfig::instance().GetValue("DISABLE_HOTBACKUP", &iDisableHotBackup))
|
||||
{
|
||||
if (iDisableHotBackup)
|
||||
{
|
||||
sys_log(0, "CONFIG: DISABLE_HOTBACKUP");
|
||||
g_bHotBackup = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CConfig::instance().GetValue("TABLE_POSTFIX", szBuf, 256))
|
||||
{
|
||||
sys_log(0, "TABLE_POSTFIX not configured use default"); // @warme012
|
||||
szBuf[0] = '\0';
|
||||
}
|
||||
|
||||
SetTablePostfix(szBuf);
|
||||
|
||||
if (CConfig::instance().GetValue("PLAYER_CACHE_FLUSH_SECONDS", szBuf, 256))
|
||||
{
|
||||
str_to_number(g_iPlayerCacheFlushSeconds, szBuf);
|
||||
sys_log(0, "PLAYER_CACHE_FLUSH_SECONDS: %d", g_iPlayerCacheFlushSeconds);
|
||||
}
|
||||
|
||||
if (CConfig::instance().GetValue("ITEM_CACHE_FLUSH_SECONDS", szBuf, 256))
|
||||
{
|
||||
str_to_number(g_iItemCacheFlushSeconds, szBuf);
|
||||
sys_log(0, "ITEM_CACHE_FLUSH_SECONDS: %d", g_iItemCacheFlushSeconds);
|
||||
}
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
if (CConfig::instance().GetValue("ITEM_PRICELIST_CACHE_FLUSH_SECONDS", szBuf, 256))
|
||||
{
|
||||
str_to_number(g_iItemPriceListTableCacheFlushSeconds, szBuf);
|
||||
sys_log(0, "ITEM_PRICELIST_CACHE_FLUSH_SECONDS: %d", g_iItemPriceListTableCacheFlushSeconds);
|
||||
}
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
|
||||
if (CConfig::instance().GetValue("CACHE_FLUSH_LIMIT_PER_SECOND", szBuf, 256))
|
||||
{
|
||||
DWORD dwVal = 0; str_to_number(dwVal, szBuf);
|
||||
CClientManager::instance().SetCacheFlushCountLimit(dwVal);
|
||||
}
|
||||
|
||||
int iIDStart;
|
||||
if (!CConfig::instance().GetValue("PLAYER_ID_START", &iIDStart))
|
||||
{
|
||||
sys_err("PLAYER_ID_START not configured");
|
||||
return false;
|
||||
}
|
||||
|
||||
CClientManager::instance().SetPlayerIDStart(iIDStart);
|
||||
|
||||
if (CConfig::instance().GetValue("NAME_COLUMN", szBuf, 256))
|
||||
{
|
||||
fprintf(stderr, "%s %s", g_stLocaleNameColumn.c_str(), szBuf);
|
||||
g_stLocaleNameColumn = szBuf;
|
||||
}
|
||||
|
||||
char szAddr[64], szDB[64], szUser[64], szPassword[64];
|
||||
int iPort;
|
||||
char line[256+1];
|
||||
|
||||
if (CConfig::instance().GetValue("SQL_PLAYER", line, 256))
|
||||
{
|
||||
sscanf(line, " %s %s %s %s %d ", szAddr, szDB, szUser, szPassword, &iPort);
|
||||
sys_log(0, "connecting to MySQL server (player)");
|
||||
|
||||
int iRetry = 5;
|
||||
|
||||
do
|
||||
{
|
||||
if (CDBManager::instance().Connect(SQL_PLAYER, szAddr, iPort, szDB, szUser, szPassword))
|
||||
{
|
||||
sys_log(0, " OK");
|
||||
break;
|
||||
}
|
||||
|
||||
sys_log(0, " failed, retrying in 5 seconds");
|
||||
fprintf(stderr, " failed, retrying in 5 seconds");
|
||||
sleep(5);
|
||||
} while (iRetry--);
|
||||
fprintf(stderr, "Success PLAYER\n");
|
||||
SetPlayerDBName(szDB);
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_err("SQL_PLAYER not configured");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CConfig::instance().GetValue("SQL_ACCOUNT", line, 256))
|
||||
{
|
||||
sscanf(line, " %s %s %s %s %d ", szAddr, szDB, szUser, szPassword, &iPort);
|
||||
sys_log(0, "connecting to MySQL server (account)");
|
||||
|
||||
int iRetry = 5;
|
||||
|
||||
do
|
||||
{
|
||||
if (CDBManager::instance().Connect(SQL_ACCOUNT, szAddr, iPort, szDB, szUser, szPassword))
|
||||
{
|
||||
sys_log(0, " OK");
|
||||
break;
|
||||
}
|
||||
|
||||
sys_log(0, " failed, retrying in 5 seconds");
|
||||
fprintf(stderr, " failed, retrying in 5 seconds");
|
||||
sleep(5);
|
||||
} while (iRetry--);
|
||||
fprintf(stderr, "Success ACCOUNT\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_err("SQL_ACCOUNT not configured");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CConfig::instance().GetValue("SQL_COMMON", line, 256))
|
||||
{
|
||||
sscanf(line, " %s %s %s %s %d ", szAddr, szDB, szUser, szPassword, &iPort);
|
||||
sys_log(0, "connecting to MySQL server (common)");
|
||||
|
||||
int iRetry = 5;
|
||||
|
||||
do
|
||||
{
|
||||
if (CDBManager::instance().Connect(SQL_COMMON, szAddr, iPort, szDB, szUser, szPassword))
|
||||
{
|
||||
sys_log(0, " OK");
|
||||
break;
|
||||
}
|
||||
|
||||
sys_log(0, " failed, retrying in 5 seconds");
|
||||
fprintf(stderr, " failed, retrying in 5 seconds");
|
||||
sleep(5);
|
||||
} while (iRetry--);
|
||||
fprintf(stderr, "Success COMMON\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_err("SQL_COMMON not configured");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CConfig::instance().GetValue("SQL_HOTBACKUP", line, 256))
|
||||
{
|
||||
sscanf(line, " %s %s %s %s %d ", szAddr, szDB, szUser, szPassword, &iPort);
|
||||
sys_log(0, "connecting to MySQL server (hotbackup)");
|
||||
|
||||
int iRetry = 5;
|
||||
|
||||
do
|
||||
{
|
||||
if (CDBManager::instance().Connect(SQL_HOTBACKUP, szAddr, iPort, szDB, szUser, szPassword))
|
||||
{
|
||||
sys_log(0, " OK");
|
||||
break;
|
||||
}
|
||||
|
||||
sys_log(0, " failed, retrying in 5 seconds");
|
||||
fprintf(stderr, " failed, retrying in 5 seconds");
|
||||
sleep(5);
|
||||
}
|
||||
while (iRetry--);
|
||||
|
||||
fprintf(stderr, "Success HOTBACKUP\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_err("SQL_HOTBACKUP not configured");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_DB_SQL_LOG
|
||||
if (CConfig::instance().GetValue("SQL_LOG", line, 256))
|
||||
{
|
||||
sscanf(line, " %s %s %s %s %d ", szAddr, szDB, szUser, szPassword, &iPort);
|
||||
sys_log(0, "connecting to MySQL server (log)");
|
||||
|
||||
int iRetry = 5;
|
||||
|
||||
do
|
||||
{
|
||||
if (CDBManager::instance().Connect(SQL_LOG, szAddr, iPort, szDB, szUser, szPassword))
|
||||
{
|
||||
sys_log(0, " OK");
|
||||
break;
|
||||
}
|
||||
|
||||
sys_log(0, " failed, retrying in 5 seconds");
|
||||
fprintf(stderr, " failed, retrying in 5 seconds");
|
||||
sleep(5);
|
||||
} while (iRetry--);
|
||||
|
||||
fprintf(stderr, "Success LOG\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_err("SQL_LOG not configured");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!CNetPoller::instance().Create())
|
||||
{
|
||||
sys_err("Cannot create network poller");
|
||||
return false;
|
||||
}
|
||||
|
||||
sys_log(0, "ClientManager initialization.. ");
|
||||
|
||||
if (!CClientManager::instance().Initialize())
|
||||
{
|
||||
sys_log(0, " failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
sys_log(0, " OK");
|
||||
|
||||
if (!PlayerHB::instance().Initialize())
|
||||
{
|
||||
sys_err("cannot initialize player hotbackup");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef __WIN32__
|
||||
signal(SIGUSR1, emergency_sig);
|
||||
#endif
|
||||
signal(SIGSEGV, emergency_sig);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetTablePostfix(const char* c_pszTablePostfix)
|
||||
{
|
||||
if (!c_pszTablePostfix || !*c_pszTablePostfix)
|
||||
g_stTablePostfix = "";
|
||||
else
|
||||
g_stTablePostfix = c_pszTablePostfix;
|
||||
}
|
||||
|
||||
const char * GetTablePostfix()
|
||||
{
|
||||
return g_stTablePostfix.c_str();
|
||||
}
|
||||
|
||||
void SetPlayerDBName(const char* c_pszPlayerDBName)
|
||||
{
|
||||
if (! c_pszPlayerDBName || ! *c_pszPlayerDBName)
|
||||
g_stPlayerDBName = "";
|
||||
else
|
||||
{
|
||||
g_stPlayerDBName = c_pszPlayerDBName;
|
||||
g_stPlayerDBName += ".";
|
||||
}
|
||||
}
|
||||
|
||||
const char * GetPlayerDBName()
|
||||
{
|
||||
return g_stPlayerDBName.c_str();
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
10
source-server/Srcs/Server/db/src/Main.h
Normal file
10
source-server/Srcs/Server/db/src/Main.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef __INC_MAIN_H__
|
||||
#define __INC_MAIN_H__
|
||||
|
||||
int Start();
|
||||
void End();
|
||||
const char * GetTablePostfix();
|
||||
const char * GetPlayerDBName();
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
136
source-server/Srcs/Server/db/src/Makefile
Normal file
136
source-server/Srcs/Server/db/src/Makefile
Normal file
@ -0,0 +1,136 @@
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
|
||||
DB_VERSION = $(shell cat ../../__REVISION__)
|
||||
LBITS := $(shell getconf LONG_BIT)
|
||||
|
||||
INCDIR =
|
||||
LIBDIR =
|
||||
BINDIR = ..
|
||||
OBJDIR = .obj
|
||||
$(shell if [ ! -d $(OBJDIR) ]; then mkdir $(OBJDIR); fi)
|
||||
|
||||
# LIST_OF_CONSTANTS BEGIN
|
||||
ENABLE_GCC_AUTODEPEND = 1
|
||||
ENABLE_STATIC = 0
|
||||
# LIST_OF_CONSTANTS END
|
||||
|
||||
# Depend Path File
|
||||
ifneq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
DEPFILE = Depend
|
||||
endif
|
||||
|
||||
# Project Flags
|
||||
CFLAGS = -m32 -g -Wall -O2 -pipe -fno-rtti -fno-exceptions -Wno-long-long -pthread -D_THREAD_SAFE
|
||||
CFLAGS += -Wno-deprecated-declarations -Wno-nonnull-compare -Wno-deprecated-declarations -Wno-array-bounds -Wno-address
|
||||
CFLAGS += -Wno-int-in-bool-context -Wno-format-truncation -Wno-deprecated-enum-enum-conversion
|
||||
CXXFLAGS = -std=c++20
|
||||
|
||||
# for clang
|
||||
ifneq '' '$(findstring clang++,$(CXX))'
|
||||
CFLAGS += -Wno-invalid-source-encoding -Wno-deprecated-anon-enum-enum-conversion -Wno-unknown-warning-option
|
||||
# for gcc
|
||||
else ifneq '' '$(findstring g++,$(CXX))'
|
||||
# for 32bit on 64bit
|
||||
ifeq ($(LBITS),64)
|
||||
CFLAGS += -L/usr/local/lib32/gcc12
|
||||
CFLAGS += -Wl,-rpath=/usr/local/lib32/gcc12
|
||||
else
|
||||
# for 32bit on 32bit
|
||||
CXXFLAGS += -Wl,-rpath=/usr/local/lib/gcc12
|
||||
endif
|
||||
endif
|
||||
|
||||
# MySQL
|
||||
INCDIR += -I/usr/local/include/mysql
|
||||
ifeq ($(LBITS),64)
|
||||
LIBS += ../../../Extern/lib/libmysqlclient.a -lz
|
||||
else
|
||||
LIBS += /usr/local/lib/mysql/libmysqlclient.a /usr/lib/libz.a
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_STATIC), 1)
|
||||
CFLAGS += -static
|
||||
endif
|
||||
|
||||
# Version defines
|
||||
CFLAGS += -D__USER__=\"$(USER)\" -D__HOSTNAME__=\"$(HOSTNAME)\" -D__PWD__=\"$(PWD)\" -D__DB_VERSION__=\"$(DB_VERSION)\"
|
||||
|
||||
# Boost
|
||||
INCDIR += -I../../../Extern/include/boost
|
||||
|
||||
# Project Libraries
|
||||
INCDIR += -I/usr/local/include
|
||||
INCDIR += -I../../../Extern/include
|
||||
LIBDIR += -I../../../Extern/lib
|
||||
|
||||
LIBDIR += -L../../libthecore/lib -L../../libsql -L../../libpoly -L../../libgame/lib
|
||||
LIBS += -lthecore -lsql -lpoly -lgame -lm
|
||||
|
||||
# OpenSSL
|
||||
ifeq ($(LBITS),64)
|
||||
LIBS += /usr/lib32/libcrypto.a /usr/lib32/libssl.a
|
||||
else
|
||||
LIBS += -lssl -lcrypto
|
||||
endif
|
||||
|
||||
# PROJECT_SRC_FILES BEGIN
|
||||
CPPFILE = Config.cpp NetBase.cpp Peer.cpp PeerBase.cpp Main.cpp Lock.cpp DBManager.cpp \
|
||||
Cache.cpp LoginData.cpp ClientManager.cpp ClientManagerPlayer.cpp ClientManagerLogin.cpp \
|
||||
ClientManagerBoot.cpp ClientManagerParty.cpp ClientManagerGuild.cpp GuildManager.cpp HB.cpp \
|
||||
PrivManager.cpp MoneyLog.cpp ItemAwardManager.cpp ClientManagerEventFlag.cpp Marriage.cpp \
|
||||
Monarch.cpp ItemIDRangeManager.cpp ClientManagerHorseName.cpp version.cpp \
|
||||
ProtoReader.cpp CsvReader.cpp
|
||||
# PROJECT_SRC_FILES END
|
||||
|
||||
# PROJECT_OBJ_FILES BEGIN
|
||||
CPPOBJS = $(CPPFILE:%.cpp=$(OBJDIR)/%.o)
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
CPPDEPS = $(CPPOBJS:%.o=%.d)
|
||||
endif
|
||||
# PROJECT_OBJ_FILES END
|
||||
|
||||
# Target Paths
|
||||
MAIN_TARGET = $(BINDIR)/db_r$(DB_VERSION)
|
||||
|
||||
default: $(MAIN_TARGET)
|
||||
|
||||
$(MAIN_TARGET): $(CPPOBJS)
|
||||
@echo linking $(MAIN_TARGET)
|
||||
@$(CXX) $(CFLAGS) $(CXXFLAGS) $(LIBDIR) $(CPPOBJS) $(LIBS) -o $(MAIN_TARGET)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
@echo compiling $<
|
||||
@$(CXX) $(CFLAGS) $(CXXFLAGS) $(INCDIR) -c $< -o $@
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
@$(CXX) -MM -MG -MP $(CFLAGS) $(CXXFLAGS) $(INCDIR) -c $< -o $(OBJDIR)/$*.d
|
||||
@sed -i '' -e's/$*.o:/$(OBJDIR)\/$*.o:/g' $(OBJDIR)/$*.d
|
||||
endif
|
||||
|
||||
$(OBJDIR):
|
||||
@mkdir $(OBJDIR)
|
||||
|
||||
symlink:
|
||||
@ln -fs db_r$(DB_VERSION) $(BINDIR)/db_symlink
|
||||
|
||||
strip:
|
||||
@cp $(BINDIR)/db_r$(DB_VERSION) $(BINDIR)/db_r
|
||||
@strip $(BINDIR)/db_r
|
||||
|
||||
clean:
|
||||
@rm -f $(CPPOBJS) $(BINDIR)/db_r*
|
||||
|
||||
dep:
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
@echo "Note: gcc autodepend is autodetected, so target dep skipped"
|
||||
else
|
||||
makedepend -f $(DEPFILE) $(INCDIR) -I/usr/include/c++/3.3 -I/usr/include/c++/4.2 -p$(OBJDIR)/ $(CPPFILE) 2> /dev/null > $(DEPFILE)
|
||||
endif
|
||||
|
||||
# AUTO_DEPEND_CHECK BEGIN
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
sinclude $(CPPDEPS)
|
||||
else
|
||||
sinclude $(DEPFILE)
|
||||
endif
|
||||
# AUTO_DEPEND_CHECK END
|
||||
377
source-server/Srcs/Server/db/src/Marriage.cpp
Normal file
377
source-server/Srcs/Server/db/src/Marriage.cpp
Normal file
@ -0,0 +1,377 @@
|
||||
#include "stdafx.h"
|
||||
#include "Marriage.h"
|
||||
#include "Main.h"
|
||||
#include "DBManager.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
namespace marriage
|
||||
{
|
||||
const DWORD WEDDING_LENGTH = 60 * 60; // sec
|
||||
bool operator < (const TWedding& lhs, const TWedding& rhs)
|
||||
{
|
||||
return lhs.dwTime < rhs.dwTime;
|
||||
}
|
||||
|
||||
bool operator > (const TWedding& lhs, const TWedding& rhs)
|
||||
{
|
||||
return lhs.dwTime > rhs.dwTime;
|
||||
}
|
||||
|
||||
bool operator > (const TWeddingInfo &lhs, const TWeddingInfo& rhs)
|
||||
{
|
||||
return lhs.dwTime > rhs.dwTime;
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
|
||||
CManager::CManager()
|
||||
{
|
||||
}
|
||||
|
||||
CManager::~CManager()
|
||||
{
|
||||
}
|
||||
|
||||
bool CManager::Initialize()
|
||||
{
|
||||
char szQuery[1024];
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"SELECT pid1, pid2, love_point, time, is_married, p1.name, p2.name FROM marriage, player%s as p1, player%s as p2 WHERE p1.id = pid1 AND p2.id = pid2",
|
||||
GetTablePostfix(), GetTablePostfix());
|
||||
|
||||
auto pmsg_delete(CDBManager::instance().DirectQuery("DELETE FROM marriage WHERE is_married = 0"));
|
||||
auto pmsg(CDBManager::instance().DirectQuery(szQuery));
|
||||
|
||||
SQLResult * pRes = pmsg->Get();
|
||||
sys_log(0, "MarriageList(size=%lu)", pRes->uiNumRows);
|
||||
|
||||
if (pRes->uiNumRows > 0)
|
||||
{
|
||||
for (uint uiRow = 0; uiRow != pRes->uiNumRows; ++uiRow)
|
||||
{
|
||||
MYSQL_ROW row = mysql_fetch_row(pRes->pSQLResult);
|
||||
|
||||
DWORD pid1 = 0; str_to_number(pid1, row[0]);
|
||||
DWORD pid2 = 0; str_to_number(pid2, row[1]);
|
||||
int love_point = 0; str_to_number(love_point, row[2]);
|
||||
DWORD time = 0; str_to_number(time, row[3]);
|
||||
BYTE is_married = 0; str_to_number(is_married, row[4]);
|
||||
const char* name1 = row[5];
|
||||
const char* name2 = row[6];
|
||||
|
||||
TMarriage* pMarriage = new TMarriage(pid1, pid2, love_point, time, is_married, name1, name2);
|
||||
m_Marriages.emplace(pMarriage);
|
||||
m_MarriageByPID.emplace(pid1, pMarriage);
|
||||
m_MarriageByPID.emplace(pid2, pMarriage);
|
||||
|
||||
sys_log(0, "Marriage %lu: LP:%d TM:%u ST:%d %10lu:%16s %10lu:%16s ", uiRow, love_point, time, is_married, pid1, name1, pid2, name2);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TMarriage* CManager::Get(DWORD dwPlayerID)
|
||||
{
|
||||
itertype(m_MarriageByPID) it = m_MarriageByPID.find(dwPlayerID);
|
||||
|
||||
if (it != m_MarriageByPID.end())
|
||||
return it->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Align(DWORD& rPID1, DWORD& rPID2)
|
||||
{
|
||||
if (rPID1 > rPID2)
|
||||
std::swap(rPID1, rPID2);
|
||||
}
|
||||
|
||||
void CManager::Add(DWORD dwPID1, DWORD dwPID2, const char* szName1, const char* szName2)
|
||||
{
|
||||
DWORD now = CClientManager::instance().GetCurrentTime();
|
||||
if (IsMarried(dwPID1) || IsMarried(dwPID2))
|
||||
{
|
||||
sys_err("cannot marry already married character. %d - %d", dwPID1, dwPID2);
|
||||
return;
|
||||
}
|
||||
|
||||
Align(dwPID1, dwPID2);
|
||||
|
||||
char szQuery[512];
|
||||
snprintf(szQuery, sizeof(szQuery), "INSERT INTO marriage(pid1, pid2, love_point, time) VALUES (%u, %u, 0, %u)", dwPID1, dwPID2, now);
|
||||
|
||||
auto pmsg(CDBManager::instance().DirectQuery(szQuery));
|
||||
SQLResult* res = pmsg->Get();
|
||||
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
|
||||
{
|
||||
sys_err("cannot insert marriage");
|
||||
return;
|
||||
}
|
||||
|
||||
sys_log(0, "MARRIAGE ADD %u %u", dwPID1, dwPID2);
|
||||
|
||||
TMarriage* pMarriage = new TMarriage(dwPID1, dwPID2, 0, now, 0, szName1, szName2);
|
||||
m_Marriages.emplace(pMarriage);
|
||||
m_MarriageByPID.emplace(dwPID1, pMarriage);
|
||||
m_MarriageByPID.emplace(dwPID2, pMarriage);
|
||||
|
||||
TPacketMarriageAdd p;
|
||||
p.dwPID1 = dwPID1;
|
||||
p.dwPID2 = dwPID2;
|
||||
p.tMarryTime = now;
|
||||
strlcpy(p.szName1, szName1, sizeof(p.szName1));
|
||||
strlcpy(p.szName2, szName2, sizeof(p.szName2));
|
||||
CClientManager::instance().ForwardPacket(HEADER_DG_MARRIAGE_ADD, &p, sizeof(p));
|
||||
}
|
||||
|
||||
void CManager::Update(DWORD dwPID1, DWORD dwPID2, INT iLovePoint, BYTE byMarried)
|
||||
{
|
||||
TMarriage* pMarriage = Get(dwPID1);
|
||||
if (!pMarriage || pMarriage->GetOther(dwPID1) != dwPID2)
|
||||
{
|
||||
sys_err("not under marriage : %u %u", dwPID1, dwPID2);
|
||||
return;
|
||||
}
|
||||
|
||||
Align(dwPID1, dwPID2);
|
||||
|
||||
char szQuery[512];
|
||||
snprintf(szQuery, sizeof(szQuery), "UPDATE marriage SET love_point = %d, is_married = %d WHERE pid1 = %u AND pid2 = %u",
|
||||
iLovePoint, byMarried, pMarriage->pid1, pMarriage->pid2);
|
||||
|
||||
auto pmsg(CDBManager::instance().DirectQuery(szQuery));
|
||||
SQLResult* res = pmsg->Get();
|
||||
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
|
||||
{
|
||||
sys_log(0, "cannot update marriage : PID:%u %u", dwPID1, dwPID2); // @warme012
|
||||
return;
|
||||
}
|
||||
|
||||
sys_log(0, "MARRIAGE UPDATE PID:%u %u LP:%u ST:%d", dwPID1, dwPID2, iLovePoint, byMarried);
|
||||
pMarriage->love_point = iLovePoint;
|
||||
pMarriage->is_married = byMarried;
|
||||
|
||||
TPacketMarriageUpdate p;
|
||||
p.dwPID1 = dwPID1;
|
||||
p.dwPID2 = dwPID2;
|
||||
p.iLovePoint = pMarriage->love_point;
|
||||
p.byMarried = pMarriage->is_married;
|
||||
CClientManager::instance().ForwardPacket(HEADER_DG_MARRIAGE_UPDATE, &p, sizeof(p));
|
||||
}
|
||||
|
||||
void CManager::Remove(DWORD dwPID1, DWORD dwPID2)
|
||||
{
|
||||
TMarriage* pMarriage = Get(dwPID1);
|
||||
|
||||
if (pMarriage)
|
||||
{
|
||||
sys_log(0, "Break Marriage pid1 %d pid2 %d Other %d", dwPID1, dwPID2, pMarriage->GetOther(dwPID1));
|
||||
}
|
||||
if (!pMarriage || pMarriage->GetOther(dwPID1) != dwPID2)
|
||||
{
|
||||
itertype(m_MarriageByPID) it = m_MarriageByPID.begin();
|
||||
|
||||
for (; it != m_MarriageByPID.end(); ++it)
|
||||
{
|
||||
sys_log(0, "Marriage List pid1 %d pid2 %d", it->second->pid1, it->second->pid2);
|
||||
}
|
||||
sys_err("not under marriage : PID:%u %u", dwPID1, dwPID2);
|
||||
return;
|
||||
}
|
||||
|
||||
Align(dwPID1, dwPID2);
|
||||
|
||||
char szQuery[512];
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM marriage WHERE pid1 = %u AND pid2 = %u", dwPID1, dwPID2);
|
||||
|
||||
auto pmsg(CDBManager::instance().DirectQuery(szQuery));
|
||||
SQLResult* res = pmsg->Get();
|
||||
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
|
||||
{
|
||||
sys_err("cannot delete marriage : PID:%u %u", dwPID1, dwPID2);
|
||||
return;
|
||||
}
|
||||
|
||||
sys_log(0, "MARRIAGE REMOVE PID:%u %u", dwPID1, dwPID2);
|
||||
|
||||
m_Marriages.erase(pMarriage);
|
||||
m_MarriageByPID.erase(dwPID1);
|
||||
m_MarriageByPID.erase(dwPID2);
|
||||
|
||||
TPacketMarriageRemove p;
|
||||
p.dwPID1 = dwPID1;
|
||||
p.dwPID2 = dwPID2;
|
||||
CClientManager::instance().ForwardPacket(HEADER_DG_MARRIAGE_REMOVE, &p, sizeof(p));
|
||||
|
||||
delete pMarriage;
|
||||
}
|
||||
|
||||
void CManager::EngageToMarriage(DWORD dwPID1, DWORD dwPID2)
|
||||
{
|
||||
TMarriage* pMarriage = Get(dwPID1);
|
||||
if (!pMarriage || pMarriage->GetOther(dwPID1) != dwPID2)
|
||||
{
|
||||
sys_err("not under marriage : PID:%u %u", dwPID1, dwPID2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pMarriage->is_married)
|
||||
{
|
||||
sys_err("already married, cannot change engage to marry : PID:%u %u", dwPID1, dwPID2);
|
||||
return;
|
||||
}
|
||||
|
||||
Align(dwPID1, dwPID2);
|
||||
|
||||
char szQuery[512];
|
||||
snprintf(szQuery, sizeof(szQuery), "UPDATE marriage SET is_married = 1 WHERE pid1 = %u AND pid2 = %u",
|
||||
pMarriage->pid1, pMarriage->pid2);
|
||||
|
||||
auto pmsg(CDBManager::instance().DirectQuery(szQuery));
|
||||
SQLResult* res = pmsg->Get();
|
||||
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
|
||||
{
|
||||
sys_err("cannot change engage to marriage : PID:%u %u", dwPID1, dwPID2);
|
||||
return;
|
||||
}
|
||||
|
||||
sys_log(0, "MARRIAGE ENGAGE->MARRIAGE PID:%u %u", dwPID1, dwPID2);
|
||||
pMarriage->is_married = 1;
|
||||
|
||||
TPacketMarriageUpdate p;
|
||||
p.dwPID1 = dwPID1;
|
||||
p.dwPID2 = dwPID2;
|
||||
p.iLovePoint = pMarriage->love_point;
|
||||
p.byMarried = pMarriage->is_married;
|
||||
CClientManager::instance().ForwardPacket(HEADER_DG_MARRIAGE_UPDATE, &p, sizeof(p));
|
||||
}
|
||||
|
||||
void CManager::OnSetup(CPeer* peer)
|
||||
{
|
||||
for (itertype(m_Marriages) it = m_Marriages.begin(); it != m_Marriages.end(); ++it)
|
||||
{
|
||||
TMarriage* pMarriage = *it;
|
||||
|
||||
{
|
||||
TPacketMarriageAdd p;
|
||||
p.dwPID1 = pMarriage->pid1;
|
||||
p.dwPID2 = pMarriage->pid2;
|
||||
p.tMarryTime = pMarriage->time;
|
||||
strlcpy(p.szName1, pMarriage->name1.c_str(), sizeof(p.szName1));
|
||||
strlcpy(p.szName2, pMarriage->name2.c_str(), sizeof(p.szName2));
|
||||
peer->EncodeHeader(HEADER_DG_MARRIAGE_ADD, 0, sizeof(p));
|
||||
peer->Encode(&p, sizeof(p));
|
||||
}
|
||||
|
||||
{
|
||||
TPacketMarriageUpdate p;
|
||||
p.dwPID1 = pMarriage->pid1;
|
||||
p.dwPID2 = pMarriage->pid2;
|
||||
p.iLovePoint = pMarriage->love_point;
|
||||
p.byMarried = pMarriage->is_married;
|
||||
peer->EncodeHeader(HEADER_DG_MARRIAGE_UPDATE, 0, sizeof(p));
|
||||
peer->Encode(&p, sizeof(p));
|
||||
}
|
||||
}
|
||||
|
||||
for (itertype(m_mapRunningWedding) it = m_mapRunningWedding.begin(); it != m_mapRunningWedding.end(); ++it)
|
||||
{
|
||||
const TWedding& t = it->second;
|
||||
|
||||
TPacketWeddingReady p;
|
||||
p.dwPID1 = t.dwPID1;
|
||||
p.dwPID2 = t.dwPID2;
|
||||
p.dwMapIndex = t.dwMapIndex;
|
||||
|
||||
peer->EncodeHeader(HEADER_DG_WEDDING_READY, 0, sizeof(p));
|
||||
peer->Encode(&p, sizeof(p));
|
||||
|
||||
TPacketWeddingStart p2;
|
||||
p2.dwPID1 = t.dwPID1;
|
||||
p2.dwPID2 = t.dwPID2;
|
||||
|
||||
peer->EncodeHeader(HEADER_DG_WEDDING_START, 0, sizeof(p2));
|
||||
peer->Encode(&p2, sizeof(p2));
|
||||
}
|
||||
}
|
||||
|
||||
void CManager::ReadyWedding(DWORD dwMapIndex, DWORD dwPID1, DWORD dwPID2)
|
||||
{
|
||||
DWORD dwStartTime = CClientManager::instance().GetCurrentTime();
|
||||
m_pqWeddingStart.push(TWedding(dwStartTime + 5, dwMapIndex, dwPID1, dwPID2));
|
||||
}
|
||||
|
||||
void CManager::EndWedding(DWORD dwPID1, DWORD dwPID2)
|
||||
{
|
||||
itertype(m_mapRunningWedding) it = m_mapRunningWedding.find(make_pair(dwPID1, dwPID2));
|
||||
if (it == m_mapRunningWedding.end())
|
||||
{
|
||||
sys_err("try to end wedding %u %u", dwPID1, dwPID2);
|
||||
return;
|
||||
}
|
||||
|
||||
TWedding& w = it->second;
|
||||
|
||||
TPacketWeddingEnd p;
|
||||
p.dwPID1 = w.dwPID1;
|
||||
p.dwPID2 = w.dwPID2;
|
||||
CClientManager::instance().ForwardPacket(HEADER_DG_WEDDING_END, &p, sizeof(p));
|
||||
m_mapRunningWedding.erase(it);
|
||||
}
|
||||
|
||||
void CManager::Update()
|
||||
{
|
||||
DWORD now = CClientManager::instance().GetCurrentTime();
|
||||
|
||||
if (!m_pqWeddingEnd.empty())
|
||||
{
|
||||
while (!m_pqWeddingEnd.empty() && m_pqWeddingEnd.top().dwTime <= now)
|
||||
{
|
||||
TWeddingInfo wi = m_pqWeddingEnd.top();
|
||||
m_pqWeddingEnd.pop();
|
||||
|
||||
itertype(m_mapRunningWedding) it = m_mapRunningWedding.find(make_pair(wi.dwPID1, wi.dwPID2));
|
||||
if (it == m_mapRunningWedding.end())
|
||||
continue;
|
||||
|
||||
TWedding& w = it->second;
|
||||
|
||||
TPacketWeddingEnd p;
|
||||
p.dwPID1 = w.dwPID1;
|
||||
p.dwPID2 = w.dwPID2;
|
||||
CClientManager::instance().ForwardPacket(HEADER_DG_WEDDING_END, &p, sizeof(p));
|
||||
m_mapRunningWedding.erase(it);
|
||||
|
||||
itertype(m_MarriageByPID) it_marriage = m_MarriageByPID.find(w.dwPID1);
|
||||
|
||||
if (it_marriage != m_MarriageByPID.end())
|
||||
{
|
||||
TMarriage* pMarriage = it_marriage->second;
|
||||
if (!pMarriage->is_married)
|
||||
{
|
||||
Remove(pMarriage->pid1, pMarriage->pid2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!m_pqWeddingStart.empty())
|
||||
{
|
||||
while (!m_pqWeddingStart.empty() && m_pqWeddingStart.top().dwTime <= now)
|
||||
{
|
||||
TWedding w = m_pqWeddingStart.top();
|
||||
m_pqWeddingStart.pop();
|
||||
|
||||
TPacketWeddingStart p;
|
||||
p.dwPID1 = w.dwPID1;
|
||||
p.dwPID2 = w.dwPID2;
|
||||
CClientManager::instance().ForwardPacket(HEADER_DG_WEDDING_START, &p, sizeof(p));
|
||||
|
||||
w.dwTime += WEDDING_LENGTH;
|
||||
m_pqWeddingEnd.push(TWeddingInfo(w.dwTime, w.dwPID1, w.dwPID2));
|
||||
m_mapRunningWedding.emplace(make_pair(w.dwPID1, w.dwPID2), w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
114
source-server/Srcs/Server/db/src/Marriage.h
Normal file
114
source-server/Srcs/Server/db/src/Marriage.h
Normal file
@ -0,0 +1,114 @@
|
||||
// vim: ts=4 sw=4
|
||||
#ifndef __MARRIAGE_H
|
||||
#define __MARRIAGE_H
|
||||
|
||||
#include <set>
|
||||
#include <queue>
|
||||
#include <deque>
|
||||
|
||||
#include "Peer.h"
|
||||
|
||||
namespace marriage
|
||||
{
|
||||
struct TWeddingInfo
|
||||
{
|
||||
DWORD dwTime;
|
||||
DWORD dwPID1;
|
||||
DWORD dwPID2;
|
||||
TWeddingInfo(DWORD time, DWORD pid1, DWORD pid2)
|
||||
: dwTime(time),
|
||||
dwPID1(pid1),
|
||||
dwPID2(pid2)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TWedding
|
||||
{
|
||||
DWORD dwTime;
|
||||
DWORD dwMapIndex;
|
||||
DWORD dwPID1;
|
||||
DWORD dwPID2;
|
||||
|
||||
TWedding(DWORD time, DWORD dwMapIndex, DWORD pid1, DWORD pid2)
|
||||
: dwTime(time),
|
||||
dwMapIndex(dwMapIndex),
|
||||
dwPID1(pid1),
|
||||
dwPID2(pid2)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
extern bool operator < (const TWedding& lhs, const TWedding& rhs);
|
||||
extern bool operator > (const TWedding& lhs, const TWedding& rhs);
|
||||
extern bool operator > (const TWeddingInfo& lhs, const TWeddingInfo& rhs);
|
||||
|
||||
struct TMarriage
|
||||
{
|
||||
DWORD pid1;
|
||||
DWORD pid2;
|
||||
int love_point;
|
||||
DWORD time;
|
||||
BYTE is_married;
|
||||
std::string name1;
|
||||
std::string name2;
|
||||
|
||||
TMarriage(DWORD _pid1, DWORD _pid2, int _love_point, DWORD _time, BYTE _is_married, const char* name1, const char* name2)
|
||||
: pid1(_pid1), pid2(_pid2), love_point(_love_point), time(_time), is_married(_is_married), name1(name1), name2(name2)
|
||||
{
|
||||
}
|
||||
|
||||
DWORD GetOther(DWORD PID)
|
||||
{
|
||||
if (pid1 == PID)
|
||||
return pid2;
|
||||
|
||||
if (pid2 == PID)
|
||||
return pid1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CManager : public singleton<CManager>
|
||||
{
|
||||
public:
|
||||
CManager();
|
||||
virtual ~CManager();
|
||||
|
||||
bool Initialize();
|
||||
|
||||
TMarriage* Get(DWORD dwPlayerID);
|
||||
bool IsMarried(DWORD dwPlayerID)
|
||||
{
|
||||
return Get(dwPlayerID) != NULL;
|
||||
}
|
||||
|
||||
//void Reserve(DWORD dwPID1, DWORD dwPID2);
|
||||
void Add(DWORD dwPID1, DWORD dwPID2, const char* szName1, const char* szName2);
|
||||
void Remove(DWORD dwPID1, DWORD dwPID2);
|
||||
void Update(DWORD dwPID1, DWORD dwPID2, INT iLovePoint, BYTE byMarried);
|
||||
|
||||
void EngageToMarriage(DWORD dwPID1, DWORD dwPID2);
|
||||
|
||||
void ReadyWedding(DWORD dwMapIndex, DWORD dwPID1, DWORD dwPID2);
|
||||
void EndWedding(DWORD dwPID1, DWORD dwPID2);
|
||||
|
||||
void OnSetup(CPeer* peer);
|
||||
|
||||
void Update();
|
||||
|
||||
private:
|
||||
std::set<TMarriage *> m_Marriages;
|
||||
std::map<DWORD, TMarriage *> m_MarriageByPID;
|
||||
|
||||
std::priority_queue<TWedding, std::vector<TWedding>, std::greater<TWedding> > m_pqWeddingStart;
|
||||
|
||||
std::priority_queue<TWeddingInfo, std::vector<TWeddingInfo>, std::greater<TWeddingInfo> > m_pqWeddingEnd;
|
||||
|
||||
std::map<std::pair<DWORD, DWORD>, TWedding> m_mapRunningWedding;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
291
source-server/Srcs/Server/db/src/Monarch.cpp
Normal file
291
source-server/Srcs/Server/db/src/Monarch.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
#include "stdafx.h"
|
||||
#include "Monarch.h"
|
||||
#include "../../common/utils.h"
|
||||
#include "Main.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
extern int g_test_server;
|
||||
|
||||
CMonarch::CMonarch()
|
||||
{
|
||||
memset(&m_MonarchInfo, 0, sizeof(MonarchInfo));
|
||||
}
|
||||
|
||||
CMonarch::~CMonarch()
|
||||
{
|
||||
}
|
||||
|
||||
bool CMonarch::VoteMonarch(DWORD pid, DWORD selectdpid)
|
||||
{
|
||||
MAP_MONARCHELECTION::iterator it = m_map_MonarchElection.find(pid);
|
||||
|
||||
if (it == m_map_MonarchElection.end())
|
||||
{
|
||||
MonarchElectionInfo * p = new MonarchElectionInfo;
|
||||
p->pid = pid;
|
||||
p->selectedpid= selectdpid;
|
||||
m_map_MonarchElection.emplace(pid, p);
|
||||
|
||||
char szQuery[256];
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"INSERT INTO monarch_election(pid, selectedpid, electiondata) VALUES(%d, %d, now())", pid, selectdpid);
|
||||
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CMonarch::ElectMonarch()
|
||||
{
|
||||
int size = GetVecMonarchCandidacy().size();
|
||||
|
||||
int * s = new int[size];
|
||||
|
||||
itertype(m_map_MonarchElection) it = m_map_MonarchElection.begin();
|
||||
|
||||
int idx = 0;
|
||||
|
||||
for (; it != m_map_MonarchElection.end(); ++it)
|
||||
{
|
||||
if ((idx = GetCandidacyIndex(it->second->pid)) < 0)
|
||||
continue;
|
||||
|
||||
++s[idx];
|
||||
|
||||
if (g_test_server)
|
||||
sys_log (0, "[MONARCH_VOTE] pid(%d) come to vote candidacy pid(%d)", it->second->pid, m_vec_MonarchCandidacy[idx].pid);
|
||||
}
|
||||
|
||||
delete [] s;
|
||||
}
|
||||
|
||||
bool CMonarch::IsCandidacy(DWORD pid)
|
||||
{
|
||||
VEC_MONARCHCANDIDACY::iterator it = m_vec_MonarchCandidacy.begin();
|
||||
|
||||
for (; it != m_vec_MonarchCandidacy.end(); ++it)
|
||||
{
|
||||
if (it->pid == pid)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMonarch::AddCandidacy(DWORD pid, const char * name)
|
||||
{
|
||||
if (IsCandidacy(pid) == false)
|
||||
return false;
|
||||
|
||||
MonarchCandidacy info;
|
||||
|
||||
info.pid = pid;
|
||||
strlcpy(info.name, name, sizeof(info.name));
|
||||
m_vec_MonarchCandidacy.emplace_back(info);
|
||||
|
||||
char szQuery[256];
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"INSERT INTO monarch_candidacy(pid, date) VALUES(%d, now())", pid);
|
||||
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMonarch::DelCandidacy(const char * name)
|
||||
{
|
||||
itertype(m_vec_MonarchCandidacy) it = m_vec_MonarchCandidacy.begin();
|
||||
for (; it != m_vec_MonarchCandidacy.end(); ++it)
|
||||
{
|
||||
if (0 == strncmp(it->name, name, sizeof(it->name)))
|
||||
{
|
||||
char szQuery[256];
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"DELETE FROM monarch_candidacy WHERE pid=%d ", it->pid);
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
m_vec_MonarchCandidacy.erase (it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMonarch::IsMonarch(int Empire, DWORD pid)
|
||||
{
|
||||
if (m_MonarchInfo.pid[Empire] != pid)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMonarch::AddMoney(int Empire, int64_t Money)
|
||||
{
|
||||
if (m_MonarchInfo.money[Empire] + Money > 2000000000)
|
||||
return true;
|
||||
|
||||
m_MonarchInfo.money[Empire] += Money;
|
||||
|
||||
int64_t Money64 = m_MonarchInfo.money[Empire];
|
||||
|
||||
char szQuery[1024];
|
||||
snprintf(szQuery, sizeof(szQuery), "UPDATE monarch SET money=%lld WHERE empire=%d", Money64, Empire);
|
||||
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMonarch::DecMoney(int Empire, int64_t Money)
|
||||
{
|
||||
if (m_MonarchInfo.money[Empire] - Money < 0)
|
||||
return false;
|
||||
m_MonarchInfo.money[Empire] -= Money;
|
||||
|
||||
int64_t Money64 = m_MonarchInfo.money[Empire];
|
||||
|
||||
char szQuery[1024];
|
||||
snprintf(szQuery, sizeof(szQuery), "UPDATE monarch SET money=%lld WHERE empire=%d", Money64, Empire);
|
||||
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMonarch::TakeMoney(int Empire, DWORD pid, int64_t Money)
|
||||
{
|
||||
if (IsMonarch(Empire, pid) == false)
|
||||
return false;
|
||||
|
||||
if (m_MonarchInfo.money[Empire] < Money)
|
||||
return false;
|
||||
|
||||
m_MonarchInfo.money[Empire] -= Money;
|
||||
|
||||
char szQuery[1024];
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"UPDATE monarch SET money=%lld WHERE empire=%d", m_MonarchInfo.money[Empire], Empire);
|
||||
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
|
||||
if (g_test_server)
|
||||
sys_log(0, "[MONARCH] Take money empire(%d) money(%lld)", Empire, m_MonarchInfo.money[Empire]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMonarch::LoadMonarch()
|
||||
{
|
||||
MonarchInfo * p = &m_MonarchInfo;
|
||||
char szQuery[256];
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT a.empire, a.pid, b.name, a.money, a.windate FROM monarch a, player%s b WHERE a.pid=b.id", GetTablePostfix());
|
||||
auto pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER);
|
||||
|
||||
if (pMsg->Get()->uiNumRows == 0)
|
||||
return false;
|
||||
|
||||
MYSQL_ROW row;
|
||||
while ((row = mysql_fetch_row(pMsg->Get()->pSQLResult)) != nullptr)
|
||||
{
|
||||
int idx = 0;
|
||||
int Empire = 0; str_to_number(Empire, row[idx++]);
|
||||
|
||||
str_to_number(p->pid[Empire], row[idx++]);
|
||||
strlcpy(p->name[Empire], row[idx++], sizeof(p->name[Empire]));
|
||||
|
||||
str_to_number(p->money[Empire], row[idx++]);
|
||||
strlcpy(p->date[Empire], row[idx++], sizeof(p->date[Empire]));
|
||||
|
||||
if (g_test_server)
|
||||
sys_log(0, "[LOAD_MONARCH] Empire %d pid %d money %lld windate %s", Empire, p->pid[Empire], p->money[Empire], p->date[Empire]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMonarch::SetMonarch(const char * name)
|
||||
{
|
||||
MonarchInfo * p = &m_MonarchInfo;
|
||||
char szQuery[256];
|
||||
snprintf(szQuery, sizeof(szQuery), "SELECT player_index.empire, player.id, player.name, player.gold FROM player JOIN player_index ON player_index.id = player.account_id WHERE player.name = '%s'", name);
|
||||
|
||||
auto pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER);
|
||||
if (pMsg->Get()->uiNumRows == 0)
|
||||
return false;
|
||||
|
||||
MYSQL_ROW row;
|
||||
int Empire = 0;
|
||||
while ((row = mysql_fetch_row(pMsg->Get()->pSQLResult)) != nullptr)
|
||||
{
|
||||
int idx = 0;
|
||||
str_to_number(Empire, row[idx++]);
|
||||
|
||||
str_to_number(p->pid[Empire], row[idx++]);
|
||||
strlcpy(p->name[Empire], row[idx++], sizeof(p->name[Empire]));
|
||||
p->money[Empire] = atoll(row[idx++]);
|
||||
|
||||
if (g_test_server)
|
||||
sys_log(0, "[Set_MONARCH] Empire %d pid %d money %lld windate %s", Empire, p->pid[Empire], p->money[Empire], p->date[Empire]);
|
||||
}
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"REPLACE INTO monarch (empire, name, windate, money) VALUES(%d, %d, now(), %lld)", Empire, p->pid[Empire], p->money[Empire]);
|
||||
|
||||
CDBManager::instance().AsyncQuery(szQuery, SQL_PLAYER);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMonarch::DelMonarch(int Empire)
|
||||
{
|
||||
char szQuery[256];
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM monarch WHERE empire=%d", Empire);
|
||||
|
||||
auto pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER);
|
||||
if (pMsg->Get()->uiNumRows == 0)
|
||||
return false;
|
||||
|
||||
memset(m_MonarchInfo.name[Empire], 0, sizeof(m_MonarchInfo.name[Empire]));
|
||||
m_MonarchInfo.money[Empire] = 0;
|
||||
m_MonarchInfo.pid[Empire] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMonarch::DelMonarch(const char * name)
|
||||
{
|
||||
for (int n = 1; n < 4; ++n)
|
||||
{
|
||||
if (0 == strncmp(m_MonarchInfo.name[n], name, sizeof(m_MonarchInfo.name[n])))
|
||||
{
|
||||
char szQuery[256];
|
||||
|
||||
int Empire = n;
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM monarch WHERE empire=%d", Empire);
|
||||
|
||||
auto pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER);
|
||||
if (pMsg->Get()->uiNumRows == 0)
|
||||
{
|
||||
sys_err(" DirectQuery failed(%s)", szQuery);
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(m_MonarchInfo.name[Empire], 0, 32);
|
||||
m_MonarchInfo.money[Empire] = 0;
|
||||
m_MonarchInfo.pid[Empire] = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int CMonarch::GetCandidacyIndex(DWORD pid)
|
||||
{
|
||||
itertype(m_vec_MonarchCandidacy) it = m_vec_MonarchCandidacy.begin();
|
||||
|
||||
for (int n = 0; it != m_vec_MonarchCandidacy.end(); ++it, ++n)
|
||||
{
|
||||
if (it->pid == pid)
|
||||
return n;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
71
source-server/Srcs/Server/db/src/Monarch.h
Normal file
71
source-server/Srcs/Server/db/src/Monarch.h
Normal file
@ -0,0 +1,71 @@
|
||||
// vim: ts=4 sw=4
|
||||
#ifndef METIN2_MONARCH_H
|
||||
#define METIN2_MONARCH_H
|
||||
|
||||
#include "../../libthecore/include/stdafx.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "../../common/singleton.h"
|
||||
#include "../../common/tables.h"
|
||||
|
||||
class CMonarch : public singleton<CMonarch>
|
||||
{
|
||||
public:
|
||||
typedef std::map<DWORD, MonarchElectionInfo*> MAP_MONARCHELECTION;
|
||||
typedef std::vector<MonarchCandidacy> VEC_MONARCHCANDIDACY;
|
||||
|
||||
CMonarch();
|
||||
virtual ~CMonarch();
|
||||
|
||||
bool VoteMonarch(DWORD pid, DWORD selectedpid);
|
||||
void ElectMonarch();
|
||||
|
||||
bool IsCandidacy(DWORD pid);
|
||||
bool AddCandidacy(DWORD pid, const char * name);
|
||||
bool DelCandidacy(const char * name);
|
||||
|
||||
bool LoadMonarch();
|
||||
bool SetMonarch(const char * name);
|
||||
bool DelMonarch(int Empire);
|
||||
bool DelMonarch(const char * name);
|
||||
|
||||
bool IsMonarch(int Empire, DWORD pid);
|
||||
bool AddMoney(int Empire, int64_t Money);
|
||||
bool DecMoney(int Empire, int64_t Money);
|
||||
bool TakeMoney(int Empire, DWORD pid, int64_t Money);
|
||||
|
||||
TMonarchInfo* GetMonarch()
|
||||
{
|
||||
return &m_MonarchInfo;
|
||||
}
|
||||
|
||||
VEC_MONARCHCANDIDACY& GetVecMonarchCandidacy()
|
||||
{
|
||||
return m_vec_MonarchCandidacy;
|
||||
}
|
||||
|
||||
size_t MonarchCandidacySize()
|
||||
{
|
||||
return m_vec_MonarchCandidacy.size();
|
||||
}
|
||||
|
||||
private:
|
||||
int GetCandidacyIndex(DWORD pid);
|
||||
|
||||
MAP_MONARCHELECTION m_map_MonarchElection;
|
||||
VEC_MONARCHCANDIDACY m_vec_MonarchCandidacy;
|
||||
TMonarchInfo m_MonarchInfo;
|
||||
|
||||
MonarchElectionInfo* GetMonarchElection(DWORD pid)
|
||||
{
|
||||
MAP_MONARCHELECTION::iterator it = m_map_MonarchElection.find(pid);
|
||||
|
||||
if (it != m_map_MonarchElection.end())
|
||||
return it->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
58
source-server/Srcs/Server/db/src/MoneyLog.cpp
Normal file
58
source-server/Srcs/Server/db/src/MoneyLog.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "stdafx.h"
|
||||
#include "MoneyLog.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Peer.h"
|
||||
|
||||
CMoneyLog::CMoneyLog()
|
||||
{
|
||||
}
|
||||
|
||||
CMoneyLog::~CMoneyLog()
|
||||
{
|
||||
}
|
||||
|
||||
void CMoneyLog::Save()
|
||||
{
|
||||
CPeer* peer = CClientManager::instance().GetAnyPeer();
|
||||
if (!peer)
|
||||
return;
|
||||
for (BYTE bType = 0; bType < MONEY_LOG_TYPE_MAX_NUM; bType ++)
|
||||
{
|
||||
typeof(m_MoneyLogContainer[bType].begin()) it;
|
||||
for (it = m_MoneyLogContainer[bType].begin(); it != m_MoneyLogContainer[bType].end(); ++it)
|
||||
{
|
||||
//bType;
|
||||
TPacketMoneyLog p;
|
||||
p.type = bType;
|
||||
p.vnum = it->first;
|
||||
p.gold = it->second;
|
||||
peer->EncodeHeader(HEADER_DG_MONEY_LOG, 0, sizeof(p));
|
||||
peer->Encode(&p, sizeof(p));
|
||||
}
|
||||
m_MoneyLogContainer[bType].clear();
|
||||
}
|
||||
/*
|
||||
CPeer* peer = GetPeer();
|
||||
|
||||
peer->
|
||||
|
||||
for (BYTE bType = 0; bType < MONEY_LOG_TYPE_MAX_NUM; bType++)
|
||||
{
|
||||
//"INSERT INTO money_log%s VALUES('%s', %d, %d, %d)", CClientManager::instance().GetTablePostfix(),
|
||||
typeof(m_MoneyLogContainer[bType].begin()) it;
|
||||
for (it = m_MoneyLogContainer[bType].begin(); it != m_MoneyLogContainer[bType].end(); ++it)
|
||||
{
|
||||
typeof(it->second.begin())
|
||||
}
|
||||
}
|
||||
|
||||
for (BYTE bType = 0; bType < MONEY_LOG_TYPE_MAX_NUM; bType++)
|
||||
m_MoneyLogContainer[bType].clear()
|
||||
*/
|
||||
}
|
||||
|
||||
void CMoneyLog::AddLog(BYTE bType, DWORD dwVnum, int iGold)
|
||||
{
|
||||
m_MoneyLogContainer[bType][dwVnum] += iGold;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
21
source-server/Srcs/Server/db/src/MoneyLog.h
Normal file
21
source-server/Srcs/Server/db/src/MoneyLog.h
Normal file
@ -0,0 +1,21 @@
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_MONEY_LOG
|
||||
#define __INC_MONEY_LOG
|
||||
|
||||
#include <map>
|
||||
|
||||
class CMoneyLog : public singleton<CMoneyLog>
|
||||
{
|
||||
public:
|
||||
CMoneyLog();
|
||||
virtual ~CMoneyLog();
|
||||
|
||||
void Save();
|
||||
void AddLog(BYTE bType, DWORD dwVnum, int iGold);
|
||||
|
||||
private:
|
||||
std::map<DWORD, int> m_MoneyLogContainer[MONEY_LOG_TYPE_MAX_NUM];
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
55
source-server/Srcs/Server/db/src/NetBase.cpp
Normal file
55
source-server/Srcs/Server/db/src/NetBase.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "stdafx.h"
|
||||
#include "NetBase.h"
|
||||
#include "Config.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
LPFDWATCH CNetBase::m_fdWatcher = NULL;
|
||||
|
||||
CNetBase::CNetBase()
|
||||
{
|
||||
}
|
||||
|
||||
CNetBase::~CNetBase()
|
||||
{
|
||||
}
|
||||
|
||||
CNetPoller::CNetPoller()
|
||||
{
|
||||
}
|
||||
|
||||
CNetPoller::~CNetPoller()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool CNetPoller::Create()
|
||||
{
|
||||
sys_log(1, "NetPoller::Create()");
|
||||
|
||||
if (m_fdWatcher)
|
||||
return true;
|
||||
|
||||
m_fdWatcher = fdwatch_new(512);
|
||||
|
||||
if (!m_fdWatcher)
|
||||
{
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNetPoller::Destroy()
|
||||
{
|
||||
sys_log(1, "NetPoller::Destroy()");
|
||||
|
||||
if (m_fdWatcher)
|
||||
{
|
||||
fdwatch_delete(m_fdWatcher);
|
||||
m_fdWatcher = NULL;
|
||||
}
|
||||
|
||||
thecore_destroy();
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
26
source-server/Srcs/Server/db/src/NetBase.h
Normal file
26
source-server/Srcs/Server/db/src/NetBase.h
Normal file
@ -0,0 +1,26 @@
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_NETWORKBASE_H__
|
||||
#define __INC_NETWORKBASE_H__
|
||||
|
||||
class CNetBase
|
||||
{
|
||||
public:
|
||||
CNetBase();
|
||||
virtual ~CNetBase();
|
||||
|
||||
protected:
|
||||
static LPFDWATCH m_fdWatcher;
|
||||
};
|
||||
|
||||
class CNetPoller : public CNetBase, public singleton<CNetPoller>
|
||||
{
|
||||
public:
|
||||
CNetPoller();
|
||||
virtual ~CNetPoller();
|
||||
|
||||
bool Create();
|
||||
void Destroy();
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
196
source-server/Srcs/Server/db/src/Peer.cpp
Normal file
196
source-server/Srcs/Server/db/src/Peer.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
#include "stdafx.h"
|
||||
#include "Peer.h"
|
||||
#include "ItemIDRangeManager.h"
|
||||
|
||||
CPeer::CPeer()
|
||||
{
|
||||
m_state = 0;
|
||||
m_bChannel = 0;
|
||||
m_dwHandle = 0;
|
||||
m_dwUserCount = 0;
|
||||
m_wListenPort = 0;
|
||||
m_wP2PPort = 0;
|
||||
|
||||
memset(m_alMaps, 0, sizeof(m_alMaps));
|
||||
|
||||
m_itemRange.dwMin = m_itemRange.dwMax = m_itemRange.dwUsableItemIDMin = 0;
|
||||
m_itemSpareRange.dwMin = m_itemSpareRange.dwMax = m_itemSpareRange.dwUsableItemIDMin = 0;
|
||||
}
|
||||
|
||||
CPeer::~CPeer()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void CPeer::OnAccept()
|
||||
{
|
||||
m_state = STATE_PLAYING;
|
||||
|
||||
static DWORD current_handle = 0;
|
||||
m_dwHandle = ++current_handle;
|
||||
|
||||
sys_log(0, "Connection accepted. (host: %s handle: %u fd: %d)", m_host, m_dwHandle, m_fd);
|
||||
}
|
||||
|
||||
void CPeer::OnConnect()
|
||||
{
|
||||
sys_log(0, "Connection established. (host: %s handle: %u fd: %d)", m_host, m_dwHandle, m_fd);
|
||||
m_state = STATE_PLAYING;
|
||||
}
|
||||
|
||||
void CPeer::OnClose()
|
||||
{
|
||||
m_state = STATE_CLOSE;
|
||||
|
||||
sys_log(0, "Connection closed. (host: %s)", m_host);
|
||||
sys_log(0, "ItemIDRange: returned. %u ~ %u", m_itemRange.dwMin, m_itemRange.dwMax);
|
||||
|
||||
CItemIDRangeManager::instance().UpdateRange(m_itemRange.dwMin, m_itemRange.dwMax);
|
||||
|
||||
m_itemRange.dwMin = 0;
|
||||
m_itemRange.dwMax = 0;
|
||||
m_itemRange.dwUsableItemIDMin = 0;
|
||||
}
|
||||
|
||||
DWORD CPeer::GetHandle()
|
||||
{
|
||||
return m_dwHandle;
|
||||
}
|
||||
|
||||
DWORD CPeer::GetUserCount()
|
||||
{
|
||||
return m_dwUserCount;
|
||||
}
|
||||
|
||||
void CPeer::SetUserCount(DWORD dwCount)
|
||||
{
|
||||
m_dwUserCount = dwCount;
|
||||
}
|
||||
|
||||
bool CPeer::PeekPacket(int & iBytesProceed, BYTE & header, DWORD & dwHandle, DWORD & dwLength, const char ** data)
|
||||
{
|
||||
if (GetRecvLength() < iBytesProceed + 9)
|
||||
return false;
|
||||
|
||||
const char * buf = (const char *) GetRecvBuffer();
|
||||
buf += iBytesProceed;
|
||||
|
||||
header = *(buf++);
|
||||
|
||||
dwHandle = *((DWORD *) buf);
|
||||
buf += sizeof(DWORD);
|
||||
|
||||
dwLength = *((DWORD *) buf);
|
||||
buf += sizeof(DWORD);
|
||||
|
||||
//sys_log(0, "%d header %d handle %u length %u", GetRecvLength(), header, dwHandle, dwLength);
|
||||
if (iBytesProceed + dwLength + 9 > (DWORD) GetRecvLength())
|
||||
{
|
||||
sys_log(0, "PeekPacket: not enough buffer size: len %u, recv %d",
|
||||
9+dwLength, GetRecvLength()-iBytesProceed);
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = buf;
|
||||
iBytesProceed += dwLength + 9;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPeer::EncodeHeader(BYTE header, DWORD dwHandle, DWORD dwSize)
|
||||
{
|
||||
HEADER h;
|
||||
|
||||
sys_log(1, "EncodeHeader %u handle %u size %u", header, dwHandle, dwSize);
|
||||
|
||||
h.bHeader = header;
|
||||
h.dwHandle = dwHandle;
|
||||
h.dwSize = dwSize;
|
||||
|
||||
Encode(&h, sizeof(HEADER));
|
||||
}
|
||||
|
||||
void CPeer::EncodeReturn(BYTE header, DWORD dwHandle)
|
||||
{
|
||||
EncodeHeader(header, dwHandle, 0);
|
||||
}
|
||||
|
||||
int CPeer::Send()
|
||||
{
|
||||
if (m_state == STATE_CLOSE)
|
||||
return -1;
|
||||
|
||||
return (CPeerBase::Send());
|
||||
}
|
||||
|
||||
void CPeer::SetP2PPort(WORD wPort)
|
||||
{
|
||||
m_wP2PPort = wPort;
|
||||
}
|
||||
|
||||
void CPeer::SetMaps(long * pl)
|
||||
{
|
||||
thecore_memcpy(m_alMaps, pl, sizeof(m_alMaps));
|
||||
}
|
||||
|
||||
void CPeer::SendSpareItemIDRange()
|
||||
{
|
||||
if (m_itemSpareRange.dwMin == 0 || m_itemSpareRange.dwMax == 0 || m_itemSpareRange.dwUsableItemIDMin == 0)
|
||||
{
|
||||
EncodeHeader(HEADER_DG_ACK_SPARE_ITEM_ID_RANGE, 0, sizeof(TItemIDRangeTable));
|
||||
Encode(&m_itemSpareRange, sizeof(TItemIDRangeTable));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetItemIDRange(m_itemSpareRange);
|
||||
|
||||
if (SetSpareItemIDRange(CItemIDRangeManager::instance().GetRange()) == false)
|
||||
{
|
||||
sys_log(0, "ItemIDRange: spare range set error");
|
||||
m_itemSpareRange.dwMin = m_itemSpareRange.dwMax = m_itemSpareRange.dwUsableItemIDMin = 0;
|
||||
}
|
||||
|
||||
EncodeHeader(HEADER_DG_ACK_SPARE_ITEM_ID_RANGE, 0, sizeof(TItemIDRangeTable));
|
||||
Encode(&m_itemSpareRange, sizeof(TItemIDRangeTable));
|
||||
}
|
||||
}
|
||||
|
||||
bool CPeer::SetItemIDRange(TItemIDRangeTable itemRange)
|
||||
{
|
||||
if (itemRange.dwMin == 0 || itemRange.dwMax == 0 || itemRange.dwUsableItemIDMin == 0) return false;
|
||||
|
||||
m_itemRange = itemRange;
|
||||
sys_log(0, "ItemIDRange: SET %s %u ~ %u start: %u", GetPublicIP(), m_itemRange.dwMin, m_itemRange.dwMax, m_itemRange.dwUsableItemIDMin);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPeer::SetSpareItemIDRange(TItemIDRangeTable itemRange)
|
||||
{
|
||||
if (itemRange.dwMin == 0 || itemRange.dwMax == 0 || itemRange.dwUsableItemIDMin == 0) return false;
|
||||
|
||||
m_itemSpareRange = itemRange;
|
||||
sys_log(0, "ItemIDRange: SPARE SET %s %u ~ %u start: %u", GetPublicIP(), m_itemSpareRange.dwMin, m_itemSpareRange.dwMax,
|
||||
m_itemSpareRange.dwUsableItemIDMin);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPeer::CheckItemIDRangeCollision(TItemIDRangeTable itemRange)
|
||||
{
|
||||
if (m_itemRange.dwMin < itemRange.dwMax && m_itemRange.dwMax > itemRange.dwMin)
|
||||
{
|
||||
sys_err("ItemIDRange: Collision!! this %u ~ %u check %u ~ %u",
|
||||
m_itemRange.dwMin, m_itemRange.dwMax, itemRange.dwMin, itemRange.dwMax);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_itemSpareRange.dwMin < itemRange.dwMax && m_itemSpareRange.dwMax > itemRange.dwMin)
|
||||
{
|
||||
sys_err("ItemIDRange: Collision with spare range this %u ~ %u check %u ~ %u",
|
||||
m_itemSpareRange.dwMin, m_itemSpareRange.dwMax, itemRange.dwMin, itemRange.dwMax);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
81
source-server/Srcs/Server/db/src/Peer.h
Normal file
81
source-server/Srcs/Server/db/src/Peer.h
Normal file
@ -0,0 +1,81 @@
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_PEER_H__
|
||||
#define __INC_PEER_H__
|
||||
|
||||
#include "PeerBase.h"
|
||||
#include "../../common/CommonDefines.h"
|
||||
|
||||
class CPeer : public CPeerBase
|
||||
{
|
||||
protected:
|
||||
virtual void OnAccept();
|
||||
virtual void OnClose();
|
||||
virtual void OnConnect();
|
||||
|
||||
public:
|
||||
#pragma pack(1)
|
||||
typedef struct _header
|
||||
{
|
||||
BYTE bHeader;
|
||||
DWORD dwHandle;
|
||||
DWORD dwSize;
|
||||
} HEADER;
|
||||
#pragma pack()
|
||||
enum EState
|
||||
{
|
||||
STATE_CLOSE = 0,
|
||||
STATE_PLAYING = 1
|
||||
};
|
||||
|
||||
CPeer();
|
||||
virtual ~CPeer();
|
||||
|
||||
void EncodeHeader(BYTE header, DWORD dwHandle, DWORD dwSize);
|
||||
bool PeekPacket(int & iBytesProceed, BYTE & header, DWORD & dwHandle, DWORD & dwLength, const char ** data);
|
||||
void EncodeReturn(BYTE header, DWORD dwHandle);
|
||||
|
||||
void ProcessInput();
|
||||
int Send();
|
||||
|
||||
DWORD GetHandle();
|
||||
DWORD GetUserCount();
|
||||
void SetUserCount(DWORD dwCount);
|
||||
|
||||
void SetPublicIP(const char * ip) { m_stPublicIP = ip; }
|
||||
const char * GetPublicIP() { return m_stPublicIP.c_str(); }
|
||||
|
||||
void SetChannel(BYTE bChannel) { m_bChannel = bChannel; }
|
||||
BYTE GetChannel() { return m_bChannel; }
|
||||
|
||||
void SetListenPort(WORD wPort) { m_wListenPort = wPort; }
|
||||
WORD GetListenPort() { return m_wListenPort; }
|
||||
|
||||
void SetP2PPort(WORD wPort);
|
||||
WORD GetP2PPort() { return m_wP2PPort; }
|
||||
|
||||
void SetMaps(long* pl);
|
||||
long * GetMaps() { return &m_alMaps[0]; }
|
||||
|
||||
bool SetItemIDRange(TItemIDRangeTable itemRange);
|
||||
bool SetSpareItemIDRange(TItemIDRangeTable itemRange);
|
||||
bool CheckItemIDRangeCollision(TItemIDRangeTable itemRange);
|
||||
void SendSpareItemIDRange();
|
||||
|
||||
private:
|
||||
int m_state;
|
||||
|
||||
BYTE m_bChannel;
|
||||
DWORD m_dwHandle;
|
||||
DWORD m_dwUserCount;
|
||||
WORD m_wListenPort;
|
||||
WORD m_wP2PPort;
|
||||
long m_alMaps[MAP_ALLOW_LIMIT];
|
||||
|
||||
TItemIDRangeTable m_itemRange;
|
||||
TItemIDRangeTable m_itemSpareRange;
|
||||
|
||||
std::string m_stPublicIP;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
230
source-server/Srcs/Server/db/src/PeerBase.cpp
Normal file
230
source-server/Srcs/Server/db/src/PeerBase.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
#include "stdafx.h"
|
||||
#include "PeerBase.h"
|
||||
#include "../../common/CommonDefines.h"
|
||||
|
||||
CPeerBase::CPeerBase() : m_fd(INVALID_SOCKET), m_BytesRemain(0), m_outBuffer(NULL), m_inBuffer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CPeerBase::~CPeerBase()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void CPeerBase::Disconnect()
|
||||
{
|
||||
if (m_fd != INVALID_SOCKET)
|
||||
{
|
||||
fdwatch_del_fd(m_fdWatcher, m_fd);
|
||||
|
||||
socket_close(m_fd);
|
||||
m_fd = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
void CPeerBase::Destroy()
|
||||
{
|
||||
Disconnect();
|
||||
|
||||
if (m_outBuffer)
|
||||
{
|
||||
buffer_delete(m_outBuffer);
|
||||
m_outBuffer = NULL;
|
||||
}
|
||||
|
||||
if (m_inBuffer)
|
||||
{
|
||||
buffer_delete(m_inBuffer);
|
||||
m_inBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPeerBase::Accept(socket_t fd_accept)
|
||||
{
|
||||
struct sockaddr_in peer;
|
||||
|
||||
if ((m_fd = socket_accept(fd_accept, &peer)) == INVALID_SOCKET)
|
||||
{
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PORT_SECURITY
|
||||
// refuse if remote host != localhost (only the same machine must be able to connect in here)
|
||||
std::string targetIP = inet_ntoa(peer.sin_addr);
|
||||
if (targetIP.rfind("127.0.0.1", 0) && targetIP.rfind("192.168.", 0) && targetIP.rfind("10.", 0))
|
||||
{
|
||||
sys_log(0, "BLOCK CONNECTION FROM %s", inet_ntoa(peer.sin_addr));
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//socket_block(m_fd);
|
||||
socket_sndbuf(m_fd, 233016);
|
||||
socket_rcvbuf(m_fd, 233016);
|
||||
|
||||
strlcpy(m_host, inet_ntoa(peer.sin_addr), sizeof(m_host));
|
||||
m_wPort = peer.sin_port;
|
||||
|
||||
m_outBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE);
|
||||
m_inBuffer = buffer_new(MAX_INPUT_LEN);
|
||||
|
||||
if (!m_outBuffer || !m_inBuffer)
|
||||
{
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_READ, false);
|
||||
|
||||
OnAccept();
|
||||
sys_log(0, "ACCEPT FROM %s", inet_ntoa(peer.sin_addr));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPeerBase::Connect(const char* host, WORD port)
|
||||
{
|
||||
strlcpy(m_host, host, sizeof(m_host));
|
||||
m_wPort = port;
|
||||
|
||||
if ((m_fd = socket_connect(host, port)) == INVALID_SOCKET)
|
||||
return false;
|
||||
|
||||
m_outBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE);
|
||||
|
||||
if (!m_outBuffer)
|
||||
{
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_READ, false);
|
||||
|
||||
OnConnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPeerBase::Close()
|
||||
{
|
||||
OnClose();
|
||||
}
|
||||
|
||||
void CPeerBase::EncodeBYTE(BYTE b)
|
||||
{
|
||||
if (!m_outBuffer)
|
||||
{
|
||||
sys_err("Not ready to write");
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_write(m_outBuffer, &b, 1);
|
||||
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
|
||||
}
|
||||
|
||||
void CPeerBase::EncodeWORD(WORD w)
|
||||
{
|
||||
if (!m_outBuffer)
|
||||
{
|
||||
sys_err("Not ready to write");
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_write(m_outBuffer, &w, 2);
|
||||
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
|
||||
}
|
||||
|
||||
void CPeerBase::EncodeDWORD(DWORD dw)
|
||||
{
|
||||
if (!m_outBuffer)
|
||||
{
|
||||
sys_err("Not ready to write");
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_write(m_outBuffer, &dw, 4);
|
||||
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
|
||||
}
|
||||
|
||||
void CPeerBase::Encode(const void* data, DWORD size)
|
||||
{
|
||||
if (!m_outBuffer)
|
||||
{
|
||||
sys_err("Not ready to write");
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_write(m_outBuffer, data, size);
|
||||
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
|
||||
}
|
||||
|
||||
int CPeerBase::Recv()
|
||||
{
|
||||
if (!m_inBuffer)
|
||||
{
|
||||
sys_err("input buffer nil");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_adjust_size(m_inBuffer, MAX_INPUT_LEN >> 2);
|
||||
int bytes_to_read = buffer_has_space(m_inBuffer);
|
||||
ssize_t bytes_read = socket_read(m_fd, (char *) buffer_write_peek(m_inBuffer), bytes_to_read);
|
||||
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
sys_err("socket_read failed %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (bytes_read == 0)
|
||||
return 0;
|
||||
|
||||
buffer_write_proceed(m_inBuffer, bytes_read);
|
||||
m_BytesRemain = buffer_size(m_inBuffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CPeerBase::RecvEnd(int proceed_bytes)
|
||||
{
|
||||
buffer_read_proceed(m_inBuffer, proceed_bytes);
|
||||
m_BytesRemain = buffer_size(m_inBuffer);
|
||||
}
|
||||
|
||||
int CPeerBase::GetRecvLength()
|
||||
{
|
||||
return m_BytesRemain;
|
||||
}
|
||||
|
||||
const void * CPeerBase::GetRecvBuffer()
|
||||
{
|
||||
return buffer_read_peek(m_inBuffer);
|
||||
}
|
||||
|
||||
int CPeerBase::GetSendLength()
|
||||
{
|
||||
return buffer_size(m_outBuffer);
|
||||
}
|
||||
|
||||
int CPeerBase::Send()
|
||||
{
|
||||
if (buffer_size(m_outBuffer) <= 0)
|
||||
return 0;
|
||||
|
||||
int iBufferLeft = fdwatch_get_buffer_size(m_fdWatcher, m_fd);
|
||||
int iBytesToWrite = MIN(iBufferLeft, buffer_size(m_outBuffer));
|
||||
|
||||
if (iBytesToWrite == 0)
|
||||
return 0;
|
||||
|
||||
int result = socket_write(m_fd, (const char *) buffer_read_peek(m_outBuffer), iBytesToWrite);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
buffer_read_proceed(m_outBuffer, iBytesToWrite);
|
||||
|
||||
if (buffer_size(m_outBuffer) != 0)
|
||||
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
73
source-server/Srcs/Server/db/src/PeerBase.h
Normal file
73
source-server/Srcs/Server/db/src/PeerBase.h
Normal file
@ -0,0 +1,73 @@
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_PEERBASE_H__
|
||||
#define __INC_PEERBASE_H__
|
||||
|
||||
#include "NetBase.h"
|
||||
|
||||
class CPeerBase : public CNetBase
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_HOST_LENGTH = 30,
|
||||
MAX_INPUT_LEN = 1024 * 1024 * 2,
|
||||
DEFAULT_PACKET_BUFFER_SIZE = 1024 * 1024 * 2
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void OnAccept() = 0;
|
||||
virtual void OnConnect() = 0;
|
||||
virtual void OnClose() = 0;
|
||||
|
||||
public:
|
||||
bool Accept(socket_t accept_fd);
|
||||
bool Connect(const char* host, WORD port);
|
||||
void Close();
|
||||
|
||||
public:
|
||||
CPeerBase();
|
||||
virtual ~CPeerBase();
|
||||
|
||||
void Disconnect();
|
||||
void Destroy();
|
||||
|
||||
socket_t GetFd() { return m_fd; }
|
||||
|
||||
void EncodeBYTE(BYTE b);
|
||||
void EncodeWORD(WORD w);
|
||||
void EncodeDWORD(DWORD dw);
|
||||
void Encode(const void* data, DWORD size);
|
||||
int Send();
|
||||
|
||||
template<typename T, std::enable_if_t<utils::IsRawV<T>>* = nullptr>
|
||||
void Encode(const T& c_pvData) {
|
||||
Encode(&c_pvData, sizeof(T));
|
||||
}
|
||||
template<typename C, std::enable_if_t<utils::IsContiguousV<C>>* = nullptr>
|
||||
void Encode(const C& v) {
|
||||
Encode(v.data(), v.size() * sizeof(typename C::value_type));
|
||||
}
|
||||
|
||||
int Recv();
|
||||
void RecvEnd(int proceed_bytes);
|
||||
int GetRecvLength();
|
||||
const void * GetRecvBuffer();
|
||||
|
||||
int GetSendLength();
|
||||
|
||||
const char * GetHost() { return m_host; }
|
||||
WORD GetPort() { return m_wPort; }
|
||||
|
||||
protected:
|
||||
char m_host[MAX_HOST_LENGTH + 1];
|
||||
socket_t m_fd;
|
||||
WORD m_wPort;
|
||||
|
||||
private:
|
||||
int m_BytesRemain;
|
||||
LPBUFFER m_outBuffer;
|
||||
LPBUFFER m_inBuffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
283
source-server/Srcs/Server/db/src/PrivManager.cpp
Normal file
283
source-server/Srcs/Server/db/src/PrivManager.cpp
Normal file
@ -0,0 +1,283 @@
|
||||
#include "stdafx.h"
|
||||
#include "PrivManager.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
const int CHARACTER_GOOD_PRIV_DURATION = 2*60*60;
|
||||
const int CHARACTER_BAD_PRIV_DURATION = 60*60;
|
||||
|
||||
CPrivManager::CPrivManager()
|
||||
{
|
||||
for (int type = 0; type < MAX_PRIV_NUM; ++type)
|
||||
{
|
||||
for (int empire = 0; empire < EMPIRE_MAX_NUM; ++empire)
|
||||
m_aaPrivEmpire[type][empire] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CPrivManager::~CPrivManager()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
void CPrivManager::Update()
|
||||
{
|
||||
time_t now = CClientManager::instance().GetCurrentTime();
|
||||
|
||||
while (!m_pqPrivGuild.empty() && m_pqPrivGuild.top().first <= now)
|
||||
{
|
||||
TPrivGuildData* p = m_pqPrivGuild.top().second;
|
||||
m_pqPrivGuild.pop();
|
||||
|
||||
if (p->value != 0 && !p->bRemoved)
|
||||
{
|
||||
typeof(m_aPrivGuild[p->type].begin()) it = m_aPrivGuild[p->type].find(p->guild_id);
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
|
||||
if (it != m_aPrivGuild[p->type].end() && it->second == p) {
|
||||
m_aPrivGuild[p->type].erase(it);
|
||||
SendChangeGuildPriv(p->guild_id, p->type, 0, 0);
|
||||
// END_OF_ADD_GUILD_PRIV_TIME
|
||||
}
|
||||
}
|
||||
|
||||
delete p;
|
||||
}
|
||||
|
||||
while (!m_pqPrivEmpire.empty() && m_pqPrivEmpire.top().first <= now)
|
||||
{
|
||||
TPrivEmpireData* p = (m_pqPrivEmpire.top().second);
|
||||
m_pqPrivEmpire.pop();
|
||||
|
||||
if (p->value != 0 && !p->bRemoved)
|
||||
{
|
||||
SendChangeEmpirePriv(p->empire, p->type, 0, 0);
|
||||
m_aaPrivEmpire[p->type][p->empire] = 0;
|
||||
}
|
||||
|
||||
delete p;
|
||||
}
|
||||
|
||||
while (!m_pqPrivChar.empty() && m_pqPrivChar.top().first <= now)
|
||||
{
|
||||
TPrivCharData* p = (m_pqPrivChar.top().second);
|
||||
m_pqPrivChar.pop();
|
||||
|
||||
if (!p->bRemoved)
|
||||
{
|
||||
// TODO send packet
|
||||
SendChangeCharPriv(p->pid, p->type, 0);
|
||||
typeof(m_aPrivChar[p->type].begin()) it = m_aPrivChar[p->type].find(p->pid);
|
||||
if (it != m_aPrivChar[p->type].end())
|
||||
m_aPrivChar[p->type].erase(it);
|
||||
}
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
|
||||
void CPrivManager::AddCharPriv(DWORD pid, BYTE type, int value)
|
||||
{
|
||||
if (MAX_PRIV_NUM <= type)
|
||||
{
|
||||
sys_err("PRIV_MANAGER: AddCharPriv: wrong char priv type(%u) recved", type);
|
||||
return;
|
||||
}
|
||||
|
||||
typeof(m_aPrivChar[type].begin()) it = m_aPrivChar[type].find(pid);
|
||||
|
||||
if (it != m_aPrivChar[type].end())
|
||||
return;
|
||||
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
time_t now = CClientManager::instance().GetCurrentTime();
|
||||
TPrivCharData* p = new TPrivCharData(type, value, pid);
|
||||
|
||||
int iDuration = CHARACTER_BAD_PRIV_DURATION;
|
||||
|
||||
if (value > 0)
|
||||
iDuration = CHARACTER_GOOD_PRIV_DURATION;
|
||||
|
||||
m_pqPrivChar.push(std::make_pair(now+iDuration, p));
|
||||
m_aPrivChar[type].emplace(pid, p);
|
||||
|
||||
// TODO send packet
|
||||
sys_log(0, "AddCharPriv %d %d %d", pid, type, value);
|
||||
SendChangeCharPriv(pid, type, value);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
void CPrivManager::AddGuildPriv(DWORD guild_id, BYTE type, int value, time_t duration_sec)
|
||||
{
|
||||
if (MAX_PRIV_NUM <= type)
|
||||
{
|
||||
sys_err("PRIV_MANAGER: AddGuildPriv: wrong guild priv type(%u) recved", type);
|
||||
return;
|
||||
}
|
||||
|
||||
typeof(m_aPrivGuild[type].begin()) it = m_aPrivGuild[type].find(guild_id);
|
||||
|
||||
time_t now = CClientManager::instance().GetCurrentTime();
|
||||
time_t end = now + duration_sec;
|
||||
TPrivGuildData * p = new TPrivGuildData(type, value, guild_id, end);
|
||||
m_pqPrivGuild.push(std::make_pair(end, p));
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
|
||||
if (it != m_aPrivGuild[type].end())
|
||||
it->second = p;
|
||||
else
|
||||
m_aPrivGuild[type].emplace(guild_id, p);
|
||||
|
||||
SendChangeGuildPriv(guild_id, type, value, end);
|
||||
// END_OF_ADD_GUILD_PRIV_TIME
|
||||
|
||||
sys_log(0, "Guild Priv guild(%d) type(%d) value(%d) duration_sec(%d)", guild_id, type, value, duration_sec);
|
||||
}
|
||||
|
||||
void CPrivManager::AddEmpirePriv(BYTE empire, BYTE type, int value, time_t duration_sec)
|
||||
{
|
||||
if (MAX_PRIV_NUM <= type)
|
||||
{
|
||||
sys_err("PRIV_MANAGER: AddEmpirePriv: wrong empire priv type(%u) recved", type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (duration_sec < 0)
|
||||
duration_sec = 0;
|
||||
|
||||
time_t now = CClientManager::instance().GetCurrentTime();
|
||||
time_t end = now+duration_sec;
|
||||
|
||||
{
|
||||
if (m_aaPrivEmpire[type][empire])
|
||||
m_aaPrivEmpire[type][empire]->bRemoved = true;
|
||||
}
|
||||
|
||||
TPrivEmpireData * p = new TPrivEmpireData(type, value, empire, end);
|
||||
m_pqPrivEmpire.push(std::make_pair(end, p));
|
||||
m_aaPrivEmpire[type][empire] = p;
|
||||
|
||||
// ADD_EMPIRE_PRIV_TIME
|
||||
SendChangeEmpirePriv(empire, type, value, end);
|
||||
// END_OF_ADD_EMPIRE_PRIV_TIME
|
||||
|
||||
sys_log(0, "Empire Priv empire(%d) type(%d) value(%d) duration_sec(%d)", empire, type, value, duration_sec);
|
||||
}
|
||||
|
||||
struct FSendChangeGuildPriv
|
||||
{
|
||||
FSendChangeGuildPriv(DWORD guild_id, BYTE type, int value, time_t end_time_sec)
|
||||
{
|
||||
p.guild_id = guild_id;
|
||||
p.type = type;
|
||||
p.value = value;
|
||||
p.bLog = 1;
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
p.end_time_sec = end_time_sec;
|
||||
// END_OF_ADD_GUILD_PRIV_TIME
|
||||
}
|
||||
|
||||
void operator() (CPeer* peer)
|
||||
{
|
||||
peer->EncodeHeader(HEADER_DG_CHANGE_GUILD_PRIV, 0, sizeof(TPacketDGChangeGuildPriv));
|
||||
peer->Encode(&p, sizeof(TPacketDGChangeGuildPriv));
|
||||
p.bLog = 0;
|
||||
}
|
||||
|
||||
TPacketDGChangeGuildPriv p;
|
||||
};
|
||||
|
||||
struct FSendChangeEmpirePriv
|
||||
{
|
||||
FSendChangeEmpirePriv(BYTE empire, BYTE type, int value, time_t end_time_sec)
|
||||
{
|
||||
p.empire = empire;
|
||||
p.type = type;
|
||||
p.value = value;
|
||||
p.bLog = 1;
|
||||
// ADD_EMPIRE_PRIV_TIME
|
||||
p.end_time_sec = end_time_sec;
|
||||
// END_OF_ADD_EMPIRE_PRIV_TIME
|
||||
}
|
||||
|
||||
void operator ()(CPeer* peer)
|
||||
{
|
||||
peer->EncodeHeader(HEADER_DG_CHANGE_EMPIRE_PRIV, 0, sizeof(TPacketDGChangeEmpirePriv));
|
||||
peer->Encode(&p, sizeof(TPacketDGChangeEmpirePriv));
|
||||
p.bLog = 0;
|
||||
}
|
||||
|
||||
TPacketDGChangeEmpirePriv p;
|
||||
};
|
||||
|
||||
struct FSendChangeCharPriv
|
||||
{
|
||||
FSendChangeCharPriv(DWORD pid, BYTE type, int value)
|
||||
{
|
||||
p.pid = pid;
|
||||
p.type = type;
|
||||
p.value = value;
|
||||
p.bLog = 1;
|
||||
}
|
||||
void operator()(CPeer* peer)
|
||||
{
|
||||
peer->EncodeHeader(HEADER_DG_CHANGE_CHARACTER_PRIV, 0, sizeof(TPacketDGChangeCharacterPriv));
|
||||
peer->Encode(&p, sizeof(TPacketDGChangeCharacterPriv));
|
||||
p.bLog = 0;
|
||||
}
|
||||
TPacketDGChangeCharacterPriv p;
|
||||
};
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
void CPrivManager::SendChangeGuildPriv(DWORD guild_id, BYTE type, int value, time_t end_time_sec)
|
||||
{
|
||||
CClientManager::instance().for_each_peer(FSendChangeGuildPriv(guild_id, type, value, end_time_sec));
|
||||
}
|
||||
// END_OF_ADD_GUILD_PRIV_TIME
|
||||
|
||||
// ADD_EMPIRE_PRIV_TIME
|
||||
void CPrivManager::SendChangeEmpirePriv(BYTE empire, BYTE type, int value, time_t end_time_sec)
|
||||
{
|
||||
CClientManager::instance().for_each_peer(FSendChangeEmpirePriv(empire, type, value, end_time_sec));
|
||||
}
|
||||
// END_OF_ADD_EMPIRE_PRIV_TIME
|
||||
|
||||
void CPrivManager::SendChangeCharPriv(DWORD pid, BYTE type, int value)
|
||||
{
|
||||
CClientManager::instance().for_each_peer(FSendChangeCharPriv(pid, type, value));
|
||||
}
|
||||
|
||||
void CPrivManager::SendPrivOnSetup(CPeer* peer)
|
||||
{
|
||||
for (int i = 1; i < MAX_PRIV_NUM; ++i)
|
||||
{
|
||||
for (int e = 0; e < EMPIRE_MAX_NUM; ++e)
|
||||
{
|
||||
// ADD_EMPIRE_PRIV_TIME
|
||||
TPrivEmpireData* pPrivEmpireData = m_aaPrivEmpire[i][e];
|
||||
if (pPrivEmpireData)
|
||||
{
|
||||
FSendChangeEmpirePriv(e, i, pPrivEmpireData->value, pPrivEmpireData->end_time_sec)(peer);
|
||||
}
|
||||
// END_OF_ADD_EMPIRE_PRIV_TIME
|
||||
}
|
||||
|
||||
for (typeof(m_aPrivGuild[i].begin()) it = m_aPrivGuild[i].begin(); it != m_aPrivGuild[i].end();++it)
|
||||
{
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
FSendChangeGuildPriv(it->first, i, it->second->value, it->second->end_time_sec)(peer);
|
||||
// END_OF_ADD_GUILD_PRIV_TIME
|
||||
}
|
||||
for (typeof(m_aPrivChar[i].begin()) it = m_aPrivChar[i].begin(); it != m_aPrivChar[i].end(); ++it)
|
||||
{
|
||||
FSendChangeCharPriv(it->first, i, it->second->value)(peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
101
source-server/Srcs/Server/db/src/PrivManager.h
Normal file
101
source-server/Srcs/Server/db/src/PrivManager.h
Normal file
@ -0,0 +1,101 @@
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_PRIV_MANAGER_H
|
||||
#define __INC_PRIV_MANAGER_H
|
||||
|
||||
#include "Peer.h"
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
|
||||
struct TPrivEmpireData
|
||||
{
|
||||
BYTE type;
|
||||
int value;
|
||||
bool bRemoved;
|
||||
BYTE empire;
|
||||
|
||||
// ADD_EMPIRE_PRIV_TIME
|
||||
time_t end_time_sec;
|
||||
|
||||
TPrivEmpireData(BYTE type, int value, BYTE empire, time_t end_time_sec)
|
||||
: type(type), value(value), bRemoved(false), empire(empire), end_time_sec(end_time_sec)
|
||||
{}
|
||||
// END_OF_ADD_EMPIRE_PRIV_TIME
|
||||
};
|
||||
|
||||
struct TPrivGuildData
|
||||
{
|
||||
BYTE type;
|
||||
int value;
|
||||
bool bRemoved;
|
||||
DWORD guild_id;
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
time_t end_time_sec;
|
||||
|
||||
TPrivGuildData(BYTE type, int value, DWORD guild_id, time_t _end_time_sec)
|
||||
: type(type), value(value), bRemoved(false), guild_id(guild_id), end_time_sec(_end_time_sec )
|
||||
{}
|
||||
// END_OF_ADD_GUILD_PRIV_TIME
|
||||
};
|
||||
|
||||
struct TPrivCharData
|
||||
{
|
||||
BYTE type;
|
||||
int value;
|
||||
bool bRemoved;
|
||||
DWORD pid;
|
||||
TPrivCharData(BYTE type, int value, DWORD pid)
|
||||
: type(type), value(value), bRemoved(false), pid(pid)
|
||||
{}
|
||||
};
|
||||
|
||||
class CPrivManager : public singleton<CPrivManager>
|
||||
{
|
||||
public:
|
||||
CPrivManager();
|
||||
virtual ~CPrivManager();
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
void AddGuildPriv(DWORD guild_id, BYTE type, int value, time_t time_sec);
|
||||
// END_OF_ADD_GUILD_PRIV_TIME
|
||||
|
||||
// ADD_EMPIRE_PRIV_TIME
|
||||
void AddEmpirePriv(BYTE empire, BYTE type, int value, time_t time_sec);
|
||||
// END_OF_ADD_EMPIRE_PRIV_TIME
|
||||
|
||||
void AddCharPriv(DWORD pid, BYTE type, int value);
|
||||
|
||||
void Update();
|
||||
|
||||
void SendPrivOnSetup(CPeer* peer);
|
||||
|
||||
private:
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
void SendChangeGuildPriv(DWORD guild_id, BYTE type, int value, time_t end_time_sec);
|
||||
// END_OF_ADD_GUILD_PRIV_TIME
|
||||
|
||||
// ADD_EMPIRE_PRIV_TIME
|
||||
void SendChangeEmpirePriv(BYTE empire, BYTE type, int value, time_t end_time_sec);
|
||||
// END_OF_ADD_EMPIRE_PRIV_TIME
|
||||
|
||||
void SendChangeCharPriv(DWORD pid, BYTE type, int value);
|
||||
|
||||
typedef std::pair<time_t, TPrivCharData *> stPairChar;
|
||||
typedef std::pair<time_t, TPrivGuildData*> stPairGuild;
|
||||
typedef std::pair<time_t, TPrivEmpireData*> stPairEmpire;
|
||||
|
||||
std::priority_queue<stPairChar, std::vector<stPairChar>, std::greater<stPairChar> >
|
||||
m_pqPrivChar;
|
||||
std::priority_queue<stPairGuild, std::vector<stPairGuild>, std::greater<stPairGuild> >
|
||||
m_pqPrivGuild;
|
||||
std::priority_queue<stPairEmpire, std::vector<stPairEmpire>, std::greater<stPairEmpire> >
|
||||
m_pqPrivEmpire;
|
||||
|
||||
TPrivEmpireData* m_aaPrivEmpire[MAX_PRIV_NUM][EMPIRE_MAX_NUM];
|
||||
std::map<DWORD, TPrivGuildData*> m_aPrivGuild[MAX_PRIV_NUM];
|
||||
std::map<DWORD, TPrivCharData*> m_aPrivChar[MAX_PRIV_NUM];
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
825
source-server/Srcs/Server/db/src/ProtoReader.cpp
Normal file
825
source-server/Srcs/Server/db/src/ProtoReader.cpp
Normal file
@ -0,0 +1,825 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <math.h>
|
||||
#include "ProtoReader.h"
|
||||
|
||||
#include "CsvReader.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define ENABLE_NUMERIC_FIELD
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
bool _IsNumericString(const std::string& trimInputString)
|
||||
{
|
||||
if (trimInputString.empty())
|
||||
return false;
|
||||
bool isNumber = true;
|
||||
for (auto& c : trimInputString)
|
||||
{
|
||||
if (!std::isdigit(c) && c != '-' && c != '+')
|
||||
{
|
||||
isNumber = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isNumber;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline string trim_left(const string& str)
|
||||
{
|
||||
string::size_type n = str.find_first_not_of(" \t\v\n\r");
|
||||
return n == string::npos ? str : str.substr(n, str.length());
|
||||
}
|
||||
|
||||
inline string trim_right(const string& str)
|
||||
{
|
||||
string::size_type n = str.find_last_not_of(" \t\v\n\r");
|
||||
return n == string::npos ? str : str.substr(0, n + 1);
|
||||
}
|
||||
|
||||
string trim(const string& str){return trim_left(trim_right(str));}
|
||||
|
||||
static string* StringSplit(string strOrigin, string strTok)
|
||||
{
|
||||
size_t cutAt;
|
||||
int index = 0;
|
||||
string* strResult = new string[30];
|
||||
|
||||
while ((cutAt = strOrigin.find_first_of(strTok)) != strOrigin.npos)
|
||||
{
|
||||
if (cutAt > 0)
|
||||
{
|
||||
strResult[index++] = strOrigin.substr(0, cutAt);
|
||||
}
|
||||
strOrigin = strOrigin.substr(cutAt+1);
|
||||
}
|
||||
|
||||
if(strOrigin.length() > 0)
|
||||
{
|
||||
strResult[index++] = strOrigin.substr(0, cutAt);
|
||||
}
|
||||
|
||||
for( int i=0;i<index;i++)
|
||||
{
|
||||
strResult[i] = trim(strResult[i]);
|
||||
}
|
||||
|
||||
return strResult;
|
||||
}
|
||||
|
||||
static const std::vector<std::string> arItemType = {
|
||||
"ITEM_NONE", "ITEM_WEAPON",
|
||||
"ITEM_ARMOR", "ITEM_USE",
|
||||
"ITEM_AUTOUSE", "ITEM_MATERIAL",
|
||||
"ITEM_SPECIAL", "ITEM_TOOL",
|
||||
"ITEM_LOTTERY", "ITEM_ELK",
|
||||
|
||||
"ITEM_METIN", "ITEM_CONTAINER",
|
||||
"ITEM_FISH", "ITEM_ROD",
|
||||
"ITEM_RESOURCE", "ITEM_CAMPFIRE",
|
||||
"ITEM_UNIQUE", "ITEM_SKILLBOOK",
|
||||
"ITEM_QUEST", "ITEM_POLYMORPH",
|
||||
|
||||
"ITEM_TREASURE_BOX", "ITEM_TREASURE_KEY",
|
||||
"ITEM_SKILLFORGET", "ITEM_GIFTBOX",
|
||||
"ITEM_PICK", "ITEM_HAIR",
|
||||
"ITEM_TOTEM", "ITEM_BLEND",
|
||||
"ITEM_COSTUME", "ITEM_DS",
|
||||
|
||||
"ITEM_SPECIAL_DS", "ITEM_EXTRACT",
|
||||
"ITEM_SECONDARY_COIN",
|
||||
|
||||
"ITEM_RING",
|
||||
"ITEM_BELT",
|
||||
"ITEM_PET", "ITEM_MEDIUM", // 35,36
|
||||
"ITEM_GACHA", "ITEM_SOUL" // 37,38
|
||||
"ITEM_PASSIVE" // 39
|
||||
};
|
||||
|
||||
int get_Item_Type_Value(std::string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
|
||||
auto it = std::find(std::begin(arItemType), std::end(arItemType), inputString);
|
||||
if (it == std::end(arItemType))
|
||||
return -1;
|
||||
return std::distance(std::begin(arItemType), it);
|
||||
}
|
||||
|
||||
static const std::unordered_map<uint32_t, std::vector<std::string>> mapItemSubType {
|
||||
{1, { "WEAPON_SWORD", "WEAPON_DAGGER", "WEAPON_BOW", "WEAPON_TWO_HANDED",
|
||||
"WEAPON_BELL", "WEAPON_FAN", "WEAPON_ARROW", "WEAPON_MOUNT_SPEAR", "WEAPON_CLAW", "WEAPON_QUIVER", "WEAPON_BOUQUET"}},
|
||||
{2, { "ARMOR_BODY", "ARMOR_HEAD", "ARMOR_SHIELD", "ARMOR_WRIST", "ARMOR_FOOTS",
|
||||
"ARMOR_NECK", "ARMOR_EAR", "ARMOR_PENDANT", "ARMOR_GLOVE", "ARMOR_NUM_TYPES"}},
|
||||
{3, { "USE_POTION", "USE_TALISMAN", "USE_TUNING", "USE_MOVE", "USE_TREASURE_BOX", "USE_MONEYBAG", "USE_BAIT",
|
||||
"USE_ABILITY_UP", "USE_AFFECT", "USE_CREATE_STONE", "USE_SPECIAL", "USE_POTION_NODELAY", "USE_CLEAR",
|
||||
"USE_INVISIBILITY", "USE_DETACHMENT", "USE_BUCKET", "USE_POTION_CONTINUE", "USE_CLEAN_SOCKET",
|
||||
"USE_CHANGE_ATTRIBUTE", "USE_ADD_ATTRIBUTE", "USE_ADD_ACCESSORY_SOCKET", "USE_PUT_INTO_ACCESSORY_SOCKET",
|
||||
"USE_ADD_ATTRIBUTE2", "USE_RECIPE", "USE_CHANGE_ATTRIBUTE2", "USE_BIND", "USE_UNBIND", "USE_TIME_CHARGE_PER", "USE_TIME_CHARGE_FIX", "USE_PUT_INTO_BELT_SOCKET", "USE_PUT_INTO_RING_SOCKET",
|
||||
"USE_CHANGE_COSTUME_ATTR", "USE_RESET_COSTUME_ATTR", "USE_UNK33", "USE_CHANGE_ATTRIBUTE_PLUS"}},
|
||||
{4, { "AUTOUSE_POTION", "AUTOUSE_ABILITY_UP", "AUTOUSE_BOMB", "AUTOUSE_GOLD", "AUTOUSE_MONEYBAG", "AUTOUSE_TREASURE_BOX"}},
|
||||
{5, { "MATERIAL_LEATHER", "MATERIAL_BLOOD", "MATERIAL_ROOT", "MATERIAL_NEEDLE", "MATERIAL_JEWEL",
|
||||
"MATERIAL_DS_REFINE_NORMAL", "MATERIAL_DS_REFINE_BLESSED", "MATERIAL_DS_REFINE_HOLLY"}},
|
||||
{6, { "SPECIAL_MAP", "SPECIAL_KEY", "SPECIAL_DOC", "SPECIAL_SPIRIT"}},
|
||||
{7, { "TOOL_FISHING_ROD"}},
|
||||
{8, { "LOTTERY_TICKET", "LOTTERY_INSTANT"}},
|
||||
{10, { "METIN_NORMAL", "METIN_GOLD"}},
|
||||
{12, { "FISH_ALIVE", "FISH_DEAD"}},
|
||||
{14, { "RESOURCE_FISHBONE", "RESOURCE_WATERSTONEPIECE", "RESOURCE_WATERSTONE", "RESOURCE_BLOOD_PEARL",
|
||||
"RESOURCE_BLUE_PEARL", "RESOURCE_WHITE_PEARL", "RESOURCE_BUCKET", "RESOURCE_CRYSTAL", "RESOURCE_GEM",
|
||||
"RESOURCE_STONE", "RESOURCE_METIN", "RESOURCE_ORE"}},
|
||||
{16, { "UNIQUE_NONE", "UNIQUE_BOOK", "UNIQUE_SPECIAL_RIDE", "UNIQUE_3", "UNIQUE_4", "UNIQUE_5",
|
||||
"UNIQUE_6", "UNIQUE_7", "UNIQUE_8", "UNIQUE_9", "USE_SPECIAL"}},
|
||||
{28, { "COSTUME_BODY", "COSTUME_HAIR", "COSTUME_MOUNT", "COSTUME_ACCE", "COSTUME_WEAPON"}},
|
||||
{29, { "DS_SLOT1", "DS_SLOT2", "DS_SLOT3", "DS_SLOT4", "DS_SLOT5", "DS_SLOT6"}},
|
||||
{31, { "EXTRACT_DRAGON_SOUL", "EXTRACT_DRAGON_HEART"}},
|
||||
{35, { "PET_EGG", "PET_UPBRINGING", "PET_BAG", "PET_FEEDSTUFF", "PET_SKILL",
|
||||
"PET_SKILL_DEL_BOOK", "PET_NAME_CHANGE", "PET_EXPFOOD", "PET_SKILL_ALL_DEL_BOOK", "PET_EXPFOOD_PER",
|
||||
"PET_ATTR_DETERMINE", "PET_ATTR_CHANGE", "PET_PAY", "PET_PRIMIUM_FEEDSTUFF"}},
|
||||
};
|
||||
|
||||
int get_Item_SubType_Value(int type_value, std::string inputString)
|
||||
{
|
||||
inputString = trim(inputString);
|
||||
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
|
||||
auto itType = mapItemSubType.find(type_value);
|
||||
if (itType == mapItemSubType.end())
|
||||
{
|
||||
sys_err("Type Out of range! (type_value: %d)", type_value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto vecSubtype = itType->second;
|
||||
auto itSubtype = std::find(vecSubtype.begin(), vecSubtype.end(), inputString);
|
||||
if (itSubtype == vecSubtype.end())
|
||||
{
|
||||
sys_err("Subtype Out of range! (type_value: %d)", type_value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return std::distance(vecSubtype.begin(), itSubtype);
|
||||
}
|
||||
|
||||
int get_Item_AntiFlag_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arAntiFlag[] = {"ANTI_FEMALE", "ANTI_MALE", "ANTI_MUSA", "ANTI_ASSASSIN", "ANTI_SURA", "ANTI_MUDANG",
|
||||
"ANTI_GET", "ANTI_DROP", "ANTI_SELL", "ANTI_EMPIRE_A", "ANTI_EMPIRE_B", "ANTI_EMPIRE_C",
|
||||
"ANTI_SAVE", "ANTI_GIVE", "ANTI_PKDROP", "ANTI_STACK", "ANTI_MYSHOP", "ANTI_SAFEBOX", "ANTI_WOLFMAN",
|
||||
"ANTI_PET20", "ANTI_PET21"};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, "|");
|
||||
for(size_t i=0;i<_countof(arAntiFlag);i++) {
|
||||
string tempString = arAntiFlag[i];
|
||||
for (size_t j=0; j<30 ; j++)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) {
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
if(tempString2.compare("") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete []arInputString;
|
||||
//cout << "AntiFlag : " << antiFlagStr << " -> " << retValue << endl;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
int get_Item_Flag_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arFlag[] = {"ITEM_TUNABLE", "ITEM_SAVE", "ITEM_STACKABLE", "COUNT_PER_1GOLD", "ITEM_SLOW_QUERY", "ITEM_UNIQUE",
|
||||
"ITEM_MAKECOUNT", "ITEM_IRREMOVABLE", "CONFIRM_WHEN_USE", "QUEST_USE", "QUEST_USE_MULTIPLE",
|
||||
"QUEST_GIVE", "ITEM_QUEST", "LOG", "STACKABLE", "SLOW_QUERY", "REFINEABLE", "IRREMOVABLE", "ITEM_APPLICABLE"};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, "|");
|
||||
for(size_t i=0;i<_countof(arFlag);i++) {
|
||||
string tempString = arFlag[i];
|
||||
for (size_t j=0; j<30 ; j++)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) {
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
if(tempString2.compare("") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete []arInputString;
|
||||
//cout << "Flag : " << flagStr << " -> " << retValue << endl;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
int get_Item_WearFlag_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arWearrFlag[] = {"WEAR_BODY", "WEAR_HEAD", "WEAR_FOOTS", "WEAR_WRIST", "WEAR_WEAPON", "WEAR_NECK", "WEAR_EAR", "WEAR_SHIELD", "WEAR_UNIQUE",
|
||||
"WEAR_ARROW", "WEAR_HAIR", "WEAR_ABILITY", "WEAR_PENDANT", "WEAR_GLOVE"
|
||||
};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, "|");
|
||||
for(size_t i=0;i<_countof(arWearrFlag);i++) {
|
||||
string tempString = arWearrFlag[i];
|
||||
for (size_t j=0; j<30 ; j++)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) {
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
if(tempString2.compare("") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete []arInputString;
|
||||
//cout << "WearFlag : " << wearFlagStr << " -> " << retValue << endl;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
int get_Item_Immune_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arImmune[] = {"PARA","CURSE","STUN","SLEEP","SLOW","POISON","TERROR"};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, "|");
|
||||
for(size_t i=0;i<_countof(arImmune);i++) {
|
||||
string tempString = arImmune[i];
|
||||
for (size_t j=0; j<30 ; j++)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) {
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
if(tempString2.compare("") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete []arInputString;
|
||||
//cout << "Immune : " << immuneStr << " -> " << retValue << endl;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
int get_Item_LimitType_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arLimitType[] = {"LIMIT_NONE", "LEVEL", "STR", "DEX", "INT", "CON", "PC_BANG", "REAL_TIME", "REAL_TIME_FIRST_USE", "TIMER_BASED_ON_WEAR"};
|
||||
|
||||
int retInt = -1;
|
||||
//cout << "LimitType : " << limitTypeStr << " -> ";
|
||||
for (unsigned int j=0;j<_countof(arLimitType);j++) {
|
||||
string tempString = arLimitType[j];
|
||||
string tempInputString = trim(inputString);
|
||||
if (tempInputString.compare(tempString)==0)
|
||||
{
|
||||
//cout << j << " ";
|
||||
retInt = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//cout << endl;
|
||||
|
||||
return retInt;
|
||||
}
|
||||
|
||||
int get_Item_ApplyType_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arApplyType[] = {"APPLY_NONE", "APPLY_MAX_HP", "APPLY_MAX_SP", "APPLY_CON", "APPLY_INT", "APPLY_STR", "APPLY_DEX", "APPLY_ATT_SPEED",
|
||||
"APPLY_MOV_SPEED", "APPLY_CAST_SPEED", "APPLY_HP_REGEN", "APPLY_SP_REGEN", "APPLY_POISON_PCT", "APPLY_STUN_PCT",
|
||||
"APPLY_SLOW_PCT", "APPLY_CRITICAL_PCT", "APPLY_PENETRATE_PCT", "APPLY_ATTBONUS_HUMAN", "APPLY_ATTBONUS_ANIMAL",
|
||||
"APPLY_ATTBONUS_ORC", "APPLY_ATTBONUS_MILGYO", "APPLY_ATTBONUS_UNDEAD", "APPLY_ATTBONUS_DEVIL", "APPLY_STEAL_HP",
|
||||
"APPLY_STEAL_SP", "APPLY_MANA_BURN_PCT", "APPLY_DAMAGE_SP_RECOVER", "APPLY_BLOCK", "APPLY_DODGE", "APPLY_RESIST_SWORD",
|
||||
"APPLY_RESIST_TWOHAND", "APPLY_RESIST_DAGGER", "APPLY_RESIST_BELL", "APPLY_RESIST_FAN", "APPLY_RESIST_BOW", "APPLY_RESIST_FIRE",
|
||||
"APPLY_RESIST_ELEC", "APPLY_RESIST_MAGIC", "APPLY_RESIST_WIND", "APPLY_REFLECT_MELEE", "APPLY_REFLECT_CURSE", "APPLY_POISON_REDUCE",
|
||||
"APPLY_KILL_SP_RECOVER", "APPLY_EXP_DOUBLE_BONUS", "APPLY_GOLD_DOUBLE_BONUS", "APPLY_ITEM_DROP_BONUS", "APPLY_POTION_BONUS",
|
||||
"APPLY_KILL_HP_RECOVER", "APPLY_IMMUNE_STUN", "APPLY_IMMUNE_SLOW", "APPLY_IMMUNE_FALL", "APPLY_SKILL", "APPLY_BOW_DISTANCE",
|
||||
"APPLY_ATT_GRADE_BONUS", "APPLY_DEF_GRADE_BONUS", "APPLY_MAGIC_ATT_GRADE", "APPLY_MAGIC_DEF_GRADE", "APPLY_CURSE_PCT",
|
||||
"APPLY_MAX_STAMINA", "APPLY_ATTBONUS_WARRIOR", "APPLY_ATTBONUS_ASSASSIN", "APPLY_ATTBONUS_SURA", "APPLY_ATTBONUS_SHAMAN",
|
||||
"APPLY_ATTBONUS_MONSTER", "APPLY_MALL_ATTBONUS", "APPLY_MALL_DEFBONUS", "APPLY_MALL_EXPBONUS", "APPLY_MALL_ITEMBONUS",
|
||||
"APPLY_MALL_GOLDBONUS", "APPLY_MAX_HP_PCT", "APPLY_MAX_SP_PCT", "APPLY_SKILL_DAMAGE_BONUS", "APPLY_NORMAL_HIT_DAMAGE_BONUS",
|
||||
"APPLY_SKILL_DEFEND_BONUS", "APPLY_NORMAL_HIT_DEFEND_BONUS", "APPLY_PC_BANG_EXP_BONUS", "APPLY_PC_BANG_DROP_BONUS",
|
||||
"APPLY_EXTRACT_HP_PCT", "APPLY_RESIST_WARRIOR", "APPLY_RESIST_ASSASSIN", "APPLY_RESIST_SURA", "APPLY_RESIST_SHAMAN",
|
||||
"APPLY_ENERGY", "APPLY_DEF_GRADE", "APPLY_COSTUME_ATTR_BONUS", "APPLY_MAGIC_ATTBONUS_PER", "APPLY_MELEE_MAGIC_ATTBONUS_PER",
|
||||
"APPLY_RESIST_ICE", "APPLY_RESIST_EARTH", "APPLY_RESIST_DARK", "APPLY_ANTI_CRITICAL_PCT", "APPLY_ANTI_PENETRATE_PCT",
|
||||
"APPLY_BLEEDING_REDUCE", "APPLY_BLEEDING_PCT", "APPLY_ATTBONUS_WOLFMAN", "APPLY_RESIST_WOLFMAN", "APPLY_RESIST_CLAW",
|
||||
"APPLY_ACCEDRAIN_RATE", "APPLY_RESIST_MAGIC_REDUCTION", // 97,98
|
||||
"APPLY_ENCHANT_ELECT", "APPLY_ENCHANT_FIRE", "APPLY_ENCHANT_ICE", "APPLY_ENCHANT_WIND", "APPLY_ENCHANT_EARTH", "APPLY_ENCHANT_DARK", // 99-104
|
||||
"APPLY_ATTBONUS_CZ","APPLY_ATTBONUS_INSECT","APPLY_ATTBONUS_DESERT","APPLY_ATTBONUS_SWORD","APPLY_ATTBONUS_TWOHAND", // 105,109
|
||||
"APPLY_ATTBONUS_DAGGER","APPLY_ATTBONUS_BELL","APPLY_ATTBONUS_FAN","APPLY_ATTBONUS_BOW","APPLY_ATTBONUS_CLAW", "APPLY_RESIST_HUMAN", // 110,115
|
||||
"APPLY_RESIST_MOUNT_FALL", "APPLY_UNK117", "APPLY_MOUNT" // 116-118
|
||||
};
|
||||
|
||||
int retInt = -1;
|
||||
//cout << "ApplyType : " << applyTypeStr << " -> ";
|
||||
for (size_t j=0;j<_countof(arApplyType);j++) {
|
||||
string tempString = arApplyType[j];
|
||||
string tempInputString = trim(inputString);
|
||||
if (tempInputString.compare(tempString)==0)
|
||||
{
|
||||
//cout << j << " ";
|
||||
retInt = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//cout << endl;
|
||||
|
||||
return retInt;
|
||||
}
|
||||
|
||||
int get_Mob_Rank_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arRank[] = {"PAWN", "S_PAWN", "KNIGHT", "S_KNIGHT", "BOSS", "KING"};
|
||||
|
||||
int retInt = -1;
|
||||
//cout << "Rank : " << rankStr << " -> ";
|
||||
for (size_t j=0;j<_countof(arRank);j++) {
|
||||
string tempString = arRank[j];
|
||||
string tempInputString = trim(inputString);
|
||||
if (tempInputString.compare(tempString)==0)
|
||||
{
|
||||
//cout << j << " ";
|
||||
retInt = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//cout << endl;
|
||||
|
||||
return retInt;
|
||||
}
|
||||
|
||||
int get_Mob_Type_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arType[] = { "MONSTER", "NPC", "STONE", "WARP", "DOOR", "BUILDING", "PC", "POLYMORPH_PC", "HORSE", "GOTO"};
|
||||
|
||||
int retInt = -1;
|
||||
//cout << "Type : " << typeStr << " -> ";
|
||||
for (size_t j=0;j<_countof(arType);j++) {
|
||||
string tempString = arType[j];
|
||||
string tempInputString = trim(inputString);
|
||||
if (tempInputString.compare(tempString)==0)
|
||||
{
|
||||
//cout << j << " ";
|
||||
retInt = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//cout << endl;
|
||||
|
||||
return retInt;
|
||||
}
|
||||
|
||||
int get_Mob_BattleType_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arBattleType[] = { "MELEE", "RANGE", "MAGIC", "SPECIAL", "POWER", "TANKER", "SUPER_POWER", "SUPER_TANKER"};
|
||||
|
||||
int retInt = -1;
|
||||
//cout << "Battle Type : " << battleTypeStr << " -> ";
|
||||
for (size_t j=0;j<_countof(arBattleType);j++) {
|
||||
string tempString = arBattleType[j];
|
||||
string tempInputString = trim(inputString);
|
||||
if (tempInputString.compare(tempString)==0)
|
||||
{
|
||||
//cout << j << " ";
|
||||
retInt = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//cout << endl;
|
||||
|
||||
return retInt;
|
||||
}
|
||||
|
||||
int get_Mob_Size_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arSize[] = { "SMALL", "MEDIUM", "BIG"}; //@fixme201 SAMLL to SMALL
|
||||
|
||||
int retInt = 0;
|
||||
//cout << "Size : " << sizeStr << " -> ";
|
||||
for (size_t j=0;j<_countof(arSize);j++) {
|
||||
string tempString = arSize[j];
|
||||
string tempInputString = trim(inputString);
|
||||
if (tempInputString.compare(tempString)==0)
|
||||
{
|
||||
//cout << j << " ";
|
||||
retInt = j + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//cout << endl;
|
||||
|
||||
return retInt;
|
||||
}
|
||||
|
||||
int get_Mob_AIFlag_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arAIFlag[] = {"AGGR","NOMOVE","COWARD","NOATTSHINSU","NOATTCHUNJO","NOATTJINNO","ATTMOB","BERSERK","STONESKIN","GODSPEED","DEATHBLOW","REVIVE",
|
||||
};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, ",");
|
||||
for (size_t i =0;i<_countof(arAIFlag);i++) {
|
||||
string tempString = arAIFlag[i];
|
||||
for (size_t j=0; j<30 ; j++)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) {
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
if(tempString2.compare("") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete []arInputString;
|
||||
//cout << "AIFlag : " << aiFlagStr << " -> " << retValue << endl;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
int get_Mob_RaceFlag_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arRaceFlag[] = {"ANIMAL","UNDEAD","DEVIL","HUMAN","ORC","MILGYO","INSECT","FIRE","ICE","DESERT","TREE",
|
||||
"ATT_ELEC","ATT_FIRE","ATT_ICE","ATT_WIND","ATT_EARTH","ATT_DARK","ZODIAC"};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, ",");
|
||||
for(size_t i =0;i<_countof(arRaceFlag);i++) {
|
||||
string tempString = arRaceFlag[i];
|
||||
for (size_t j=0; j<30 ; j++)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) {
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
if(tempString2.compare("") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete []arInputString;
|
||||
//cout << "Race Flag : " << raceFlagStr << " -> " << retValue << endl;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
int get_Mob_ImmuneFlag_Value(string inputString)
|
||||
{
|
||||
#ifdef ENABLE_NUMERIC_FIELD
|
||||
if (_IsNumericString(inputString))
|
||||
return std::stoi(inputString);
|
||||
#endif
|
||||
string arImmuneFlag[] = {"STUN","SLOW","FALL","CURSE","POISON","TERROR", "REFLECT"};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, ",");
|
||||
for(size_t i =0;i<_countof(arImmuneFlag);i++) {
|
||||
string tempString = arImmuneFlag[i];
|
||||
for (size_t j=0; j<30 ; j++)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) {
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
if(tempString2.compare("") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete []arInputString;
|
||||
//cout << "Immune Flag : " << immuneFlagStr << " -> " << retValue << endl;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
#ifndef __DUMP_PROTO__
|
||||
|
||||
bool Set_Proto_Mob_Table(TMobTable *mobTable, cCsvTable &csvTable,std::map<int,const char*> &nameMap)
|
||||
{
|
||||
int col = 0;
|
||||
str_to_number(mobTable->dwVnum, csvTable.AsStringByIndex(col++));
|
||||
strlcpy(mobTable->szName, csvTable.AsStringByIndex(col++), sizeof(mobTable->szName));
|
||||
|
||||
auto it = nameMap.find(mobTable->dwVnum);
|
||||
if (it != nameMap.end()) {
|
||||
const char * localeName = it->second;
|
||||
strlcpy(mobTable->szLocaleName, localeName, sizeof(mobTable->szLocaleName));
|
||||
} else {
|
||||
strlcpy(mobTable->szLocaleName, mobTable->szName, sizeof(mobTable->szLocaleName));
|
||||
}
|
||||
|
||||
//RANK
|
||||
int rankValue = get_Mob_Rank_Value(csvTable.AsStringByIndex(col++));
|
||||
mobTable->bRank = rankValue;
|
||||
//TYPE
|
||||
int typeValue = get_Mob_Type_Value(csvTable.AsStringByIndex(col++));
|
||||
mobTable->bType = typeValue;
|
||||
//BATTLE_TYPE
|
||||
int battleTypeValue = get_Mob_BattleType_Value(csvTable.AsStringByIndex(col++));
|
||||
mobTable->bBattleType = battleTypeValue;
|
||||
|
||||
str_to_number(mobTable->bLevel, csvTable.AsStringByIndex(col++));
|
||||
//SIZE
|
||||
int sizeValue = get_Mob_Size_Value(csvTable.AsStringByIndex(col++));
|
||||
mobTable->bSize = sizeValue;
|
||||
//AI_FLAG
|
||||
int aiFlagValue = get_Mob_AIFlag_Value(csvTable.AsStringByIndex(col++));
|
||||
mobTable->dwAIFlag = aiFlagValue;
|
||||
//mount_capacity;
|
||||
col++;
|
||||
//RACE_FLAG
|
||||
int raceFlagValue = get_Mob_RaceFlag_Value(csvTable.AsStringByIndex(col++));
|
||||
mobTable->dwRaceFlag = raceFlagValue;
|
||||
//IMMUNE_FLAG
|
||||
int immuneFlagValue = get_Mob_ImmuneFlag_Value(csvTable.AsStringByIndex(col++));
|
||||
mobTable->dwImmuneFlag = immuneFlagValue;
|
||||
|
||||
str_to_number(mobTable->bEmpire, csvTable.AsStringByIndex(col++)); //col = 11
|
||||
|
||||
strlcpy(mobTable->szFolder, csvTable.AsStringByIndex(col++), sizeof(mobTable->szFolder));
|
||||
|
||||
str_to_number(mobTable->bOnClickType, csvTable.AsStringByIndex(col++));
|
||||
|
||||
str_to_number(mobTable->bStr, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bDex, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bCon, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bInt, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->dwDamageRange[0], csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->dwDamageRange[1], csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->dwMaxHP, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bRegenCycle, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bRegenPercent, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->dwGoldMin, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->dwGoldMax, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->dwExp, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->wDef, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->sAttackSpeed, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->sMovingSpeed, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bAggresiveHPPct, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->wAggressiveSight, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->wAttackRange, csvTable.AsStringByIndex(col++));
|
||||
|
||||
str_to_number(mobTable->dwDropItemVnum, csvTable.AsStringByIndex(col++)); //32
|
||||
str_to_number(mobTable->dwResurrectionVnum, csvTable.AsStringByIndex(col++));
|
||||
for (int i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i)
|
||||
str_to_number(mobTable->cEnchants[i], csvTable.AsStringByIndex(col++));
|
||||
|
||||
for (int i = 0; i < MOB_RESISTS_MAX_NUM; ++i)
|
||||
str_to_number(mobTable->cResists[i], csvTable.AsStringByIndex(col++));
|
||||
|
||||
str_to_number(mobTable->fDamMultiply, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->dwSummonVnum, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->dwDrainSP, csvTable.AsStringByIndex(col++));
|
||||
|
||||
//Mob_Color
|
||||
++col;
|
||||
|
||||
str_to_number(mobTable->dwPolymorphItemVnum, csvTable.AsStringByIndex(col++));
|
||||
|
||||
str_to_number(mobTable->Skills[0].bLevel, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->Skills[0].dwVnum, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->Skills[1].bLevel, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->Skills[1].dwVnum, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->Skills[2].bLevel, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->Skills[2].dwVnum, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->Skills[3].bLevel, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->Skills[3].dwVnum, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->Skills[4].bLevel, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->Skills[4].dwVnum, csvTable.AsStringByIndex(col++));
|
||||
|
||||
str_to_number(mobTable->bBerserkPoint, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bStoneSkinPoint, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bGodSpeedPoint, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bDeathBlowPoint, csvTable.AsStringByIndex(col++));
|
||||
str_to_number(mobTable->bRevivePoint, csvTable.AsStringByIndex(col++));
|
||||
|
||||
sys_log(0, "MOB #%-5d %-24s level: %-3u rank: %u empire: %d", mobTable->dwVnum, mobTable->szLocaleName, mobTable->bLevel, mobTable->bRank, mobTable->bEmpire);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Set_Proto_Item_Table(TItemTable *itemTable, cCsvTable &csvTable,std::map<int,const char*> &nameMap)
|
||||
{
|
||||
int col = 0;
|
||||
|
||||
int dataArray[33];
|
||||
for (size_t i=0; i<_countof(dataArray);i++) {
|
||||
int validCheck = 0;
|
||||
if (i==2) {
|
||||
dataArray[i] = get_Item_Type_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==3) {
|
||||
dataArray[i] = get_Item_SubType_Value(dataArray[i-1], csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==5) {
|
||||
dataArray[i] = get_Item_AntiFlag_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==6) {
|
||||
dataArray[i] = get_Item_Flag_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==7) {
|
||||
dataArray[i] = get_Item_WearFlag_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==8) {
|
||||
dataArray[i] = get_Item_Immune_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==14) {
|
||||
dataArray[i] = get_Item_LimitType_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==16) {
|
||||
dataArray[i] = get_Item_LimitType_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==18) {
|
||||
dataArray[i] = get_Item_ApplyType_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==20) {
|
||||
dataArray[i] = get_Item_ApplyType_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else if (i==22) {
|
||||
dataArray[i] = get_Item_ApplyType_Value(csvTable.AsStringByIndex(col));
|
||||
validCheck = dataArray[i];
|
||||
} else {
|
||||
str_to_number(dataArray[i], csvTable.AsStringByIndex(col));
|
||||
}
|
||||
|
||||
if (validCheck == -1)
|
||||
{
|
||||
std::ostringstream dataStream;
|
||||
|
||||
for (size_t j = 0; j < i; ++j)
|
||||
dataStream << dataArray[j] << ",";
|
||||
|
||||
//fprintf(stderr, "ItemProto Reading Failed : Invalid value.\n");
|
||||
sys_err("ItemProto Reading Failed : Invalid value. (index: %d, col: %d, value: %s)", i, col, csvTable.AsStringByIndex(col));
|
||||
sys_err("\t%d ~ %d Values: %s", 0, i, dataStream.str().c_str());
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
col = col + 1;
|
||||
}
|
||||
|
||||
{
|
||||
std::string s(csvTable.AsStringByIndex(0));
|
||||
size_t pos = s.find("~");
|
||||
if (std::string::npos == pos)
|
||||
{
|
||||
itemTable->dwVnum = dataArray[0];
|
||||
itemTable->dwVnumRange = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string s_start_vnum (s.substr(0, pos));
|
||||
std::string s_end_vnum (s.substr(pos +1 ));
|
||||
|
||||
int start_vnum = atoi(s_start_vnum.c_str());
|
||||
int end_vnum = atoi(s_end_vnum.c_str());
|
||||
if (0 == start_vnum || (0 != end_vnum && end_vnum < start_vnum))
|
||||
{
|
||||
sys_err ("INVALID VNUM %s", s.c_str());
|
||||
return false;
|
||||
}
|
||||
itemTable->dwVnum = start_vnum;
|
||||
itemTable->dwVnumRange = end_vnum - start_vnum;
|
||||
}
|
||||
}
|
||||
|
||||
strlcpy(itemTable->szName, csvTable.AsStringByIndex(1), sizeof(itemTable->szName));
|
||||
auto it = nameMap.find(itemTable->dwVnum);
|
||||
if (it != nameMap.end()) {
|
||||
const char * localeName = it->second;
|
||||
strlcpy(itemTable->szLocaleName, localeName, sizeof(itemTable->szLocaleName));
|
||||
} else {
|
||||
strlcpy(itemTable->szLocaleName, itemTable->szName, sizeof(itemTable->szLocaleName));
|
||||
}
|
||||
itemTable->bType = dataArray[2];
|
||||
itemTable->bSubType = dataArray[3];
|
||||
itemTable->bSize = MINMAX(1, dataArray[4], 3); // @fixme179
|
||||
itemTable->dwAntiFlags = dataArray[5];
|
||||
itemTable->dwFlags = dataArray[6];
|
||||
itemTable->dwWearFlags = dataArray[7];
|
||||
itemTable->dwImmuneFlag = dataArray[8];
|
||||
itemTable->dwGold = dataArray[9];
|
||||
itemTable->dwShopBuyPrice = dataArray[10];
|
||||
itemTable->dwRefinedVnum = dataArray[11];
|
||||
itemTable->wRefineSet = dataArray[12];
|
||||
itemTable->bAlterToMagicItemPct = dataArray[13];
|
||||
itemTable->cLimitRealTimeFirstUseIndex = -1;
|
||||
itemTable->cLimitTimerBasedOnWearIndex = -1;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
|
||||
{
|
||||
itemTable->aLimits[i].bType = dataArray[14+i*2];
|
||||
itemTable->aLimits[i].lValue = dataArray[15+i*2];
|
||||
|
||||
if (LIMIT_REAL_TIME_START_FIRST_USE == itemTable->aLimits[i].bType)
|
||||
itemTable->cLimitRealTimeFirstUseIndex = (char)i;
|
||||
|
||||
if (LIMIT_TIMER_BASED_ON_WEAR == itemTable->aLimits[i].bType)
|
||||
itemTable->cLimitTimerBasedOnWearIndex = (char)i;
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
|
||||
{
|
||||
itemTable->aApplies[i].bType = dataArray[18+i*2];
|
||||
itemTable->aApplies[i].lValue = dataArray[19+i*2];
|
||||
}
|
||||
|
||||
for (i = 0; i < ITEM_VALUES_MAX_NUM; ++i)
|
||||
itemTable->alValues[i] = dataArray[24+i];
|
||||
|
||||
itemTable->bGainSocketPct = dataArray[31];
|
||||
itemTable->sAddonType = dataArray[32];
|
||||
|
||||
str_to_number(itemTable->bWeight, "0");
|
||||
|
||||
#ifdef ENABLE_CHECK_SELL_PRICE
|
||||
auto dwPrice = itemTable->dwShopBuyPrice;
|
||||
#ifndef ENABLE_NO_SELL_PRICE_DIVIDED_BY_5
|
||||
dwPrice /= 5;
|
||||
#endif
|
||||
if (dwPrice > itemTable->dwGold)
|
||||
{
|
||||
sys_err("ITEM: #%-5lu %-24s SELL_OVERFLOW dwGold: %u < dwShopBuyPrice %u",
|
||||
itemTable->dwVnum,
|
||||
itemTable->szLocaleName,
|
||||
itemTable->dwGold,
|
||||
dwPrice
|
||||
);
|
||||
itemTable->dwGold = dwPrice;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
34
source-server/Srcs/Server/db/src/ProtoReader.h
Normal file
34
source-server/Srcs/Server/db/src/ProtoReader.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef __Item_CSV_READER_H__
|
||||
#define __Item_CSV_READER_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include "CsvReader.h"
|
||||
|
||||
void putItemIntoTable();
|
||||
|
||||
int get_Item_Type_Value(std::string inputString);
|
||||
int get_Item_SubType_Value(int type_value, std::string inputString);
|
||||
int get_Item_AntiFlag_Value(std::string inputString);
|
||||
int get_Item_Flag_Value(std::string inputString);
|
||||
int get_Item_WearFlag_Value(std::string inputString);
|
||||
int get_Item_Immune_Value(std::string inputString);
|
||||
int get_Item_LimitType_Value(std::string inputString);
|
||||
int get_Item_ApplyType_Value(std::string inputString);
|
||||
|
||||
int get_Mob_Rank_Value(std::string inputString);
|
||||
int get_Mob_Type_Value(std::string inputString);
|
||||
int get_Mob_BattleType_Value(std::string inputString);
|
||||
|
||||
int get_Mob_Size_Value(std::string inputString);
|
||||
int get_Mob_AIFlag_Value(std::string inputString);
|
||||
int get_Mob_RaceFlag_Value(std::string inputString);
|
||||
int get_Mob_ImmuneFlag_Value(std::string inputString);
|
||||
|
||||
//
|
||||
bool Set_Proto_Mob_Table(TMobTable *mobTable, cCsvTable &csvTable, std::map<int,const char*> &nameMap);
|
||||
bool Set_Proto_Item_Table(TItemTable *itemTable, cCsvTable &csvTable,std::map<int,const char*> &nameMap);
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
36
source-server/Srcs/Server/db/src/QID.h
Normal file
36
source-server/Srcs/Server/db/src/QID.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef __INC_METIN_II_DB_QID_H__
|
||||
#define __INC_METIN_II_DB_QID_H__
|
||||
|
||||
enum QID
|
||||
{
|
||||
QID_PLAYER, // 0
|
||||
QID_ITEM, // 1
|
||||
QID_QUEST, // 2
|
||||
QID_AFFECT, // 3
|
||||
QID_LOGIN, // 4
|
||||
QID_SAFEBOX_LOAD, // 5
|
||||
QID_SAFEBOX_CHANGE_SIZE, // 6
|
||||
QID_SAFEBOX_CHANGE_PASSWORD, // 7
|
||||
QID_SAFEBOX_CHANGE_PASSWORD_SECOND, // 8
|
||||
QID_SAFEBOX_SAVE, // 9
|
||||
QID_ITEM_SAVE, // 10
|
||||
QID_ITEM_DESTROY, // 11
|
||||
QID_QUEST_SAVE, // 12
|
||||
QID_PLAYER_SAVE, // 13
|
||||
QID_PLAYER_DELETE, // 15
|
||||
QID_LOGIN_BY_KEY, // 16
|
||||
QID_PLAYER_INDEX_CREATE, // 17
|
||||
QID_ITEM_AWARD_LOAD, // 18
|
||||
QID_ITEM_AWARD_TAKEN, // 19
|
||||
QID_GUILD_RANKING, // 20
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
QID_ITEMPRICE_SAVE,
|
||||
QID_ITEMPRICE_DESTROY,
|
||||
QID_ITEMPRICE_LOAD_FOR_UPDATE,
|
||||
QID_ITEMPRICE_LOAD,
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
190
source-server/Srcs/Server/db/src/db.vcxproj
Normal file
190
source-server/Srcs/Server/db/src/db.vcxproj
Normal file
@ -0,0 +1,190 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>db</ProjectName>
|
||||
<ProjectGuid>{ADC2E26A-C39B-4817-A24C-A99827B74EB2}</ProjectGuid>
|
||||
<RootNamespace>db</RootNamespace>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\db\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../bin/release\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)../../libmysql/6.0.2/win32;$(ProjectDir)../../../Extern/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NOMINMAX;_DEBUG;_CONSOLE;__WIN32__;_CRT_SECURE_NO_WARNINGS;_USE_32BIT_TIME_T;_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>libmysql.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(ProjectName)_d.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)../../libmysql/6.0.2/win32/lib;$(ProjectDir)../../../Extern/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMT;libcpmt;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)../../libmysql/6.0.2/win32;$(ProjectDir)../../../Extern/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NOMINMAX;NDEBUG;_CONSOLE;__WIN32__;_CRT_SECURE_NO_WARNINGS;_USE_32BIT_TIME_T;_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>libmysql.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)../../libmysql/6.0.2/win32/lib;$(ProjectDir)../../../Extern/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Cache.cpp" />
|
||||
<ClCompile Include="ClientManager.cpp" />
|
||||
<ClCompile Include="ClientManagerBoot.cpp" />
|
||||
<ClCompile Include="ClientManagerEventFlag.cpp" />
|
||||
<ClCompile Include="ClientManagerGuild.cpp" />
|
||||
<ClCompile Include="ClientManagerHorseName.cpp" />
|
||||
<ClCompile Include="ClientManagerLogin.cpp" />
|
||||
<ClCompile Include="ClientManagerParty.cpp" />
|
||||
<ClCompile Include="ClientManagerPlayer.cpp" />
|
||||
<ClCompile Include="Config.cpp" />
|
||||
<ClCompile Include="CsvReader.cpp" />
|
||||
<ClCompile Include="DBManager.cpp" />
|
||||
<ClCompile Include="GuildManager.cpp" />
|
||||
<ClCompile Include="HB.cpp" />
|
||||
<ClCompile Include="ItemAwardManager.cpp" />
|
||||
<ClCompile Include="ItemIDRangeManager.cpp" />
|
||||
<ClCompile Include="Lock.cpp" />
|
||||
<ClCompile Include="LoginData.cpp" />
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="Marriage.cpp" />
|
||||
<ClCompile Include="Monarch.cpp" />
|
||||
<ClCompile Include="MoneyLog.cpp" />
|
||||
<ClCompile Include="NetBase.cpp" />
|
||||
<ClCompile Include="Peer.cpp" />
|
||||
<ClCompile Include="PeerBase.cpp" />
|
||||
<ClCompile Include="PrivManager.cpp" />
|
||||
<ClCompile Include="ProtoReader.cpp" />
|
||||
<ClCompile Include="version.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Cache.h" />
|
||||
<ClInclude Include="ClientManager.h" />
|
||||
<ClInclude Include="Config.h" />
|
||||
<ClInclude Include="CsvReader.h" />
|
||||
<ClInclude Include="DBManager.h" />
|
||||
<ClInclude Include="GuildManager.h" />
|
||||
<ClInclude Include="HB.h" />
|
||||
<ClInclude Include="ItemAwardManager.h" />
|
||||
<ClInclude Include="ItemIDRangeManager.h" />
|
||||
<ClInclude Include="Lock.h" />
|
||||
<ClInclude Include="LoginData.h" />
|
||||
<ClInclude Include="Main.h" />
|
||||
<ClInclude Include="Marriage.h" />
|
||||
<ClInclude Include="Monarch.h" />
|
||||
<ClInclude Include="MoneyLog.h" />
|
||||
<ClInclude Include="NetBase.h" />
|
||||
<ClInclude Include="Peer.h" />
|
||||
<ClInclude Include="PeerBase.h" />
|
||||
<ClInclude Include="PrivManager.h" />
|
||||
<ClInclude Include="ProtoReader.h" />
|
||||
<ClInclude Include="QID.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libgame\libgame.vcxproj">
|
||||
<Project>{2ab4a5a4-3eaa-4486-b93c-38e8d39bf218}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\libpoly\libpoly.vcxproj">
|
||||
<Project>{bd8e86dd-07ba-49b0-bf04-3282da8377eb}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\libsql\libsql.vcxproj">
|
||||
<Project>{3967853d-4e19-4548-ac3a-f6012b78e384}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\libthecore\libthecore.vcxproj">
|
||||
<Project>{5c8620c9-5d1f-419d-8267-48d2863c3d13}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
163
source-server/Srcs/Server/db/src/db.vcxproj.filters
Normal file
163
source-server/Srcs/Server/db/src/db.vcxproj.filters
Normal file
@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Cache.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ClientManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ClientManagerBoot.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ClientManagerEventFlag.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ClientManagerGuild.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ClientManagerHorseName.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ClientManagerLogin.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ClientManagerParty.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ClientManagerPlayer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Config.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CsvReader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DBManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GuildManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HB.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ItemAwardManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ItemIDRangeManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Lock.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LoginData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Marriage.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Monarch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MoneyLog.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NetBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Peer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PeerBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PrivManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ProtoReader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="version.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Cache.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ClientManager.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Config.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CsvReader.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DBManager.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GuildManager.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HB.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ItemAwardManager.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ItemIDRangeManager.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Lock.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LoginData.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Main.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Marriage.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Monarch.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MoneyLog.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NetBase.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Peer.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PeerBase.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PrivManager.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ProtoReader.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="QID.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
3
source-server/Srcs/Server/db/src/db.vcxproj.user
Normal file
3
source-server/Srcs/Server/db/src/db.vcxproj.user
Normal file
@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
</Project>
|
||||
21
source-server/Srcs/Server/db/src/stdafx.h
Normal file
21
source-server/Srcs/Server/db/src/stdafx.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __INC_METiN_II_DBSERV_STDAFX_H__
|
||||
#define __INC_METiN_II_DBSERV_STDAFX_H__
|
||||
|
||||
#include "../../libthecore/include/stdafx.h"
|
||||
|
||||
#ifndef __WIN32__
|
||||
#include <semaphore.h>
|
||||
#else
|
||||
#define isdigit iswdigit
|
||||
#define isspace iswspace
|
||||
#endif
|
||||
|
||||
#include "../../common/length.h"
|
||||
#include "../../common/tables.h"
|
||||
#include "../../common/singleton.h"
|
||||
#include "../../common/utils.h"
|
||||
#include "../../common/stl.h"
|
||||
#include "../../common/service.h"
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
22
source-server/Srcs/Server/db/src/version.cpp
Normal file
22
source-server/Srcs/Server/db/src/version.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void WriteVersion()
|
||||
{
|
||||
#ifndef __WIN32__
|
||||
FILE* fp(fopen("VERSION.txt", "w"));
|
||||
|
||||
if (NULL != fp)
|
||||
{
|
||||
fprintf(fp, "__DB_VERSION__: %s\n", __DB_VERSION__);
|
||||
fprintf(fp, "%s@%s:%s\n", "cHVjaGF0eQ==", __HOSTNAME__, __PWD__);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "cannot open VERSION.txt\n");
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
194
source-server/Srcs/Server/game/src/BlueDragon.cpp
Normal file
194
source-server/Srcs/Server/game/src/BlueDragon.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
#include "stdafx.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "BlueDragon.h"
|
||||
|
||||
#include "vector.h"
|
||||
#include "utils.h"
|
||||
#include "char.h"
|
||||
#include "mob_manager.h"
|
||||
#include "sectree_manager.h"
|
||||
#include "battle.h"
|
||||
#include "affect.h"
|
||||
#include "BlueDragon_Binder.h"
|
||||
#include "BlueDragon_Skill.h"
|
||||
#include "packet.h"
|
||||
#include "motion.h"
|
||||
|
||||
time_t UseBlueDragonSkill(LPCHARACTER pChar, unsigned int idx)
|
||||
{
|
||||
LPSECTREE_MAP pSecMap = SECTREE_MANAGER::instance().GetMap( pChar->GetMapIndex() );
|
||||
|
||||
if (NULL == pSecMap)
|
||||
return 0;
|
||||
|
||||
int nextUsingTime = 0;
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
sys_log(0, "BlueDragon: Using Skill Breath");
|
||||
|
||||
FSkillBreath f(pChar);
|
||||
|
||||
pSecMap->for_each( f );
|
||||
|
||||
nextUsingTime = number(BlueDragon_GetSkillFactor(3, "Skill0", "period", "min"), BlueDragon_GetSkillFactor(3, "Skill0", "period", "max"));
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
sys_log(0, "BlueDragon: Using Skill Weak Breath");
|
||||
|
||||
FSkillWeakBreath f(pChar);
|
||||
|
||||
pSecMap->for_each( f );
|
||||
|
||||
nextUsingTime = number(BlueDragon_GetSkillFactor(3, "Skill1", "period", "min"), BlueDragon_GetSkillFactor(3, "Skill1", "period", "max"));
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
sys_log(0, "BlueDragon: Using Skill EarthQuake");
|
||||
|
||||
FSkillEarthQuake f(pChar);
|
||||
|
||||
pSecMap->for_each( f );
|
||||
|
||||
nextUsingTime = number(BlueDragon_GetSkillFactor(3, "Skill2", "period", "min"), BlueDragon_GetSkillFactor(3, "Skill2", "period", "max"));
|
||||
|
||||
if (NULL != f.pFarthestChar)
|
||||
{
|
||||
pChar->BeginFight( f.pFarthestChar );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sys_err("BlueDragon: Wrong Skill Index: %d", idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int addPct = BlueDragon_GetRangeFactor("hp_period", pChar->GetHPPct());
|
||||
|
||||
nextUsingTime += (nextUsingTime * addPct) / 100;
|
||||
|
||||
return nextUsingTime;
|
||||
}
|
||||
|
||||
int BlueDragon_StateBattle(LPCHARACTER pChar)
|
||||
{
|
||||
if (pChar->GetHPPct() > 98)
|
||||
return PASSES_PER_SEC(1);
|
||||
|
||||
const int SkillCount = 3;
|
||||
int SkillPriority[SkillCount];
|
||||
static time_t timeSkillCanUseTime[SkillCount];
|
||||
|
||||
if (pChar->GetHPPct() > 76)
|
||||
{
|
||||
SkillPriority[0] = 1;
|
||||
SkillPriority[1] = 0;
|
||||
SkillPriority[2] = 2;
|
||||
}
|
||||
else if (pChar->GetHPPct() > 31)
|
||||
{
|
||||
SkillPriority[0] = 0;
|
||||
SkillPriority[1] = 1;
|
||||
SkillPriority[2] = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
SkillPriority[0] = 0;
|
||||
SkillPriority[1] = 2;
|
||||
SkillPriority[2] = 1;
|
||||
}
|
||||
|
||||
time_t timeNow = static_cast<time_t>(get_dword_time());
|
||||
|
||||
for (int i=0 ; i < SkillCount ; ++i)
|
||||
{
|
||||
const int SkillIndex = SkillPriority[i];
|
||||
|
||||
if (timeSkillCanUseTime[SkillIndex] < timeNow)
|
||||
{
|
||||
int SkillUsingDuration =
|
||||
static_cast<int>(CMotionManager::instance().GetMotionDuration( pChar->GetRaceNum(), MAKE_MOTION_KEY(MOTION_MODE_GENERAL, MOTION_SPECIAL_1 + SkillIndex) ));
|
||||
|
||||
timeSkillCanUseTime[SkillIndex] = timeNow + (UseBlueDragonSkill( pChar, SkillIndex ) * 1000) + SkillUsingDuration + 3000;
|
||||
|
||||
pChar->SendMovePacket(FUNC_MOB_SKILL, SkillIndex, pChar->GetX(), pChar->GetY(), 0, timeNow);
|
||||
|
||||
return 0 == SkillUsingDuration ? PASSES_PER_SEC(1) : PASSES_PER_SEC(SkillUsingDuration);
|
||||
}
|
||||
}
|
||||
|
||||
return PASSES_PER_SEC(1);
|
||||
}
|
||||
|
||||
int BlueDragon_Damage (LPCHARACTER me, LPCHARACTER pAttacker, int dam)
|
||||
{
|
||||
if (NULL == me || NULL == pAttacker)
|
||||
return dam;
|
||||
|
||||
if (true == pAttacker->IsMonster() && 2493 == pAttacker->GetMobTable().dwVnum)
|
||||
{
|
||||
for (int i=1 ; i <= 4 ; ++i)
|
||||
{
|
||||
if (ATK_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type"))
|
||||
{
|
||||
DWORD dwDragonStoneID = BlueDragon_GetIndexFactor("DragonStone", i, "vnum");
|
||||
size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "val");
|
||||
size_t cnt = SECTREE_MANAGER::instance().GetMonsterCountInMap( pAttacker->GetMapIndex(), dwDragonStoneID );
|
||||
|
||||
dam += (dam * (val*cnt))/100;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (true == me->IsMonster() && 2493 == me->GetMobTable().dwVnum)
|
||||
{
|
||||
for (int i=1 ; i <= 4 ; ++i)
|
||||
{
|
||||
if (DEF_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type"))
|
||||
{
|
||||
DWORD dwDragonStoneID = BlueDragon_GetIndexFactor("DragonStone", i, "vnum");
|
||||
size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "val");
|
||||
size_t cnt = SECTREE_MANAGER::instance().GetMonsterCountInMap( me->GetMapIndex(), dwDragonStoneID );
|
||||
|
||||
dam -= (dam * (val*cnt))/100;
|
||||
|
||||
if (dam <= 0)
|
||||
dam = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (true == me->IsStone() && 0 != pAttacker->GetMountVnum())
|
||||
{
|
||||
for (int i=1 ; i <= 4 ; ++i)
|
||||
{
|
||||
if (me->GetMobTable().dwVnum == BlueDragon_GetIndexFactor("DragonStone", i, "vnum"))
|
||||
{
|
||||
if (pAttacker->GetMountVnum() == BlueDragon_GetIndexFactor("DragonStone", i, "enemy"))
|
||||
{
|
||||
size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "enemy_val");
|
||||
|
||||
dam *= val;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dam;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
4
source-server/Srcs/Server/game/src/BlueDragon.h
Normal file
4
source-server/Srcs/Server/game/src/BlueDragon.h
Normal file
@ -0,0 +1,4 @@
|
||||
extern int BlueDragon_StateBattle (LPCHARACTER);
|
||||
extern time_t UseBlueDragonSkill (LPCHARACTER, unsigned int);
|
||||
extern int BlueDragon_Damage (LPCHARACTER me, LPCHARACTER attacker, int dam);
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
217
source-server/Srcs/Server/game/src/BlueDragon_Binder.cpp
Normal file
217
source-server/Srcs/Server/game/src/BlueDragon_Binder.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "BlueDragon_Binder.h"
|
||||
|
||||
#include "questmanager.h"
|
||||
|
||||
unsigned int BlueDragon_GetSkillFactor(const size_t cnt, ...)
|
||||
{
|
||||
lua_State* L = quest::CQuestManager::instance().GetLuaState();
|
||||
|
||||
const int stack_top = lua_gettop(L);
|
||||
|
||||
lua_getglobal( L, "BlueDragonSetting" );
|
||||
|
||||
if (false == lua_istable(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, cnt);
|
||||
|
||||
for( size_t i=0 ; i < cnt ; ++i )
|
||||
{
|
||||
const char* key = va_arg(vl, const char*);
|
||||
|
||||
if (NULL == key)
|
||||
{
|
||||
va_end(vl);
|
||||
lua_settop( L, stack_top );
|
||||
sys_err("BlueDragon: wrong key list");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushstring( L, key );
|
||||
lua_gettable( L, -2 );
|
||||
|
||||
if (false == lua_istable(L, -1) && i != cnt-1)
|
||||
{
|
||||
va_end(vl);
|
||||
lua_settop( L, stack_top );
|
||||
sys_err("BlueDragon: wrong key table %s", key);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(vl);
|
||||
|
||||
if (false == lua_isnumber(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
sys_err("BlueDragon: Last key is not a number");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int val = static_cast<int>(lua_tonumber( L, -1 ));
|
||||
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
unsigned int BlueDragon_GetRangeFactor(const char* key, const int val)
|
||||
{
|
||||
lua_State* L = quest::CQuestManager::instance().GetLuaState();
|
||||
|
||||
const int stack_top = lua_gettop(L);
|
||||
|
||||
lua_getglobal( L, "BlueDragonSetting" );
|
||||
|
||||
if (false == lua_istable(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushstring( L, key );
|
||||
lua_gettable( L, -2 );
|
||||
|
||||
if (false == lua_istable(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
sys_err("BlueDragon: no required table %s", key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t cnt = static_cast<size_t>(luaL_getn(L, -1));
|
||||
|
||||
for( size_t i=1 ; i <= cnt ; ++i )
|
||||
{
|
||||
lua_rawgeti( L, -1, i );
|
||||
|
||||
if (false == lua_istable(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
sys_err("BlueDragon: wrong table index %s %d", key, i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushstring( L, "min" );
|
||||
lua_gettable( L, -2 );
|
||||
|
||||
if (false == lua_isnumber(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
sys_err("BlueDragon: no min value set %s", key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int min = static_cast<int>(lua_tonumber(L, -1));
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_pushstring( L, "max" );
|
||||
lua_gettable( L, -2 );
|
||||
|
||||
if (false == lua_isnumber(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
sys_err("BlueDragon: no max value set %s", key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int max = static_cast<int>(lua_tonumber(L, -1));
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (min <= val && val <= max)
|
||||
{
|
||||
lua_pushstring( L, "pct" );
|
||||
lua_gettable( L, -2 );
|
||||
|
||||
if (false == lua_isnumber(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
sys_err("BlueDragon: no pct value set %s", key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int pct = static_cast<int>(lua_tonumber(L, -1));
|
||||
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
return pct;
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int BlueDragon_GetIndexFactor(const char* container, const size_t idx, const char* key)
|
||||
{
|
||||
lua_State* L = quest::CQuestManager::instance().GetLuaState();
|
||||
|
||||
const int stack_top = lua_gettop(L);
|
||||
|
||||
lua_getglobal( L, "BlueDragonSetting" );
|
||||
|
||||
if (false == lua_istable(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushstring( L, container );
|
||||
lua_gettable( L, -2 );
|
||||
|
||||
if (false == lua_istable(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
sys_err("BlueDragon: no required table %s", key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_rawgeti( L, -1, idx );
|
||||
|
||||
if (false == lua_istable(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
sys_err("BlueDragon: wrong table index %s %d", key, idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushstring( L, key );
|
||||
lua_gettable( L, -2 );
|
||||
|
||||
if (false == lua_isnumber(L, -1))
|
||||
{
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
sys_err("BlueDragon: no min value set %s", key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unsigned int ret = static_cast<unsigned int>(lua_tonumber(L, -1));
|
||||
|
||||
lua_settop( L, stack_top );
|
||||
|
||||
return ret;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
12
source-server/Srcs/Server/game/src/BlueDragon_Binder.h
Normal file
12
source-server/Srcs/Server/game/src/BlueDragon_Binder.h
Normal file
@ -0,0 +1,12 @@
|
||||
enum BLUEDRAGON_STONE_EFFECT
|
||||
{
|
||||
DEF_BONUS = 1,
|
||||
ATK_BONUS = 2,
|
||||
REGEN_TIME_BONUS = 3,
|
||||
REGEN_PECT_BONUS = 4,
|
||||
};
|
||||
|
||||
extern unsigned int BlueDragon_GetRangeFactor (const char* key, const int val);
|
||||
extern unsigned int BlueDragon_GetSkillFactor (const size_t cnt, ...);
|
||||
extern unsigned int BlueDragon_GetIndexFactor (const char* container, const size_t idx, const char* key);
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
355
source-server/Srcs/Server/game/src/BlueDragon_Skill.h
Normal file
355
source-server/Srcs/Server/game/src/BlueDragon_Skill.h
Normal file
@ -0,0 +1,355 @@
|
||||
#ifndef _INC_BLUE_DRAGON_SKILL_H__INC_
|
||||
#define _INC_BLUE_DRAGON_SKILL_H__INC_
|
||||
#include "../../common/CommonDefines.h"
|
||||
struct FSkillBreath
|
||||
{
|
||||
EJobs Set1;
|
||||
EJobs Set2;
|
||||
ESex gender;
|
||||
LPCHARACTER pAttacker;
|
||||
|
||||
FSkillBreath(LPCHARACTER p)
|
||||
{
|
||||
pAttacker = p;
|
||||
|
||||
Set1 = static_cast<EJobs>(number(0,3));
|
||||
Set2 = static_cast<EJobs>(number(0,3));
|
||||
gender = static_cast<ESex>(number(0,2));
|
||||
}
|
||||
|
||||
void operator()(LPENTITY ent)
|
||||
{
|
||||
if (NULL != ent)
|
||||
{
|
||||
if (true == ent->IsType(ENTITY_CHARACTER))
|
||||
{
|
||||
LPCHARACTER ch = static_cast<LPCHARACTER>(ent);
|
||||
|
||||
if (true == ch->IsPC() && false == ch->IsDead())
|
||||
{
|
||||
if (NULL != ch->FindAffect(AFFECT_REVIVE_INVISIBLE, APPLY_NONE))
|
||||
return;
|
||||
|
||||
if ((signed)BlueDragon_GetSkillFactor(2, "Skill0", "damage_area") < DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()))
|
||||
{
|
||||
sys_log(0, "BlueDragon: Breath too far (%d)", DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()) );
|
||||
return;
|
||||
}
|
||||
|
||||
int overlapDamageCount = 0;
|
||||
|
||||
int pct = 0;
|
||||
if (ch->GetJob() == Set1)
|
||||
{
|
||||
const char* ptr = NULL;
|
||||
|
||||
switch ( Set1 )
|
||||
{
|
||||
case JOB_WARRIOR: ptr = "musa"; break;
|
||||
case JOB_ASSASSIN: ptr = "assa"; break;
|
||||
case JOB_SURA: ptr = "sura"; break;
|
||||
case JOB_SHAMAN: ptr = "muda"; break;
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
case JOB_WOLFMAN: ptr = "wolf"; break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
case JOB_MAX_NUM: return;
|
||||
}
|
||||
|
||||
int firstDamagePercent = number(BlueDragon_GetSkillFactor(4, "Skill0", "damage", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill0", "damage", ptr, "max"));
|
||||
pct += firstDamagePercent;
|
||||
|
||||
if (firstDamagePercent > 0)
|
||||
overlapDamageCount++;
|
||||
}
|
||||
|
||||
if (ch->GetJob() == Set2)
|
||||
{
|
||||
const char* ptr = NULL;
|
||||
|
||||
switch ( Set2 )
|
||||
{
|
||||
case JOB_WARRIOR: ptr = "musa"; break;
|
||||
case JOB_ASSASSIN: ptr = "assa"; break;
|
||||
case JOB_SURA: ptr = "sura"; break;
|
||||
case JOB_SHAMAN: ptr = "muda"; break;
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
case JOB_WOLFMAN: ptr = "wolf"; break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
case JOB_MAX_NUM: return;
|
||||
}
|
||||
|
||||
int secondDamagePercent = number(BlueDragon_GetSkillFactor(4, "Skill0", "damage", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill0", "damage", ptr, "max"));
|
||||
pct += secondDamagePercent;
|
||||
|
||||
if (secondDamagePercent > 0)
|
||||
overlapDamageCount++;
|
||||
}
|
||||
|
||||
if (GET_SEX(ch) == gender)
|
||||
{
|
||||
const char* ptr = NULL;
|
||||
|
||||
switch (gender)
|
||||
{
|
||||
case SEX_MALE: ptr = "male"; break;
|
||||
case SEX_FEMALE: ptr = "female"; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
int thirdDamagePercent = number(BlueDragon_GetSkillFactor(4, "Skill0", "gender", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill0", "gender", ptr, "max"));
|
||||
pct += thirdDamagePercent;
|
||||
|
||||
if (thirdDamagePercent > 0)
|
||||
overlapDamageCount++;
|
||||
}
|
||||
|
||||
switch (overlapDamageCount)
|
||||
{
|
||||
case 1:
|
||||
ch->EffectPacket(SE_PERCENT_DAMAGE1);
|
||||
break;
|
||||
case 2:
|
||||
ch->EffectPacket(SE_PERCENT_DAMAGE2);
|
||||
break;
|
||||
case 3:
|
||||
ch->EffectPacket(SE_PERCENT_DAMAGE3);
|
||||
break;
|
||||
}
|
||||
|
||||
int addPct = BlueDragon_GetRangeFactor("hp_damage", pAttacker->GetHPPct());
|
||||
|
||||
pct += addPct;
|
||||
|
||||
int dam = number(BlueDragon_GetSkillFactor(3, "Skill0", "default_damage", "min"), BlueDragon_GetSkillFactor(3, "Skill0", "default_damage", "max"));
|
||||
|
||||
dam += (dam * addPct) / 100;
|
||||
dam += (ch->GetMaxHP() * pct) / 100;
|
||||
|
||||
ch->Damage( pAttacker, dam, DAMAGE_TYPE_ICE );
|
||||
|
||||
sys_log(0, "BlueDragon: Breath to %s pct(%d) dam(%d) overlap(%d)", ch->GetName(), pct, dam, overlapDamageCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FSkillWeakBreath
|
||||
{
|
||||
LPCHARACTER pAttacker;
|
||||
|
||||
FSkillWeakBreath(LPCHARACTER p)
|
||||
{
|
||||
pAttacker = p;
|
||||
}
|
||||
|
||||
void operator()(LPENTITY ent)
|
||||
{
|
||||
if (NULL != ent)
|
||||
{
|
||||
if (true == ent->IsType(ENTITY_CHARACTER))
|
||||
{
|
||||
LPCHARACTER ch = static_cast<LPCHARACTER>(ent);
|
||||
|
||||
if (true == ch->IsPC() && false == ch->IsDead())
|
||||
{
|
||||
if (NULL != ch->FindAffect(AFFECT_REVIVE_INVISIBLE, APPLY_NONE))
|
||||
return;
|
||||
|
||||
if ((signed)BlueDragon_GetSkillFactor(2, "Skill1", "damage_area") < DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()))
|
||||
{
|
||||
sys_log(0, "BlueDragon: Breath too far (%d)", DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()) );
|
||||
return;
|
||||
}
|
||||
|
||||
int addPct = BlueDragon_GetRangeFactor("hp_damage", pAttacker->GetHPPct());
|
||||
|
||||
int dam = number( BlueDragon_GetSkillFactor(3, "Skill1", "default_damage", "min"), BlueDragon_GetSkillFactor(3, "Skill1", "default_damage", "max") );
|
||||
dam += (dam * addPct) / 100;
|
||||
|
||||
ch->Damage( pAttacker, dam, DAMAGE_TYPE_ICE );
|
||||
|
||||
sys_log(0, "BlueDragon: WeakBreath to %s addPct(%d) dam(%d)", ch->GetName(), addPct, dam);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FSkillEarthQuake
|
||||
{
|
||||
EJobs Set1;
|
||||
EJobs Set2;
|
||||
ESex gender;
|
||||
long MaxDistance;
|
||||
LPCHARACTER pAttacker;
|
||||
LPCHARACTER pFarthestChar;
|
||||
|
||||
FSkillEarthQuake(LPCHARACTER p)
|
||||
{
|
||||
pAttacker = p;
|
||||
|
||||
MaxDistance = 0;
|
||||
pFarthestChar = NULL;
|
||||
|
||||
Set1 = static_cast<EJobs>(number(0,3));
|
||||
Set2 = static_cast<EJobs>(number(0,3));
|
||||
gender = static_cast<ESex>(number(0,2));
|
||||
}
|
||||
|
||||
void operator()(LPENTITY ent)
|
||||
{
|
||||
if (NULL != ent)
|
||||
{
|
||||
if (true == ent->IsType(ENTITY_CHARACTER))
|
||||
{
|
||||
LPCHARACTER ch = static_cast<LPCHARACTER>(ent);
|
||||
|
||||
if (true == ch->IsPC() && false == ch->IsDead())
|
||||
{
|
||||
if (NULL != ch->FindAffect(AFFECT_REVIVE_INVISIBLE, APPLY_NONE))
|
||||
return;
|
||||
|
||||
if ((signed)BlueDragon_GetSkillFactor(2, "Skill2", "damage_area") < DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()))
|
||||
{
|
||||
sys_log(0, "BlueDragon: Breath too far (%d)", DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()) );
|
||||
return;
|
||||
}
|
||||
|
||||
int sec = number(BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", "default", "min"), BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", "default", "max"));
|
||||
|
||||
if (ch->GetJob() == Set1)
|
||||
{
|
||||
const char* ptr = NULL;
|
||||
|
||||
switch ( Set1 )
|
||||
{
|
||||
case JOB_WARRIOR: ptr = "musa"; break;
|
||||
case JOB_ASSASSIN: ptr = "assa"; break;
|
||||
case JOB_SURA: ptr = "sura"; break;
|
||||
case JOB_SHAMAN: ptr = "muda"; break;
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
case JOB_WOLFMAN: ptr = "wolf"; break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
case JOB_MAX_NUM: return;
|
||||
}
|
||||
|
||||
sec += number(BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", ptr, "max"));
|
||||
}
|
||||
|
||||
if (ch->GetJob() == Set2)
|
||||
{
|
||||
const char* ptr = NULL;
|
||||
|
||||
switch ( Set2 )
|
||||
{
|
||||
case JOB_WARRIOR: ptr = "musa"; break;
|
||||
case JOB_ASSASSIN: ptr = "assa"; break;
|
||||
case JOB_SURA: ptr = "sura"; break;
|
||||
case JOB_SHAMAN: ptr = "muda"; break;
|
||||
#ifdef ENABLE_WOLFMAN_CHARACTER
|
||||
case JOB_WOLFMAN: ptr = "wolf"; break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
case JOB_MAX_NUM: return;
|
||||
}
|
||||
|
||||
sec += number(BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", ptr, "max"));
|
||||
}
|
||||
|
||||
if (GET_SEX(ch) == gender)
|
||||
{
|
||||
const char* ptr = NULL;
|
||||
|
||||
switch (gender)
|
||||
{
|
||||
case SEX_MALE: ptr = "male"; break;
|
||||
case SEX_FEMALE: ptr = "female"; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
sec += number(BlueDragon_GetSkillFactor(4, "Skill2", "gender", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill2", "gender", ptr, "max"));
|
||||
}
|
||||
|
||||
int addPct = BlueDragon_GetRangeFactor("hp_damage", pAttacker->GetHPPct());
|
||||
|
||||
int dam = number( BlueDragon_GetSkillFactor(3, "Skill2", "default_damage", "min"), BlueDragon_GetSkillFactor(3, "Skill2", "default_damage", "max") );
|
||||
dam += (dam * addPct) / 100;
|
||||
|
||||
ch->Damage( pAttacker, dam, DAMAGE_TYPE_ICE);
|
||||
|
||||
SkillAttackAffect( ch, 1000, IMMUNE_STUN, AFFECT_STUN, POINT_NONE, 0, AFF_STUN, sec, "BDRAGON_STUN" );
|
||||
|
||||
sys_log(0, "BlueDragon: EarthQuake to %s addPct(%d) dam(%d) sec(%d)", ch->GetName(), addPct, dam, sec);
|
||||
|
||||
VECTOR vec;
|
||||
vec.x = static_cast<float>(pAttacker->GetX() - ch->GetX());
|
||||
vec.y = static_cast<float>(pAttacker->GetY() - ch->GetY());
|
||||
vec.z = 0.0f;
|
||||
|
||||
Normalize( &vec, &vec );
|
||||
|
||||
const int nFlyDistance = 1000;
|
||||
|
||||
long tx = ch->GetX() + vec.x * nFlyDistance;
|
||||
long ty = ch->GetY() + vec.y * nFlyDistance;
|
||||
|
||||
for (int i=0 ; i < 5 ; ++i)
|
||||
{
|
||||
if (true == SECTREE_MANAGER::instance().IsMovablePosition( ch->GetMapIndex(), tx, ty ))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch( i )
|
||||
{
|
||||
case 0:
|
||||
tx = ch->GetX() + vec.x * nFlyDistance * -1;
|
||||
ty = ch->GetY() + vec.y * nFlyDistance * -1;
|
||||
break;
|
||||
case 1:
|
||||
tx = ch->GetX() + vec.x * nFlyDistance * -1;
|
||||
ty = ch->GetY() + vec.y * nFlyDistance;
|
||||
break;
|
||||
case 2:
|
||||
tx = ch->GetX() + vec.x * nFlyDistance;
|
||||
ty = ch->GetY() + vec.y * nFlyDistance * -1;
|
||||
break;
|
||||
case 3:
|
||||
tx = ch->GetX() + vec.x * number(1,100);
|
||||
ty = ch->GetY() + vec.y * number(1,100);
|
||||
break;
|
||||
case 4:
|
||||
tx = ch->GetX() + vec.x * number(1,10);
|
||||
ty = ch->GetY() + vec.y * number(1,10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ch->Sync( tx , ty );
|
||||
ch->Goto( tx , ty );
|
||||
ch->CalculateMoveDuration();
|
||||
|
||||
ch->SyncPacket();
|
||||
|
||||
long dist = DISTANCE_APPROX( pAttacker->GetX() - ch->GetX(), pAttacker->GetY() - ch->GetY() );
|
||||
|
||||
if (dist > MaxDistance)
|
||||
{
|
||||
MaxDistance = dist;
|
||||
pFarthestChar = ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
222
source-server/Srcs/Server/game/src/ClientPackageCryptInfo.cpp
Normal file
222
source-server/Srcs/Server/game/src/ClientPackageCryptInfo.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
#include "stdafx.h"
|
||||
#include "ClientPackageCryptInfo.h"
|
||||
#include "../../common/stl.h"
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
#include "../../libthecore/include/xdirent.h"
|
||||
#endif
|
||||
|
||||
CClientPackageCryptInfo::CClientPackageCryptInfo() : m_nCryptKeyPackageCnt(0), m_pSerializedCryptKeyStream(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CClientPackageCryptInfo::~CClientPackageCryptInfo()
|
||||
{
|
||||
m_vecPackageCryptKeys.clear();
|
||||
m_mapPackageSDB.clear();
|
||||
if( m_pSerializedCryptKeyStream )
|
||||
{
|
||||
delete[] m_pSerializedCryptKeyStream;
|
||||
m_pSerializedCryptKeyStream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CClientPackageCryptInfo::LoadPackageCryptFile( const char* pCryptFile )
|
||||
{
|
||||
FILE * fp = fopen(pCryptFile, "rb");
|
||||
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
int iSDBDataOffset;
|
||||
fread(&iSDBDataOffset, sizeof(int), 1, fp);
|
||||
|
||||
int iPackageCnt;
|
||||
fread( &iPackageCnt, sizeof(int), 1, fp );
|
||||
m_nCryptKeyPackageCnt += iPackageCnt;
|
||||
|
||||
int iCryptKeySize = iSDBDataOffset - 2*sizeof(int);
|
||||
|
||||
{
|
||||
if (0 == iCryptKeySize)
|
||||
{
|
||||
sys_log(0, "[PackageCryptInfo] failed to load crypt key. (file: %s, key size: %d)", pCryptFile, iCryptKeySize);
|
||||
m_nCryptKeyPackageCnt -= iPackageCnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nCurKeySize = (int)m_vecPackageCryptKeys.size();
|
||||
m_vecPackageCryptKeys.resize( nCurKeySize + sizeof(int) + iCryptKeySize);
|
||||
|
||||
memcpy( &m_vecPackageCryptKeys[nCurKeySize], &iCryptKeySize, sizeof(int));
|
||||
fread( &m_vecPackageCryptKeys[nCurKeySize + sizeof(int)], sizeof(BYTE), iCryptKeySize, fp );
|
||||
sys_log(0, "[PackageCryptInfo] %s loaded. (key size: %d, count: %d, total: %d)", pCryptFile, iCryptKeySize, iPackageCnt, m_nCryptKeyPackageCnt);
|
||||
}
|
||||
}
|
||||
|
||||
//about SDB data
|
||||
//total packagecnt (4byte)
|
||||
// for packagecnt
|
||||
// db name hash 4byte( stl.h stringhash ) +child node size(4byte)
|
||||
|
||||
//stream to client
|
||||
// sdb file cnt( 4byte )
|
||||
// for sdb file cnt
|
||||
// filename hash ( stl.h stringhash )
|
||||
// related map name size(4), relate map name
|
||||
// sdb block size( 1byte )
|
||||
// sdb blocks
|
||||
|
||||
int iSDBPackageCnt;
|
||||
fread(&iSDBPackageCnt, sizeof(int), 1, fp);
|
||||
|
||||
DWORD dwPackageNameHash, dwPackageStreamSize, dwSDBFileCnt, dwFileNameHash, dwMapNameSize;
|
||||
|
||||
std::string strRelatedMapName;
|
||||
|
||||
if (0 == iCryptKeySize && 0 == iSDBPackageCnt)
|
||||
return false;
|
||||
|
||||
for( int i = 0; i < iSDBPackageCnt; ++i )
|
||||
{
|
||||
fread(&dwPackageNameHash, sizeof(DWORD), 1, fp);
|
||||
fread(&dwPackageStreamSize, sizeof(DWORD), 1, fp);
|
||||
|
||||
fread(&dwSDBFileCnt, sizeof(DWORD), 1, fp);
|
||||
|
||||
sys_log(0, "[PackageCryptInfo] SDB Loaded. (Name Hash : %d, Stream Size: %d, File Count: %d)", dwPackageNameHash,dwPackageStreamSize, dwSDBFileCnt);
|
||||
|
||||
for( int j = 0; j < (int)dwSDBFileCnt; ++j )
|
||||
{
|
||||
fread(&dwFileNameHash, sizeof(DWORD), 1, fp);
|
||||
fread(&dwMapNameSize, sizeof(DWORD), 1, fp);
|
||||
|
||||
strRelatedMapName.resize( dwMapNameSize );
|
||||
fread(&strRelatedMapName[0], sizeof(BYTE), dwMapNameSize, fp);
|
||||
|
||||
sys_log(0, "[PackageCryptInfo] \t SDB each file info loaded.(MapName: %s, NameHash: %X)", strRelatedMapName.c_str(), dwFileNameHash);
|
||||
|
||||
BYTE bSDBStreamSize;
|
||||
std::vector<BYTE> vecSDBStream;
|
||||
fread(&bSDBStreamSize, sizeof(BYTE), 1, fp);
|
||||
|
||||
vecSDBStream.resize(bSDBStreamSize);
|
||||
fread(&vecSDBStream[0], sizeof(BYTE), bSDBStreamSize, fp);
|
||||
|
||||
//reconstruct it
|
||||
TPackageSDBMap::iterator it = m_mapPackageSDB.find( strRelatedMapName );
|
||||
if (it == m_mapPackageSDB.end())
|
||||
{
|
||||
TPerFileSDBInfo fileSDBInfo;
|
||||
m_mapPackageSDB[strRelatedMapName] = fileSDBInfo;
|
||||
}
|
||||
|
||||
TSupplementaryDataBlockInfo SDBInfo;
|
||||
std::vector<TSupplementaryDataBlockInfo>& rSDBInfos = m_mapPackageSDB[strRelatedMapName].vecSDBInfos;
|
||||
{
|
||||
SDBInfo.dwPackageIdentifier = dwPackageNameHash;
|
||||
SDBInfo.dwFileIdentifier = dwFileNameHash;
|
||||
SDBInfo.vecSDBStream.resize(bSDBStreamSize);
|
||||
|
||||
memcpy(&SDBInfo.vecSDBStream[0], &vecSDBStream[0], bSDBStreamSize);
|
||||
|
||||
rSDBInfos.emplace_back(SDBInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClientPackageCryptInfo::LoadPackageCryptInfo( const char* pCryptInfoDir )
|
||||
{
|
||||
DIR * pDir = opendir(pCryptInfoDir);
|
||||
|
||||
if (!pDir)
|
||||
return false;
|
||||
|
||||
m_nCryptKeyPackageCnt = 0;
|
||||
if( m_pSerializedCryptKeyStream )
|
||||
{
|
||||
delete[] m_pSerializedCryptKeyStream;
|
||||
m_pSerializedCryptKeyStream = NULL;
|
||||
}
|
||||
|
||||
m_mapPackageSDB.clear();
|
||||
m_vecPackageCryptKeys.clear();
|
||||
|
||||
const char szPrefixCryptInfoFile[] = "cshybridcrypt";
|
||||
|
||||
dirent * pDirEnt;
|
||||
while ((pDirEnt = readdir(pDir)))
|
||||
{
|
||||
//if (strncmp( &(pDirEnt->d_name[0]), szPrefixCryptInfoFile, strlen(szPrefixCryptInfoFile)) )
|
||||
if (std::string::npos == std::string(pDirEnt->d_name).find(szPrefixCryptInfoFile))
|
||||
{
|
||||
sys_log(0, "[PackageCryptInfo] %s is not crypt file. pass!", pDirEnt->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string strFullPathName = std::string(pCryptInfoDir) + std::string(pDirEnt->d_name);
|
||||
|
||||
sys_log(0, "[PackageCryptInfo] Try to load crypt file: %s", strFullPathName.c_str());
|
||||
|
||||
if (false == LoadPackageCryptFile( strFullPathName.c_str() ))
|
||||
sys_err("[PackageCryptInfo] Failed to load %s", strFullPathName.c_str());
|
||||
}
|
||||
|
||||
closedir(pDir);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CClientPackageCryptInfo::GetPackageCryptKeys( BYTE** ppData, int& iDataSize )
|
||||
{
|
||||
int nCryptKeySize = m_vecPackageCryptKeys.size();
|
||||
int iStreamSize = sizeof(int)+nCryptKeySize;
|
||||
|
||||
//NOTE : Crypt Key Info isn`t updated during runtime. ( in case of file reloading all data is cleared & recreated )
|
||||
//it`s not safe but due to performance benefit we don`t do re-serialize.
|
||||
if( m_pSerializedCryptKeyStream )
|
||||
{
|
||||
*ppData = m_pSerializedCryptKeyStream;
|
||||
iDataSize = iStreamSize;
|
||||
return;
|
||||
}
|
||||
|
||||
if( nCryptKeySize > 0 )
|
||||
{
|
||||
m_pSerializedCryptKeyStream = new BYTE[iStreamSize];
|
||||
memcpy(&m_pSerializedCryptKeyStream[0], &m_nCryptKeyPackageCnt, sizeof(int) );
|
||||
memcpy(&m_pSerializedCryptKeyStream[sizeof(int)], &m_vecPackageCryptKeys[0], nCryptKeySize );
|
||||
|
||||
*ppData = m_pSerializedCryptKeyStream;
|
||||
iDataSize = iStreamSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppData = NULL;
|
||||
iDataSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CClientPackageCryptInfo::GetRelatedMapSDBStreams(const char* pMapName, BYTE** ppData, int& iDataSize )
|
||||
{
|
||||
std::string strLowerMapName = pMapName;
|
||||
stl_lowers(strLowerMapName);
|
||||
|
||||
TPackageSDBMap::iterator it = m_mapPackageSDB.find( strLowerMapName.c_str() );
|
||||
if( it == m_mapPackageSDB.end() || it->second.vecSDBInfos.size() == 0 )
|
||||
{
|
||||
//sys_err("GetRelatedMapSDBStreams Failed(%s)", strLowerMapName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
*ppData = it->second.GetSerializedStream();
|
||||
iDataSize = it->second.GetSize();
|
||||
|
||||
//sys_log(0, "GetRelatedMapSDBStreams Size(%d)", iDataSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
110
source-server/Srcs/Server/game/src/ClientPackageCryptInfo.h
Normal file
110
source-server/Srcs/Server/game/src/ClientPackageCryptInfo.h
Normal file
@ -0,0 +1,110 @@
|
||||
#ifndef __INC_CLIENTPACKAGE_CRYPTINFO_H
|
||||
#define __INC_CLIENTPACKAGE_CRYPTINFO_H
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct SSupplementaryDataBlockInfo
|
||||
{
|
||||
DWORD dwPackageIdentifier;
|
||||
DWORD dwFileIdentifier;
|
||||
std::vector<BYTE> vecSDBStream;
|
||||
|
||||
void Serialize( BYTE* pStream )
|
||||
{
|
||||
memcpy(pStream, &dwPackageIdentifier, sizeof(DWORD));
|
||||
memcpy(pStream+4, &dwFileIdentifier, sizeof(DWORD));
|
||||
|
||||
BYTE bSize = vecSDBStream.size();
|
||||
memcpy(pStream+8, &bSize, sizeof(BYTE));
|
||||
memcpy(pStream+9, &vecSDBStream[0], bSize);
|
||||
}
|
||||
|
||||
DWORD GetSerializedSize() const
|
||||
{
|
||||
return sizeof(DWORD)*2 + sizeof(BYTE) + vecSDBStream.size();
|
||||
}
|
||||
} TSupplementaryDataBlockInfo;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
class CClientPackageCryptInfo
|
||||
{
|
||||
public:
|
||||
CClientPackageCryptInfo();
|
||||
~CClientPackageCryptInfo();
|
||||
|
||||
bool LoadPackageCryptInfo( const char* pCryptInfoDir );
|
||||
void GetPackageCryptKeys( BYTE** ppData, int& iDataSize );
|
||||
|
||||
bool GetRelatedMapSDBStreams(const char* pMapName, BYTE** ppData, int& iDataSize );
|
||||
|
||||
private:
|
||||
bool LoadPackageCryptFile( const char* pCryptFile );
|
||||
|
||||
private:
|
||||
int m_nCryptKeyPackageCnt;
|
||||
std::vector<BYTE> m_vecPackageCryptKeys;
|
||||
BYTE* m_pSerializedCryptKeyStream;
|
||||
|
||||
typedef struct SPerFileSDBInfo
|
||||
{
|
||||
SPerFileSDBInfo() : m_pSerializedStream(NULL) {}
|
||||
~SPerFileSDBInfo()
|
||||
{
|
||||
if(m_pSerializedStream)
|
||||
{
|
||||
delete[]m_pSerializedStream;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD GetSize() const
|
||||
{
|
||||
DWORD dwSize = 4; //initial vecSDBInfo count
|
||||
|
||||
for(int i = 0; i < (int)vecSDBInfos.size(); ++i)
|
||||
{
|
||||
dwSize += vecSDBInfos[i].GetSerializedSize();
|
||||
}
|
||||
|
||||
return dwSize;
|
||||
}
|
||||
|
||||
BYTE* GetSerializedStream()
|
||||
{
|
||||
//NOTE : SDB Data isn`t updated during runtime. ( in case of file reloading all data is cleared & recreated )
|
||||
//it`s not safe but due to performance benefit we don`t do re-serialize.
|
||||
if(m_pSerializedStream)
|
||||
return m_pSerializedStream;
|
||||
|
||||
m_pSerializedStream = new BYTE[GetSize()];
|
||||
|
||||
int iWrittenOffset = 0;
|
||||
int iSDBInfoSize = vecSDBInfos.size();
|
||||
|
||||
//write size
|
||||
memcpy( m_pSerializedStream, &iSDBInfoSize, sizeof(int) );
|
||||
iWrittenOffset += sizeof(int);
|
||||
for(int i = 0; i < iSDBInfoSize; ++i)
|
||||
{
|
||||
vecSDBInfos[i].Serialize( m_pSerializedStream + iWrittenOffset );
|
||||
iWrittenOffset += vecSDBInfos[i].GetSerializedSize();
|
||||
}
|
||||
|
||||
return m_pSerializedStream;
|
||||
}
|
||||
|
||||
std::vector<TSupplementaryDataBlockInfo> vecSDBInfos;
|
||||
|
||||
private:
|
||||
BYTE* m_pSerializedStream;
|
||||
|
||||
} TPerFileSDBInfo;
|
||||
|
||||
typedef boost::unordered_map<std::string, TPerFileSDBInfo > TPackageSDBMap; //key: related map name
|
||||
TPackageSDBMap m_mapPackageSDB;
|
||||
};
|
||||
|
||||
#endif //__INC_CLIENTPACKAGE_CRYPTINFO_H
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
232
source-server/Srcs/Server/game/src/DragonLair.cpp
Normal file
232
source-server/Srcs/Server/game/src/DragonLair.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
#include "stdafx.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "DragonLair.h"
|
||||
|
||||
#include "entity.h"
|
||||
#include "sectree_manager.h"
|
||||
#include "char.h"
|
||||
#include "guild.h"
|
||||
#include "locale_service.h"
|
||||
#include "regen.h"
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
|
||||
struct FWarpToDragronLairWithGuildMembers
|
||||
{
|
||||
DWORD dwGuildID;
|
||||
long mapIndex;
|
||||
long x, y;
|
||||
|
||||
FWarpToDragronLairWithGuildMembers( DWORD guildID, long map, long X, long Y )
|
||||
: dwGuildID(guildID), mapIndex(map), x(X), y(Y)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(LPENTITY ent)
|
||||
{
|
||||
if (NULL != ent && true == ent->IsType(ENTITY_CHARACTER))
|
||||
{
|
||||
LPCHARACTER pChar = static_cast<LPCHARACTER>(ent);
|
||||
|
||||
if (true == pChar->IsPC())
|
||||
{
|
||||
if (NULL != pChar->GetGuild())
|
||||
{
|
||||
if (dwGuildID == pChar->GetGuild()->GetID())
|
||||
{
|
||||
pChar->WarpSet(x, y, mapIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FWarpToVillage
|
||||
{
|
||||
void operator() (LPENTITY ent)
|
||||
{
|
||||
if (NULL != ent)
|
||||
{
|
||||
LPCHARACTER pChar = static_cast<LPCHARACTER>(ent);
|
||||
|
||||
if (NULL != pChar)
|
||||
{
|
||||
if (true == pChar->IsPC())
|
||||
{
|
||||
pChar->GoHome();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EVENTINFO(tag_DragonLair_Collapse_EventInfo)
|
||||
{
|
||||
int step;
|
||||
CDragonLair* pLair;
|
||||
long InstanceMapIndex;
|
||||
|
||||
tag_DragonLair_Collapse_EventInfo()
|
||||
: step( 0 )
|
||||
, pLair( 0 )
|
||||
, InstanceMapIndex( 0 )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
EVENTFUNC( DragonLair_Collapse_Event )
|
||||
{
|
||||
tag_DragonLair_Collapse_EventInfo* pInfo = dynamic_cast<tag_DragonLair_Collapse_EventInfo*>(event->info);
|
||||
|
||||
if ( pInfo == NULL )
|
||||
{
|
||||
sys_err( "DragonLair_Collapse_Event> <Factor> Null pointer" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == pInfo->step)
|
||||
{
|
||||
char buf[512];
|
||||
snprintf(buf, 512, LC_TEXT("용가리가 %d 초만에 죽어써효ㅠㅠ"), pInfo->pLair->GetEstimatedTime());
|
||||
SendNoticeMap(buf, pInfo->InstanceMapIndex, true);
|
||||
|
||||
pInfo->step++;
|
||||
|
||||
return PASSES_PER_SEC( 30 );
|
||||
}
|
||||
else if (1 == pInfo->step)
|
||||
{
|
||||
LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap( pInfo->InstanceMapIndex );
|
||||
|
||||
if (NULL != pMap)
|
||||
{
|
||||
FWarpToVillage f;
|
||||
pMap->for_each( f );
|
||||
}
|
||||
|
||||
pInfo->step++;
|
||||
|
||||
return PASSES_PER_SEC( 30 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SECTREE_MANAGER::instance().DestroyPrivateMap( pInfo->InstanceMapIndex );
|
||||
M2_DELETE(pInfo->pLair);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CDragonLair::CDragonLair(DWORD guildID, long BaseMapID, long PrivateMapID)
|
||||
: GuildID_(guildID), BaseMapIndex_(BaseMapID), PrivateMapIndex_(PrivateMapID)
|
||||
{
|
||||
StartTime_ = get_global_time();
|
||||
}
|
||||
|
||||
CDragonLair::~CDragonLair()
|
||||
{
|
||||
}
|
||||
|
||||
DWORD CDragonLair::GetEstimatedTime() const
|
||||
{
|
||||
return get_global_time() - StartTime_;
|
||||
}
|
||||
|
||||
void CDragonLair::OnDragonDead(LPCHARACTER pDragon)
|
||||
{
|
||||
sys_log(0, "DragonLair: 도라곤이 죽어써효");
|
||||
|
||||
LogManager::instance().DragonSlayLog( GuildID_, pDragon->GetMobTable().dwVnum, StartTime_, get_global_time() );
|
||||
}
|
||||
|
||||
CDragonLairManager::CDragonLairManager()
|
||||
{
|
||||
}
|
||||
|
||||
CDragonLairManager::~CDragonLairManager()
|
||||
{
|
||||
}
|
||||
|
||||
bool CDragonLairManager::Start(long MapIndexFrom, long BaseMapIndex, DWORD GuildID)
|
||||
{
|
||||
long instanceMapIndex = SECTREE_MANAGER::instance().CreatePrivateMap(BaseMapIndex);
|
||||
if (instanceMapIndex == 0) {
|
||||
sys_err("CDragonLairManager::Start() : no private map index available");
|
||||
return false;
|
||||
}
|
||||
|
||||
LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(MapIndexFrom);
|
||||
|
||||
if (NULL != pMap)
|
||||
{
|
||||
LPSECTREE_MAP pTargetMap = SECTREE_MANAGER::instance().GetMap(BaseMapIndex);
|
||||
|
||||
if (NULL == pTargetMap)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const TMapRegion* pRegionInfo = SECTREE_MANAGER::instance().GetMapRegion( pTargetMap->m_setting.iIndex );
|
||||
|
||||
if (NULL != pRegionInfo)
|
||||
{
|
||||
FWarpToDragronLairWithGuildMembers f(GuildID, instanceMapIndex, 844000, 1066900);
|
||||
|
||||
pMap->for_each( f );
|
||||
|
||||
LairMap_.emplace(GuildID, M2_NEW CDragonLair(GuildID, BaseMapIndex, instanceMapIndex));
|
||||
|
||||
std::string strMapBasePath( LocaleService_GetMapPath() );
|
||||
|
||||
strMapBasePath += "/" + pRegionInfo->strMapName + "/instance_regen.txt";
|
||||
|
||||
sys_log(0, "%s", strMapBasePath.c_str());
|
||||
|
||||
regen_do(strMapBasePath.c_str(), instanceMapIndex, pTargetMap->m_setting.iBaseX, pTargetMap->m_setting.iBaseY, NULL, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CDragonLairManager::OnDragonDead(LPCHARACTER pDragon, DWORD KillerGuildID)
|
||||
{
|
||||
if (NULL == pDragon)
|
||||
return;
|
||||
|
||||
if (false == pDragon->IsMonster())
|
||||
return;
|
||||
|
||||
boost::unordered_map<DWORD, CDragonLair*>::iterator iter = LairMap_.find( KillerGuildID );
|
||||
|
||||
if (LairMap_.end() == iter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap( pDragon->GetMapIndex() );
|
||||
|
||||
if (NULL == iter->second || NULL == pMap)
|
||||
{
|
||||
LairMap_.erase( iter );
|
||||
return;
|
||||
}
|
||||
|
||||
iter->second->OnDragonDead( pDragon );
|
||||
|
||||
tag_DragonLair_Collapse_EventInfo* info;
|
||||
info = AllocEventInfo<tag_DragonLair_Collapse_EventInfo>();
|
||||
|
||||
info->step = 0;
|
||||
info->pLair = iter->second;
|
||||
info->InstanceMapIndex = pDragon->GetMapIndex();
|
||||
|
||||
event_create(DragonLair_Collapse_Event, info, PASSES_PER_SEC(10));
|
||||
|
||||
LairMap_.erase( iter );
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
36
source-server/Srcs/Server/game/src/DragonLair.h
Normal file
36
source-server/Srcs/Server/game/src/DragonLair.h
Normal file
@ -0,0 +1,36 @@
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include "../../common/stl.h"
|
||||
|
||||
class CDragonLair
|
||||
{
|
||||
public:
|
||||
CDragonLair (DWORD dwGuildID, long BaseMapID, long PrivateMapID);
|
||||
virtual ~CDragonLair ();
|
||||
|
||||
DWORD GetEstimatedTime () const;
|
||||
|
||||
void OnDragonDead (LPCHARACTER pDragon);
|
||||
|
||||
private:
|
||||
DWORD StartTime_;
|
||||
DWORD GuildID_;
|
||||
[[maybe_unused]] long BaseMapIndex_;
|
||||
[[maybe_unused]] long PrivateMapIndex_;
|
||||
};
|
||||
|
||||
class CDragonLairManager : public singleton<CDragonLairManager>
|
||||
{
|
||||
public:
|
||||
CDragonLairManager ();
|
||||
virtual ~CDragonLairManager ();
|
||||
|
||||
bool Start (long MapIndexFrom, long BaseMapIndex, DWORD GuildID);
|
||||
void OnDragonDead (LPCHARACTER pDragon, DWORD KillerGuildID);
|
||||
|
||||
size_t GetLairCount () const { return LairMap_.size(); }
|
||||
|
||||
private:
|
||||
boost::unordered_map<DWORD, CDragonLair*> LairMap_;
|
||||
};
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
1113
source-server/Srcs/Server/game/src/DragonSoul.cpp
Normal file
1113
source-server/Srcs/Server/game/src/DragonSoul.cpp
Normal file
File diff suppressed because it is too large
Load Diff
51
source-server/Srcs/Server/game/src/DragonSoul.h
Normal file
51
source-server/Srcs/Server/game/src/DragonSoul.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef __INC_METIN_II_GAME_DRAGON_SOUL_H__
|
||||
#define __INC_METIN_II_GAME_DRAGON_SOUL_H__
|
||||
|
||||
#include "../../common/length.h"
|
||||
|
||||
class CHARACTER;
|
||||
class CItem;
|
||||
|
||||
class DragonSoulTable;
|
||||
|
||||
class DSManager : public singleton<DSManager>
|
||||
{
|
||||
public:
|
||||
DSManager();
|
||||
~DSManager();
|
||||
bool ReadDragonSoulTableFile(const char * c_pszFileName);
|
||||
|
||||
void GetDragonSoulInfo(DWORD dwVnum, OUT BYTE& bType, OUT BYTE& bGrade, OUT BYTE& bStep, OUT BYTE& bRefine) const;
|
||||
WORD GetBasePosition(const LPITEM pItem) const;
|
||||
bool IsValidCellForThisItem(const LPITEM pItem, const TItemPos& Cell) const;
|
||||
int GetDuration(const LPITEM pItem) const;
|
||||
|
||||
bool ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtractor = NULL);
|
||||
|
||||
bool PullOut(LPCHARACTER ch, TItemPos DestCell, IN OUT LPITEM& pItem, LPITEM pExtractor = NULL);
|
||||
|
||||
bool DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]);
|
||||
bool DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]);
|
||||
bool DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]);
|
||||
|
||||
bool DragonSoulItemInitialize(LPITEM pItem);
|
||||
|
||||
bool IsTimeLeftDragonSoul(LPITEM pItem) const;
|
||||
int LeftTime(LPITEM pItem) const;
|
||||
bool ActivateDragonSoul(LPITEM pItem);
|
||||
bool DeactivateDragonSoul(LPITEM pItem, bool bSkipRefreshOwnerActiveState = false);
|
||||
bool IsActiveDragonSoul(LPITEM pItem) const;
|
||||
private:
|
||||
void SendRefineResultPacket(LPCHARACTER ch, BYTE bSubHeader, const TItemPos& pos);
|
||||
|
||||
void RefreshDragonSoulState(LPCHARACTER ch);
|
||||
|
||||
DWORD MakeDragonSoulVnum(BYTE bType, BYTE grade, BYTE step, BYTE refine);
|
||||
bool PutAttributes(LPITEM pDS);
|
||||
bool RefreshItemAttributes(LPITEM pItem);
|
||||
|
||||
DragonSoulTable* m_pTable;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
62
source-server/Srcs/Server/game/src/FSM.cpp
Normal file
62
source-server/Srcs/Server/game/src/FSM.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
// Local Includes
|
||||
#include "stdafx.h"
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "FSM.h"
|
||||
|
||||
// Constructor
|
||||
CFSM::CFSM()
|
||||
{
|
||||
// Initialize States
|
||||
m_stateInitial.Set(this, &CFSM::BeginStateInitial, &CFSM::StateInitial, &CFSM::EndStateInitial);
|
||||
|
||||
// Initialize State Machine
|
||||
m_pCurrentState = static_cast<CState *>(&m_stateInitial);
|
||||
m_pNewState = NULL;
|
||||
}
|
||||
|
||||
//======================================================================================================
|
||||
// Global Functions
|
||||
|
||||
// Update
|
||||
void CFSM::Update()
|
||||
{
|
||||
// Check New State
|
||||
if (m_pNewState)
|
||||
{
|
||||
// Execute End State
|
||||
m_pCurrentState->ExecuteEndState();
|
||||
|
||||
// Set New State
|
||||
m_pCurrentState = m_pNewState;
|
||||
m_pNewState = 0;
|
||||
|
||||
// Execute Begin State
|
||||
m_pCurrentState->ExecuteBeginState();
|
||||
}
|
||||
|
||||
// Execute State
|
||||
m_pCurrentState->ExecuteState();
|
||||
}
|
||||
|
||||
//======================================================================================================
|
||||
// State Functions
|
||||
|
||||
// Is State
|
||||
bool CFSM::IsState(CState & State) const
|
||||
{
|
||||
return (m_pCurrentState == &State);
|
||||
}
|
||||
|
||||
// Goto State
|
||||
bool CFSM::GotoState(CState & NewState)
|
||||
{
|
||||
if (IsState(NewState) && m_pNewState == &NewState)
|
||||
return true;
|
||||
|
||||
// Set New State
|
||||
m_pNewState = &NewState;
|
||||
return true;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
35
source-server/Srcs/Server/game/src/FSM.h
Normal file
35
source-server/Srcs/Server/game/src/FSM.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef _fsm_fsm_h
|
||||
#define _fsm_fsm_h
|
||||
|
||||
// Local Includes
|
||||
#include "state.h"
|
||||
|
||||
// FSM Class
|
||||
class CFSM
|
||||
{
|
||||
protected:
|
||||
CState * m_pCurrentState; // Current State
|
||||
CState * m_pNewState; // New State
|
||||
CStateTemplate<CFSM> m_stateInitial; // Initial State
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
CFSM();
|
||||
|
||||
// Destructor
|
||||
virtual ~CFSM() {}
|
||||
|
||||
// Global Functions
|
||||
virtual void Update();
|
||||
|
||||
// State Functions
|
||||
bool IsState(CState &State) const;
|
||||
bool GotoState(CState &NewState);
|
||||
|
||||
virtual void BeginStateInitial() {}
|
||||
virtual void StateInitial() {}
|
||||
virtual void EndStateInitial() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
135
source-server/Srcs/Server/game/src/FileMonitor_FreeBSD.cpp
Normal file
135
source-server/Srcs/Server/game/src/FileMonitor_FreeBSD.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
#include "stdafx.h"
|
||||
#include "FileMonitor_FreeBSD.h"
|
||||
#include "../../libthecore/include/log.h"
|
||||
|
||||
#define INVALID_KERNEL_EVENT -1
|
||||
|
||||
FileMonitorFreeBSD::FileMonitorFreeBSD()
|
||||
{
|
||||
m_KernelEventQueue = INVALID_KERNEL_EVENT;
|
||||
}
|
||||
|
||||
FileMonitorFreeBSD::~FileMonitorFreeBSD()
|
||||
{
|
||||
if( m_KernelEventQueue != INVALID_KERNEL_EVENT )
|
||||
{
|
||||
close ( m_KernelEventQueue );
|
||||
m_KernelEventQueue = INVALID_KERNEL_EVENT;
|
||||
}
|
||||
|
||||
TMonitorFileHashMap::iterator it;
|
||||
for( it = m_FileLists.begin(); it != m_FileLists.end(); ++it )
|
||||
{
|
||||
close(it->second.fhMonitor);
|
||||
}
|
||||
|
||||
m_FileLists.clear();
|
||||
|
||||
m_MonitoredEventLists.clear();
|
||||
m_TriggeredEventLists.clear();
|
||||
}
|
||||
|
||||
void FileMonitorFreeBSD::Update(DWORD dwPulses)
|
||||
{
|
||||
if( m_KernelEventQueue == INVALID_KERNEL_EVENT || m_FileLists.size() == 0 )
|
||||
return;
|
||||
|
||||
int nEvent = kevent(m_KernelEventQueue, &m_TriggeredEventLists[0], (int)m_TriggeredEventLists.size(), &m_MonitoredEventLists[0], (int)m_MonitoredEventLists.size(), NULL );
|
||||
if( nEvent == INVALID_KERNEL_EVENT )
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if( nEvent > 0 )
|
||||
{
|
||||
for( int i = 0; i < nEvent; ++i )
|
||||
{
|
||||
int nEventFlags = m_MonitoredEventLists[i].flags;
|
||||
eFileUpdatedOptions eUpdateOption = e_FileUpdate_None;
|
||||
|
||||
if (nEventFlags & EV_ERROR)
|
||||
eUpdateOption = e_FileUpdate_Error;
|
||||
|
||||
else if (nEventFlags & NOTE_DELETE)
|
||||
eUpdateOption = e_FileUpdate_Deleted;
|
||||
|
||||
else if (nEventFlags & NOTE_EXTEND || nEventFlags & NOTE_WRITE)
|
||||
eUpdateOption = e_FileUpdate_Modified;
|
||||
|
||||
else if (nEventFlags & NOTE_ATTRIB)
|
||||
eUpdateOption = e_FileUpdate_AttrModified;
|
||||
|
||||
else if (nEventFlags & NOTE_LINK)
|
||||
eUpdateOption = e_FileUpdate_Linked;
|
||||
|
||||
else if (nEventFlags & NOTE_RENAME)
|
||||
eUpdateOption = e_FileUpdate_Renamed;
|
||||
|
||||
else if (nEventFlags & NOTE_REVOKE)
|
||||
eUpdateOption = e_FileUpdate_Revoked;
|
||||
|
||||
if( eUpdateOption != e_FileUpdate_None )
|
||||
{
|
||||
TMonitorFileHashMap::iterator it;
|
||||
for( it = m_FileLists.begin(); it != m_FileLists.end(); ++it )
|
||||
{
|
||||
FileIOContext_FreeBSD& context = it->second;
|
||||
if( context.idxToEventList == i )
|
||||
{
|
||||
std::string strModifedFileName = it->first;
|
||||
context.pListenFunc( strModifedFileName, eUpdateOption );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileMonitorFreeBSD::AddWatch(const std::string& strFileName, PFN_FileChangeListener pListenerFunc)
|
||||
{
|
||||
int iFileHandle = -1;
|
||||
if( (iFileHandle = open(strFileName.c_str(), O_RDONLY)) == -1)
|
||||
{
|
||||
sys_err("FileMonitorFreeBSD:AddWatch : can`t open file(%s).\n", strFileName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
//create kqueue if not exists
|
||||
if( m_KernelEventQueue == INVALID_KERNEL_EVENT )
|
||||
m_KernelEventQueue = kqueue();
|
||||
|
||||
if( m_KernelEventQueue == INVALID_KERNEL_EVENT )
|
||||
{
|
||||
sys_err("FileMonitorFreeBSD:AddWatch : failed to create kqueue.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
TMonitorFileHashMap::iterator it = m_FileLists.find( strFileName );
|
||||
if( it != m_FileLists.end() )
|
||||
{
|
||||
sys_log(0, "FileMonitorFreeBSD:AddWatch : trying to add duplicated watch on file(%s).\n", strFileName.c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
//set file context
|
||||
FileIOContext_FreeBSD context;
|
||||
{
|
||||
context.fhMonitor = iFileHandle;
|
||||
context.idxToEventList = (int)m_MonitoredEventLists.size();
|
||||
context.pListenFunc = pListenerFunc;
|
||||
}
|
||||
|
||||
m_FileLists[strFileName] = context;
|
||||
|
||||
//set events
|
||||
struct kevent kTriggerEvent, kMonitorEvent;
|
||||
|
||||
EV_SET(&kTriggerEvent, iFileHandle, EVFILT_VNODE,
|
||||
EV_ADD | EV_ENABLE | EV_ONESHOT,
|
||||
NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_LINK | NOTE_RENAME | NOTE_REVOKE,
|
||||
0, 0);
|
||||
|
||||
m_TriggeredEventLists.emplace_back(kTriggerEvent);
|
||||
m_MonitoredEventLists.emplace_back(kMonitorEvent);
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
47
source-server/Srcs/Server/game/src/FileMonitor_FreeBSD.h
Normal file
47
source-server/Srcs/Server/game/src/FileMonitor_FreeBSD.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef FILEMONITOR_FREEBSD_INCLUDED
|
||||
#define FILEMONITOR_FREEBSD_INCLUDED
|
||||
|
||||
#include "IFileMonitor.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
struct FileIOContext_FreeBSD
|
||||
{
|
||||
int fhMonitor;
|
||||
int idxToEventList; // evtTrigger & evtMonitor index should be same
|
||||
PFN_FileChangeListener pListenFunc;
|
||||
};
|
||||
|
||||
class FileMonitorFreeBSD : public IFileMonitor
|
||||
{
|
||||
private:
|
||||
FileMonitorFreeBSD(); //hidden
|
||||
|
||||
public:
|
||||
virtual ~FileMonitorFreeBSD();
|
||||
|
||||
void AddWatch (const std::string& strFileName, PFN_FileChangeListener pListenerFunc);
|
||||
void Update (DWORD dwPulses);
|
||||
|
||||
static FileMonitorFreeBSD& Instance()
|
||||
{
|
||||
static FileMonitorFreeBSD theMonitor;
|
||||
return theMonitor;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef boost::unordered_map<std::string, FileIOContext_FreeBSD> TMonitorFileHashMap;
|
||||
typedef std::vector<struct kevent> TEventList;
|
||||
|
||||
TMonitorFileHashMap m_FileLists;
|
||||
TEventList m_MonitoredEventLists;
|
||||
TEventList m_TriggeredEventLists;
|
||||
|
||||
int m_KernelEventQueue;
|
||||
};
|
||||
|
||||
#endif //FILEMONITOR_FREEBSD_INCLUDED
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
31
source-server/Srcs/Server/game/src/IFileMonitor.h
Normal file
31
source-server/Srcs/Server/game/src/IFileMonitor.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef IFILEMONITOR_INCLUDED
|
||||
#define IFILEMONITOR_INCLUDED
|
||||
|
||||
//#include <boost/function.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
enum eFileUpdatedOptions
|
||||
{
|
||||
e_FileUpdate_None = -1,
|
||||
e_FileUpdate_Error,
|
||||
e_FileUpdate_Deleted,
|
||||
e_FileUpdate_Modified,
|
||||
e_FileUpdate_AttrModified,
|
||||
e_FileUpdate_Linked,
|
||||
e_FileUpdate_Renamed,
|
||||
e_FileUpdate_Revoked,
|
||||
};
|
||||
|
||||
// TODO : in FreeBSD boost function doesn`t work with boost bind
|
||||
// so currently we only support for static function ptr only
|
||||
//typedef boost::function< void ( const std::string&, eFileUpdatedOptions ) > PFN_FileChangeListener;
|
||||
typedef void (* PFN_FileChangeListener )(const std::string&, eFileUpdatedOptions);
|
||||
|
||||
struct IFileMonitor
|
||||
{
|
||||
virtual void Update (DWORD dwPulses) = 0;
|
||||
virtual void AddWatch (const std::string& strFileName, PFN_FileChangeListener pListenerFunc) = 0;
|
||||
};
|
||||
|
||||
#endif // IFILEMONITOR_INCLUDED
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
228
source-server/Srcs/Server/game/src/Makefile
Normal file
228
source-server/Srcs/Server/game/src/Makefile
Normal file
@ -0,0 +1,228 @@
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
|
||||
GAME_VERSION := $(shell cat ../../__REVISION__)
|
||||
LBITS := $(shell getconf LONG_BIT)
|
||||
|
||||
GccMajorVersion := $(shell expr `$(CXX) -dumpversion | cut -f1 -d.`)
|
||||
GccMinorVersion := $(shell expr `$(CXX) -dumpversion | cut -f2 -d.`)
|
||||
GccMinorEGT8 := $(shell expr $(GccMinorVersion) \>= 8)
|
||||
|
||||
INCDIR =
|
||||
LIBDIR =
|
||||
BINDIR = ..
|
||||
OBJDIR = .obj
|
||||
$(shell if [ ! -d $(OBJDIR) ]; then mkdir $(OBJDIR); fi)
|
||||
|
||||
## LIST OF CONSTANTS BEGIN
|
||||
ENABLE_GOOGLE_TEST = 0
|
||||
ENABLE_LUA_5_VERSION = 0
|
||||
ENABLE_GCC_AUTODEPEND = 1
|
||||
ENABLE_STATIC = 0
|
||||
## LIST OF CONSTANTS END
|
||||
|
||||
# Depend Path File
|
||||
ifneq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
DEPFILE = Depend
|
||||
endif
|
||||
|
||||
# Standard Libraries
|
||||
LIBS = -lm -lmd
|
||||
|
||||
# Project Flags
|
||||
CFLAGS = -m32 -g -Wall -O2 -pipe -fexceptions -fno-strict-aliasing -pthread -D_THREAD_SAFE -DNDEBUG
|
||||
CFLAGS += -Wno-deprecated-declarations -Wno-nonnull-compare -Wno-deprecated-declarations -Wno-array-bounds -Wno-address
|
||||
CFLAGS += -Wno-int-in-bool-context -Wno-format-truncation -Wno-stringop-truncation -Wno-sign-compare -Wno-deprecated-enum-enum-conversion
|
||||
CXXFLAGS = -std=c++20
|
||||
|
||||
# for clang
|
||||
ifneq '' '$(findstring clang++,$(CXX))'
|
||||
CFLAGS += -Wno-invalid-source-encoding -Wno-deprecated-anon-enum-enum-conversion -Wno-unknown-warning-option
|
||||
# for gcc
|
||||
else ifneq '' '$(findstring g++,$(CXX))'
|
||||
# for 32bit on 64bit
|
||||
ifeq ($(LBITS),64)
|
||||
CFLAGS += -L/usr/local/lib32/gcc12
|
||||
CFLAGS += -Wl,-rpath=/usr/local/lib32/gcc12
|
||||
else
|
||||
# for 32bit on 32bit
|
||||
CXXFLAGS += -Wl,-rpath=/usr/local/lib/gcc12
|
||||
endif
|
||||
endif
|
||||
|
||||
# MySQL
|
||||
INCDIR += -I/usr/local/include/mysql
|
||||
ifeq ($(LBITS),64)
|
||||
LIBS += ../../../Extern/lib/libmysqlclient.a -lz
|
||||
else
|
||||
LIBS += /usr/local/lib/mysql/libmysqlclient.a /usr/lib/libz.a
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_STATIC), 1)
|
||||
CFLAGS += -static
|
||||
endif
|
||||
|
||||
ifeq ($(GccMinorEGT8), 1)
|
||||
CFLAGS += -Wno-unused-local-typedefs
|
||||
endif
|
||||
|
||||
# FreeBSD stack protector
|
||||
CFLAGS += -fstack-protector-all
|
||||
|
||||
# Version defines
|
||||
CFLAGS += -D__USER__=\"$(USER)\" -D__HOSTNAME__=\"$(HOSTNAME)\" -D__PWD__=\"$(PWD)\" -D__GAME_VERSION__=\"$(GAME_VERSION)\"
|
||||
|
||||
# Boost
|
||||
INCDIR += -I../../../Extern/include/boost
|
||||
|
||||
# DevIL
|
||||
INCDIR += -I../../../Extern/include/IL
|
||||
LIBS += ../../../Extern/lib/libIL.a
|
||||
|
||||
# CryptoPP
|
||||
LIBS += ../../../Extern/lib/libcryptopp.a
|
||||
|
||||
# GTest
|
||||
ifeq ($(ENABLE_GOOGLE_TEST), 1)
|
||||
LIBS += /usr/local/lib/libgtest.a
|
||||
CFLAGS += -DENABLE_GOOGLE_TEST
|
||||
endif
|
||||
|
||||
# OpenSSL
|
||||
INCDIR += -I/usr/include
|
||||
ifeq ($(LBITS),64)
|
||||
LIBS += /usr/lib32/libcrypto.a /usr/lib32/libssl.a
|
||||
else
|
||||
LIBS += -lssl -lcrypto
|
||||
endif
|
||||
|
||||
# Lua
|
||||
CFLAGS += -DENABLE_LUA_5_VERSION=ENABLE_LUA_5_VERSION
|
||||
ifeq ($(ENABLE_LUA_5_VERSION), 2)
|
||||
INCDIR += -I../../liblua/5.2/install/include
|
||||
LIBDIR += -L../../liblua/5.2/install/lib
|
||||
LIBS += ../../liblua/5.2/install/lib/liblua.a
|
||||
else
|
||||
INCDIR += -I../../liblua/5.0/include
|
||||
LIBDIR += -L../../liblua/5.0/lib
|
||||
LIBS += ../../liblua/5.0/lib/liblua.a ../../liblua/5.0/lib/liblualib.a
|
||||
endif
|
||||
|
||||
# Project Libraries
|
||||
INCDIR += -I../../../Extern/include
|
||||
INCDIR += -I/usr/local/include
|
||||
LIBDIR += -L/usr/local/lib
|
||||
|
||||
LIBDIR += -L../../libthecore/lib -L../../libpoly -L../../libsql -L../../libgame/lib
|
||||
LIBS += -lthecore -lpoly -lsql -lgame
|
||||
|
||||
# PROJECT_SRC_FILES BEGIN
|
||||
MAINCPP = main.cpp
|
||||
|
||||
CFILE = minilzo.c
|
||||
|
||||
CPPFILE = FSM.cpp MarkConvert.cpp MarkImage.cpp MarkManager.cpp OXEvent.cpp ani.cpp\
|
||||
arena.cpp banword.cpp battle.cpp blend_item.cpp buffer_manager.cpp building.cpp castle.cpp\
|
||||
char.cpp char_affect.cpp char_battle.cpp char_change_empire.cpp char_horse.cpp char_item.cpp char_manager.cpp\
|
||||
char_quickslot.cpp char_resist.cpp char_skill.cpp char_state.cpp PetSystem.cpp cmd.cpp cmd_emotion.cpp cmd_general.cpp\
|
||||
cmd_gm.cpp cmd_oxevent.cpp config.cpp constants.cpp crc32.cpp cube.cpp db.cpp desc.cpp\
|
||||
desc_client.cpp desc_manager.cpp desc_p2p.cpp dungeon.cpp empire_text_convert.cpp entity.cpp\
|
||||
entity_view.cpp event.cpp event_queue.cpp exchange.cpp file_loader.cpp fishing.cpp gm.cpp guild.cpp\
|
||||
guild_manager.cpp guild_war.cpp horse_rider.cpp horsename_manager.cpp input.cpp input_auth.cpp input_db.cpp\
|
||||
input_login.cpp input_main.cpp input_p2p.cpp input_udp.cpp\
|
||||
item.cpp item_addon.cpp item_attribute.cpp item_manager.cpp item_manager_idrange.cpp locale.cpp\
|
||||
locale_service.cpp log.cpp login_data.cpp lzo_manager.cpp marriage.cpp\
|
||||
messenger_manager.cpp mining.cpp mob_manager.cpp monarch.cpp motion.cpp over9refine.cpp p2p.cpp packet_info.cpp\
|
||||
party.cpp polymorph.cpp priv_manager.cpp pvp.cpp\
|
||||
questevent.cpp questlua.cpp questlua_affect.cpp questlua_arena.cpp questlua_building.cpp\
|
||||
questlua_danceevent.cpp questlua_dungeon.cpp questlua_forked.cpp questlua_game.cpp questlua_global.cpp\
|
||||
questlua_guild.cpp questlua_horse.cpp questlua_pet.cpp questlua_item.cpp questlua_marriage.cpp questlua_mgmt.cpp\
|
||||
questlua_monarch.cpp questlua_npc.cpp questlua_oxevent.cpp questlua_party.cpp questlua_pc.cpp\
|
||||
questlua_quest.cpp questlua_target.cpp questmanager.cpp questnpc.cpp questpc.cpp\
|
||||
refine.cpp regen.cpp safebox.cpp sectree.cpp sectree_manager.cpp sequence.cpp shop.cpp\
|
||||
skill.cpp start_position.cpp target.cpp text_file_loader.cpp trigger.cpp utils.cpp vector.cpp war_map.cpp\
|
||||
wedding.cpp xmas_event.cpp version.cpp panama.cpp threeway_war.cpp map_location.cpp\
|
||||
BlueDragon.cpp BlueDragon_Binder.cpp DragonLair.cpp questlua_dragonlair.cpp\
|
||||
skill_power.cpp affect.cpp\
|
||||
FileMonitor_FreeBSD.cpp ClientPackageCryptInfo.cpp cipher.cpp\
|
||||
buff_on_attributes.cpp dragon_soul_table.cpp DragonSoul.cpp\
|
||||
group_text_parse_tree.cpp char_dragonsoul.cpp questlua_dragonsoul.cpp\
|
||||
shop_manager.cpp shopEx.cpp item_manager_read_tables.cpp shutdown_manager.cpp\
|
||||
questlua_dnd.cpp
|
||||
# PROJECT_SRC_FILES END
|
||||
|
||||
# PROJECT_OBJ_FILES BEGIN
|
||||
COBJS = $(CFILE:%.c=$(OBJDIR)/%.o)
|
||||
CPPOBJS = $(CPPFILE:%.cpp=$(OBJDIR)/%.o)
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
CDEPS = $(COBJS:%.o=%.d)
|
||||
CPPDEPS = $(CPPOBJS:%.o=%.d)
|
||||
endif
|
||||
|
||||
MAINOBJ = $(MAINCPP:%.cpp=$(OBJDIR)/%.o)
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
MAINDEPS = $(MAINOBJ:%.o=%.d)
|
||||
endif
|
||||
|
||||
# PROJECT_OBJ_FILES END
|
||||
|
||||
# Target Paths
|
||||
MAIN_TARGET = $(BINDIR)/game_r$(GAME_VERSION)
|
||||
|
||||
default: $(MAIN_TARGET)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@echo compiling $<
|
||||
@$(CC) $(CFLAGS) $(INCDIR) -c $< -o $@
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
@$(CC) -MM -MG -MP $(CFLAGS) $(INCDIR) -c $< -o $(OBJDIR)/$*.d
|
||||
@sed -i '' -e's/$*.o:/$(OBJDIR)\/$*.o:/g' $(OBJDIR)/$*.d
|
||||
endif
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
@echo compiling $<
|
||||
@$(CXX) $(CFLAGS) $(CXXFLAGS) $(INCDIR) -c $< -o $@
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
@$(CXX) -MM -MG -MP $(CFLAGS) $(CXXFLAGS) $(INCDIR) -c $< -o $(OBJDIR)/$*.d
|
||||
@sed -i '' -e's/$*.o:/$(OBJDIR)\/$*.o:/g' $(OBJDIR)/$*.d
|
||||
endif
|
||||
|
||||
limit_time:
|
||||
@echo update limit time
|
||||
@python update_limit_time.py
|
||||
|
||||
$(MAIN_TARGET): $(CPPOBJS) $(COBJS) $(MAINOBJ)
|
||||
@echo linking $(MAIN_TARGET)
|
||||
@$(CXX) $(CFLAGS) $(CXXFLAGS) $(LIBDIR) $(COBJS) $(CPPOBJS) $(MAINOBJ) $(LIBS) -o $(MAIN_TARGET)
|
||||
|
||||
symlink:
|
||||
@ln -fs game_r$(GAME_VERSION) $(BINDIR)/game_symlink
|
||||
|
||||
strip:
|
||||
@cp $(MAIN_TARGET) $(BINDIR)/game_r
|
||||
@strip $(BINDIR)/game_r
|
||||
|
||||
clean:
|
||||
@echo cleaning $(MAIN_TARGET) $(OBJDIR)
|
||||
@rm -f $(COBJS) $(CPPOBJS) $(MAINOBJ)
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
@rm -f $(CDEPS) $(CPPDEPS) $(MAINDEPS)
|
||||
endif
|
||||
@rm -f $(BINDIR)/game_r*
|
||||
|
||||
dep:
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
@echo "Note: gcc autodepend is autodetected, so target dep skipped"
|
||||
else
|
||||
makedepend -f $(DEPFILE) $(INCDIR) -I/usr/include/c++/3.3 -I/usr/include/c++/4.2 -p$(OBJDIR)/ $(CPPFILE) $(CFILE) $(MAINCPP) 2> /dev/null > $(DEPFILE)
|
||||
endif
|
||||
|
||||
# AUTO_DEPEND_CHECK BEGIN
|
||||
ifeq ($(ENABLE_GCC_AUTODEPEND), 1)
|
||||
sinclude $(CDEPS)
|
||||
sinclude $(CPPDEPS)
|
||||
sinclude $(MAINDEPS)
|
||||
else
|
||||
sinclude $(DEPFILE)
|
||||
endif
|
||||
# AUTO_DEPEND_CHECK END
|
||||
118
source-server/Srcs/Server/game/src/MarkConvert.cpp
Normal file
118
source-server/Srcs/Server/game/src/MarkConvert.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include "stdafx.h"
|
||||
#include "MarkManager.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#define OLD_MARK_INDEX_FILENAME "guild_mark.idx"
|
||||
#define OLD_MARK_DATA_FILENAME "guild_mark.tga"
|
||||
|
||||
static Pixel * LoadOldGuildMarkImageFile()
|
||||
{
|
||||
FILE * fp = fopen(OLD_MARK_DATA_FILENAME, "rb");
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
sys_err("cannot open %s", OLD_MARK_INDEX_FILENAME);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int dataSize = 512 * 512 * sizeof(Pixel);
|
||||
Pixel * dataPtr = (Pixel *) malloc(dataSize);
|
||||
|
||||
fread(dataPtr, dataSize, 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return dataPtr;
|
||||
}
|
||||
|
||||
bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
|
||||
{
|
||||
#ifndef __WIN32__
|
||||
mkdir("mark", S_IRWXU);
|
||||
#else
|
||||
_mkdir("mark");
|
||||
#endif
|
||||
|
||||
#ifndef __WIN32__
|
||||
if (0 != access(OLD_MARK_INDEX_FILENAME, F_OK))
|
||||
#else
|
||||
if (0 != _access(OLD_MARK_INDEX_FILENAME, 0))
|
||||
#endif
|
||||
return true;
|
||||
|
||||
FILE* fp = fopen(OLD_MARK_INDEX_FILENAME, "r");
|
||||
|
||||
if (NULL == fp)
|
||||
return false;
|
||||
|
||||
Pixel * oldImagePtr = LoadOldGuildMarkImageFile();
|
||||
|
||||
if (NULL == oldImagePtr)
|
||||
{
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
sys_log(0, "Guild Mark Converting Start.");
|
||||
|
||||
char line[256];
|
||||
DWORD guild_id;
|
||||
DWORD mark_id;
|
||||
Pixel mark[SGuildMark::SIZE];
|
||||
|
||||
while (fgets(line, sizeof(line)-1, fp))
|
||||
{
|
||||
sscanf(line, "%u %u", &guild_id, &mark_id);
|
||||
|
||||
if (find(vecGuildID.begin(), vecGuildID.end(), guild_id) == vecGuildID.end())
|
||||
{
|
||||
sys_log(0, " skipping guild ID %u", guild_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint row = mark_id / 32;
|
||||
uint col = mark_id % 32;
|
||||
|
||||
if (row >= 42)
|
||||
{
|
||||
sys_err("invalid mark_id %u", mark_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint sx = col * 16;
|
||||
uint sy = row * 12;
|
||||
|
||||
Pixel * src = oldImagePtr + sy * 512 + sx;
|
||||
Pixel * dst = mark;
|
||||
|
||||
for (int y = 0; y != SGuildMark::HEIGHT; ++y)
|
||||
{
|
||||
for (int x = 0; x != SGuildMark::WIDTH; ++x)
|
||||
*(dst++) = *(src+x);
|
||||
|
||||
src += 512;
|
||||
}
|
||||
|
||||
CGuildMarkManager::instance().SaveMark(guild_id, (BYTE *) mark);
|
||||
line[0] = '\0';
|
||||
}
|
||||
|
||||
free(oldImagePtr);
|
||||
fclose(fp);
|
||||
|
||||
#ifndef __WIN32__
|
||||
system("mv -f guild_mark.idx guild_mark.idx.removable");
|
||||
system("mv -f guild_mark.tga guild_mark.tga.removable");
|
||||
#else
|
||||
system("move /Y guild_mark.idx guild_mark.idx.removable");
|
||||
system("move /Y guild_mark.tga guild_mark.tga.removable");
|
||||
#endif
|
||||
|
||||
sys_log(0, "Guild Mark Converting Complete.");
|
||||
|
||||
return true;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
293
source-server/Srcs/Server/game/src/MarkImage.cpp
Normal file
293
source-server/Srcs/Server/game/src/MarkImage.cpp
Normal file
@ -0,0 +1,293 @@
|
||||
#include "stdafx.h"
|
||||
#include "MarkImage.h"
|
||||
|
||||
#include "crc32.h"
|
||||
#include "lzo_manager.h"
|
||||
#define CLZO LZOManager
|
||||
|
||||
CGuildMarkImage * NewMarkImage()
|
||||
{
|
||||
return M2_NEW CGuildMarkImage;
|
||||
}
|
||||
|
||||
void DeleteMarkImage(CGuildMarkImage * pkImage)
|
||||
{
|
||||
M2_DELETE(pkImage);
|
||||
}
|
||||
|
||||
CGuildMarkImage::CGuildMarkImage()
|
||||
: m_uImg(INVALID_HANDLE)
|
||||
{
|
||||
memset( &m_apxImage, 0, sizeof(m_apxImage) );
|
||||
}
|
||||
|
||||
CGuildMarkImage::~CGuildMarkImage()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void CGuildMarkImage::Destroy()
|
||||
{
|
||||
if (INVALID_HANDLE == m_uImg)
|
||||
return;
|
||||
|
||||
ilDeleteImages(1, &m_uImg);
|
||||
m_uImg = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
void CGuildMarkImage::Create()
|
||||
{
|
||||
if (INVALID_HANDLE != m_uImg)
|
||||
return;
|
||||
|
||||
ilGenImages(1, &m_uImg);
|
||||
}
|
||||
|
||||
bool CGuildMarkImage::Save(const char* c_szFileName)
|
||||
{
|
||||
ilEnable(IL_FILE_OVERWRITE);
|
||||
ilBindImage(m_uImg);
|
||||
|
||||
if (!ilSave(IL_TGA, (const ILstring)c_szFileName))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGuildMarkImage::Build(const char * c_szFileName)
|
||||
{
|
||||
sys_log(0, "GuildMarkImage: creating new file %s", c_szFileName);
|
||||
|
||||
Destroy();
|
||||
Create();
|
||||
|
||||
ilBindImage(m_uImg);
|
||||
ilEnable(IL_ORIGIN_SET);
|
||||
ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
|
||||
|
||||
BYTE * data = (BYTE *) malloc(sizeof(Pixel) * WIDTH * HEIGHT);
|
||||
memset(data, 0, sizeof(Pixel) * WIDTH * HEIGHT);
|
||||
|
||||
if (!ilTexImage(WIDTH, HEIGHT, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, data))
|
||||
{
|
||||
sys_err("GuildMarkImage: cannot initialize image");
|
||||
return false;
|
||||
}
|
||||
|
||||
free(data);
|
||||
|
||||
ilEnable(IL_FILE_OVERWRITE);
|
||||
|
||||
if (!ilSave(IL_TGA, (const ILstring)c_szFileName))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGuildMarkImage::Load(const char * c_szFileName)
|
||||
{
|
||||
Destroy();
|
||||
Create();
|
||||
|
||||
ilBindImage(m_uImg);
|
||||
ilEnable(IL_ORIGIN_SET);
|
||||
ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
|
||||
|
||||
if (!ilLoad(IL_TYPE_UNKNOWN, (const ILstring) c_szFileName))
|
||||
{
|
||||
sys_err("GuildMarkImage: %s cannot open file.", c_szFileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ilGetInteger(IL_IMAGE_WIDTH) != WIDTH)
|
||||
{
|
||||
sys_err("GuildMarkImage: %s width must be %u", c_szFileName, WIDTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ilGetInteger(IL_IMAGE_HEIGHT) != HEIGHT)
|
||||
{
|
||||
sys_err("GuildMarkImage: %s height must be %u", c_szFileName, HEIGHT);
|
||||
return false;
|
||||
}
|
||||
|
||||
ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE);
|
||||
|
||||
BuildAllBlocks();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGuildMarkImage::PutData(UINT x, UINT y, UINT width, UINT height, void * data)
|
||||
{
|
||||
ilBindImage(m_uImg);
|
||||
ilSetPixels(x, y, 0, width, height, 1, IL_BGRA, IL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
void CGuildMarkImage::GetData(UINT x, UINT y, UINT width, UINT height, void * data)
|
||||
{
|
||||
ilBindImage(m_uImg);
|
||||
ilCopyPixels(x, y, 0, width, height, 1, IL_BGRA, IL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
// SERVER
|
||||
bool CGuildMarkImage::SaveMark(DWORD posMark, BYTE * pbImage)
|
||||
{
|
||||
if (posMark >= MARK_TOTAL_COUNT)
|
||||
{
|
||||
sys_err("GuildMarkImage::CopyMarkFromData: Invalid mark position %u", posMark);
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD colMark = posMark % MARK_COL_COUNT;
|
||||
DWORD rowMark = posMark / MARK_COL_COUNT;
|
||||
|
||||
printf("PutMark pos %u %ux%u\n", posMark, colMark * SGuildMark::WIDTH, rowMark * SGuildMark::HEIGHT);
|
||||
PutData(colMark * SGuildMark::WIDTH, rowMark * SGuildMark::HEIGHT, SGuildMark::WIDTH, SGuildMark::HEIGHT, pbImage);
|
||||
|
||||
DWORD rowBlock = rowMark / SGuildMarkBlock::MARK_PER_BLOCK_HEIGHT;
|
||||
DWORD colBlock = colMark / SGuildMarkBlock::MARK_PER_BLOCK_WIDTH;
|
||||
|
||||
Pixel apxBuf[SGuildMarkBlock::SIZE];
|
||||
GetData(colBlock * SGuildMarkBlock::WIDTH, rowBlock * SGuildMarkBlock::HEIGHT, SGuildMarkBlock::WIDTH, SGuildMarkBlock::HEIGHT, apxBuf);
|
||||
m_aakBlock[rowBlock][colBlock].Compress(apxBuf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGuildMarkImage::DeleteMark(DWORD posMark)
|
||||
{
|
||||
Pixel image[SGuildMark::SIZE];
|
||||
memset(&image, 0, sizeof(image));
|
||||
return SaveMark(posMark, (BYTE *) &image);
|
||||
}
|
||||
|
||||
// CLIENT
|
||||
bool CGuildMarkImage::SaveBlockFromCompressedData(DWORD posBlock, const BYTE * pbComp, DWORD dwCompSize)
|
||||
{
|
||||
if (posBlock >= BLOCK_TOTAL_COUNT)
|
||||
return false;
|
||||
|
||||
Pixel apxBuf[SGuildMarkBlock::SIZE];
|
||||
lzo_uint sizeBuf = sizeof(apxBuf);
|
||||
|
||||
if (LZO_E_OK != lzo1x_decompress_safe(pbComp, dwCompSize, (BYTE *) apxBuf, &sizeBuf, CLZO::Instance().GetWorkMemory()))
|
||||
{
|
||||
sys_err("GuildMarkImage::CopyBlockFromCompressedData: cannot decompress, compressed size = %u", dwCompSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sizeBuf != sizeof(apxBuf))
|
||||
{
|
||||
sys_err("GuildMarkImage::CopyBlockFromCompressedData: image corrupted, decompressed size = %u", sizeBuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD rowBlock = posBlock / BLOCK_COL_COUNT;
|
||||
DWORD colBlock = posBlock % BLOCK_COL_COUNT;
|
||||
|
||||
PutData(colBlock * SGuildMarkBlock::WIDTH, rowBlock * SGuildMarkBlock::HEIGHT, SGuildMarkBlock::WIDTH, SGuildMarkBlock::HEIGHT, apxBuf);
|
||||
|
||||
m_aakBlock[rowBlock][colBlock].CopyFrom(pbComp, dwCompSize, GetCRC32((const char *) apxBuf, sizeof(Pixel) * SGuildMarkBlock::SIZE));
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGuildMarkImage::BuildAllBlocks()
|
||||
{
|
||||
Pixel apxBuf[SGuildMarkBlock::SIZE];
|
||||
sys_log(0, "GuildMarkImage::BuildAllBlocks");
|
||||
|
||||
for (UINT row = 0; row < BLOCK_ROW_COUNT; ++row)
|
||||
for (UINT col = 0; col < BLOCK_COL_COUNT; ++col)
|
||||
{
|
||||
GetData(col * SGuildMarkBlock::WIDTH, row * SGuildMarkBlock::HEIGHT, SGuildMarkBlock::WIDTH, SGuildMarkBlock::HEIGHT, apxBuf);
|
||||
m_aakBlock[row][col].Compress(apxBuf);
|
||||
}
|
||||
}
|
||||
|
||||
DWORD CGuildMarkImage::GetEmptyPosition()
|
||||
{
|
||||
SGuildMark kMark;
|
||||
|
||||
for (DWORD row = 0; row < MARK_ROW_COUNT; ++row)
|
||||
{
|
||||
for (DWORD col = 0; col < MARK_COL_COUNT; ++col)
|
||||
{
|
||||
GetData(col * SGuildMark::WIDTH, row * SGuildMark::HEIGHT, SGuildMark::WIDTH, SGuildMark::HEIGHT, kMark.m_apxBuf);
|
||||
|
||||
if (kMark.IsEmpty())
|
||||
return (row * MARK_COL_COUNT + col);
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_MARK_POSITION;
|
||||
}
|
||||
|
||||
void CGuildMarkImage::GetDiffBlocks(const DWORD * crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks)
|
||||
{
|
||||
BYTE posBlock = 0;
|
||||
|
||||
for (DWORD row = 0; row < BLOCK_ROW_COUNT; ++row)
|
||||
for (DWORD col = 0; col < BLOCK_COL_COUNT; ++col)
|
||||
{
|
||||
if (m_aakBlock[row][col].m_crc != *crcList)
|
||||
{
|
||||
mapDiffBlocks.emplace(posBlock, &m_aakBlock[row][col]);
|
||||
}
|
||||
++crcList;
|
||||
++posBlock;
|
||||
}
|
||||
}
|
||||
|
||||
void CGuildMarkImage::GetBlockCRCList(DWORD * crcList)
|
||||
{
|
||||
for (DWORD row = 0; row < BLOCK_ROW_COUNT; ++row)
|
||||
for (DWORD col = 0; col < BLOCK_COL_COUNT; ++col)
|
||||
*(crcList++) = m_aakBlock[row][col].GetCRC();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void SGuildMark::Clear()
|
||||
{
|
||||
for (DWORD iPixel = 0; iPixel < SIZE; ++iPixel)
|
||||
m_apxBuf[iPixel] = 0xff000000;
|
||||
}
|
||||
|
||||
bool SGuildMark::IsEmpty()
|
||||
{
|
||||
for (DWORD iPixel = 0; iPixel < SIZE; ++iPixel)
|
||||
if (m_apxBuf[iPixel] != 0x00000000)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
DWORD SGuildMarkBlock::GetCRC() const
|
||||
{
|
||||
return m_crc;
|
||||
}
|
||||
|
||||
void SGuildMarkBlock::CopyFrom(const BYTE * pbCompBuf, DWORD dwCompSize, DWORD crc)
|
||||
{
|
||||
if (dwCompSize > MAX_COMP_SIZE)
|
||||
return;
|
||||
|
||||
m_sizeCompBuf = dwCompSize;
|
||||
thecore_memcpy(m_abCompBuf, pbCompBuf, dwCompSize);
|
||||
m_crc = crc;
|
||||
//printf("SGuildMarkBlock::CopyFrom: %u > %u crc %u\n", sizeof(Pixel) * SGuildMarkBlock::SIZE, m_sizeCompBuf, m_crc);
|
||||
}
|
||||
|
||||
void SGuildMarkBlock::Compress(const Pixel * pxBuf)
|
||||
{
|
||||
m_sizeCompBuf = MAX_COMP_SIZE;
|
||||
|
||||
if (LZO_E_OK != lzo1x_1_compress((const BYTE *) pxBuf, sizeof(Pixel) * SGuildMarkBlock::SIZE, m_abCompBuf, &m_sizeCompBuf, CLZO::Instance().GetWorkMemory()))
|
||||
{
|
||||
sys_err("SGuildMarkBlock::Compress: Error! %u > %u", sizeof(Pixel) * SGuildMarkBlock::SIZE, m_sizeCompBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
//sys_log(0, "SGuildMarkBlock::Compress %u > %u", sizeof(Pixel) * SGuildMarkBlock::SIZE, m_sizeCompBuf);
|
||||
m_crc = GetCRC32((const char *) pxBuf, sizeof(Pixel) * SGuildMarkBlock::SIZE);
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
112
source-server/Srcs/Server/game/src/MarkImage.h
Normal file
112
source-server/Srcs/Server/game/src/MarkImage.h
Normal file
@ -0,0 +1,112 @@
|
||||
#ifndef __INC_METIN_II_MARKIMAGE_H__
|
||||
#define __INC_METIN_II_MARKIMAGE_H__
|
||||
|
||||
#include <IL/il.h>
|
||||
#include "minilzo.h"
|
||||
|
||||
typedef unsigned long Pixel;
|
||||
|
||||
struct SGuildMark
|
||||
{
|
||||
enum
|
||||
{
|
||||
WIDTH = 16,
|
||||
HEIGHT = 12,
|
||||
SIZE = WIDTH * HEIGHT,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Pixel m_apxBuf[SIZE];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void Clear();
|
||||
bool IsEmpty();
|
||||
};
|
||||
|
||||
struct SGuildMarkBlock
|
||||
{
|
||||
enum
|
||||
{
|
||||
MARK_PER_BLOCK_WIDTH = 4,
|
||||
MARK_PER_BLOCK_HEIGHT = 4,
|
||||
|
||||
WIDTH = SGuildMark::WIDTH * MARK_PER_BLOCK_WIDTH,
|
||||
HEIGHT = SGuildMark::HEIGHT * MARK_PER_BLOCK_HEIGHT,
|
||||
|
||||
SIZE = WIDTH * HEIGHT,
|
||||
MAX_COMP_SIZE = (SIZE * sizeof(Pixel)) + ((SIZE * sizeof(Pixel)) >> 4) + 64 + 3
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Pixel m_apxBuf[SIZE];
|
||||
|
||||
BYTE m_abCompBuf[MAX_COMP_SIZE];
|
||||
lzo_uint m_sizeCompBuf;
|
||||
DWORD m_crc;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
DWORD GetCRC() const;
|
||||
|
||||
void CopyFrom(const BYTE * pbCompBuf, DWORD dwCompSize, DWORD crc);
|
||||
void Compress(const Pixel * pxBuf);
|
||||
};
|
||||
|
||||
class CGuildMarkImage
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
WIDTH = 512,
|
||||
HEIGHT = 512,
|
||||
|
||||
BLOCK_ROW_COUNT = HEIGHT / SGuildMarkBlock::HEIGHT, // 10
|
||||
BLOCK_COL_COUNT = WIDTH / SGuildMarkBlock::WIDTH, // 8
|
||||
|
||||
BLOCK_TOTAL_COUNT = BLOCK_ROW_COUNT * BLOCK_COL_COUNT, // 80
|
||||
|
||||
MARK_ROW_COUNT = BLOCK_ROW_COUNT * SGuildMarkBlock::MARK_PER_BLOCK_HEIGHT, // 40
|
||||
MARK_COL_COUNT = BLOCK_COL_COUNT * SGuildMarkBlock::MARK_PER_BLOCK_WIDTH, // 32
|
||||
|
||||
MARK_TOTAL_COUNT = MARK_ROW_COUNT * MARK_COL_COUNT, // 1280
|
||||
|
||||
INVALID_MARK_POSITION = 0xffffffff,
|
||||
};
|
||||
|
||||
CGuildMarkImage();
|
||||
virtual ~CGuildMarkImage();
|
||||
|
||||
void Create();
|
||||
void Destroy();
|
||||
|
||||
bool Build(const char * c_szFileName);
|
||||
bool Save(const char* c_szFileName);
|
||||
bool Load(const char* c_szFileName);
|
||||
|
||||
void PutData(UINT x, UINT y, UINT width, UINT height, void* data);
|
||||
void GetData(UINT x, UINT y, UINT width, UINT height, void* data);
|
||||
|
||||
bool SaveMark(DWORD posMark, BYTE * pbMarkImage);
|
||||
bool DeleteMark(DWORD posMark);
|
||||
bool SaveBlockFromCompressedData(DWORD posBlock, const BYTE * pbComp, DWORD dwCompSize);
|
||||
|
||||
DWORD GetEmptyPosition();
|
||||
|
||||
void GetBlockCRCList(DWORD * crcList);
|
||||
void GetDiffBlocks(const DWORD * crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
INVALID_HANDLE = 0xffffffff,
|
||||
};
|
||||
|
||||
void BuildAllBlocks();
|
||||
|
||||
SGuildMarkBlock m_aakBlock[BLOCK_ROW_COUNT][BLOCK_COL_COUNT];
|
||||
Pixel m_apxImage[WIDTH * HEIGHT * sizeof(Pixel)];
|
||||
|
||||
ILuint m_uImg;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
389
source-server/Srcs/Server/game/src/MarkManager.cpp
Normal file
389
source-server/Srcs/Server/game/src/MarkManager.cpp
Normal file
@ -0,0 +1,389 @@
|
||||
#include "stdafx.h"
|
||||
#include "MarkManager.h"
|
||||
|
||||
#include "crc32.h"
|
||||
|
||||
CGuildMarkImage * CGuildMarkManager::__NewImage()
|
||||
{
|
||||
return M2_NEW CGuildMarkImage;
|
||||
}
|
||||
|
||||
void CGuildMarkManager::__DeleteImage(CGuildMarkImage * pkImgDel)
|
||||
{
|
||||
M2_DELETE(pkImgDel);
|
||||
}
|
||||
|
||||
CGuildMarkManager::CGuildMarkManager()
|
||||
{
|
||||
for (DWORD i = 0; i < MAX_IMAGE_COUNT * CGuildMarkImage::MARK_TOTAL_COUNT; ++i)
|
||||
m_setFreeMarkID.emplace(i);
|
||||
}
|
||||
|
||||
CGuildMarkManager::~CGuildMarkManager()
|
||||
{
|
||||
for (std::map<DWORD, CGuildMarkImage *>::iterator it = m_mapIdx_Image.begin(); it != m_mapIdx_Image.end(); ++it)
|
||||
__DeleteImage(it->second);
|
||||
|
||||
m_mapIdx_Image.clear();
|
||||
}
|
||||
|
||||
bool CGuildMarkManager::GetMarkImageFilename(DWORD imgIdx, std::string & path) const
|
||||
{
|
||||
if (imgIdx >= MAX_IMAGE_COUNT)
|
||||
return false;
|
||||
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "mark/%s_%u.tga", m_pathPrefix.c_str(), imgIdx);
|
||||
path = buf;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGuildMarkManager::SetMarkPathPrefix(const char * prefix)
|
||||
{
|
||||
m_pathPrefix = prefix;
|
||||
}
|
||||
|
||||
bool CGuildMarkManager::LoadMarkIndex()
|
||||
{
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "mark/%s_index", m_pathPrefix.c_str());
|
||||
FILE * fp = fopen(buf, "r");
|
||||
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
DWORD guildID;
|
||||
DWORD markID;
|
||||
|
||||
char line[256];
|
||||
|
||||
while (fgets(line, sizeof(line)-1, fp))
|
||||
{
|
||||
sscanf(line, "%u %u", &guildID, &markID);
|
||||
line[0] = '\0';
|
||||
AddMarkIDByGuildID(guildID, markID);
|
||||
}
|
||||
|
||||
LoadMarkImages();
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGuildMarkManager::SaveMarkIndex()
|
||||
{
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "mark/%s_index", m_pathPrefix.c_str());
|
||||
FILE * fp = fopen(buf, "w");
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
sys_err("MarkManager::SaveMarkIndex: cannot open index file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::map<DWORD, DWORD>::iterator it = m_mapGID_MarkID.begin(); it != m_mapGID_MarkID.end(); ++it)
|
||||
fprintf(fp, "%u %u\n", it->first, it->second);
|
||||
|
||||
fclose(fp);
|
||||
sys_log(0, "MarkManager::SaveMarkIndex: index count %d", m_mapGID_MarkID.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGuildMarkManager::LoadMarkImages()
|
||||
{
|
||||
bool isMarkExists[MAX_IMAGE_COUNT];
|
||||
memset(isMarkExists, 0, sizeof(isMarkExists));
|
||||
|
||||
for (std::map<DWORD, DWORD>::iterator it = m_mapGID_MarkID.begin(); it != m_mapGID_MarkID.end(); ++it)
|
||||
{
|
||||
DWORD markID = it->second;
|
||||
|
||||
if (markID < MAX_IMAGE_COUNT * CGuildMarkImage::MARK_TOTAL_COUNT)
|
||||
isMarkExists[markID / CGuildMarkImage::MARK_TOTAL_COUNT] = true;
|
||||
}
|
||||
|
||||
for (DWORD i = 0; i < MAX_IMAGE_COUNT; ++i)
|
||||
if (isMarkExists[i])
|
||||
__GetImage(i);
|
||||
}
|
||||
|
||||
void CGuildMarkManager::SaveMarkImage(DWORD imgIdx)
|
||||
{
|
||||
std::string path;
|
||||
|
||||
if (GetMarkImageFilename(imgIdx, path))
|
||||
if (!__GetImage(imgIdx)->Save(path.c_str()))
|
||||
sys_err("%s Save failed\n", path.c_str());
|
||||
}
|
||||
|
||||
CGuildMarkImage * CGuildMarkManager::__GetImage(DWORD imgIdx)
|
||||
{
|
||||
std::map<DWORD, CGuildMarkImage *>::iterator it = m_mapIdx_Image.find(imgIdx);
|
||||
|
||||
if (it == m_mapIdx_Image.end())
|
||||
{
|
||||
std::string imagePath;
|
||||
|
||||
if (GetMarkImageFilename(imgIdx, imagePath))
|
||||
{
|
||||
CGuildMarkImage * pkImage = __NewImage();
|
||||
m_mapIdx_Image.emplace(imgIdx, pkImage);
|
||||
|
||||
if (!pkImage->Load(imagePath.c_str()))
|
||||
{
|
||||
pkImage->Build(imagePath.c_str());
|
||||
pkImage->Load(imagePath.c_str());
|
||||
}
|
||||
|
||||
return pkImage;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool CGuildMarkManager::AddMarkIDByGuildID(DWORD guildID, DWORD markID)
|
||||
{
|
||||
if (markID >= MAX_IMAGE_COUNT * CGuildMarkImage::MARK_TOTAL_COUNT)
|
||||
return false;
|
||||
|
||||
//sys_log(0, "MarkManager: guild_id=%d mark_id=%d", guildID, markID);
|
||||
m_mapGID_MarkID.emplace(guildID, markID);
|
||||
m_setFreeMarkID.erase(markID);
|
||||
return true;
|
||||
}
|
||||
|
||||
DWORD CGuildMarkManager::GetMarkID(DWORD guildID)
|
||||
{
|
||||
std::map<DWORD, DWORD>::iterator it = m_mapGID_MarkID.find(guildID);
|
||||
|
||||
if (it == m_mapGID_MarkID.end())
|
||||
return INVALID_MARK_ID;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
DWORD CGuildMarkManager::__AllocMarkID(DWORD guildID)
|
||||
{
|
||||
std::set<DWORD>::iterator it = m_setFreeMarkID.lower_bound(0);
|
||||
|
||||
if (it == m_setFreeMarkID.end())
|
||||
return INVALID_MARK_ID;
|
||||
|
||||
DWORD markID = *it;
|
||||
|
||||
DWORD imgIdx = markID / CGuildMarkImage::MARK_TOTAL_COUNT;
|
||||
CGuildMarkImage * pkImage = __GetImage(imgIdx);
|
||||
|
||||
if (pkImage && AddMarkIDByGuildID(guildID, markID))
|
||||
return markID;
|
||||
|
||||
return INVALID_MARK_ID;
|
||||
}
|
||||
|
||||
DWORD CGuildMarkManager::GetMarkImageCount() const
|
||||
{
|
||||
return m_mapIdx_Image.size();
|
||||
}
|
||||
|
||||
DWORD CGuildMarkManager::GetMarkCount() const
|
||||
{
|
||||
return m_mapGID_MarkID.size();
|
||||
}
|
||||
|
||||
// SERVER
|
||||
void CGuildMarkManager::CopyMarkIdx(char * pcBuf) const
|
||||
{
|
||||
WORD * pwBuf = (WORD *) pcBuf;
|
||||
|
||||
for (std::map<DWORD, DWORD>::const_iterator it = m_mapGID_MarkID.begin(); it != m_mapGID_MarkID.end(); ++it)
|
||||
{
|
||||
*(pwBuf++) = it->first; // guild id
|
||||
*(pwBuf++) = it->second; // mark id
|
||||
}
|
||||
}
|
||||
|
||||
// SERVER
|
||||
DWORD CGuildMarkManager::SaveMark(DWORD guildID, BYTE * pbMarkImage)
|
||||
{
|
||||
DWORD idMark;
|
||||
|
||||
if ((idMark = GetMarkID(guildID)) == INVALID_MARK_ID)
|
||||
{
|
||||
if ((idMark = __AllocMarkID(guildID)) == INVALID_MARK_ID)
|
||||
{
|
||||
sys_err("CGuildMarkManager: cannot alloc mark id %u", guildID);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
sys_log(0, "SaveMark: mark id alloc %u", idMark);
|
||||
}
|
||||
else
|
||||
sys_log(0, "SaveMark: mark id found %u", idMark);
|
||||
|
||||
DWORD imgIdx = (idMark / CGuildMarkImage::MARK_TOTAL_COUNT);
|
||||
CGuildMarkImage * pkImage = __GetImage(imgIdx);
|
||||
|
||||
if (pkImage)
|
||||
{
|
||||
pkImage->SaveMark(idMark % CGuildMarkImage::MARK_TOTAL_COUNT, pbMarkImage);
|
||||
|
||||
SaveMarkImage(imgIdx);
|
||||
SaveMarkIndex();
|
||||
}
|
||||
|
||||
return idMark;
|
||||
}
|
||||
|
||||
// SERVER
|
||||
void CGuildMarkManager::DeleteMark(DWORD guildID)
|
||||
{
|
||||
std::map<DWORD, DWORD>::iterator it = m_mapGID_MarkID.find(guildID);
|
||||
|
||||
if (it == m_mapGID_MarkID.end())
|
||||
return;
|
||||
|
||||
CGuildMarkImage * pkImage;
|
||||
|
||||
if ((pkImage = __GetImage(it->second / CGuildMarkImage::MARK_TOTAL_COUNT)) != NULL)
|
||||
pkImage->DeleteMark(it->second % CGuildMarkImage::MARK_TOTAL_COUNT);
|
||||
|
||||
m_setFreeMarkID.emplace(it->second);
|
||||
m_mapGID_MarkID.erase(it);
|
||||
|
||||
SaveMarkIndex();
|
||||
}
|
||||
|
||||
// SERVER
|
||||
void CGuildMarkManager::GetDiffBlocks(DWORD imgIdx, const DWORD * crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks)
|
||||
{
|
||||
mapDiffBlocks.clear();
|
||||
|
||||
if (m_mapIdx_Image.end() == m_mapIdx_Image.find(imgIdx))
|
||||
{
|
||||
sys_err("invalid idx %u", imgIdx);
|
||||
return;
|
||||
}
|
||||
|
||||
CGuildMarkImage * p = __GetImage(imgIdx);
|
||||
|
||||
if (p)
|
||||
p->GetDiffBlocks(crcList, mapDiffBlocks);
|
||||
}
|
||||
|
||||
// CLIENT
|
||||
bool CGuildMarkManager::SaveBlockFromCompressedData(DWORD imgIdx, DWORD posBlock, const BYTE * pbBlock, DWORD dwSize)
|
||||
{
|
||||
CGuildMarkImage * pkImage = __GetImage(imgIdx);
|
||||
|
||||
if (pkImage)
|
||||
pkImage->SaveBlockFromCompressedData(posBlock, pbBlock, dwSize);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// CLIENT
|
||||
bool CGuildMarkManager::GetBlockCRCList(DWORD imgIdx, DWORD * crcList)
|
||||
{
|
||||
if (m_mapIdx_Image.end() == m_mapIdx_Image.find(imgIdx))
|
||||
{
|
||||
sys_err("invalid idx %u", imgIdx);
|
||||
return false;
|
||||
}
|
||||
|
||||
CGuildMarkImage * p = __GetImage(imgIdx);
|
||||
|
||||
if (p)
|
||||
p->GetBlockCRCList(crcList);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// Symbol
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
const CGuildMarkManager::TGuildSymbol * CGuildMarkManager::GetGuildSymbol(DWORD guildID)
|
||||
{
|
||||
std::map<DWORD, TGuildSymbol>::iterator it = m_mapSymbol.find(guildID);
|
||||
|
||||
if (it == m_mapSymbol.end())
|
||||
return NULL;
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
bool CGuildMarkManager::LoadSymbol(const char* filename)
|
||||
{
|
||||
FILE* fp = fopen(filename, "rb");
|
||||
|
||||
if (!fp)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
DWORD symbolCount;
|
||||
fread(&symbolCount, 4, 1, fp);
|
||||
|
||||
for (DWORD i = 0; i < symbolCount; i++)
|
||||
{
|
||||
DWORD guildID;
|
||||
DWORD dwSize;
|
||||
fread(&guildID, 4, 1, fp);
|
||||
fread(&dwSize, 4, 1, fp);
|
||||
|
||||
TGuildSymbol gs;
|
||||
gs.raw.resize(dwSize);
|
||||
fread(&gs.raw[0], 1, dwSize, fp);
|
||||
gs.crc = GetCRC32(reinterpret_cast<const char*>(&gs.raw[0]), dwSize);
|
||||
m_mapSymbol.emplace(guildID, gs);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGuildMarkManager::SaveSymbol(const char* filename)
|
||||
{
|
||||
FILE* fp = fopen(filename, "wb");
|
||||
if (!fp)
|
||||
{
|
||||
sys_err("Cannot open Symbol file (name: %s)", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD symbolCount = m_mapSymbol.size();
|
||||
fwrite(&symbolCount, 4, 1, fp);
|
||||
|
||||
for (std::map<DWORD, TGuildSymbol>::iterator it = m_mapSymbol.begin(); it != m_mapSymbol.end(); ++it)
|
||||
{
|
||||
DWORD guildID = it->first;
|
||||
DWORD dwSize = it->second.raw.size();
|
||||
fwrite(&guildID, 4, 1, fp);
|
||||
fwrite(&dwSize, 4, 1, fp);
|
||||
fwrite(&it->second.raw[0], 1, dwSize, fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void CGuildMarkManager::UploadSymbol(DWORD guildID, int iSize, const BYTE* pbyData)
|
||||
{
|
||||
sys_log(0, "GuildSymbolUpload guildID %u Size %d", guildID, iSize);
|
||||
|
||||
if (m_mapSymbol.find(guildID) == m_mapSymbol.end())
|
||||
m_mapSymbol.emplace(guildID, TGuildSymbol());
|
||||
|
||||
TGuildSymbol& rSymbol = m_mapSymbol[guildID];
|
||||
rSymbol.raw.clear();
|
||||
|
||||
if (iSize > 0)
|
||||
{
|
||||
rSymbol.raw.reserve(iSize);
|
||||
std::copy(pbyData, (pbyData + iSize), std::back_inserter(rSymbol.raw));
|
||||
rSymbol.crc = GetCRC32(reinterpret_cast<const char*>(pbyData), iSize);
|
||||
}
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
82
source-server/Srcs/Server/game/src/MarkManager.h
Normal file
82
source-server/Srcs/Server/game/src/MarkManager.h
Normal file
@ -0,0 +1,82 @@
|
||||
#ifndef __INC_METIN_II_GUILDLIB_MARK_MANAGER_H__
|
||||
#define __INC_METIN_II_GUILDLIB_MARK_MANAGER_H__
|
||||
|
||||
#include "MarkImage.h"
|
||||
|
||||
class CGuildMarkManager : public singleton<CGuildMarkManager>
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_IMAGE_COUNT = 5,
|
||||
INVALID_MARK_ID = 0xffffffff,
|
||||
};
|
||||
|
||||
// Symbol
|
||||
struct TGuildSymbol
|
||||
{
|
||||
DWORD crc;
|
||||
std::vector<BYTE> raw;
|
||||
};
|
||||
|
||||
CGuildMarkManager();
|
||||
virtual ~CGuildMarkManager();
|
||||
|
||||
const TGuildSymbol * GetGuildSymbol(DWORD GID);
|
||||
bool LoadSymbol(const char* filename);
|
||||
void SaveSymbol(const char* filename);
|
||||
void UploadSymbol(DWORD guildID, int iSize, const BYTE* pbyData);
|
||||
|
||||
// Mark
|
||||
|
||||
void SetMarkPathPrefix(const char * prefix);
|
||||
|
||||
bool LoadMarkIndex();
|
||||
bool SaveMarkIndex();
|
||||
|
||||
void LoadMarkImages();
|
||||
void SaveMarkImage(DWORD imgIdx);
|
||||
|
||||
bool GetMarkImageFilename(DWORD imgIdx, std::string & path) const;
|
||||
bool AddMarkIDByGuildID(DWORD guildID, DWORD markID);
|
||||
DWORD GetMarkImageCount() const;
|
||||
DWORD GetMarkCount() const;
|
||||
DWORD GetMarkID(DWORD guildID);
|
||||
|
||||
// SERVER
|
||||
void CopyMarkIdx(char * pcBuf) const;
|
||||
DWORD SaveMark(DWORD guildID, BYTE * pbMarkImage);
|
||||
void DeleteMark(DWORD guildID);
|
||||
void GetDiffBlocks(DWORD imgIdx, const DWORD * crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks);
|
||||
|
||||
// CLIENT
|
||||
bool SaveBlockFromCompressedData(DWORD imgIdx, DWORD idBlock, const BYTE * pbBlock, DWORD dwSize);
|
||||
bool GetBlockCRCList(DWORD imgIdx, DWORD * crcList);
|
||||
|
||||
private:
|
||||
|
||||
// Mark
|
||||
|
||||
CGuildMarkImage * __NewImage();
|
||||
void __DeleteImage(CGuildMarkImage * pkImgDel);
|
||||
|
||||
DWORD __AllocMarkID(DWORD guildID);
|
||||
|
||||
CGuildMarkImage * __GetImage(DWORD imgIdx);
|
||||
CGuildMarkImage * __GetImagePtr(DWORD idMark);
|
||||
|
||||
std::map<DWORD, CGuildMarkImage *> m_mapIdx_Image; // index = image index
|
||||
std::map<DWORD, DWORD> m_mapGID_MarkID; // index = guild id
|
||||
|
||||
std::set<DWORD> m_setFreeMarkID;
|
||||
std::string m_pathPrefix;
|
||||
|
||||
private:
|
||||
|
||||
// Symbol
|
||||
|
||||
std::map<DWORD, TGuildSymbol> m_mapSymbol;
|
||||
};
|
||||
|
||||
#endif
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
432
source-server/Srcs/Server/game/src/OXEvent.cpp
Normal file
432
source-server/Srcs/Server/game/src/OXEvent.cpp
Normal file
@ -0,0 +1,432 @@
|
||||
#include "stdafx.h"
|
||||
#include "constants.h"
|
||||
#include "config.h"
|
||||
#include "questmanager.h"
|
||||
#include "start_position.h"
|
||||
#include "packet.h"
|
||||
#include "buffer_manager.h"
|
||||
#include "log.h"
|
||||
#include "char.h"
|
||||
#include "char_manager.h"
|
||||
#include "OXEvent.h"
|
||||
#include "desc.h"
|
||||
|
||||
bool COXEventManager::Initialize()
|
||||
{
|
||||
m_timedEvent = NULL;
|
||||
m_map_char.clear();
|
||||
m_map_attender.clear();
|
||||
m_vec_quiz.clear();
|
||||
|
||||
SetStatus(OXEVENT_FINISH);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void COXEventManager::Destroy()
|
||||
{
|
||||
CloseEvent();
|
||||
|
||||
m_map_char.clear();
|
||||
m_map_attender.clear();
|
||||
m_vec_quiz.clear();
|
||||
|
||||
SetStatus(OXEVENT_FINISH);
|
||||
}
|
||||
|
||||
OXEventStatus COXEventManager::GetStatus()
|
||||
{
|
||||
BYTE ret = quest::CQuestManager::instance().GetEventFlag("oxevent_status");
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case 0 :
|
||||
return OXEVENT_FINISH;
|
||||
|
||||
case 1 :
|
||||
return OXEVENT_OPEN;
|
||||
|
||||
case 2 :
|
||||
return OXEVENT_CLOSE;
|
||||
|
||||
case 3 :
|
||||
return OXEVENT_QUIZ;
|
||||
|
||||
default :
|
||||
return OXEVENT_ERR;
|
||||
}
|
||||
|
||||
return OXEVENT_ERR;
|
||||
}
|
||||
|
||||
void COXEventManager::SetStatus(OXEventStatus status)
|
||||
{
|
||||
BYTE val = 0;
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case OXEVENT_OPEN :
|
||||
val = 1;
|
||||
break;
|
||||
|
||||
case OXEVENT_CLOSE :
|
||||
val = 2;
|
||||
break;
|
||||
|
||||
case OXEVENT_QUIZ :
|
||||
val = 3;
|
||||
break;
|
||||
|
||||
case OXEVENT_FINISH :
|
||||
case OXEVENT_ERR :
|
||||
default :
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
quest::CQuestManager::instance().RequestSetEventFlag("oxevent_status", val);
|
||||
}
|
||||
|
||||
bool COXEventManager::Enter(LPCHARACTER pkChar)
|
||||
{
|
||||
if (GetStatus() == OXEVENT_FINISH)
|
||||
{
|
||||
sys_log(0, "OXEVENT : map finished. but char enter. %s", pkChar->GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
PIXEL_POSITION pos = pkChar->GetXYZ();
|
||||
|
||||
if (pos.x == 896500 && pos.y == 24600)
|
||||
{
|
||||
return EnterAttender(pkChar);
|
||||
}
|
||||
else if (pos.x == 896300 && pos.y == 28900)
|
||||
{
|
||||
return EnterAudience(pkChar);
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_log(0, "OXEVENT : wrong pos enter %d %d", pos.x, pos.y);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool COXEventManager::EnterAttender(LPCHARACTER pkChar)
|
||||
{
|
||||
DWORD pid = pkChar->GetPlayerID();
|
||||
|
||||
m_map_char.emplace(pid, pid);
|
||||
m_map_attender.emplace(pid, pid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COXEventManager::EnterAudience(LPCHARACTER pkChar)
|
||||
{
|
||||
DWORD pid = pkChar->GetPlayerID();
|
||||
|
||||
m_map_char.emplace(pid, pid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COXEventManager::AddQuiz(unsigned char level, const char* pszQuestion, bool answer)
|
||||
{
|
||||
if (m_vec_quiz.size() < (size_t) level + 1)
|
||||
m_vec_quiz.resize(level + 1);
|
||||
|
||||
struct tag_Quiz tmpQuiz;
|
||||
|
||||
tmpQuiz.level = level;
|
||||
strlcpy(tmpQuiz.Quiz, pszQuestion, sizeof(tmpQuiz.Quiz));
|
||||
tmpQuiz.answer = answer;
|
||||
|
||||
m_vec_quiz[level].emplace_back(tmpQuiz);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COXEventManager::ShowQuizList(LPCHARACTER pkChar)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
for (size_t i = 0; i < m_vec_quiz.size(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < m_vec_quiz[i].size(); ++j, ++c)
|
||||
{
|
||||
pkChar->ChatPacket(CHAT_TYPE_INFO, "%d %s %s", m_vec_quiz[i][j].level, m_vec_quiz[i][j].Quiz, m_vec_quiz[i][j].answer ? LC_TEXT("참") : LC_TEXT("거짓"));
|
||||
}
|
||||
}
|
||||
|
||||
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("총 퀴즈 수: %d"), c);
|
||||
return true;
|
||||
}
|
||||
|
||||
void COXEventManager::ClearQuiz()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_vec_quiz.size(); ++i)
|
||||
{
|
||||
m_vec_quiz[i].clear();
|
||||
}
|
||||
|
||||
m_vec_quiz.clear();
|
||||
}
|
||||
|
||||
EVENTINFO(OXEventInfoData)
|
||||
{
|
||||
bool answer;
|
||||
|
||||
OXEventInfoData()
|
||||
: answer( false )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
EVENTFUNC(oxevent_timer)
|
||||
{
|
||||
static BYTE flag = 0;
|
||||
OXEventInfoData* info = dynamic_cast<OXEventInfoData*>(event->info);
|
||||
|
||||
if ( info == NULL )
|
||||
{
|
||||
sys_err( "oxevent_timer> <Factor> Null pointer" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (flag)
|
||||
{
|
||||
case 0:
|
||||
SendNoticeMap(LC_TEXT("10초뒤 판정하겠습니다."), OXEVENT_MAP_INDEX, true);
|
||||
flag++;
|
||||
return PASSES_PER_SEC(10);
|
||||
|
||||
case 1:
|
||||
SendNoticeMap(LC_TEXT("정답은"), OXEVENT_MAP_INDEX, true);
|
||||
|
||||
if (info->answer == true)
|
||||
{
|
||||
COXEventManager::instance().CheckAnswer(true);
|
||||
SendNoticeMap(LC_TEXT("O 입니다"), OXEVENT_MAP_INDEX, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
COXEventManager::instance().CheckAnswer(false);
|
||||
SendNoticeMap(LC_TEXT("X 입니다"), OXEVENT_MAP_INDEX, true);
|
||||
}
|
||||
|
||||
SendNoticeMap(LC_TEXT("5초 뒤 틀리신 분들을 바깥으로 이동 시키겠습니다."), OXEVENT_MAP_INDEX, true);
|
||||
|
||||
flag++;
|
||||
return PASSES_PER_SEC(5);
|
||||
|
||||
case 2:
|
||||
COXEventManager::instance().WarpToAudience();
|
||||
COXEventManager::instance().SetStatus(OXEVENT_CLOSE);
|
||||
SendNoticeMap(LC_TEXT("다음 문제 준비해주세요."), OXEVENT_MAP_INDEX, true);
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool COXEventManager::Quiz(unsigned char level, int timelimit)
|
||||
{
|
||||
if (m_vec_quiz.size() == 0) return false;
|
||||
if (level > m_vec_quiz.size()) level = m_vec_quiz.size() - 1;
|
||||
if (m_vec_quiz[level].size() <= 0) return false;
|
||||
|
||||
if (timelimit < 0) timelimit = 30;
|
||||
|
||||
int idx = number(0, m_vec_quiz[level].size()-1);
|
||||
|
||||
SendNoticeMap(LC_TEXT("문제 입니다."), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(m_vec_quiz[level][idx].Quiz, OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("맞으면 O, 틀리면 X로 이동해주세요"), OXEVENT_MAP_INDEX, true);
|
||||
|
||||
if (m_timedEvent != NULL) {
|
||||
event_cancel(&m_timedEvent);
|
||||
}
|
||||
|
||||
OXEventInfoData* answer = AllocEventInfo<OXEventInfoData>();
|
||||
|
||||
answer->answer = m_vec_quiz[level][idx].answer;
|
||||
|
||||
timelimit -= 15;
|
||||
m_timedEvent = event_create(oxevent_timer, answer, PASSES_PER_SEC(timelimit));
|
||||
|
||||
SetStatus(OXEVENT_QUIZ);
|
||||
|
||||
m_vec_quiz[level].erase(m_vec_quiz[level].begin()+idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COXEventManager::CheckAnswer(bool answer)
|
||||
{
|
||||
if (m_map_attender.size() <= 0) return true;
|
||||
|
||||
itertype(m_map_attender) iter = m_map_attender.begin();
|
||||
itertype(m_map_attender) iter_tmp;
|
||||
|
||||
m_map_miss.clear();
|
||||
|
||||
int rect[4];
|
||||
if (answer != true)
|
||||
{
|
||||
rect[0] = 892600;
|
||||
rect[1] = 22900;
|
||||
rect[2] = 896300;
|
||||
rect[3] = 26400;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect[0] = 896600;
|
||||
rect[1] = 22900;
|
||||
rect[2] = 900300;
|
||||
rect[3] = 26400;
|
||||
}
|
||||
|
||||
LPCHARACTER pkChar = NULL;
|
||||
PIXEL_POSITION pos;
|
||||
for (; iter != m_map_attender.end();)
|
||||
{
|
||||
pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||||
if (pkChar != NULL)
|
||||
{
|
||||
pos = pkChar->GetXYZ();
|
||||
|
||||
if (pos.x < rect[0] || pos.x > rect[2] || pos.y < rect[1] || pos.y > rect[3])
|
||||
{
|
||||
pkChar->EffectPacket(SE_FAIL);
|
||||
iter_tmp = iter;
|
||||
iter++;
|
||||
m_map_attender.erase(iter_tmp);
|
||||
m_map_miss.emplace(pkChar->GetPlayerID(), pkChar->GetPlayerID());
|
||||
}
|
||||
else
|
||||
{
|
||||
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("정답입니다!"));
|
||||
// pkChar->CreateFly(number(FLY_FIREWORK1, FLY_FIREWORK6), pkChar);
|
||||
char chatbuf[256];
|
||||
int len = snprintf(chatbuf, sizeof(chatbuf),
|
||||
"%s %u %u", number(0, 1) == 1 ? "cheer1" : "cheer2", (DWORD)pkChar->GetVID(), 0);
|
||||
|
||||
if (len < 0 || len >= (int) sizeof(chatbuf))
|
||||
len = sizeof(chatbuf) - 1;
|
||||
|
||||
++len;
|
||||
|
||||
TPacketGCChat pack_chat;
|
||||
pack_chat.header = HEADER_GC_CHAT;
|
||||
pack_chat.size = sizeof(TPacketGCChat) + len;
|
||||
pack_chat.type = CHAT_TYPE_COMMAND;
|
||||
pack_chat.id = 0;
|
||||
|
||||
TEMP_BUFFER buf;
|
||||
buf.write(&pack_chat, sizeof(TPacketGCChat));
|
||||
buf.write(chatbuf, len);
|
||||
|
||||
pkChar->PacketAround(buf.read_peek(), buf.size());
|
||||
pkChar->EffectPacket(SE_SUCCESS);
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
itertype(m_map_char) err = m_map_char.find(iter->first);
|
||||
if (err != m_map_char.end()) m_map_char.erase(err);
|
||||
|
||||
itertype(m_map_miss) err2 = m_map_miss.find(iter->first);
|
||||
if (err2 != m_map_miss.end()) m_map_miss.erase(err2);
|
||||
|
||||
iter_tmp = iter;
|
||||
++iter;
|
||||
m_map_attender.erase(iter_tmp);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void COXEventManager::WarpToAudience()
|
||||
{
|
||||
if (m_map_miss.size() <= 0) return;
|
||||
|
||||
itertype(m_map_miss) iter = m_map_miss.begin();
|
||||
LPCHARACTER pkChar = NULL;
|
||||
|
||||
for (; iter != m_map_miss.end(); ++iter)
|
||||
{
|
||||
pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||||
|
||||
if (pkChar != NULL)
|
||||
{
|
||||
switch ( number(0, 3))
|
||||
{
|
||||
case 0 : pkChar->Show(OXEVENT_MAP_INDEX, 896300, 28900); break;
|
||||
case 1 : pkChar->Show(OXEVENT_MAP_INDEX, 890900, 28100); break;
|
||||
case 2 : pkChar->Show(OXEVENT_MAP_INDEX, 896600, 20500); break;
|
||||
case 3 : pkChar->Show(OXEVENT_MAP_INDEX, 902500, 28100); break;
|
||||
default : pkChar->Show(OXEVENT_MAP_INDEX, 896300, 28900); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_map_miss.clear();
|
||||
}
|
||||
|
||||
bool COXEventManager::CloseEvent()
|
||||
{
|
||||
if (m_timedEvent != NULL) {
|
||||
event_cancel(&m_timedEvent);
|
||||
}
|
||||
|
||||
itertype(m_map_char) iter = m_map_char.begin();
|
||||
|
||||
LPCHARACTER pkChar = NULL;
|
||||
for (; iter != m_map_char.end(); ++iter)
|
||||
{
|
||||
pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||||
|
||||
if (pkChar != NULL)
|
||||
pkChar->WarpSet(EMPIRE_START_X(pkChar->GetEmpire()), EMPIRE_START_Y(pkChar->GetEmpire()));
|
||||
}
|
||||
|
||||
Initialize(); // @fixme157 (instead of simply doing m_map_char.clear();)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COXEventManager::LogWinner()
|
||||
{
|
||||
itertype(m_map_attender) iter = m_map_attender.begin();
|
||||
|
||||
for (; iter != m_map_attender.end(); ++iter)
|
||||
{
|
||||
LPCHARACTER pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||||
|
||||
if (pkChar)
|
||||
LogManager::instance().CharLog(pkChar, 0, "OXEVENT", "LastManStanding");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COXEventManager::GiveItemToAttender(DWORD dwItemVnum, BYTE count)
|
||||
{
|
||||
itertype(m_map_attender) iter = m_map_attender.begin();
|
||||
|
||||
for (; iter != m_map_attender.end(); ++iter)
|
||||
{
|
||||
LPCHARACTER pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
|
||||
|
||||
if (pkChar)
|
||||
{
|
||||
pkChar->AutoGiveItem(dwItemVnum, count);
|
||||
LogManager::instance().ItemLog(pkChar->GetPlayerID(), 0, count, dwItemVnum, "OXEVENT_REWARD", "", pkChar->GetDesc()->GetHostName(), dwItemVnum);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
64
source-server/Srcs/Server/game/src/OXEvent.h
Normal file
64
source-server/Srcs/Server/game/src/OXEvent.h
Normal file
@ -0,0 +1,64 @@
|
||||
#define OXEVENT_MAP_INDEX 113
|
||||
|
||||
struct tag_Quiz
|
||||
{
|
||||
char level;
|
||||
char Quiz[256];
|
||||
bool answer;
|
||||
};
|
||||
|
||||
enum OXEventStatus
|
||||
{
|
||||
OXEVENT_FINISH = 0,
|
||||
OXEVENT_OPEN = 1,
|
||||
OXEVENT_CLOSE = 2,
|
||||
OXEVENT_QUIZ = 3,
|
||||
|
||||
OXEVENT_ERR = 0xff
|
||||
};
|
||||
|
||||
class COXEventManager : public singleton<COXEventManager>
|
||||
{
|
||||
private :
|
||||
std::map<DWORD, DWORD> m_map_char;
|
||||
std::map<DWORD, DWORD> m_map_attender;
|
||||
std::map<DWORD, DWORD> m_map_miss;
|
||||
|
||||
std::vector<std::vector<tag_Quiz> > m_vec_quiz;
|
||||
|
||||
LPEVENT m_timedEvent;
|
||||
|
||||
protected :
|
||||
bool CheckAnswer();
|
||||
|
||||
bool EnterAudience(LPCHARACTER pChar);
|
||||
bool EnterAttender(LPCHARACTER pChar);
|
||||
|
||||
public :
|
||||
bool Initialize();
|
||||
void Destroy();
|
||||
|
||||
OXEventStatus GetStatus();
|
||||
void SetStatus(OXEventStatus status);
|
||||
|
||||
bool LoadQuizScript(const char* szFileName);
|
||||
|
||||
bool Enter(LPCHARACTER pChar);
|
||||
|
||||
bool CloseEvent();
|
||||
|
||||
void ClearQuiz();
|
||||
bool AddQuiz(unsigned char level, const char* pszQuestion, bool answer);
|
||||
bool ShowQuizList(LPCHARACTER pChar);
|
||||
|
||||
bool Quiz(unsigned char level, int timelimit);
|
||||
bool GiveItemToAttender(DWORD dwItemVnum, BYTE count);
|
||||
|
||||
bool CheckAnswer(bool answer);
|
||||
void WarpToAudience();
|
||||
|
||||
bool LogWinner();
|
||||
|
||||
DWORD GetAttenderCount() { return m_map_attender.size(); }
|
||||
};
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
621
source-server/Srcs/Server/game/src/PetSystem.cpp
Normal file
621
source-server/Srcs/Server/game/src/PetSystem.cpp
Normal file
@ -0,0 +1,621 @@
|
||||
#include "stdafx.h"
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
#include "vector.h"
|
||||
#include "char.h"
|
||||
#include "sectree_manager.h"
|
||||
#include "char_manager.h"
|
||||
#include "mob_manager.h"
|
||||
#include "PetSystem.h"
|
||||
#include "../../common/VnumHelper.h"
|
||||
#include "packet.h"
|
||||
#include "item_manager.h"
|
||||
#include "item.h"
|
||||
|
||||
EVENTINFO(petsystem_event_info)
|
||||
{
|
||||
CPetSystem* pPetSystem;
|
||||
};
|
||||
|
||||
EVENTFUNC(petsystem_update_event)
|
||||
{
|
||||
petsystem_event_info* info = dynamic_cast<petsystem_event_info*>( event->info );
|
||||
if ( info == NULL )
|
||||
{
|
||||
sys_err( "check_speedhack_event> <Factor> Null pointer" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
CPetSystem* pPetSystem = info->pPetSystem;
|
||||
|
||||
if (NULL == pPetSystem)
|
||||
return 0;
|
||||
|
||||
pPetSystem->Update(0);
|
||||
|
||||
return PASSES_PER_SEC(1) / 4;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// CPetActor
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CPetActor::CPetActor(LPCHARACTER owner, DWORD vnum, DWORD options)
|
||||
{
|
||||
m_dwVnum = vnum;
|
||||
m_dwVID = 0;
|
||||
m_dwOptions = options;
|
||||
m_dwLastActionTime = 0;
|
||||
|
||||
m_pkChar = 0;
|
||||
m_pkOwner = owner;
|
||||
|
||||
m_originalMoveSpeed = 0;
|
||||
|
||||
m_dwSummonItemVID = 0;
|
||||
m_dwSummonItemVnum = 0;
|
||||
}
|
||||
|
||||
CPetActor::~CPetActor()
|
||||
{
|
||||
this->Unsummon(
|
||||
#ifdef USE_ACTIVE_PET_SEAL_EFFECT
|
||||
false
|
||||
#endif
|
||||
);
|
||||
|
||||
m_pkOwner = 0;
|
||||
}
|
||||
|
||||
void CPetActor::SetName(const char* name)
|
||||
{
|
||||
std::string petName = m_pkOwner->GetName();
|
||||
petName += "'s ";
|
||||
petName += (name) ? name : "Pet";
|
||||
|
||||
if (IsSummoned())
|
||||
m_pkChar->SetName(petName);
|
||||
|
||||
m_name = petName;
|
||||
}
|
||||
|
||||
bool CPetActor::Mount()
|
||||
{
|
||||
if (0 == m_pkOwner)
|
||||
return false;
|
||||
|
||||
if (true == HasOption(EPetOption_Mountable))
|
||||
m_pkOwner->MountVnum(m_dwVnum);
|
||||
|
||||
return m_pkOwner->GetMountVnum() == m_dwVnum;;
|
||||
}
|
||||
|
||||
void CPetActor::Unmount()
|
||||
{
|
||||
if (0 == m_pkOwner)
|
||||
return;
|
||||
|
||||
if (m_pkOwner->IsHorseRiding())
|
||||
m_pkOwner->StopRiding();
|
||||
}
|
||||
|
||||
void CPetActor::Unsummon(
|
||||
#ifdef USE_ACTIVE_PET_SEAL_EFFECT
|
||||
bool updateSocket
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (true == this->IsSummoned())
|
||||
{
|
||||
this->ClearBuff();
|
||||
this->SetSummonItem(NULL
|
||||
#ifdef USE_ACTIVE_PET_SEAL_EFFECT
|
||||
, updateSocket
|
||||
#endif
|
||||
);
|
||||
|
||||
if (NULL != m_pkOwner)
|
||||
m_pkOwner->ComputePoints();
|
||||
|
||||
if (NULL != m_pkChar)
|
||||
M2_DESTROY_CHARACTER(m_pkChar);
|
||||
|
||||
m_pkChar = 0;
|
||||
m_dwVID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD CPetActor::Summon(const char* petName, LPITEM pSummonItem, bool bSpawnFar)
|
||||
{
|
||||
long x = m_pkOwner->GetX();
|
||||
long y = m_pkOwner->GetY();
|
||||
long z = m_pkOwner->GetZ();
|
||||
|
||||
if (true == bSpawnFar)
|
||||
{
|
||||
x += (number(0, 1) * 2 - 1) * number(2000, 2500);
|
||||
y += (number(0, 1) * 2 - 1) * number(2000, 2500);
|
||||
}
|
||||
else
|
||||
{
|
||||
x += number(-100, 100);
|
||||
y += number(-100, 100);
|
||||
}
|
||||
|
||||
if (0 != m_pkChar)
|
||||
{
|
||||
m_pkChar->Show (m_pkOwner->GetMapIndex(), x, y);
|
||||
m_dwVID = m_pkChar->GetVID();
|
||||
|
||||
return m_dwVID;
|
||||
}
|
||||
|
||||
m_pkChar = CHARACTER_MANAGER::instance().SpawnMob(
|
||||
m_dwVnum,
|
||||
m_pkOwner->GetMapIndex(),
|
||||
x, y, z,
|
||||
false, (int)(m_pkOwner->GetRotation()+180), false);
|
||||
|
||||
if (0 == m_pkChar)
|
||||
{
|
||||
sys_err("[CPetSystem::Summon] Failed to summon the pet. (vnum: %d)", m_dwVnum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_pkChar->SetPet();
|
||||
|
||||
m_pkChar->SetEmpire(m_pkOwner->GetEmpire());
|
||||
|
||||
m_dwVID = m_pkChar->GetVID();
|
||||
|
||||
this->SetName(petName);
|
||||
|
||||
this->SetSummonItem(pSummonItem);
|
||||
m_pkOwner->ComputePoints();
|
||||
m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z);
|
||||
|
||||
return m_dwVID;
|
||||
}
|
||||
|
||||
bool CPetActor::_UpdatAloneActionAI(float fMinDist, float fMaxDist)
|
||||
{
|
||||
float fDist = number(fMinDist, fMaxDist);
|
||||
float r = (float)number (0, 359);
|
||||
float dest_x = GetOwner()->GetX() + fDist * cos(r);
|
||||
float dest_y = GetOwner()->GetY() + fDist * sin(r);
|
||||
|
||||
m_pkChar->SetNowWalking(true);
|
||||
|
||||
if (!m_pkChar->IsStateMove() && m_pkChar->Goto(dest_x, dest_y))
|
||||
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
|
||||
|
||||
m_dwLastActionTime = get_dword_time();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPetActor::_UpdateFollowAI()
|
||||
{
|
||||
if (0 == m_pkChar->m_pkMobData)
|
||||
{
|
||||
//sys_err("[CPetActor::_UpdateFollowAI] m_pkChar->m_pkMobData is NULL");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 == m_originalMoveSpeed)
|
||||
{
|
||||
const CMob* mobData = CMobManager::Instance().Get(m_dwVnum);
|
||||
|
||||
if (0 != mobData)
|
||||
m_originalMoveSpeed = mobData->m_table.sMovingSpeed;
|
||||
}
|
||||
float START_FOLLOW_DISTANCE = 300.0f;
|
||||
float START_RUN_DISTANCE = 900.0f;
|
||||
|
||||
float RESPAWN_DISTANCE = 4500.f;
|
||||
int APPROACH = 200;
|
||||
|
||||
bool bRun = false;
|
||||
|
||||
DWORD currentTime = get_dword_time();
|
||||
|
||||
long ownerX = m_pkOwner->GetX(); long ownerY = m_pkOwner->GetY();
|
||||
long charX = m_pkChar->GetX(); long charY = m_pkChar->GetY();
|
||||
|
||||
float fDist = DISTANCE_APPROX(charX - ownerX, charY - ownerY);
|
||||
|
||||
if (fDist >= RESPAWN_DISTANCE)
|
||||
{
|
||||
float fOwnerRot = m_pkOwner->GetRotation() * 3.141592f / 180.f;
|
||||
float fx = -APPROACH * cos(fOwnerRot);
|
||||
float fy = -APPROACH * sin(fOwnerRot);
|
||||
if (m_pkChar->Show(m_pkOwner->GetMapIndex(), ownerX + fx, ownerY + fy))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fDist >= START_FOLLOW_DISTANCE)
|
||||
{
|
||||
if( fDist >= START_RUN_DISTANCE)
|
||||
{
|
||||
bRun = true;
|
||||
}
|
||||
|
||||
m_pkChar->SetNowWalking(!bRun);
|
||||
|
||||
Follow(APPROACH);
|
||||
|
||||
m_pkChar->SetLastAttacked(currentTime);
|
||||
m_dwLastActionTime = currentTime;
|
||||
}
|
||||
|
||||
else
|
||||
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPetActor::Update(DWORD deltaTime)
|
||||
{
|
||||
bool bResult = true;
|
||||
|
||||
if (m_pkOwner->IsDead() || (IsSummoned() && m_pkChar->IsDead())
|
||||
|| NULL == ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())
|
||||
|| ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())->GetOwner() != this->GetOwner()
|
||||
)
|
||||
{
|
||||
this->Unsummon();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this->IsSummoned() && HasOption(EPetOption_Followable))
|
||||
bResult = bResult && this->_UpdateFollowAI();
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool CPetActor::Follow(float fMinDistance)
|
||||
{
|
||||
if( !m_pkOwner || !m_pkChar)
|
||||
return false;
|
||||
|
||||
float fOwnerX = m_pkOwner->GetX();
|
||||
float fOwnerY = m_pkOwner->GetY();
|
||||
|
||||
float fPetX = m_pkChar->GetX();
|
||||
float fPetY = m_pkChar->GetY();
|
||||
|
||||
float fDist = DISTANCE_SQRT(fOwnerX - fPetX, fOwnerY - fPetY);
|
||||
if (fDist <= fMinDistance)
|
||||
return false;
|
||||
|
||||
m_pkChar->SetRotationToXY(fOwnerX, fOwnerY);
|
||||
|
||||
float fx, fy;
|
||||
|
||||
float fDistToGo = fDist - fMinDistance;
|
||||
GetDeltaByDegree(m_pkChar->GetRotation(), fDistToGo, &fx, &fy);
|
||||
|
||||
if (!m_pkChar->Goto((int)(fPetX+fx+0.5f), (int)(fPetY+fy+0.5f)) )
|
||||
return false;
|
||||
|
||||
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPetActor::SetSummonItem(LPITEM pItem
|
||||
#ifdef USE_ACTIVE_PET_SEAL_EFFECT
|
||||
, bool updateSocket
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (!pItem)
|
||||
{
|
||||
#ifdef USE_ACTIVE_PET_SEAL_EFFECT
|
||||
LPITEM pSummonItem = ITEM_MANAGER::instance().FindByVID(m_dwSummonItemVID);
|
||||
if (pSummonItem && updateSocket)
|
||||
pSummonItem->SetSocket(PET_SEAL_ACTIVE_SOCKET_IDX, false);
|
||||
#endif
|
||||
m_dwSummonItemVID = 0;
|
||||
m_dwSummonItemVnum = 0;
|
||||
return false;
|
||||
}
|
||||
#ifdef USE_ACTIVE_PET_SEAL_EFFECT
|
||||
pItem->SetSocket(PET_SEAL_ACTIVE_SOCKET_IDX, true);
|
||||
#endif
|
||||
m_dwSummonItemVID = pItem->GetVID();
|
||||
m_dwSummonItemVnum = pItem->GetVnum();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool __PetCheckBuff(const CPetActor* pPetActor)
|
||||
{
|
||||
bool bMustHaveBuff = true;
|
||||
switch (pPetActor->GetVnum())
|
||||
{
|
||||
case 34004:
|
||||
case 34009:
|
||||
if (!pPetActor->GetOwner()->GetDungeon())
|
||||
bMustHaveBuff = false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return bMustHaveBuff;
|
||||
}
|
||||
|
||||
void CPetActor::GiveBuff()
|
||||
{
|
||||
if (!__PetCheckBuff(this))
|
||||
return;
|
||||
LPITEM item = ITEM_MANAGER::instance().FindByVID(m_dwSummonItemVID);
|
||||
if (item)
|
||||
item->ModifyPoints(true);
|
||||
return ;
|
||||
}
|
||||
|
||||
void CPetActor::ClearBuff()
|
||||
{
|
||||
if (NULL == m_pkOwner)
|
||||
return ;
|
||||
TItemTable* item_proto = ITEM_MANAGER::instance().GetTable(m_dwSummonItemVnum);
|
||||
if (NULL == item_proto)
|
||||
return;
|
||||
if (!__PetCheckBuff(this)) // @fixme129
|
||||
return;
|
||||
for (int i = 0; i < ITEM_APPLY_MAX_NUM; i++)
|
||||
{
|
||||
if (item_proto->aApplies[i].bType == APPLY_NONE)
|
||||
continue;
|
||||
m_pkOwner->ApplyPoint(item_proto->aApplies[i].bType, -item_proto->aApplies[i].lValue);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// CPetSystem
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CPetSystem::CPetSystem(LPCHARACTER owner)
|
||||
{
|
||||
// assert(0 != owner && "[CPetSystem::CPetSystem] Invalid owner");
|
||||
|
||||
m_pkOwner = owner;
|
||||
m_dwUpdatePeriod = 400;
|
||||
|
||||
m_dwLastUpdateTime = 0;
|
||||
}
|
||||
|
||||
CPetSystem::~CPetSystem()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void CPetSystem::Destroy()
|
||||
{
|
||||
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
||||
{
|
||||
CPetActor* petActor = iter->second;
|
||||
|
||||
if (0 != petActor)
|
||||
{
|
||||
delete petActor;
|
||||
}
|
||||
}
|
||||
event_cancel(&m_pkPetSystemUpdateEvent);
|
||||
m_petActorMap.clear();
|
||||
}
|
||||
|
||||
bool CPetSystem::Update(DWORD deltaTime)
|
||||
{
|
||||
bool bResult = true;
|
||||
|
||||
DWORD currentTime = get_dword_time();
|
||||
|
||||
if (m_dwUpdatePeriod > currentTime - m_dwLastUpdateTime)
|
||||
return true;
|
||||
|
||||
std::vector <CPetActor*> v_garbageActor;
|
||||
|
||||
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
||||
{
|
||||
CPetActor* petActor = iter->second;
|
||||
|
||||
if (0 != petActor && petActor->IsSummoned())
|
||||
{
|
||||
LPCHARACTER pPet = petActor->GetCharacter();
|
||||
|
||||
if (NULL == CHARACTER_MANAGER::instance().Find(pPet->GetVID()))
|
||||
{
|
||||
v_garbageActor.emplace_back(petActor);
|
||||
}
|
||||
else
|
||||
{
|
||||
bResult = bResult && petActor->Update(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (std::vector<CPetActor*>::iterator it = v_garbageActor.begin(); it != v_garbageActor.end(); it++)
|
||||
DeletePet(*it);
|
||||
|
||||
m_dwLastUpdateTime = currentTime;
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
void CPetSystem::DeletePet(DWORD mobVnum)
|
||||
{
|
||||
TPetActorMap::iterator iter = m_petActorMap.find(mobVnum);
|
||||
|
||||
if (m_petActorMap.end() == iter)
|
||||
{
|
||||
sys_err("[CPetSystem::DeletePet] Can't find pet on my list (VNUM: %d)", mobVnum);
|
||||
return;
|
||||
}
|
||||
|
||||
CPetActor* petActor = iter->second;
|
||||
|
||||
if (0 == petActor)
|
||||
sys_err("[CPetSystem::DeletePet] Null Pointer (petActor)");
|
||||
else
|
||||
delete petActor;
|
||||
|
||||
m_petActorMap.erase(iter);
|
||||
}
|
||||
|
||||
void CPetSystem::DeletePet(CPetActor* petActor)
|
||||
{
|
||||
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
||||
{
|
||||
if (iter->second == petActor)
|
||||
{
|
||||
delete petActor;
|
||||
m_petActorMap.erase(iter);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sys_err("[CPetSystem::DeletePet] Can't find petActor(0x%x) on my list(size: %d) ", petActor, m_petActorMap.size());
|
||||
}
|
||||
|
||||
void CPetSystem::Unsummon(DWORD vnum, bool bDeleteFromList)
|
||||
{
|
||||
CPetActor* actor = this->GetByVnum(vnum);
|
||||
|
||||
if (0 == actor)
|
||||
{
|
||||
sys_err("[CPetSystem::GetByVnum(%d)] Null Pointer (petActor)", vnum);
|
||||
return;
|
||||
}
|
||||
actor->Unsummon();
|
||||
|
||||
if (true == bDeleteFromList)
|
||||
this->DeletePet(actor);
|
||||
|
||||
bool bActive = false;
|
||||
for (TPetActorMap::iterator it = m_petActorMap.begin(); it != m_petActorMap.end(); it++)
|
||||
{
|
||||
bActive |= it->second->IsSummoned();
|
||||
}
|
||||
if (false == bActive)
|
||||
{
|
||||
event_cancel(&m_pkPetSystemUpdateEvent);
|
||||
m_pkPetSystemUpdateEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CPetSystem::UnsummonAll()
|
||||
{
|
||||
for (auto & iter : m_petActorMap)
|
||||
{
|
||||
auto * actor = iter.second;
|
||||
if (actor)
|
||||
actor->Unsummon();
|
||||
}
|
||||
|
||||
bool bActive = false;
|
||||
for (auto & it : m_petActorMap)
|
||||
bActive |= it.second->IsSummoned();
|
||||
if (!bActive)
|
||||
{
|
||||
event_cancel(&m_pkPetSystemUpdateEvent);
|
||||
m_pkPetSystemUpdateEvent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
CPetActor* CPetSystem::Summon(DWORD mobVnum, LPITEM pSummonItem, const char* petName, bool bSpawnFar, DWORD options)
|
||||
{
|
||||
CPetActor* petActor = this->GetByVnum(mobVnum);
|
||||
|
||||
if (0 == petActor)
|
||||
{
|
||||
petActor = M2_NEW CPetActor(m_pkOwner, mobVnum, options);
|
||||
m_petActorMap.emplace(mobVnum, petActor);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_NEWSTUFF
|
||||
DWORD petVID = petActor->Summon(petName, pSummonItem, bSpawnFar);
|
||||
if (!petVID)
|
||||
sys_err("[CPetSystem::Summon(%d)] Null Pointer (petVID)", pSummonItem);
|
||||
#endif
|
||||
|
||||
if (NULL == m_pkPetSystemUpdateEvent)
|
||||
{
|
||||
petsystem_event_info* info = AllocEventInfo<petsystem_event_info>();
|
||||
|
||||
info->pPetSystem = this;
|
||||
|
||||
m_pkPetSystemUpdateEvent = event_create(petsystem_update_event, info, PASSES_PER_SEC(1) / 4);
|
||||
}
|
||||
|
||||
return petActor;
|
||||
}
|
||||
|
||||
CPetActor* CPetSystem::GetByVID(DWORD vid) const
|
||||
{
|
||||
CPetActor* petActor = 0;
|
||||
|
||||
bool bFound = false;
|
||||
|
||||
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
||||
{
|
||||
petActor = iter->second;
|
||||
|
||||
if (0 == petActor)
|
||||
{
|
||||
sys_err("[CPetSystem::GetByVID(%d)] Null Pointer (petActor)", vid);
|
||||
continue;
|
||||
}
|
||||
|
||||
bFound = petActor->GetVID() == vid;
|
||||
|
||||
if (true == bFound)
|
||||
break;
|
||||
}
|
||||
|
||||
return bFound ? petActor : 0;
|
||||
}
|
||||
|
||||
CPetActor* CPetSystem::GetByVnum(DWORD vnum) const
|
||||
{
|
||||
CPetActor* petActor = 0;
|
||||
|
||||
TPetActorMap::const_iterator iter = m_petActorMap.find(vnum);
|
||||
|
||||
if (m_petActorMap.end() != iter)
|
||||
petActor = iter->second;
|
||||
|
||||
return petActor;
|
||||
}
|
||||
|
||||
size_t CPetSystem::CountSummoned() const
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
||||
{
|
||||
CPetActor* petActor = iter->second;
|
||||
|
||||
if (0 != petActor)
|
||||
{
|
||||
if (petActor->IsSummoned())
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void CPetSystem::RefreshBuff()
|
||||
{
|
||||
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
||||
{
|
||||
CPetActor* petActor = iter->second;
|
||||
if (petActor && petActor->IsSummoned())
|
||||
petActor->GiveBuff();
|
||||
}
|
||||
}
|
||||
//martysama0134's 623a0779c74cb7565145d45548376308
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user