diff options
58 files changed, 963 insertions, 911 deletions
diff --git a/src/char/char.cpp b/src/char/char.cpp index 4f52663..98a2178 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -1506,7 +1506,7 @@ void parse_tologin(Session *ls) CharKey *k = &cp.key; CharData& cd = *cp.data.get(); CharData *c = &cd; - Storage *s = account2storage(k->account_id); + Borrowed<Storage> s = account2storage(k->account_id); int changes = 0; #define FIX(v) if (v == source_id) {v = dest_id; ++changes; } for (IOff0 j : IOff0::iter()) @@ -1520,7 +1520,6 @@ void parse_tologin(Session *ls) FIX(c->head_mid); FIX(c->head_bottom); - if (s) { for (SOff0 j : SOff0::iter()) { diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp index 96a3f13..0ce827e 100644 --- a/src/char/int_party.cpp +++ b/src/char/int_party.cpp @@ -171,8 +171,7 @@ void inter_party_init(void) } PartyMost pm; - PartyPair pp; - pp.party_most = ± + PartyPair pp{PartyId(), borrow(pm)}; if (extract(line, &pp) && pp.party_id) { if (party_newid < next(pp.party_id)) @@ -212,9 +211,7 @@ int inter_party_save(void) } for (auto& pair : party_db) { - PartyPair tmp; - tmp.party_id = pair.first; - tmp.party_most = &pair.second; + PartyPair tmp{pair.first, borrow(pair.second)}; inter_party_save_sub(tmp, fp); } @@ -223,23 +220,21 @@ int inter_party_save(void) // パーティ名検索用 static -void search_partyname_sub(PartyPair p, PartyName str, PartyPair *dst) +void search_partyname_sub(PartyPair p, PartyName str, Borrowed<Option<PartyPair>> dst) { if (p->name == str) - *dst = p; + *dst = Some(p); } // パーティ名検索 static -PartyPair search_partyname(PartyName str) +Option<PartyPair> search_partyname(PartyName str) { - PartyPair p; + Option<PartyPair> p = None; for (auto& pair : party_db) { - PartyPair tmp; - tmp.party_id = pair.first; - tmp.party_most = &pair.second; - search_partyname_sub(tmp, str, &p); + PartyPair tmp{pair.first, borrow(pair.second)}; + search_partyname_sub(tmp, str, borrow(p)); } return p; @@ -315,9 +310,7 @@ void party_check_conflict(PartyId party_id, AccountId account_id, CharName nick) { for (auto& pair : party_db) { - PartyPair tmp; - tmp.party_id = pair.first; - tmp.party_most = &pair.second; + PartyPair tmp{pair.first, borrow(pair.second)}; party_check_conflict_sub(tmp, party_id, account_id, nick); } @@ -328,11 +321,11 @@ void party_check_conflict(PartyId party_id, AccountId account_id, CharName nick) // パーティ作成可否 static -void mapif_party_created(Session *s, AccountId account_id, const PartyPair p) +void mapif_party_created(Session *s, AccountId account_id, Option<PartyPair> p_) { Packet_Fixed<0x3820> fixed_20; fixed_20.account_id = account_id; - if (p) + if OPTION_IS_SOME(p, p_) { fixed_20.error = 0; fixed_20.party_id = p.party_id; @@ -492,22 +485,21 @@ void mapif_parse_CreateParty(Session *s, AccountId account_id, PartyName name, C if (!name.is_print()) { PRINTF("int_party: illegal party name [%s]\n"_fmt, name); - mapif_party_created(s, account_id, PartyPair()); + mapif_party_created(s, account_id, None); return; } } - if (search_partyname(name)) + if (search_partyname(name).is_some()) { PRINTF("int_party: same name party exists [%s]\n"_fmt, name); - mapif_party_created(s, account_id, PartyPair()); + mapif_party_created(s, account_id, None); return; } + PartyMost p {}; - PartyPair pp; - pp.party_most = &p; party_newid = next(party_newid); - pp.party_id = party_newid; + PartyPair pp{party_newid, borrow(p)}; p.name = name; p.exp = 0; p.item = 0; @@ -521,7 +513,7 @@ void mapif_parse_CreateParty(Session *s, AccountId account_id, PartyName name, C party_db.insert(pp.party_id, p); // pointer to noncanonical version - mapif_party_created(s, account_id, pp); + mapif_party_created(s, account_id, Some(pp)); mapif_party_info(s, pp); } @@ -529,11 +521,9 @@ void mapif_parse_CreateParty(Session *s, AccountId account_id, PartyName name, C static void mapif_parse_PartyInfo(Session *s, PartyId party_id) { - PartyPair p; - p.party_id = party_id; - p.party_most = party_db.search(party_id); - if (p) - mapif_party_info(s, p); + Option<P<PartyMost>> maybe_party_most = party_db.search(party_id); + if OPTION_IS_SOME(party_most, maybe_party_most) + mapif_party_info(s, PartyPair{party_id, party_most}); else mapif_party_noinfo(s, party_id); } @@ -543,14 +533,13 @@ static void mapif_parse_PartyAddMember(Session *s, PartyId party_id, AccountId account_id, CharName nick, MapName map, int lv) { - PartyPair p; - p.party_id = party_id; - p.party_most = party_db.search(party_id); - if (!p) - { - mapif_party_memberadded(s, party_id, account_id, 1); - return; - } + Option<P<PartyMost>> maybe_party_most = party_db.search(party_id); + P<PartyMost> party_most = TRY_UNWRAP(maybe_party_most, + { + mapif_party_memberadded(s, party_id, account_id, 1); + return; + }); + PartyPair p{party_id, party_most}; for (int i = 0; i < MAX_PARTY; i++) { @@ -585,11 +574,7 @@ static void mapif_parse_PartyChangeOption(Session *s, PartyId party_id, AccountId account_id, int exp, int item) { - PartyPair p; - p.party_id = party_id; - p.party_most = party_db.search(party_id); - if (!p) - return; + PartyPair p{party_id, TRY_UNWRAP(party_db.search(party_id), return)}; p->exp = exp; int flag = 0; @@ -607,11 +592,8 @@ void mapif_parse_PartyChangeOption(Session *s, PartyId party_id, AccountId accou // パーティ脱退要求 void mapif_parse_PartyLeave(Session *, PartyId party_id, AccountId account_id) { - PartyPair p; - p.party_id = party_id; - p.party_most = party_db.search(party_id); - if (!p) - return; + PartyPair p{party_id, TRY_UNWRAP(party_db.search(party_id), return)}; + for (int i = 0; i < MAX_PARTY; i++) { if (p->member[i].account_id != account_id) @@ -630,11 +612,7 @@ static void mapif_parse_PartyChangeMap(Session *s, PartyId party_id, AccountId account_id, MapName map, int online, int lv) { - PartyPair p; - p.party_id = party_id; - p.party_most = party_db.search(party_id); - if (!p) - return; + PartyPair p{party_id, TRY_UNWRAP(party_db.search(party_id), return)}; for (int i = 0; i < MAX_PARTY; i++) { diff --git a/src/char/int_storage.cpp b/src/char/int_storage.cpp index 76eff34..a2b0bc7 100644 --- a/src/char/int_storage.cpp +++ b/src/char/int_storage.cpp @@ -117,14 +117,10 @@ bool extract(XString str, Storage *p) } // アカウントから倉庫データインデックスを得る(新規倉庫追加可能) -Storage *account2storage(AccountId account_id) +Borrowed<Storage> account2storage(AccountId account_id) { - Storage *s = storage_db.search(account_id); - if (s == nullptr) - { - s = storage_db.init(account_id); - s->account_id = account_id; - } + P<Storage> s = storage_db.init(account_id); + s->account_id = account_id; return s; } @@ -196,7 +192,7 @@ void inter_storage_delete(AccountId account_id) static void mapif_load_storage(Session *ss, AccountId account_id) { - Storage *st = account2storage(account_id); + P<Storage> st = account2storage(account_id); Packet_Payload<0x3810> payload_10; payload_10.account_id = account_id; payload_10.storage = *st; @@ -240,11 +236,10 @@ RecvResult mapif_parse_SaveStorage(Session *ss) if (rv != RecvResult::Complete) return rv; - Storage *st; AccountId account_id = payload.account_id; { - st = account2storage(account_id); + P<Storage> st = account2storage(account_id); *st = payload.storage; mapif_save_storage_ack(ss, account_id); } diff --git a/src/char/int_storage.hpp b/src/char/int_storage.hpp index b8ec9db..0a80027 100644 --- a/src/char/int_storage.hpp +++ b/src/char/int_storage.hpp @@ -22,6 +22,8 @@ #include "fwd.hpp" +#include "../compat/fwd.hpp" + #include "../strings/fwd.hpp" #include "../net/fwd.hpp" @@ -34,7 +36,7 @@ namespace tmwa void inter_storage_init(void); int inter_storage_save(void); void inter_storage_delete(AccountId account_id); -Storage *account2storage(AccountId account_id); +Borrowed<Storage> account2storage(AccountId account_id); RecvResult inter_storage_parse_frommap(Session *ms, uint16_t); diff --git a/src/char/inter.cpp b/src/char/inter.cpp index f757991..2efcc83 100644 --- a/src/char/inter.cpp +++ b/src/char/inter.cpp @@ -264,12 +264,12 @@ void mapif_account_reg(Session *s, AccountId account_id, const std::vector<Packe static void mapif_account_reg_reply(Session *s, AccountId account_id) { - struct accreg *reg = accreg_db.search(account_id); + Option<P<struct accreg>> reg_ = accreg_db.search(account_id); Packet_Head<0x3804> head_04; head_04.account_id = account_id; std::vector<Packet_Repeat<0x3804>> repeat_04; - if (reg) + if OPTION_IS_SOME(reg, reg_) { repeat_04.resize(reg->reg_num); assert (reg->reg_num < ACCOUNT_REG_NUM); @@ -408,13 +408,9 @@ RecvResult mapif_parse_AccReg(Session *s) if (rv != RecvResult::Complete) return rv; - struct accreg *reg = accreg_db.search(head.account_id); - - if (reg == nullptr) + P<struct accreg> reg = accreg_db.init(head.account_id); { - AccountId account_id = head.account_id; - reg = accreg_db.init(account_id); - reg->account_id = account_id; + reg->account_id = head.account_id; } size_t jlim = std::min(repeat.size(), ACCOUNT_REG_NUM); diff --git a/src/compat/borrow.hpp b/src/compat/borrow.hpp index 5cb6a7c..0ea6a26 100644 --- a/src/compat/borrow.hpp +++ b/src/compat/borrow.hpp @@ -68,6 +68,15 @@ namespace tmwa static_assert(!std::is_same<T, U>::value, "same check"); return Borrowed<U>(stupid); } + + friend bool operator == (Borrowed l, Borrowed r) + { + return l.stupid == r.stupid; + } + friend bool operator != (Borrowed l, Borrowed r) + { + return !(l == r); + } }; namespace option diff --git a/src/compat/borrow.py b/src/compat/borrow.py new file mode 100644 index 0000000..58cd19b --- /dev/null +++ b/src/compat/borrow.py @@ -0,0 +1,18 @@ +class Borrowed(object): + __slots__ = ('_value') + name = 'tmwa::Borrowed' + enabled = True + + def __init__(self, value): + self._value = value['stupid'] + + def to_string(self): + return self._value + + test_extra = ''' + static int borrow_thingy; + ''' + + tests = [ + ('tmwa::borrow(borrow_thingy)', '<borrow_thingy>'), + ] diff --git a/src/compat/fwd.hpp b/src/compat/fwd.hpp index 7e2be28..c16e196 100644 --- a/src/compat/fwd.hpp +++ b/src/compat/fwd.hpp @@ -28,6 +28,7 @@ namespace tmwa template<class T> class Option; } + using option::Option; template<class T> class Borrowed; diff --git a/src/compat/nullpo.hpp b/src/compat/nullpo.hpp index 5be674a..718c7aa 100644 --- a/src/compat/nullpo.hpp +++ b/src/compat/nullpo.hpp @@ -52,6 +52,8 @@ bool nullpo_chk(const char *file, int line, const char *func, const void *target); template<class T> +bool nullpo_chk(const char *file, int line, const char *func, Borrowed<T> target) = delete; +template<class T> bool nullpo_chk(const char *file, int line, const char *func, T target) { return nullpo_chk(file, line, func, target.operator->()); diff --git a/src/compat/option.hpp b/src/compat/option.hpp index ad83395..27ee0bc 100644 --- a/src/compat/option.hpp +++ b/src/compat/option.hpp @@ -66,6 +66,7 @@ namespace option return rv; } + // TODO all *_or and *_set methods should have a lazy version too template<class T> class Option { @@ -210,6 +211,10 @@ namespace option { return repr.is_some(); } + bool is_none() const + { + return !is_some(); + } template<class F> auto move_map(F&& f) -> Option<decltype(std::forward<F>(f)(std::move(*repr.ptr())))> @@ -262,6 +267,47 @@ namespace option return None; } } + // wanting members is *so* common + template<class M, class B> + Option<M> pmd_get(const M B::*pmd) const + { + if (repr.is_some()) + { + return Some((*repr.ptr()).*pmd); + } + else + { + return None; + } + } + template<class M, class B> + void pmd_set(M B::*pmd, M value) + { + if (repr.is_some()) + { + ((*repr.ptr()).*pmd) = std::move(value); + } + } + template<class M, class B> + Option<M> pmd_pget(const M B::*pmd) const + { + if (repr.is_some()) + { + return Some((**repr.ptr()).*pmd); + } + else + { + return None; + } + } + template<class M, class B> + void pmd_pset(M B::*pmd, M value) + { + if (repr.is_some()) + { + ((**repr.ptr()).*pmd) = std::move(value); + } + } }; template<class T> @@ -371,16 +417,16 @@ namespace option #define TRY_UNWRAP(opt, falsy) \ ({ \ tmwa::option::RefWrapper<decltype((opt))> o = {(opt)}; \ - if (!o.maybe_ref.is_some()) falsy; \ + if (o.maybe_ref.is_none()) falsy; \ tmwa::option::option_unwrap(std::move(o)); \ }).maybe_ref_fun() // immediately preceded by 'if'; not double-eval-safe -#define OPTION_IS_SOME(var, expr) \ - ((expr).is_some()) \ +#define OPTION_IS_SOME(var, expr) \ + ((expr).is_some()) \ WITH_VAR(auto&, var, *(expr).ptr_or(nullptr)) } // namespace option -using option::Option; +//using option::Option; using option::None; using option::Some; } // namespace tmwa diff --git a/src/compat/option.py b/src/compat/option.py new file mode 100644 index 0000000..a410ac8 --- /dev/null +++ b/src/compat/option.py @@ -0,0 +1,37 @@ +class Option(object): + __slots__ = ('_value') + name = 'tmwa::option::Option' + enabled = True + + def __init__(self, value): + self._value = value['repr'] + + def to_string(self): + value = self._value + ty = value.type.template_argument(0) + try: + some = bool(value['_some']) + except gdb.error: + stupider = value['stupider'] + if stupider: + return 'Some<%s>(%s)' % (ty, stupider) + else: + return 'None<%s>' % ty + else: + if some: + data = value['_data'] + data = data.address.cast(ty.pointer()).dereference() + return 'Some<%s>(%s)' % (ty, data) + else: + return 'None<%s>' % ty + + test_extra = ''' + static int option_borrow_thingy; + ''' + + tests = [ + ('tmwa::None<int>()', 'None<int>'), + ('tmwa::Some(1)', 'Some<int>(1)'), + ('tmwa::Option<tmwa::Borrowed<int>>(tmwa::None)', 'None<tmwa::Borrowed<int>>'), + ('tmwa::Some(tmwa::borrow(option_borrow_thingy))', 'regex:Some<tmwa::Borrowed<int>>\(0x[0-9a-f]* <option_borrow_thingy>\)'), + ] diff --git a/src/compat/option_test.cpp b/src/compat/option_test.cpp index d99eda9..b963a29 100644 --- a/src/compat/option_test.cpp +++ b/src/compat/option_test.cpp @@ -255,6 +255,43 @@ TEST(Option, map) } } +TEST(Option, member) +{ + struct Foo + { + int bar = 404; + }; + + Option<Foo> vng = None; + EXPECT_EQ(vng.pmd_get(&Foo::bar).copy_or(42), 42); + Option<Foo> vsg = Some(Foo()); + EXPECT_EQ(vsg.pmd_get(&Foo::bar).copy_or(42), 404); + + Option<Foo> vns = None; + vns.pmd_set(&Foo::bar, 42); + EXPECT_EQ(vns.copy_or(Foo()).bar, 404); + Option<Foo> vss = Some(Foo()); + vss.pmd_set(&Foo::bar, 42); + EXPECT_EQ(vss.copy_or(Foo()).bar, 42); + + Foo foo, alt; + + Option<P<Foo>> png = None; + EXPECT_EQ(png.pmd_pget(&Foo::bar).copy_or(42), 42); + Option<P<Foo>> psg = Some(borrow(foo)); + EXPECT_EQ(psg.pmd_pget(&Foo::bar).copy_or(42), 404); + + Option<P<Foo>> pns = None; + pns.pmd_pset(&Foo::bar, 42); + EXPECT_EQ(pns.copy_or(borrow(alt))->bar, 404); + EXPECT_EQ(foo.bar, 404); + Option<P<Foo>> pss = Some(borrow(foo)); + pss.pmd_pset(&Foo::bar, 42); + EXPECT_EQ(pss.copy_or(borrow(alt))->bar, 42); + EXPECT_EQ(foo.bar, 42); + EXPECT_EQ(alt.bar, 404); +} + #if __cplusplus >= 201300 // c++14 as given by gcc 4.9 # define DECLTYPE_AUTO decltype(auto) #else diff --git a/src/generic/db.hpp b/src/generic/db.hpp index 90c4f92..707d8ae 100644 --- a/src/generic/db.hpp +++ b/src/generic/db.hpp @@ -23,6 +23,8 @@ #include <map> #include <memory> +#include "../compat/borrow.hpp" + namespace tmwa { @@ -45,19 +47,19 @@ public: const_iterator begin() const { return impl.begin(); } const_iterator end() const { return impl.end(); } - V *search(const K& k) + Option<Borrowed<V>> search(const K& k) { iterator it = impl.find(k); if (it == impl.end()) - return nullptr; - return &it->second; + return None; + return Some(borrow(it->second)); } - const V *search(const K& k) const + Option<Borrowed<const V>> search(const K& k) const { const_iterator it = impl.find(k); if (it == impl.end()) - return nullptr; - return &it->second; + return None; + return Some(borrow(it->second)); } void insert(const K& k, V v) { @@ -72,9 +74,9 @@ public: return (void)&it->second; } - V *init(const K& k) + Borrowed<V> init(const K& k) { - return &impl[k]; + return borrow(impl[k]); } void erase(const K& k) { @@ -112,8 +114,12 @@ public: // const V& ? with a static default V? V get(const K& k) { - V *vp = impl.search(k); - return vp ? *vp : V(); + Option<Borrowed<V>> vp = impl.search(k); + if OPTION_IS_SOME(v, vp) + { + return *v; + } + return V(); } void put(const K& k, V v) { @@ -153,10 +159,14 @@ public: const_iterator end() const { return impl.end(); } // const V& ? with a static default V? - V *get(const K& k) - { - U *up = impl.search(k); - return up ? up->get() : nullptr; + Option<Borrowed<V>> get(const K& k) + { + Option<Borrowed<U>> up = impl.search(k); + if OPTION_IS_SOME(u, up) + { + return Some(borrow(*u->get())); + } + return None; } void put(const K& k, U v) { diff --git a/src/login/login.cpp b/src/login/login.cpp index ccb68fc..a84c96a 100644 --- a/src/login/login.cpp +++ b/src/login/login.cpp @@ -231,6 +231,7 @@ AString gm_pass; static GmLevel level_new_gm = GmLevel::from(60u); +// TODO make this just be Map<AccountId, GmLevel> static Map<AccountId, GM_Account> gm_account_db; @@ -287,10 +288,8 @@ void delete_admin(Session *s) static GmLevel isGM(AccountId account_id) { - GM_Account *p = gm_account_db.search(account_id); - if (p == nullptr) - return GmLevel(); - return p->level; + Option<P<GM_Account>> p = gm_account_db.search(account_id); + return TRY_UNWRAP(p, return GmLevel())->level; } //------------------------------------------------------- diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 9b53497..bf64473 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -104,7 +104,7 @@ Map<XString, AtCommandInfo> atcommand_info; static -AtCommandInfo *atcommand(XString cmd); +Option<Borrowed<AtCommandInfo>> atcommand(XString cmd); // These @commands are used within other @commands. static @@ -202,9 +202,7 @@ void log_atcommand(dumb_ptr<map_session_data> sd, ZString cmd) return; timestamp_seconds_buffer tmpstr; stamp_time(tmpstr); - MapName map = (sd->bl_m - ? sd->bl_m->name_ - : stringish<MapName>("undefined.gat"_s)); + MapName map = (sd->bl_m->name_); FPRINTF(*fp, "[%s] %s(%d,%d) %s(%d) : %s\n"_fmt, tmpstr, map, sd->bl_x, sd->bl_y, @@ -259,8 +257,6 @@ bool is_atcommand(Session *s, dumb_ptr<map_session_data> sd, ZString arg; asplit(message, &command, &arg); - AtCommandInfo *info = atcommand(command); - if (!gmlvl) gmlvl = pc_isGM(sd); if (battle_config.atcommand_gm_only != 0 && !gmlvl) @@ -270,14 +266,16 @@ bool is_atcommand(Session *s, dumb_ptr<map_session_data> sd, clif_displaymessage(s, output); return true; } - if (!info) + + Option<P<AtCommandInfo>> info_ = atcommand(command); + P<AtCommandInfo> info = TRY_UNWRAP(info_, { AString output = STRPRINTF("GM command not found: %s"_fmt, AString(command)); clif_displaymessage(s, output); return true; // don't show in chat - } + }); if (!(gmlvl.satisfies(info->level))) { AString output = STRPRINTF("GM command is level %d, but you are level %d: %s"_fmt, @@ -319,15 +317,15 @@ bool is_atcommand(Session *s, dumb_ptr<map_session_data> sd, } } -AtCommandInfo *atcommand(XString cmd) +Option<Borrowed<AtCommandInfo>> atcommand(XString cmd) { if (cmd.startswith('@')) { XString command = cmd.xslice_t(1); - AtCommandInfo *it = atcommand_info.search(command); + Option<P<AtCommandInfo>> it = atcommand_info.search(command); return it; } - return nullptr; + return None; } static @@ -343,7 +341,7 @@ void atkillmonster_sub(dumb_ptr<block_list> bl, int flag) } static -AtCommandInfo *get_atcommandinfo_byname(XString name) +Option<Borrowed<AtCommandInfo>> get_atcommandinfo_byname(XString name) { return atcommand_info.search(name); } @@ -371,8 +369,8 @@ bool atcommand_config_read(ZString cfgName) rv = false; continue; } - AtCommandInfo *p = get_atcommandinfo_byname(w1); - if (p != nullptr) + Option<P<AtCommandInfo>> p_ = get_atcommandinfo_byname(w1); + if OPTION_IS_SOME(p, p_) { p->level = GmLevel::from(static_cast<uint32_t>(atoi(w2.c_str()))); } @@ -420,9 +418,7 @@ ATCE atcommand_help(Session *s, dumb_ptr<map_session_data>, if (message.startswith('@')) { ZString cmd = message.xslice_t(1); - const AtCommandInfo *info = atcommand_info.search(cmd); - if (!info) - return ATCE::EXIST; + P<AtCommandInfo> info = TRY_UNWRAP(atcommand_info.search(cmd), return ATCE::EXIST); clif_displaymessage(s, STRPRINTF("Usage: @%s %s"_fmt, cmd, info->args)); clif_displaymessage(s, info->help); return ATCE::OKAY; @@ -533,15 +529,15 @@ ATCE atcommand_charwarp(Session *s, dumb_ptr<map_session_data> sd, // you can rura+ only lower or same GM level if (x > 0 && x < 800 && y > 0 && y < 800) { - map_local *m = map_mapname2mapid(map_name); - if (m != nullptr && m->flag.get(MapFlag::NOWARPTO) + Option<P<map_local>> m = map_mapname2mapid(map_name); + if (m.map([](P<map_local> m_){ return m_->flag.get(MapFlag::NOWARPTO); }).copy_or(false) && !pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level)))) { clif_displaymessage(s, "You are not authorised to warp someone to this map."_s); return ATCE::PERM; } - if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARP) + if (pl_sd->bl_m->flag.get(MapFlag::NOWARP) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, @@ -602,15 +598,15 @@ ATCE atcommand_warp(Session *s, dumb_ptr<map_session_data> sd, if (x > 0 && x < 800 && y > 0 && y < 800) { - map_local *m = map_mapname2mapid(map_name); - if (m != nullptr && m->flag.get(MapFlag::NOWARPTO) + Option<P<map_local>> m = map_mapname2mapid(map_name); + if (m.map([](P<map_local> m_){ return m_->flag.get(MapFlag::NOWARPTO); }).copy_or(false) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, "You are not authorised to warp you to this map."_s); return ATCE::PERM; } - if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) + if (sd->bl_m->flag.get(MapFlag::NOWARP) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, @@ -678,14 +674,14 @@ ATCE atcommand_goto(Session *s, dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); if (pl_sd != nullptr) { - if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARPTO) + if (pl_sd->bl_m->flag.get(MapFlag::NOWARPTO) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, "You are not authorised to warp you to the map of this player."_s); return ATCE::PERM; } - if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) + if (sd->bl_m->flag.get(MapFlag::NOWARP) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, @@ -719,14 +715,14 @@ ATCE atcommand_jump(Session *s, dumb_ptr<map_session_data> sd, y = random_::in(1, 399); if (x > 0 && x < 800 && y > 0 && y < 800) { - if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARPTO) + if (sd->bl_m->flag.get(MapFlag::NOWARPTO) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, "You are not authorised to warp you to your actual map."_s); return ATCE::PERM; } - if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) + if (sd->bl_m->flag.get(MapFlag::NOWARP) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, @@ -811,7 +807,6 @@ ATCE atcommand_whogroup(Session *s, dumb_ptr<map_session_data> sd, ZString message) { int count; - PartyPair p; VString<23> match_text = message; match_text = match_text.to_lower(); @@ -837,8 +832,8 @@ ATCE atcommand_whogroup(Session *s, dumb_ptr<map_session_data> sd, if (player_name.contains_seq(match_text)) { // search with no case sensitive - p = party_search(pl_sd->status.party_id); - PartyName temp0 = p ? p->name : stringish<PartyName>("None"_s); + Option<PartyPair> p_ = party_search(pl_sd->status.party_id); + PartyName temp0 = p_.pmd_pget(&PartyMost::name).move_or(stringish<PartyName>("None"_s)); AString output; if (pl_gm_level) output = STRPRINTF( @@ -869,15 +864,14 @@ ATCE atcommand_whomap(Session *s, dumb_ptr<map_session_data> sd, ZString message) { int count; - map_local *map_id; - { + Borrowed<map_local> map_id = + ({ MapName map_name; extract(message, &map_name); - map_id = map_mapname2mapid(map_name); - if (map_id == nullptr) - map_id = sd->bl_m; - } + + map_mapname2mapid(map_name).copy_or(sd->bl_m); + }); count = 0; GmLevel gm_level = pc_isGM(sd); @@ -928,16 +922,14 @@ ATCE atcommand_whomapgroup(Session *s, dumb_ptr<map_session_data> sd, ZString message) { int count; - PartyPair p; - map_local *map_id; - { + P<map_local> map_id = + ({ MapName map_name; extract(message, &map_name); - map_id = map_mapname2mapid(map_name); - if (map_id == nullptr) - map_id = sd->bl_m; - } + + map_mapname2mapid(map_name).copy_or(sd->bl_m); + }); count = 0; GmLevel gm_level = pc_isGM(sd); @@ -958,8 +950,8 @@ ATCE atcommand_whomapgroup(Session *s, dumb_ptr<map_session_data> sd, // you can look only lower or same level if (pl_sd->bl_m == map_id) { - p = party_search(pl_sd->status.party_id); - PartyName temp0 = p ? p->name : stringish<PartyName>("None"_s); + Option<PartyPair> p_ = party_search(pl_sd->status.party_id); + PartyName temp0 = p_.pmd_pget(&PartyMost::name).copy_or(stringish<PartyName>("None"_s)); AString output; if (pl_gm_level) output = STRPRINTF("Name: %s (GM:%d) | Party: '%s'"_fmt, @@ -993,7 +985,6 @@ ATCE atcommand_whogm(Session *s, dumb_ptr<map_session_data> sd, ZString message) { int count; - PartyPair p; VString<23> match_text = message; match_text = match_text.to_lower(); @@ -1033,8 +1024,8 @@ ATCE atcommand_whogm(Session *s, dumb_ptr<map_session_data> sd, "Novice/Human"_s, pl_sd->status.job_level); clif_displaymessage(s, output); - p = party_search(pl_sd->status.party_id); - PartyName temp0 = p ? p->name : stringish<PartyName>("None"_s); + Option<PartyPair> p_ = party_search(pl_sd->status.party_id); + PartyName temp0 = p_.pmd_pget(&PartyMost::name).copy_or(stringish<PartyName>("None"_s)); output = STRPRINTF( " Party: '%s'"_fmt, temp0); @@ -1075,15 +1066,15 @@ static ATCE atcommand_load(Session *s, dumb_ptr<map_session_data> sd, ZString) { - map_local *m = map_mapname2mapid(sd->status.save_point.map_); - if (m != nullptr && m->flag.get(MapFlag::NOWARPTO) + Option<P<map_local>> m = map_mapname2mapid(sd->status.save_point.map_); + if (m.map([](P<map_local> m_){ return m_->flag.get(MapFlag::NOWARPTO); }).copy_or(false) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, "You are not authorised to warp you to your save map."_s); return ATCE::PERM; } - if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) + if (sd->bl_m->flag.get(MapFlag::NOWARP) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, @@ -1147,16 +1138,13 @@ static ATCE atcommand_storage(Session *s, dumb_ptr<map_session_data> sd, ZString) { - Storage *stor; - if (sd->state.storage_open) { clif_displaymessage(s, "msg_table[250]"_s); return ATCE::EXIST; } - if ((stor = account2storage2(sd->status_key.account_id)) != nullptr - && stor->storage_status == 1) + if (account2storage2(sd->status_key.account_id).pmd_pget(&Storage::storage_status).copy_or(0) == 1) { clif_displaymessage(s, "msg_table[250]"_s); return ATCE::EXIST; @@ -1331,13 +1319,27 @@ ATCE atcommand_heal(Session *s, dumb_ptr<map_session_data> sd, } static +Option<P<struct item_data>> extract_item_opt(XString item_name) +{ + Option<P<struct item_data>> item_data = itemdb_searchname(item_name); + if (item_data.is_some()) + return item_data; + + ItemNameId item_id; + if (extract(item_name, &item_id)) + { + item_data = itemdb_exists(item_id); + return item_data; + } + return None; +} + +static ATCE atcommand_item(Session *s, dumb_ptr<map_session_data> sd, ZString message) { XString item_name; int number = 0; - ItemNameId item_id; - struct item_data *item_data = nullptr; int get_count, i; if (!extract(message, record<' ', 1>(&item_name, &number))) @@ -1350,14 +1352,10 @@ ATCE atcommand_item(Session *s, dumb_ptr<map_session_data> sd, if (number <= 0) number = 1; - if ((item_data = itemdb_searchname(item_name)) != nullptr) - item_id = item_data->nameid; - else if (extract(item_name, &item_id) && (item_data = itemdb_exists(item_id)) != nullptr) - item_id = item_data->nameid; - else - return ATCE::EXIST; + P<struct item_data> item_data = TRY_UNWRAP(extract_item_opt(item_name), return ATCE::EXIST); + ItemNameId item_id = item_data->nameid; + assert (item_id); - if (item_id) { get_count = number; if (item_data->type == ItemType::WEAPON @@ -1378,11 +1376,6 @@ ATCE atcommand_item(Session *s, dumb_ptr<map_session_data> sd, } clif_displaymessage(s, "Item created."_s); } - else - { - clif_displaymessage(s, "Invalid item ID or name."_s); - return ATCE::EXIST; - } return ATCE::OKAY; } @@ -1807,14 +1800,13 @@ static void atcommand_killmonster_sub(Session *s, dumb_ptr<map_session_data> sd, ZString message, const int drop) { - map_local *map_id; - { + P<map_local> map_id = + ({ MapName map_name; extract(message, &map_name); - map_id = map_mapname2mapid(map_name); - if (map_id == nullptr) - map_id = sd->bl_m; - } + + map_mapname2mapid(map_name).copy_or(sd->bl_m); + }); map_foreachinarea(std::bind(atkillmonster_sub, ph::_1, drop), map_id, @@ -2078,14 +2070,14 @@ ATCE atcommand_recall(Session *s, dumb_ptr<map_session_data> sd, if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can recall only lower or same level - if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARPTO) + if (sd->bl_m->flag.get(MapFlag::NOWARPTO) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, "You are not authorised to warp somenone to your actual map."_s); return ATCE::PERM; } - if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARP) + if (pl_sd->bl_m->flag.get(MapFlag::NOWARP) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, @@ -2401,15 +2393,14 @@ ATCE atcommand_character_save(Session *s, dumb_ptr<map_session_data> sd, if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can change save point only to lower or same gm level - map_local *m = map_mapname2mapid(map_name); - if (m == nullptr) + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(map_name), { clif_displaymessage(s, "Map not found."_s); return ATCE::EXIST; - } - else + }); + { - if (m != nullptr && m->flag.get(MapFlag::NOWARPTO) + if (m->flag.get(MapFlag::NOWARPTO) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, @@ -2974,7 +2965,6 @@ ATCE atcommand_idsearch(Session *s, dumb_ptr<map_session_data>, { ItemName item_name; int match; - struct item_data *item; if (!extract(message, &item_name) || !item_name) return ATCE::USAGE; @@ -2984,8 +2974,8 @@ ATCE atcommand_idsearch(Session *s, dumb_ptr<map_session_data>, match = 0; for (ItemNameId i = wrap<ItemNameId>(0); i < wrap<ItemNameId>(-1); i = next(i)) { - if ((item = itemdb_exists(i)) != nullptr - && item->jname.contains_seq(item_name)) + P<struct item_data> item = TRY_UNWRAP(itemdb_exists(i), continue); + if (item->jname.contains_seq(item_name)) { match++; output = STRPRINTF("%s: %d"_fmt, item->jname, item->nameid); @@ -3348,7 +3338,7 @@ ATCE atcommand_recallall(Session *s, dumb_ptr<map_session_data> sd, { int count; - if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARPTO) + if (sd->bl_m->flag.get(MapFlag::NOWARPTO) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, @@ -3369,7 +3359,7 @@ ATCE atcommand_recallall(Session *s, dumb_ptr<map_session_data> sd, && pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can recall only lower or same level - if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARP) + if (pl_sd->bl_m->flag.get(MapFlag::NOWARP) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) count++; else @@ -3394,13 +3384,12 @@ ATCE atcommand_partyrecall(Session *s, dumb_ptr<map_session_data> sd, ZString message) { PartyName party_name; - PartyPair p; int count; if (!extract(message, &party_name) || !party_name) return ATCE::USAGE; - if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARPTO) + if (sd->bl_m->flag.get(MapFlag::NOWARPTO) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, @@ -3408,9 +3397,11 @@ ATCE atcommand_partyrecall(Session *s, dumb_ptr<map_session_data> sd, return ATCE::PERM; } - if ((p = party_searchname(party_name)) || - // name first to avoid error when name begin with a number - (p = party_search(wrap<PartyId>(static_cast<uint32_t>(atoi(message.c_str())))))) + // name first to avoid error when name begin with a number + Option<PartyPair> p_ = party_searchname(party_name); + if (p_.is_none()) + p_ = party_search(wrap<PartyId>(static_cast<uint32_t>(atoi(message.c_str())))); + if OPTION_IS_SOME(p, p_) { count = 0; for (io::FD i : iter_fds()) @@ -3423,7 +3414,7 @@ ATCE atcommand_partyrecall(Session *s, dumb_ptr<map_session_data> sd, && sd->status_key.account_id != pl_sd->status_key.account_id && pl_sd->status.party_id == p.party_id) { - if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARP) + if (pl_sd->bl_m->flag.get(MapFlag::NOWARP) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) count++; else @@ -3466,9 +3457,7 @@ ATCE atcommand_mapinfo(Session *s, dumb_ptr<map_session_data> sd, if (!map_name) map_name = sd->mapname_; - map_local *m_id = map_mapname2mapid(map_name); - if (m_id != nullptr) - return ATCE::EXIST; + P<map_local> m_id = TRY_UNWRAP(map_mapname2mapid(map_name), return ATCE::EXIST); clif_displaymessage(s, "------ Map Info ------"_s); AString output = STRPRINTF("Map Name: %s"_fmt, map_name); @@ -3590,10 +3579,11 @@ ATCE atcommand_partyspy(Session *s, dumb_ptr<map_session_data> sd, if (!extract(message, &party_name)) return ATCE::USAGE; - PartyPair p; - if ((p = party_searchname(party_name)) || - // name first to avoid error when name begin with a number - (p = party_search(wrap<PartyId>(static_cast<uint32_t>(atoi(message.c_str())))))) + // name first to avoid error when name begin with a number + Option<PartyPair> p_ = party_searchname(party_name); + if (p_.is_none()) + p_ = party_search(wrap<PartyId>(static_cast<uint32_t>(atoi(message.c_str())))); + if OPTION_IS_SOME(p, p_) { if (sd->partyspy == p.party_id) { @@ -3682,19 +3672,15 @@ ATCE atcommand_chardelitem(Session *s, dumb_ptr<map_session_data> sd, CharName character; XString item_name; int i, number = 0; - ItemNameId item_id; int count; - struct item_data *item_data; if (!asplit(message, &item_name, &number, &character) || number < 1) return ATCE::USAGE; - if ((item_data = itemdb_searchname(item_name)) != nullptr) - item_id = item_data->nameid; - else if (extract(item_name, &item_id) && (item_data = itemdb_exists(item_id)) != nullptr) - item_id = item_data->nameid; + P<struct item_data> item_data = TRY_UNWRAP(extract_item_opt(item_name), return ATCE::EXIST); + ItemNameId item_id = item_data->nameid; + assert (item_id); - if (item_id) { dumb_ptr<map_session_data> pl_sd = map_nick2sd(character); if (pl_sd != nullptr) @@ -3742,11 +3728,6 @@ ATCE atcommand_chardelitem(Session *s, dumb_ptr<map_session_data> sd, return ATCE::EXIST; } } - else - { - clif_displaymessage(s, "Invalid item ID or name."_s); - return ATCE::RANGE; - } return ATCE::OKAY; } @@ -3853,7 +3834,6 @@ static ATCE atcommand_character_item_list(Session *s, dumb_ptr<map_session_data> sd, ZString message) { - struct item_data *item_data = nullptr; int count, counter; CharName character; @@ -3870,10 +3850,10 @@ ATCE atcommand_character_item_list(Session *s, dumb_ptr<map_session_data> sd, count = 0; for (IOff0 i : IOff0::iter()) { - if (pl_sd->status.inventory[i].nameid - && (item_data = - itemdb_search(pl_sd->status.inventory[i].nameid)) != - nullptr) + if (!pl_sd->status.inventory[i].nameid) + continue; + P<struct item_data> item_data = TRY_UNWRAP(itemdb_exists(pl_sd->status.inventory[i].nameid), continue); + { counter = counter + pl_sd->status.inventory[i].amount; count++; @@ -3964,8 +3944,6 @@ static ATCE atcommand_character_storage_list(Session *s, dumb_ptr<map_session_data> sd, ZString message) { - Storage *stor; - struct item_data *item_data = nullptr; int count, counter; CharName character; @@ -3978,15 +3956,17 @@ ATCE atcommand_character_storage_list(Session *s, dumb_ptr<map_session_data> sd, if (pc_isGM(sd).overwhelms(pc_isGM(pl_sd))) { // you can look items only lower or same level - if ((stor = account2storage2(pl_sd->status_key.account_id)) != nullptr) + Option<P<Storage>> stor_ = account2storage2(pl_sd->status_key.account_id); + if OPTION_IS_SOME(stor, stor_) { counter = 0; count = 0; for (SOff0 i : SOff0::iter()) { - if (stor->storage_[i].nameid - && (item_data = - itemdb_search(stor->storage_[i].nameid)) != nullptr) + if (!stor->storage_[i].nameid) + continue; + P<struct item_data> item_data = TRY_UNWRAP(itemdb_exists(stor->storage_[i].nameid), continue); + { counter = counter + stor->storage_[i].amount; count++; @@ -4431,9 +4411,9 @@ ATCE atcommand_adjcmdlvl(Session *s, dumb_ptr<map_session_data>, return ATCE::USAGE; } - AtCommandInfo *it = atcommand_info.search(cmd); + Option<P<AtCommandInfo>> it_ = atcommand_info.search(cmd); { - if (it) + if OPTION_IS_SOME(it, it_) { it->level = newlev; clif_displaymessage(s, "@command level changed."_s); @@ -4663,14 +4643,14 @@ ATCE atcommand_jump_iterate(Session *s, dumb_ptr<map_session_data> sd, pl_sd = get_start(); } - if (pl_sd->bl_m && pl_sd->bl_m->flag.get(MapFlag::NOWARPTO) + if (pl_sd->bl_m->flag.get(MapFlag::NOWARPTO) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, "You are not authorised to warp you to the map of this player."_s); return ATCE::PERM; } - if (sd->bl_m && sd->bl_m->flag.get(MapFlag::NOWARP) + if (sd->bl_m->flag.get(MapFlag::NOWARP) && !(pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.any_warp_GM_min_level))))) { clif_displaymessage(s, diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 07210fd..ce10c5c 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -1417,8 +1417,11 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON]; - if (widx.ok() && sd->inventory_data[widx]) - atkmin = atkmin * (80 + sd->inventory_data[widx]->wlv * 20) / 100; + if (widx.ok()) + { + if OPTION_IS_SOME(sdidw, sd->inventory_data[widx]) + atkmin = atkmin * (80 + sdidw->wlv * 20) / 100; + } if (sd->status.weapon == ItemLook::BOW) { //武器が弓矢の場合 atkmin = watk * ((atkmin < watk) ? atkmin : watk) / 100; //弓用最低ATK計算 @@ -1935,9 +1938,16 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, { IOff0 weapon_index = sd->equip_index_maybe[EQUIP::WEAPON]; ItemNameId weapon; - if (weapon_index.ok() && sd->inventory_data[weapon_index] - && bool(sd->status.inventory[weapon_index].equip & EPOS::WEAPON)) - weapon = sd->inventory_data[weapon_index]->nameid; + if (weapon_index.ok()) + { + if OPTION_IS_SOME(sdidw, sd->inventory_data[weapon_index]) + { + if (bool(sd->status.inventory[weapon_index].equip & EPOS::WEAPON)) + { + weapon = sdidw->nameid; + } + } + } MAP_LOG("PC%d %s:%d,%d WPNDMG %s%d %d FOR %d WPN %d"_fmt, sd->status_key.char_id, src->bl_m->name_, src->bl_x, src->bl_y, diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index 0ebdf1c..090cccf 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -960,7 +960,6 @@ void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, ItemNameId source_id, ItemNameI case BL::PC: { dumb_ptr<map_session_data> pc = bl->is_player(); - Storage *stor = account2storage2(pc->status_key.account_id); for (IOff0 j : IOff0::iter()) IFIX(pc->status.inventory[j].nameid); @@ -971,7 +970,8 @@ void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, ItemNameId source_id, ItemNameI IFIX(pc->status.head_mid); IFIX(pc->status.head_bottom); - if (stor) + Option<P<Storage>> stor_ = account2storage2(pc->status_key.account_id); + if OPTION_IS_SOME(stor, stor_) { for (SOff0 j : SOff0::iter()) FIX(stor->storage_[j]); @@ -979,8 +979,8 @@ void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, ItemNameId source_id, ItemNameI for (IOff0 j : IOff0::iter()) { - struct item_data *item = pc->inventory_data[j]; - if (item && item->nameid == source_id) + P<struct item_data> item = TRY_UNWRAP(pc->inventory_data[j], continue); + if (item->nameid == source_id) { item->nameid = dest_id; if (bool(item->equip)) diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 1b0358b..b0cb541 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -295,7 +295,6 @@ void clif_send_sub(dumb_ptr<block_list> bl, const Buffer& buf, static int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) { - PartyPair p; int x0 = 0, x1 = 0, y0 = 0, y1 = 0; if (type != SendWho::ALL_CLIENT) @@ -384,20 +383,22 @@ int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) case SendWho::PARTY_WOS: // 自分以外の全パーティーメンバに送信 case SendWho::PARTY_SAMEMAP: // 同じマップの全パーティーメンバに送信 case SendWho::PARTY_SAMEMAP_WOS: // 自分以外の同じマップの全パーティーメンバに送信 + { + Option<PartyPair> p_ = None; if (bl->bl_type == BL::PC) { dumb_ptr<map_session_data> sd = bl->is_player(); if (sd->partyspy) { - p = party_search(sd->partyspy); + p_ = party_search(sd->partyspy); } else { if (sd->status.party_id) - p = party_search(sd->status.party_id); + p_ = party_search(sd->status.party_id); } } - if (p) + if OPTION_IS_SOME(p, p_) { for (int i = 0; i < MAX_PARTY; i++) { @@ -436,6 +437,7 @@ int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) } } } + } break; case SendWho::SELF: { @@ -684,14 +686,14 @@ void clif_set0078_main_1d8(dumb_ptr<map_session_data> sd, Buffer& buf) fixed_1d8.weapon = sd->attack_spell_look_override; else { - if (widx.ok() && sd->inventory_data[widx]) + if (widx.ok() && sd->inventory_data[widx].is_some()) { fixed_1d8.weapon = sd->status.inventory[widx].nameid; } else fixed_1d8.weapon = ItemNameId(); } - if (sidx.ok() && sidx != widx && sd->inventory_data[sidx]) + if (sidx.ok() && sidx != widx && sd->inventory_data[sidx].is_some()) { fixed_1d8.shield = sd->status.inventory[sidx].nameid; } @@ -738,14 +740,14 @@ void clif_set0078_alt_1d9(dumb_ptr<map_session_data> sd, Buffer& buf) fixed_1d8.weapon = sd->attack_spell_look_override; else { - if (widx.ok() && sd->inventory_data[widx]) + if (widx.ok() && sd->inventory_data[widx].is_some()) { fixed_1d8.weapon = sd->status.inventory[widx].nameid; } else fixed_1d8.weapon = ItemNameId(); } - if (sidx.ok() && sidx != widx && sd->inventory_data[sidx]) + if (sidx.ok() && sidx != widx && sd->inventory_data[sidx].is_some()) { fixed_1d8.shield = sd->status.inventory[sidx].nameid; } @@ -791,13 +793,13 @@ void clif_set007b(dumb_ptr<map_session_data> sd, Buffer& buf) fixed_1da.hair_style = sd->status.hair; IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON]; IOff0 sidx = sd->equip_index_maybe[EQUIP::SHIELD]; - if (widx.ok() && sd->inventory_data[widx]) + if (widx.ok() && sd->inventory_data[widx].is_some()) { fixed_1da.weapon = sd->status.inventory[widx].nameid; } else fixed_1da.weapon = ItemNameId(); - if (sidx.ok() && sidx != widx && sd->inventory_data[sidx]) + if (sidx.ok() && sidx != widx && sd->inventory_data[sidx].is_some()) { fixed_1da.shield = sd->status.inventory[sidx].nameid; } @@ -1222,7 +1224,6 @@ int clif_npcbuysell(dumb_ptr<map_session_data> sd, BlockId id) */ int clif_buylist(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data_shop> nd) { - struct item_data *id; int i, val; nullpo_retz(sd); @@ -1232,7 +1233,7 @@ int clif_buylist(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data_shop> nd) std::vector<Packet_Repeat<0x00c6>> repeat_c6(nd->shop_items.size()); for (i = 0; i < nd->shop_items.size(); i++) { - id = itemdb_search(nd->shop_items[i].nameid); + P<struct item_data> id = itemdb_search(nd->shop_items[i].nameid); val = nd->shop_items[i].value; repeat_c6[i].base_price = val; // base price repeat_c6[i].actual_price = val; // actual price @@ -1256,9 +1257,11 @@ int clif_selllist(dumb_ptr<map_session_data> sd) std::vector<Packet_Repeat<0x00c7>> repeat_c7; for (IOff0 i : IOff0::iter()) { - if (sd->status.inventory[i].nameid && sd->inventory_data[i]) + if (!sd->status.inventory[i].nameid) + continue; + if OPTION_IS_SOME(sdidi, sd->inventory_data[i]) { - int val = sd->inventory_data[i]->value_sell; + int val = sdidi->value_sell; if (val < 0) continue; Packet_Repeat<0x00c7> info; @@ -1377,9 +1380,9 @@ int clif_additem(dumb_ptr<map_session_data> sd, IOff0 n, int amount, PickupFail } else { - if (!n.ok() || !sd->status.inventory[n].nameid - || sd->inventory_data[n] == nullptr) + if (!n.ok() || !sd->status.inventory[n].nameid) return 1; + auto sdidn = TRY_UNWRAP(sd->inventory_data[n], return 1); fixed_a0.ioff2 = n.shift(); fixed_a0.amount = amount; @@ -1394,9 +1397,9 @@ int clif_additem(dumb_ptr<map_session_data> sd, IOff0 n, int amount, PickupFail fixed_a0.card3 = 0; } fixed_a0.epos = pc_equippoint(sd, n); - fixed_a0.item_type = (sd->inventory_data[n]->type == ItemType::_7 + fixed_a0.item_type = (sdidn->type == ItemType::_7 ? ItemType::WEAPON - : sd->inventory_data[n]->type); + : sdidn->type); fixed_a0.pickup_fail = fail; } @@ -1433,17 +1436,18 @@ void clif_itemlist(dumb_ptr<map_session_data> sd) std::vector<Packet_Repeat<0x01ee>> repeat_1ee; for (IOff0 i : IOff0::iter()) { - if (!sd->status.inventory[i].nameid - || sd->inventory_data[i] == nullptr - || itemdb_isequip2(sd->inventory_data[i])) + if (!sd->status.inventory[i].nameid) + continue; + auto sdidi = TRY_UNWRAP(sd->inventory_data[i], continue); + if (itemdb_isequip2(sdidi)) continue; Packet_Repeat<0x01ee> info; info.ioff2 = i.shift(); info.name_id = sd->status.inventory[i].nameid; - info.item_type = sd->inventory_data[i]->type; + info.item_type = sdidi->type; info.identify = 1; info.amount = sd->status.inventory[i].amount; - if (sd->inventory_data[i]->equip == EPOS::ARROW) + if (sdidi->equip == EPOS::ARROW) { info.epos = EPOS::ARROW; if (bool(sd->status.inventory[i].equip)) @@ -1477,17 +1481,18 @@ void clif_equiplist(dumb_ptr<map_session_data> sd) std::vector<Packet_Repeat<0x00a4>> repeat_a4; for (IOff0 i : IOff0::iter()) { - if (!sd->status.inventory[i].nameid - || sd->inventory_data[i] == nullptr - || !itemdb_isequip2(sd->inventory_data[i])) + if (!sd->status.inventory[i].nameid) + continue; + P<struct item_data> sdidi = TRY_UNWRAP(sd->inventory_data[i], continue); + if (!itemdb_isequip2(sdidi)) continue; Packet_Repeat<0x00a4> info; info.ioff2 = i.shift(); info.name_id = sd->status.inventory[i].nameid; info.item_type = ( - sd->inventory_data[i]->type == ItemType::_7 + sdidi->type == ItemType::_7 ? ItemType::WEAPON - : sd->inventory_data[i]->type); + : sdidi->type); info.identify = 0; info.epos_pc = pc_equippoint(sd, i); info.epos_inv = sd->status.inventory[i].equip; @@ -1511,10 +1516,9 @@ void clif_equiplist(dumb_ptr<map_session_data> sd) * カプラさんに預けてある消耗品&収集品リスト *------------------------------------------ */ -int clif_storageitemlist(dumb_ptr<map_session_data> sd, Storage *stor) +int clif_storageitemlist(dumb_ptr<map_session_data> sd, Borrowed<Storage> stor) { nullpo_retz(sd); - nullpo_retz(stor); Session *s = sd->sess; std::vector<Packet_Repeat<0x01f0>> repeat_1f0; @@ -1523,9 +1527,7 @@ int clif_storageitemlist(dumb_ptr<map_session_data> sd, Storage *stor) if (!stor->storage_[i].nameid) continue; - struct item_data *id; - id = itemdb_search(stor->storage_[i].nameid); - nullpo_retz(id); + P<struct item_data> id = itemdb_search(stor->storage_[i].nameid); if (itemdb_isequip2(id)) continue; @@ -1553,10 +1555,9 @@ int clif_storageitemlist(dumb_ptr<map_session_data> sd, Storage *stor) * カプラさんに預けてある装備リスト *------------------------------------------ */ -int clif_storageequiplist(dumb_ptr<map_session_data> sd, Storage *stor) +int clif_storageequiplist(dumb_ptr<map_session_data> sd, Borrowed<Storage> stor) { nullpo_retz(sd); - nullpo_retz(stor); Session *s = sd->sess; std::vector<Packet_Repeat<0x00a6>> repeat_a6; @@ -1565,9 +1566,7 @@ int clif_storageequiplist(dumb_ptr<map_session_data> sd, Storage *stor) if (!stor->storage_[i].nameid) continue; - struct item_data *id; - id = itemdb_search(stor->storage_[i].nameid); - nullpo_retz(id); + P<struct item_data> id = itemdb_search(stor->storage_[i].nameid); if (!itemdb_isequip2(id)) continue; Packet_Repeat<0x00a6> info; @@ -1843,7 +1842,7 @@ int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val, fixed_1d7.look_type = type; IOff0 idx = sd->equip_index_maybe[equip_point]; - if (idx.ok() && sd->inventory_data[idx]) + if (idx.ok() && sd->inventory_data[idx].is_some()) { fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(sd->status.inventory[idx].nameid); } @@ -1860,14 +1859,14 @@ int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val, fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(sd->attack_spell_look_override); else { - if (widx.ok() && sd->inventory_data[widx]) + if (widx.ok() && sd->inventory_data[widx].is_some()) { fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(sd->status.inventory[widx].nameid); } else fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(ItemNameId()); } - if (sidx.ok() && sidx != widx && sd->inventory_data[sidx]) + if (sidx.ok() && sidx != widx && sd->inventory_data[sidx].is_some()) { fixed_1d7.shield = sd->status.inventory[sidx].nameid; } @@ -2261,10 +2260,9 @@ int clif_tradecompleted(dumb_ptr<map_session_data> sd, int fail) *------------------------------------------ */ int clif_updatestorageamount(dumb_ptr<map_session_data> sd, - Storage *stor) + Borrowed<Storage> stor) { nullpo_retz(sd); - nullpo_retz(stor); Session *s = sd->sess; Packet_Fixed<0x00f2> fixed_f2; @@ -2279,11 +2277,10 @@ int clif_updatestorageamount(dumb_ptr<map_session_data> sd, * カプラ倉庫にアイテムを追加する *------------------------------------------ */ -int clif_storageitemadded(dumb_ptr<map_session_data> sd, Storage *stor, +int clif_storageitemadded(dumb_ptr<map_session_data> sd, Borrowed<Storage> stor, SOff0 index, int amount) { nullpo_retz(sd); - nullpo_retz(stor); Session *s = sd->sess; Packet_Fixed<0x00f4> fixed_f4; @@ -2969,8 +2966,6 @@ int clif_party_info(PartyPair p, Session *s) int i; dumb_ptr<map_session_data> sd = nullptr; - nullpo_retz(p); - Packet_Head<0x00fb> head_fb; std::vector<Packet_Repeat<0x00fb>> repeat_fb; head_fb.party_name = p->name; @@ -3016,15 +3011,12 @@ int clif_party_info(PartyPair p, Session *s) void clif_party_invite(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd) { - PartyPair p; - nullpo_retv(sd); nullpo_retv(tsd); Session *s = tsd->sess; - if (!(p = party_search(sd->status.party_id))) - return; + PartyPair p = TRY_UNWRAP(party_search(sd->status.party_id), return); Packet_Fixed<0x00fe> fixed_fe; fixed_fe.account_id = sd->status_key.account_id; @@ -3066,8 +3058,6 @@ void clif_party_inviteack(dumb_ptr<map_session_data> sd, CharName nick, int flag */ void clif_party_option(PartyPair p, dumb_ptr<map_session_data> sd, int flag) { - nullpo_retv(p); - if (sd == nullptr && flag == 0) { int i; @@ -3100,8 +3090,6 @@ void clif_party_leaved(PartyPair p, dumb_ptr<map_session_data> sd, { int i; - nullpo_retv(p); - Packet_Fixed<0x0105> fixed_105; fixed_105.account_id = account_id; fixed_105.char_name = name; @@ -3138,8 +3126,6 @@ void clif_party_message(PartyPair p, AccountId account_id, XString mes) dumb_ptr<map_session_data> sd = nullptr; int i; - nullpo_retv(p); - for (i = 0; i < MAX_PARTY; i++) { sd = dumb_ptr<map_session_data>(p->member[i].sd); @@ -3639,16 +3625,19 @@ RecvResult clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> fixed_95.char_name = ssd->status_key.name; send_fpacket<0x0095, 30>(s, fixed_95); - PartyPair p; - PartyName party_name; int send = 0; - if (ssd->status.party_id && (p = party_search(ssd->status.party_id))) + if (ssd->status.party_id) { - party_name = p->name; - send = 1; + Option<PartyPair> p_ = party_search(ssd->status.party_id); + + if OPTION_IS_SOME(p, p_) + { + party_name = p->name; + send = 1; + } } if (send) @@ -4196,10 +4185,10 @@ RecvResult clif_parse_EquipItem(Session *s, dumb_ptr<map_session_data> sd) if (sd->npc_id) return rv; - if (sd->inventory_data[index]) + if OPTION_IS_SOME(sdidi, sd->inventory_data[index]) { EPOS epos = fixed.epos_ignored; - if (sd->inventory_data[index]->type == ItemType::ARROW) + if (sdidi->type == ItemType::ARROW) epos = EPOS::ARROW; // Note: the EPOS argument to pc_equipitem is actually ignored diff --git a/src/map/clif.hpp b/src/map/clif.hpp index da8aa20..12ed633 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -119,12 +119,12 @@ int clif_tradecancelled(dumb_ptr<map_session_data> sd); int clif_tradecompleted(dumb_ptr<map_session_data> sd, int fail); // storage -int clif_storageitemlist(dumb_ptr<map_session_data> sd, Storage *stor); +int clif_storageitemlist(dumb_ptr<map_session_data> sd, Borrowed<Storage> stor); int clif_storageequiplist(dumb_ptr<map_session_data> sd, - Storage *stor); + Borrowed<Storage> stor); int clif_updatestorageamount(dumb_ptr<map_session_data> sd, - Storage *stor); -int clif_storageitemadded(dumb_ptr<map_session_data> sd, Storage *stor, + Borrowed<Storage> stor); +int clif_storageitemadded(dumb_ptr<map_session_data> sd, Borrowed<Storage> stor, SOff0 index, int amount); int clif_storageitemremoved(dumb_ptr<map_session_data> sd, SOff0 index, int amount); diff --git a/src/map/intif.cpp b/src/map/intif.cpp index 314db24..6cc3772 100644 --- a/src/map/intif.cpp +++ b/src/map/intif.cpp @@ -156,9 +156,8 @@ void intif_request_storage(AccountId account_id) } // 倉庫データ送信 -void intif_send_storage(Storage *stor) +void intif_send_storage(Borrowed<Storage> stor) { - nullpo_retv(stor); if (!char_session) return; @@ -386,7 +385,6 @@ int intif_parse_AccountReg(Session *, const Packet_Head<0x3804>& head, const std static int intif_parse_LoadStorage(Session *, const Packet_Payload<0x3810>& payload) { - Storage *stor; dumb_ptr<map_session_data> sd; sd = map_id2sd(account_to_block(payload.account_id)); @@ -397,7 +395,7 @@ int intif_parse_LoadStorage(Session *, const Packet_Payload<0x3810>& payload) payload.account_id); return 1; } - stor = account2storage(payload.account_id); + P<Storage> stor = account2storage(payload.account_id); if (stor->storage_status == 1) { // Already open.. lets ignore this update if (battle_config.error_log) @@ -463,9 +461,7 @@ void intif_parse_PartyInfo(Session *, const Packet_Head<0x3821>& head, bool has_ PartyId pi = head.party_id; PartyMost pm = option.party_most; - PartyPair pp; - pp.party_id = pi; - pp.party_most = ± + PartyPair pp{pi, borrow(pm)}; party_recv_info(pp); } diff --git a/src/map/intif.hpp b/src/map/intif.hpp index 5be61a9..00f3c49 100644 --- a/src/map/intif.hpp +++ b/src/map/intif.hpp @@ -22,6 +22,8 @@ #include "fwd.hpp" +#include "../compat/fwd.hpp" + #include "../strings/fwd.hpp" #include "../generic/fwd.hpp" @@ -44,7 +46,7 @@ void intif_saveaccountreg(dumb_ptr<map_session_data> sd); void intif_request_accountreg(dumb_ptr<map_session_data> sd); void intif_request_storage(AccountId account_id); -void intif_send_storage(Storage *stor); +void intif_send_storage(Borrowed<Storage> stor); void intif_create_party(dumb_ptr<map_session_data> sd, PartyName name); void intif_request_partyinfo(PartyId party_id); diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index b0c8c02..5ffa725 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -53,24 +53,24 @@ Map<ItemNameId, struct item_data> item_db; */ // name = item alias, so we should find items aliases first. if not found then look for "jname" (full name) static -void itemdb_searchname_sub(struct item_data *item, ItemName str, struct item_data **dst) +void itemdb_searchname_sub(Borrowed<struct item_data> item, ItemName str, Borrowed<Option<Borrowed<struct item_data>>> dst) { if (item->name == str) - *dst = item; + *dst = Some(item); } /*========================================== * 名前で検索 *------------------------------------------ */ -struct item_data *itemdb_searchname(XString str_) +Option<Borrowed<struct item_data>> itemdb_searchname(XString str_) { ItemName str = stringish<ItemName>(str_); if (XString(str) != str_) - return nullptr; - struct item_data *item = nullptr; + return None; + Option<P<struct item_data>> item = None; for (auto& pair : item_db) - itemdb_searchname_sub(&pair.second, str, &item); + itemdb_searchname_sub(borrow(pair.second), str, borrow(item)); return item; } @@ -78,7 +78,7 @@ struct item_data *itemdb_searchname(XString str_) * DBの存在確認 *------------------------------------------ */ -struct item_data *itemdb_exists(ItemNameId nameid) +Option<Borrowed<struct item_data>> itemdb_exists(ItemNameId nameid) { return item_db.search(nameid); } @@ -87,13 +87,13 @@ struct item_data *itemdb_exists(ItemNameId nameid) * DBの検索 *------------------------------------------ */ -struct item_data *itemdb_search(ItemNameId nameid) +Borrowed<struct item_data> itemdb_search(ItemNameId nameid) { - struct item_data *id = item_db.search(nameid); - if (id) + Option<P<struct item_data>> id_ = item_db.search(nameid); + if OPTION_IS_SOME(id, id_) return id; - id = item_db.init(nameid); + P<struct item_data> id = item_db.init(nameid); id->nameid = nameid; id->value_buy = 10; @@ -125,10 +125,8 @@ int itemdb_isequip(ItemNameId nameid) * *------------------------------------------ */ -int itemdb_isequip2(struct item_data *data) +bool itemdb_isequip2(Borrowed<struct item_data> data) { - if (!data) - return false; ItemType type = data->type; return !(type == ItemType::USE || type == ItemType::_2 @@ -214,7 +212,7 @@ bool itemdb_readdb(ZString filename) ln++; - struct item_data *id = itemdb_search(idv.nameid); + Borrowed<struct item_data> id = itemdb_search(idv.nameid); *id = std::move(idv); if (id->value_buy == 0 && id->value_sell == 0) { diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp index 1fdca2e..fccfa23 100644 --- a/src/map/itemdb.hpp +++ b/src/map/itemdb.hpp @@ -59,11 +59,11 @@ struct random_item_data }; inline -struct item_data *itemdb_searchname(ItemName) = delete; -struct item_data *itemdb_searchname(XString name); +Option<Borrowed<struct item_data>> itemdb_searchname(ItemName) = delete; +Option<Borrowed<struct item_data>> itemdb_searchname(XString name); // TODO this function should die -struct item_data *itemdb_search(ItemNameId nameid); -struct item_data *itemdb_exists(ItemNameId nameid); +Borrowed<struct item_data> itemdb_search(ItemNameId nameid); +Option<Borrowed<struct item_data>> itemdb_exists(ItemNameId nameid); inline ItemType itemdb_type(ItemNameId n) @@ -97,7 +97,7 @@ int itemdb_value_sell(ItemNameId n) } int itemdb_isequip(ItemNameId); -int itemdb_isequip2(struct item_data *); +bool itemdb_isequip2(Borrowed<struct item_data>); int itemdb_isequip3(ItemNameId); void itemdb_reload(void); diff --git a/src/map/magic-expr.cpp b/src/map/magic-expr.cpp index a1196fa..4afa3bc 100644 --- a/src/map/magic-expr.cpp +++ b/src/map/magic-expr.cpp @@ -583,7 +583,7 @@ int fun_if_then_else(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) return 0; } -void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, +Borrowed<map_local> magic_area_rect(int *x, int *y, int *width, int *height, area_t& area_) { MATCH (area_) @@ -595,19 +595,21 @@ void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, } CASE (const location_t&, a_loc) { - *m = a_loc.m; + P<map_local> m = a_loc.m; *x = a_loc.x; *y = a_loc.y; *width = 1; *height = 1; + return m; } CASE (const AreaRect&, a_rect) { - *m = a_rect.loc.m; + P<map_local> m = a_rect.loc.m; *x = a_rect.loc.x; *y = a_rect.loc.y; *width = a_rect.width; *height = a_rect.height; + return m; } CASE (const AreaBar&, a_bar) { @@ -615,7 +617,7 @@ void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, int ty = a_bar.loc.y; int twidth = a_bar.width; int tdepth = a_bar.width; - *m = a_bar.loc.m; + P<map_local> m = a_bar.loc.m; switch (a_bar.dir) { @@ -654,11 +656,13 @@ void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, *y = ty; *width = *height = 1; } + return m; } } + abort(); } -int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area) +int magic_location_in_area(Borrowed<map_local> m, int x, int y, dumb_ptr<area_t> area) { MATCH (*area) { @@ -671,9 +675,8 @@ int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area) { (void)a_loc; // TODO this can be simplified - map_local *am; int ax, ay, awidth, aheight; - magic_area_rect(&am, &ax, &ay, &awidth, &aheight, *area); + P<map_local> am = magic_area_rect(&ax, &ay, &awidth, &aheight, *area); return (am == m && (x >= ax) && (y >= ay) && (x < ax + awidth) && (y < ay + aheight)); @@ -682,9 +685,8 @@ int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area) { (void)a_rect; // TODO this is too complicated - map_local *am; int ax, ay, awidth, aheight; - magic_area_rect(&am, &ax, &ay, &awidth, &aheight, *area); + P<map_local> am = magic_area_rect(&ax, &ay, &awidth, &aheight, *area); return (am == m && (x >= ax) && (y >= ay) && (x < ax + awidth) && (y < ay + aheight)); @@ -693,9 +695,8 @@ int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area) { (void)a_bar; // TODO this is wrong - map_local *am; int ax, ay, awidth, aheight; - magic_area_rect(&am, &ax, &ay, &awidth, &aheight, *area); + P<map_local> am = magic_area_rect(&ax, &ay, &awidth, &aheight, *area); return (am == m && (x >= ax) && (y >= ay) && (x < ax + awidth) && (y < ay + aheight)); @@ -873,18 +874,17 @@ int fun_hash_entity(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) // ret -1: not a string, ret 1: no such item, ret 0: OK int magic_find_item(Slice<val_t> args, int index, Item *item_, int *stackable) { - struct item_data *item_data; + Option<P<struct item_data>> item_data_ = None; int must_add_sequentially; if (args[index].is<ValInt>()) - item_data = itemdb_exists(wrap<ItemNameId>(static_cast<uint16_t>(ARGINT(index)))); + item_data_ = itemdb_exists(wrap<ItemNameId>(static_cast<uint16_t>(ARGINT(index)))); else if (args[index].is<ValString>()) - item_data = itemdb_searchname(ARGSTR(index)); + item_data_ = itemdb_searchname(ARGSTR(index)); else return -1; - if (!item_data) - return 1; + P<struct item_data> item_data = TRY_UNWRAP(item_data_, return 1); // Very elegant. must_add_sequentially = ( @@ -1096,9 +1096,8 @@ void magic_random_location(location_t *dest, dumb_ptr<area_t> area) { (void)a_loc; // TODO this can be simplified - map_local *m; int x, y, w, h; - magic_area_rect(&m, &x, &y, &w, &h, *area); + P<map_local> m = magic_area_rect(&x, &y, &w, &h, *area); if (w <= 1) w = 1; @@ -1118,9 +1117,8 @@ void magic_random_location(location_t *dest, dumb_ptr<area_t> area) { (void)a_rect; // TODO this can be simplified - map_local *m; int x, y, w, h; - magic_area_rect(&m, &x, &y, &w, &h, *area); + P<map_local> m = magic_area_rect(&x, &y, &w, &h, *area); if (w <= 1) w = 1; @@ -1140,9 +1138,8 @@ void magic_random_location(location_t *dest, dumb_ptr<area_t> area) { (void)a_bar; // TODO this is wrong - map_local *m; int x, y, w, h; - magic_area_rect(&m, &x, &y, &w, &h, *area); + P<map_local> m = magic_area_rect(&x, &y, &w, &h, *area); if (w <= 1) w = 1; @@ -1512,10 +1509,8 @@ int eval_location(dumb_ptr<env_t> env, location_t *dest, const e_location_t *exp && x.is<ValInt>() && y.is<ValInt>()) { MapName name = VString<15>(ZString(m.get_if<ValString>()->v_string)); - map_local *map_id = map_mapname2mapid(name); magic_clear_var(&m); - if (!map_id) - return 1; + P<map_local> map_id = TRY_UNWRAP(map_mapname2mapid(name), return 1); dest->m = map_id; dest->x = x.get_if<ValInt>()->v_int; dest->y = y.get_if<ValInt>()->v_int; diff --git a/src/map/magic-expr.hpp b/src/map/magic-expr.hpp index 294e665..2a4b4be 100644 --- a/src/map/magic-expr.hpp +++ b/src/map/magic-expr.hpp @@ -97,14 +97,14 @@ int magic_find_item(Slice<val_t> args, int index, Item *item, int *stackable); default: break; \ } -int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area); +int magic_location_in_area(Borrowed<map_local> m, int x, int y, dumb_ptr<area_t> area); /* Helper definitions for dealing with functions and operations */ int magic_signature_check(ZString opname, ZString funname, ZString signature, Slice<val_t> args, int line, int column); -void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, +Borrowed<map_local> magic_area_rect(int *x, int *y, int *width, int *height, area_t& area); } // namespace magic } // namespace tmwa diff --git a/src/map/magic-interpreter.hpp b/src/map/magic-interpreter.hpp index 7cdf7bf..09642cb 100644 --- a/src/map/magic-interpreter.hpp +++ b/src/map/magic-interpreter.hpp @@ -50,8 +50,14 @@ namespace magic { struct location_t { - map_local *m; + Borrowed<map_local> m; int x, y; + + // This constructor exists solely to work around the design constraints + // of sexpr::Variant<>. See comments in variant.tcc for future plans. + __attribute__((deprecated)) + location_t() noexcept : m(borrow(undefined_gat)), x(), y() {} + location_t(Borrowed<map_local> m_, int x_, int y_) : m(m_), x(x_), y(y_) {} }; struct AreaUnion diff --git a/src/map/magic-interpreter.py b/src/map/magic-interpreter.py index cf17b1c..bbf135c 100644 --- a/src/map/magic-interpreter.py +++ b/src/map/magic-interpreter.py @@ -27,11 +27,11 @@ class area_t(object): using tmwa::operator "" _s; inline - tmwa::map_local *fake_map_local_x_dup_for_area_t(tmwa::ZString name) + tmwa::Borrowed<tmwa::map_local> fake_map_local_x_dup_for_area_t(tmwa::ZString name) { auto *p = new tmwa::map_local{}; p->name_ = tmwa::stringish<tmwa::MapName>(name); - return p; + return tmwa::borrow(*p); } ''' @@ -55,11 +55,11 @@ class val_t(object): using tmwa::operator "" _s; inline - tmwa::map_local *fake_map_local_x_dup_for_val_t(tmwa::ZString name) + tmwa::Borrowed<tmwa::map_local> fake_map_local_x_dup_for_val_t(tmwa::ZString name) { auto *p = new tmwa::map_local{}; p->name_ = tmwa::stringish<tmwa::MapName>(name); - return p; + return tmwa::borrow(*p); } ''' diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp index a5d667c..b532ec8 100644 --- a/src/map/magic-stmt.cpp +++ b/src/map/magic-stmt.cpp @@ -220,7 +220,7 @@ BlockId trigger_spell(BlockId subject, BlockId spell) } static -void entity_warp(dumb_ptr<block_list> target, map_local *destm, int destx, int desty); +void entity_warp(dumb_ptr<block_list> target, Borrowed<map_local> destm, int destx, int desty); static void char_update(dumb_ptr<map_session_data> character) @@ -263,7 +263,7 @@ void timer_callback_effect_npc_delete(TimerData *, tick_t, BlockId npc_id) } static -dumb_ptr<npc_data> local_spell_effect(map_local *m, int x, int y, int effect, +dumb_ptr<npc_data> local_spell_effect(Borrowed<map_local> m, int x, int y, int effect, interval_t tdelay) { /* 1 minute should be enough for all interesting spell effects, I hope */ @@ -423,7 +423,7 @@ int op_messenger_npc(dumb_ptr<env_t>, Slice<val_t> args) } static -void entity_warp(dumb_ptr<block_list> target, map_local *destm, int destx, int desty) +void entity_warp(dumb_ptr<block_list> target, Borrowed<map_local> destm, int destx, int desty) { if (target->bl_type == BL::PC || target->bl_type == BL::MOB) { @@ -1146,9 +1146,8 @@ void find_entities_in_area(area_t& area_, { (void)a_loc; // TODO this can be simplified - map_local *m; int x, y, width, height; - magic_area_rect(&m, &x, &y, &width, &height, area_); + Borrowed<map_local> m = magic_area_rect(&x, &y, &width, &height, area_); map_foreachinarea(std::bind(find_entities_in_area_c, ph::_1, entities_vp, filter), m, x, y, @@ -1159,9 +1158,8 @@ void find_entities_in_area(area_t& area_, { (void)a_rect; // TODO this can be simplified - map_local *m; int x, y, width, height; - magic_area_rect(&m, &x, &y, &width, &height, area_); + Borrowed<map_local> m = magic_area_rect(&x, &y, &width, &height, area_); map_foreachinarea(std::bind(find_entities_in_area_c, ph::_1, entities_vp, filter), m, x, y, @@ -1172,9 +1170,8 @@ void find_entities_in_area(area_t& area_, { (void)a_bar; // TODO this is wrong - map_local *m; int x, y, width, height; - magic_area_rect(&m, &x, &y, &width, &height, area_); + Borrowed<map_local> m = magic_area_rect(&x, &y, &width, &height, area_); map_foreachinarea(std::bind(find_entities_in_area_c, ph::_1, entities_vp, filter), m, x, y, @@ -1393,7 +1390,7 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) // dealing with an NPC int newpos = run_script_l( - ScriptPointer(&*e_.e_script, invocation_->script_pos), + ScriptPointer(borrow(*e_.e_script), invocation_->script_pos), message_recipient, invocation_->bl_id, arg); /* Returns the new script position, or -1 once the script is finished */ diff --git a/src/map/magic-v2.cpp b/src/map/magic-v2.cpp index 8a84a2d..eeeb989 100644 --- a/src/map/magic-v2.cpp +++ b/src/map/magic-v2.cpp @@ -578,9 +578,9 @@ namespace magic_v2 { count = 1; - item_data *item = itemdb_searchname(s._str); - if (!item) - return fail(s, "no such item"_s); + Borrowed<item_data> item = TRY_UNWRAP(itemdb_searchname(s._str), + return fail(s, "no such item"_s) + ); id = item->nameid; return true; } @@ -594,9 +594,9 @@ namespace magic_v2 if (s._list[1]._type != sexpr::STRING) return fail(s._list[1], "item pair second not name"_s); - item_data *item = itemdb_searchname(s._list[1]._str); - if (!item) - return fail(s, "no such item"_s); + Borrowed<item_data> item = TRY_UNWRAP(itemdb_searchname(s._list[1]._str), + return fail(s, "no such item"_s) + ); id = item->nameid; return true; } diff --git a/src/map/map.cpp b/src/map/map.cpp index 87092cf..3d14637 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -113,6 +113,8 @@ AString motd_txt = "conf/motd.txt"_s; CharName wisp_server_name = stringish<CharName>("Server"_s); // can be modified in char-server configuration file +map_local undefined_gat = [](){ map_local rv {}; rv.name_ = stringish<MapName>("undefined.gat"_s); return rv; }(); + static void map_delmap(MapName mapname); @@ -203,10 +205,10 @@ int map_addblock(dumb_ptr<block_list> bl) return 0; } - map_local *m = bl->bl_m; + P<map_local> m = bl->bl_m; int x = bl->bl_x; int y = bl->bl_y; - if (!m || + if (m == borrow(undefined_gat) || x < 0 || x >= m->xs || y < 0 || y >= m->ys) return 1; @@ -284,7 +286,7 @@ int map_delblock(dumb_ptr<block_list> bl) * セル上のPCとMOBの数を数える (グランドクロス用) *------------------------------------------ */ -int map_count_oncell(map_local *m, int x, int y) +int map_count_oncell(Borrowed<map_local> m, int x, int y) { int bx, by; dumb_ptr<block_list> bl = nullptr; @@ -319,14 +321,12 @@ int map_count_oncell(map_local *m, int x, int y) *------------------------------------------ */ void map_foreachinarea(std::function<void(dumb_ptr<block_list>)> func, - map_local *m, + Borrowed<map_local> m, int x0, int y0, int x1, int y1, BL type) { std::vector<dumb_ptr<block_list>> bl_list; - if (!m) - return; if (x0 < 0) x0 = 0; if (y0 < 0) @@ -382,7 +382,7 @@ void map_foreachinarea(std::function<void(dumb_ptr<block_list>)> func, *------------------------------------------ */ void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)> func, - map_local *m, + Borrowed<map_local> m, int x0, int y0, int x1, int y1, int dx, int dy, BL type) @@ -502,7 +502,7 @@ void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)> func, // area radius - may be more useful in some instances) // void map_foreachincell(std::function<void(dumb_ptr<block_list>)> func, - map_local *m, + Borrowed<map_local> m, int x, int y, BL type) { @@ -675,7 +675,7 @@ void map_clearflooritem_timer(TimerData *tid, tick_t, BlockId id) map_delobject(fitem->bl_id, BL::ITEM); } -std::pair<uint16_t, uint16_t> map_randfreecell(map_local *m, +std::pair<uint16_t, uint16_t> map_randfreecell(Borrowed<map_local> m, uint16_t x, uint16_t y, uint16_t w, uint16_t h) { for (int itr : random_::iterator(w * h)) @@ -690,7 +690,7 @@ std::pair<uint16_t, uint16_t> map_randfreecell(map_local *m, /// Return a randomly selected passable cell within a given range. static -std::pair<uint16_t, uint16_t> map_searchrandfreecell(map_local *m, int x, int y, int range) +std::pair<uint16_t, uint16_t> map_searchrandfreecell(Borrowed<map_local> m, int x, int y, int range) { int whole_range = 2 * range + 1; return map_randfreecell(m, x - range, y - range, whole_range, whole_range); @@ -703,7 +703,7 @@ std::pair<uint16_t, uint16_t> map_searchrandfreecell(map_local *m, int x, int y, *------------------------------------------ */ BlockId map_addflooritem_any(Item *item_data, int amount, - map_local *m, int x, int y, + Borrowed<map_local> m, int x, int y, dumb_ptr<map_session_data> *owners, interval_t *owner_protection, interval_t lifetime, int dispersal) { @@ -768,7 +768,7 @@ BlockId map_addflooritem_any(Item *item_data, int amount, } BlockId map_addflooritem(Item *item_data, int amount, - map_local *m, int x, int y, + Borrowed<map_local> m, int x, int y, dumb_ptr<map_session_data> first_sd, dumb_ptr<map_session_data> second_sd, dumb_ptr<map_session_data> third_sd) @@ -793,9 +793,7 @@ BlockId map_addflooritem(Item *item_data, int amount, */ void map_addchariddb(CharId charid, CharName name) { - struct charid2nick *p = charid_db.search(charid); - if (p == nullptr) - p = charid_db.init(charid); + P<struct charid2nick> p = charid_db.init(charid); p->nick = name; p->req_id = 0; @@ -930,13 +928,17 @@ dumb_ptr<map_session_data> map_id2sd(BlockId id) */ CharName map_charid2nick(CharId id) { - struct charid2nick *p = charid_db.search(id); + Option<P<struct charid2nick>> p_ = charid_db.search(id); - if (p == nullptr) - return CharName(); - if (p->req_id != 0) - return CharName(); - return p->nick; + return p_.cmap( + [](P<struct charid2nick> p) + { + return p->req_id == 0; + }, + [](P<struct charid2nick> p) + { + return p->nick; + }).move_or(CharName()); } /*========================================*/ @@ -1048,11 +1050,9 @@ dumb_ptr<block_list> map_id2bl(BlockId id) * map.npcへ追加 (warp等の領域持ちのみ) *------------------------------------------ */ -int map_addnpc(map_local *m, dumb_ptr<npc_data> nd) +int map_addnpc(Borrowed<map_local> m, dumb_ptr<npc_data> nd) { int i; - if (!m) - return -1; for (i = 0; i < m->npc_num && i < MAX_NPC_PER_MAP; i++) if (m->npc[i] == nullptr) break; @@ -1110,27 +1110,39 @@ void map_removenpc(void) * map名からmap番号へ変換 *------------------------------------------ */ -map_local *map_mapname2mapid(MapName name) +Option<Borrowed<map_local>> map_mapname2mapid(MapName name) { - map_abstract *md = maps_db.get(name); - if (md == nullptr || md->gat == nullptr) - return nullptr; - return static_cast<map_local *>(md); + Option<P<map_abstract>> md_ = maps_db.get(name); + return md_.cmap( + [](P<map_abstract> md) + { + return bool(md->gat); + }, + [](P<map_abstract> md) + { + return md.downcast_to<map_local>(); + }); } /*========================================== * 他鯖map名からip,port変換 *------------------------------------------ */ -int map_mapname2ipport(MapName name, IP4Address *ip, int *port) +int map_mapname2ipport(MapName name, Borrowed<IP4Address> ip, Borrowed<int> port) { - map_abstract *md = maps_db.get(name); - if (md == nullptr || md->gat) - return -1; - map_remote *mdos = static_cast<map_remote *>(md); - *ip = mdos->ip; - *port = mdos->port; - return 0; + Option<P<map_abstract>> md_ = maps_db.get(name); + return md_.cmap( + [](P<map_abstract> md) + { + return !md->gat; + }, + [ip, port](P<map_abstract> md) + { + auto mdos = md.downcast_to<map_remote>(); + *ip = mdos->ip; + *port = mdos->port; + return 0; + }).copy_or(-1); } /// Check compatibility of directions. @@ -1209,7 +1221,7 @@ DIR map_calc_dir(dumb_ptr<block_list> src, int x, int y) * (m,x,y)の状態を調べる *------------------------------------------ */ -MapCell map_getcell(map_local *m, int x, int y) +MapCell map_getcell(Borrowed<map_local> m, int x, int y) { if (x < 0 || x >= m->xs - 1 || y < 0 || y >= m->ys - 1) return MapCell::UNWALKABLE; @@ -1220,7 +1232,7 @@ MapCell map_getcell(map_local *m, int x, int y) * (m,x,y)の状態をtにする *------------------------------------------ */ -void map_setcell(map_local *m, int x, int y, MapCell t) +void map_setcell(Borrowed<map_local> m, int x, int y, MapCell t) { if (x < 0 || x >= m->xs || y < 0 || y >= m->ys) return; @@ -1233,18 +1245,8 @@ void map_setcell(map_local *m, int x, int y, MapCell t) */ int map_setipport(MapName name, IP4Address ip, int port) { - map_abstract *md = maps_db.get(name); - if (md == nullptr) - { - // not exist -> add new data - auto mdos = make_unique<map_remote>(); - mdos->name_ = name; - mdos->gat = nullptr; - mdos->ip = ip; - mdos->port = port; - maps_db.put(mdos->name_, std::move(mdos)); - } - else + Option<P<map_abstract>> md_ = maps_db.get(name); + if OPTION_IS_SOME(md, md_) { if (md->gat) { @@ -1259,11 +1261,21 @@ int map_setipport(MapName name, IP4Address ip, int port) else { // update - map_remote *mdos = static_cast<map_remote *>(md); + P<map_remote> mdos = md.downcast_to<map_remote>(); mdos->ip = ip; mdos->port = port; } } + else + { + // not exist -> add new data + auto mdos = make_unique<map_remote>(); + mdos->name_ = name; + mdos->gat = nullptr; + mdos->ip = ip; + mdos->port = port; + maps_db.put(mdos->name_, std::move(mdos)); + } return 0; } @@ -1640,7 +1652,7 @@ void term_func(void) { if (!mit.second->gat) continue; - map_local *map_id = static_cast<map_local *>(mit.second.get()); + P<map_local> map_id = borrow(*mit.second).downcast_to<map_local>(); map_foreachinarea(cleanup_sub, map_id, diff --git a/src/map/map.hpp b/src/map/map.hpp index aeb8821..cb4273f 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -98,11 +98,13 @@ struct NpcEvent }; bool extract(XString str, NpcEvent *ev); +extern map_local undefined_gat; + struct block_list { dumb_ptr<block_list> bl_next, bl_prev; BlockId bl_id; - map_local *bl_m; + Borrowed<map_local> bl_m = borrow(undefined_gat); short bl_x, bl_y; BL bl_type; @@ -186,7 +188,19 @@ struct map_session_data : block_list, SessionData unsigned char tmw_version; // tmw client version CharKey status_key; CharData status; - GenericArray<struct item_data *, InventoryIndexing<IOff0, MAX_INVENTORY>> inventory_data; + GenericArray<Option<Borrowed<struct item_data>>, InventoryIndexing<IOff0, MAX_INVENTORY>> inventory_data = + {{ + None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, + }}; // explicit is better than implicit earray<IOff0, EQUIP, EQUIP::COUNT> equip_index_maybe; int weight, max_weight; MapName mapname_; @@ -206,7 +220,7 @@ struct map_session_data : block_list, SessionData int npc_amount; // I have no idea exactly what these are doing ... // but one should probably be replaced with a ScriptPointer ??? - const ScriptBuffer *npc_script, *npc_scriptroot; + Option<Borrowed<const ScriptBuffer>> npc_script = None, npc_scriptroot = None; std::vector<struct script_data> npc_stackbuf; RString npc_str; struct @@ -433,7 +447,7 @@ struct mob_data : block_list MobMode mode; struct { - map_local *m; + Borrowed<map_local> m = borrow(undefined_gat); short x0, y0, xs, ys; interval_t delay1, delay2; } spawn; @@ -508,6 +522,8 @@ struct map_abstract // gat is nullptr for map_remote and non-nullptr for map_local std::unique_ptr<MapCell[]> gat; + map_abstract() = default; + map_abstract(map_abstract&&) = default; virtual ~map_abstract() {} }; extern @@ -532,7 +548,7 @@ struct map_remote : map_abstract }; inline -MapCell read_gatp(map_local *m, int x, int y) +MapCell read_gatp(Borrowed<map_local> m, int x, int y) { assert (0 <= x && x < m->xs); assert (0 <= y && y < m->ys); @@ -574,21 +590,21 @@ public: int map_addblock(dumb_ptr<block_list>); int map_delblock(dumb_ptr<block_list>); void map_foreachinarea(std::function<void(dumb_ptr<block_list>)>, - map_local *, + Borrowed<map_local>, int, int, int, int, BL); // -- moonsoul (added map_foreachincell) void map_foreachincell(std::function<void(dumb_ptr<block_list>)>, - map_local *, + Borrowed<map_local>, int, int, BL); void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)>, - map_local *, + Borrowed<map_local>, int, int, int, int, int, int, BL); //block関連に追加 -int map_count_oncell(map_local *m, int x, int y); +int map_count_oncell(Borrowed<map_local> m, int x, int y); // 一時的object関連 BlockId map_addobject(dumb_ptr<block_list>); void map_delobject(BlockId, BL type); @@ -598,7 +614,7 @@ void map_foreachobject(std::function<void(dumb_ptr<block_list>)>, // void map_quit(dumb_ptr<map_session_data>); // npc -int map_addnpc(map_local *, dumb_ptr<npc_data>); +int map_addnpc(Borrowed<map_local>, dumb_ptr<npc_data>); void map_log(XString line); #define MAP_LOG(format, ...) \ @@ -606,7 +622,7 @@ void map_log(XString line); #define MAP_LOG_PC(sd, fmt, ...) \ MAP_LOG("PC%d %s:%d,%d " fmt, \ - sd->status_key.char_id, (sd->bl_m ? sd->bl_m->name_ : stringish<MapName>("undefined.gat"_s)), sd->bl_x, sd->bl_y, ## __VA_ARGS__) + sd->status_key.char_id, (sd->bl_m->name_), sd->bl_x, sd->bl_y, ## __VA_ARGS__) // 床アイテム関連 void map_clearflooritem_timer(TimerData *, tick_t, BlockId); @@ -616,11 +632,11 @@ void map_clearflooritem(BlockId id) map_clearflooritem_timer(nullptr, tick_t(), id); } BlockId map_addflooritem_any(Item *, int amount, - map_local *m, int x, int y, + Borrowed<map_local> m, int x, int y, dumb_ptr<map_session_data> *owners, interval_t *owner_protection, interval_t lifetime, int dispersal); BlockId map_addflooritem(Item *, int, - map_local *, int, int, + Borrowed<map_local>, int, int, dumb_ptr<map_session_data>, dumb_ptr<map_session_data>, dumb_ptr<map_session_data>); @@ -665,8 +681,8 @@ dumb_ptr<magic::invocation> map_id_is_spell(BlockId id) } -map_local *map_mapname2mapid(MapName); -int map_mapname2ipport(MapName, IP4Address *, int *); +Option<Borrowed<map_local>> map_mapname2mapid(MapName); +int map_mapname2ipport(MapName, Borrowed<IP4Address>, Borrowed<int>); int map_setipport(MapName name, IP4Address ip, int port); void map_addiddb(dumb_ptr<block_list>); void map_deliddb(dumb_ptr<block_list> bl); @@ -683,14 +699,14 @@ dumb_ptr<map_session_data> map_get_prev_session( dumb_ptr<map_session_data> current); // gat関連 -MapCell map_getcell(map_local *, int, int); -void map_setcell(map_local *, int, int, MapCell); +MapCell map_getcell(Borrowed<map_local>, int, int); +void map_setcell(Borrowed<map_local>, int, int, MapCell); // その他 bool map_check_dir(DIR s_dir, DIR t_dir); DIR map_calc_dir(dumb_ptr<block_list> src, int x, int y); -std::pair<uint16_t, uint16_t> map_randfreecell(map_local *m, +std::pair<uint16_t, uint16_t> map_randfreecell(Borrowed<map_local> m, uint16_t x, uint16_t y, uint16_t w, uint16_t h); inline dumb_ptr<map_session_data> block_list::as_player() { return dumb_ptr<map_session_data>(static_cast<map_session_data *>(this)) ; } diff --git a/src/map/mob.cpp b/src/map/mob.cpp index a5d3eaf..a2932d0 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -410,15 +410,15 @@ BlockId mob_once_spawn(dumb_ptr<map_session_data> sd, NpcEvent event) { dumb_ptr<mob_data> md = nullptr; - map_local *m; int count; - if (sd && mapname == MOB_THIS_MAP) - m = sd->bl_m; - else - m = map_mapname2mapid(mapname); + P<map_local> m = ( + (sd && mapname == MOB_THIS_MAP) + ? sd->bl_m + : TRY_UNWRAP(map_mapname2mapid(mapname), return BlockId()) + ); - if (m == nullptr || amount <= 0 || mobdb_checkid(mob_class) == Species()) + if (amount <= 0 || mobdb_checkid(mob_class) == Species()) return BlockId(); if (sd) @@ -470,18 +470,18 @@ BlockId mob_once_spawn_area(dumb_ptr<map_session_data> sd, { int x, y, i, max, lx = -1, ly = -1; BlockId id; - map_local *m; - if (mapname == MOB_THIS_MAP) - m = sd->bl_m; - else - m = map_mapname2mapid(mapname); + P<map_local> m = ( + (mapname == MOB_THIS_MAP) + ? sd->bl_m + : TRY_UNWRAP(map_mapname2mapid(mapname), return BlockId()) + ); max = (y1 - y0 + 1) * (x1 - x0 + 1) * 3; if (max > 1000) max = 1000; - if (m == nullptr || amount <= 0 || (mobdb_checkid(mob_class) == Species())) // A summon is stopped if a value is unusual + if (amount <= 0 || (mobdb_checkid(mob_class) == Species())) // A summon is stopped if a value is unusual return BlockId(); for (i = 0; i < amount; i++) @@ -1572,7 +1572,7 @@ int mob_ai_sub_hard_slavemob(dumb_ptr<mob_data> md, tick_t tick) // Since it is in the map on which the master is not, teleport is carried out and it pursues. if (mmd->bl_m != md->bl_m) { - mob_warp(md, mmd->bl_m, mmd->bl_x, mmd->bl_y, BeingRemoveWhy::WARPED); + mob_warp(md, Some(mmd->bl_m), mmd->bl_x, mmd->bl_y, BeingRemoveWhy::WARPED); md->state.master_check = 1; return 0; } @@ -1584,7 +1584,7 @@ int mob_ai_sub_hard_slavemob(dumb_ptr<mob_data> md, tick_t tick) // Since the master was in near immediately before, teleport is carried out and it pursues. if (old_dist < 10 && md->master_dist > 18) { - mob_warp(md, nullptr, mmd->bl_x, mmd->bl_y, BeingRemoveWhy::WARPED); + mob_warp(md, None, mmd->bl_x, mmd->bl_y, BeingRemoveWhy::WARPED); md->state.master_check = 1; return 0; } @@ -2177,7 +2177,7 @@ void mob_ai_lazy(TimerData *, tick_t tick) */ struct delay_item_drop { - map_local *m; + Borrowed<map_local> m = borrow(undefined_gat); int x, y; ItemNameId nameid; int amount; @@ -2186,7 +2186,7 @@ struct delay_item_drop struct delay_item_drop2 { - map_local *m; + Borrowed<map_local> m = borrow(undefined_gat); int x, y; Item item_data; dumb_ptr<map_session_data> first_sd, second_sd, third_sd; @@ -2541,7 +2541,6 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, int base_exp, job_exp, flag = 1; double per; - PartyPair p; // [Fate] The above is the old formula. We do a more involved computation below. // [o11c] Look in git history for old code, you idiot! @@ -2592,15 +2591,15 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, ); if (it == ptv.end()) { - p = party_search(pid); - if (p && p->exp != 0) + Option<PartyPair> p_ = party_search(pid); + if OPTION_IS_SOME(p, p_) { - DmgLogParty pn {}; - pn.p = p; - pn.base_exp = base_exp; - pn.job_exp = job_exp; - ptv.push_back(pn); - flag = 0; + if (p->exp != 0) + { + DmgLogParty pn{p, base_exp, job_exp}; + ptv.push_back(pn); + flag = 0; + } } } else @@ -2763,7 +2762,7 @@ int mob_warpslave(dumb_ptr<mob_data> md, int x, int y) * mobワープ *------------------------------------------ */ -int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy type) +int mob_warp(dumb_ptr<mob_data> md, Option<Borrowed<map_local>> m_, int x, int y, BeingRemoveWhy type) { int i = 0, xs = 0, ys = 0, bx = x, by = y; @@ -2772,8 +2771,7 @@ int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy t if (md->bl_prev == nullptr) return 0; - if (m == nullptr) - m = md->bl_m; + P<map_local> m = m_.copy_or(md->bl_m); if (type != BeingRemoveWhy::NEGATIVE1) { @@ -2892,7 +2890,7 @@ int mob_summonslave(dumb_ptr<mob_data> md2, int *value_, int amount, int flag) bx = md2->bl_x; by = md2->bl_y; - map_local *m = md2->bl_m; + P<map_local> m = md2->bl_m; Species values[5]; for (count = 0; count < 5 && value_[count]; ++count) diff --git a/src/map/mob.hpp b/src/map/mob.hpp index 1f2aead..c4fcce1 100644 --- a/src/map/mob.hpp +++ b/src/map/mob.hpp @@ -127,7 +127,7 @@ int mob_deleteslave(dumb_ptr<mob_data> md); int mob_counttargeted(dumb_ptr<mob_data> md, dumb_ptr<block_list> src, ATK target_lv); -int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy type); +int mob_warp(dumb_ptr<mob_data> md, Option<Borrowed<map_local>> m, int x, int y, BeingRemoveWhy type); int mobskill_use(dumb_ptr<mob_data> md, tick_t tick, MobSkillCondition event); int mobskill_event(dumb_ptr<mob_data> md, BF flag); diff --git a/src/map/npc-parse.cpp b/src/map/npc-parse.cpp index 6df42c9..f5b6a07 100644 --- a/src/map/npc-parse.cpp +++ b/src/map/npc-parse.cpp @@ -160,7 +160,7 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4) return 1; } - map_local *m = map_mapname2mapid(mapname); + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return 1); nd.new_(); nd->bl_id = npc_get_new_npc_id(); @@ -222,21 +222,20 @@ bool extract(XString xs, npc_item_list *itv) XString name_or_id; if (!extract(xs, record<':'>(&name_or_id, &itv->value))) return false; - struct item_data *id = nullptr; - if (extract(name_or_id, &itv->nameid) && itv->nameid) - goto return_true; - id = itemdb_searchname(name_or_id.rstrip()); - if (id == nullptr) - return false; - itv->nameid = id->nameid; - goto return_true; + P<struct item_data> id = ((extract(name_or_id, &itv->nameid) && itv->nameid) + ? ({ + P<struct item_data> id_ = itemdb_search(itv->nameid); + id_; + }) + : ({ + P<struct item_data> id_ = TRY_UNWRAP(itemdb_searchname(name_or_id.rstrip()), return false); + itv->nameid = id_->nameid; + id_; + })); -return_true: if (itv->value < 0) { - if (id == nullptr) - id = itemdb_search(itv->nameid); itv->value = id->value_buy * abs(itv->value); } return true; @@ -266,7 +265,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) return 1; } dir = static_cast<DIR>(dir_); - map_local *m = map_mapname2mapid(mapname); + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return 1); nd.new_(); ZString w4b = w4a.xislice_t(w4comma + 1); @@ -335,7 +334,6 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, { int x, y; DIR dir = DIR::S; - map_local *m; int xs = 0, ys = 0; // [Valaris] thanks to fov Species npc_class; MapName mapname; @@ -343,11 +341,12 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, dumb_ptr<npc_data_script> nd; int evflag = 0; + P<map_local> m = borrow(undefined_gat); if (w1 == "-"_s) { x = 0; y = 0; - m = nullptr; + m = borrow(undefined_gat); } else { @@ -360,7 +359,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, return 1; } dir = static_cast<DIR>(dir_); - m = map_mapname2mapid(mapname); + m = map_mapname2mapid(mapname).copy_or(borrow(undefined_gat)); } if (w2 == "script"_s) @@ -408,7 +407,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, nd.new_(); - if (m == nullptr) + if (m == borrow(undefined_gat)) { } else if (extract(w4, record<','>(&npc_class, &xs, &ys))) @@ -451,7 +450,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, nd->scr.ys = 0; } - if (npc_class == NEGATIVE_SPECIES && m != nullptr) + if (npc_class == NEGATIVE_SPECIES && m != borrow(undefined_gat)) { evflag = 1; } @@ -484,7 +483,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, npc_script++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::SCRIPT; - if (m != nullptr) + if (m != borrow(undefined_gat)) { nd->n = map_addnpc(m, nd); map_addblock(nd); @@ -627,7 +626,7 @@ int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) interval_t delay1 = std::chrono::milliseconds(delay1_); interval_t delay2 = std::chrono::milliseconds(delay2_); - map_local *m = map_mapname2mapid(mapname); + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return 1); if (num > 1 && battle_config.mob_count_rate != 100) { @@ -695,9 +694,7 @@ int npc_parse_mapflag(XString w1, XString, XString w3, ZString w4) if (!mapname) return 1; - map_local *m = map_mapname2mapid(mapname); - if (m == nullptr) - return 1; + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return 1); MapFlag mf; if (!extract(w3, &mf)) @@ -739,7 +736,7 @@ int npc_parse_mapflag(XString w1, XString, XString w3, ZString w4) return 0; } -dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, +dumb_ptr<npc_data> npc_spawn_text(Borrowed<map_local> m, int x, int y, Species npc_class, NpcName name, AString message) { dumb_ptr<npc_data_message> retval; @@ -813,8 +810,8 @@ bool do_init_npc(void) { auto comma = std::find(w1.begin(), w1.end(), ','); MapName mapname = stringish<MapName>(w1.xislice_h(comma)); - map_local *m = map_mapname2mapid(mapname); - if (m == nullptr) + Option<P<map_local>> m = map_mapname2mapid(mapname); + if (m.is_none()) { // "mapname" is not assigned to this server FPRINTF(stderr, "%s:%d: Map not found: %s\n"_fmt, nsl, lines, mapname); @@ -825,35 +822,35 @@ bool do_init_npc(void) if (w2 == "warp"_s) { NpcName npcname = stringish<NpcName>(w3); - npc_parse_warp(w1, w2, npcname, w4z); + rv &= !npc_parse_warp(w1, w2, npcname, w4z); } else if (w2 == "shop"_s) { NpcName npcname = stringish<NpcName>(w3); - npc_parse_shop(w1, w2, npcname, w4z); + rv &= !npc_parse_shop(w1, w2, npcname, w4z); } else if (w2 == "script"_s) { if (w1 == "function"_s) { - npc_parse_function(w1, w2, w3, w4z, + rv &= !npc_parse_function(w1, w2, w3, w4z, w4x, fp, &lines); } else { NpcName npcname = stringish<NpcName>(w3); - npc_parse_script(w1, w2, npcname, w4z, + rv &= !npc_parse_script(w1, w2, npcname, w4z, w4x, fp, &lines); } } else if (w2 == "monster"_s) { MobName mobname = stringish<MobName>(w3); - npc_parse_mob(w1, w2, mobname, w4z); + rv &= !npc_parse_mob(w1, w2, mobname, w4z); } else if (w2 == "mapflag"_s) { - npc_parse_mapflag(w1, w2, w3, w4z); + rv &= !npc_parse_mapflag(w1, w2, w3, w4z); } else { diff --git a/src/map/npc-parse.hpp b/src/map/npc-parse.hpp index fe528a4..0d66aa7 100644 --- a/src/map/npc-parse.hpp +++ b/src/map/npc-parse.hpp @@ -22,6 +22,8 @@ #include "fwd.hpp" +#include "../compat/fwd.hpp" + #include "../generic/fwd.hpp" #include "../strings/fwd.hpp" @@ -38,7 +40,7 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4); * * \param message The message to speak. If message is nullptr, the NPC will not do anything at all. */ -dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, +dumb_ptr<npc_data> npc_spawn_text(Borrowed<map_local> m, int x, int y, Species class_, NpcName name, AString message); void npc_addsrcfile(AString name); diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 9a5c45a..471553b 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -203,18 +203,23 @@ int npc_delete(dumb_ptr<npc_data> nd) void npc_timer_event(NpcEvent eventname) { - struct event_data *ev = ev_db.search(eventname); + P<struct event_data> ev = TRY_UNWRAP(ev_db.search(eventname), + { + PRINTF("npc_event: event not found [%s]\n"_fmt, + eventname); + return; + }); + dumb_ptr<npc_data_script> nd; -// int xs,ys; - if ((ev == nullptr || (nd = ev->nd) == nullptr)) + if ((nd = ev->nd) == nullptr) { PRINTF("npc_event: event not found [%s]\n"_fmt, eventname); return; } - run_script(ScriptPointer(nd->scr.script.get(), ev->pos), nd->bl_id, nd->bl_id); + run_script(ScriptPointer(borrow(*nd->scr.script), ev->pos), nd->bl_id, nd->bl_id); } /*========================================== @@ -231,7 +236,7 @@ void npc_event_doall_sub(NpcEvent key, struct event_data *ev, if (name == p) { - run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id, + run_script_l(ScriptPointer(borrow(*ev->nd->scr.script), ev->pos), rid, ev->nd->bl_id, argv); (*c)++; } @@ -254,7 +259,7 @@ void npc_event_do_sub(NpcEvent key, struct event_data *ev, if (name == key) { - run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id, + run_script_l(ScriptPointer(borrow(*ev->nd->scr.script), ev->pos), rid, ev->nd->bl_id, argv); (*c)++; } @@ -348,7 +353,7 @@ void npc_timerevent(TimerData *, tick_t tick, BlockId id, interval_t data) id, next)); } - run_script(ScriptPointer(nd->scr.script.get(), te->pos), BlockId(), nd->bl_id); + run_script(ScriptPointer(borrow(*nd->scr.script), te->pos), BlockId(), nd->bl_id); } /// Start (or resume) counting ticks to the next npc_timerevent. @@ -460,7 +465,7 @@ void npc_settimerevent_tick(dumb_ptr<npc_data_script> nd, interval_t newtimer) int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, int mob_kill) { - struct event_data *ev = ev_db.search(eventname); + Option<P<struct event_data>> ev_ = ev_db.search(eventname); dumb_ptr<npc_data_script> nd; int xs, ys; @@ -469,24 +474,22 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, PRINTF("npc_event nullpo?\n"_fmt); } - if (ev == nullptr && eventname.label == stringish<ScriptLabel>("OnTouch"_s)) + if (ev_.is_none() && eventname.label == stringish<ScriptLabel>("OnTouch"_s)) return 1; - if (ev == nullptr || (nd = ev->nd) == nullptr) + P<struct event_data> ev = TRY_UNWRAP(ev_, { - if (mob_kill) - { - { - return 0; - } - } - else - { - if (battle_config.error_log) - PRINTF("npc_event: event not found [%s]\n"_fmt, - eventname); - return 0; - } + if (!mob_kill && battle_config.error_log) + PRINTF("npc_event: event not found [%s]\n"_fmt, + eventname); + return 0; + }); + if ((nd = ev->nd) == nullptr) + { + if (!mob_kill && battle_config.error_log) + PRINTF("npc_event: event not found [%s]\n"_fmt, + eventname); + return 0; } xs = nd->scr.xs; @@ -516,7 +519,7 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, sd->npc_id = nd->bl_id; sd->npc_pos = - run_script(ScriptPointer(nd->scr.script.get(), ev->pos), sd->bl_id, nd->bl_id); + run_script(ScriptPointer(borrow(*nd->scr.script), ev->pos), sd->bl_id, nd->bl_id); return 0; } @@ -529,7 +532,7 @@ void npc_command_sub(NpcEvent key, struct event_data *ev, NpcName npcname, XStri XString temp = key.label.xslice_t(9); if (command == temp) - run_script(ScriptPointer(ev->nd->scr.script.get(), ev->pos), BlockId(), ev->nd->bl_id); + run_script(ScriptPointer(borrow(*ev->nd->scr.script), ev->pos), BlockId(), ev->nd->bl_id); } } @@ -545,7 +548,7 @@ int npc_command(dumb_ptr<map_session_data>, NpcName npcname, XString command) * 接触型のNPC処理 *------------------------------------------ */ -int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) +int npc_touch_areanpc(dumb_ptr<map_session_data> sd, Borrowed<map_local> m, int x, int y) { int i, f = 1; int xs, ys; @@ -691,7 +694,7 @@ int npc_click(dumb_ptr<map_session_data> sd, BlockId id) npc_event_dequeue(sd); break; case NpcSubtype::SCRIPT: - sd->npc_pos = run_script(ScriptPointer(nd->is_script()->scr.script.get(), 0), sd->bl_id, id); + sd->npc_pos = run_script(ScriptPointer(borrow(*nd->is_script()->scr.script), 0), sd->bl_id, id); break; case NpcSubtype::MESSAGE: if (nd->is_message()->message) @@ -732,7 +735,7 @@ int npc_scriptcont(dumb_ptr<map_session_data> sd, BlockId id) return 0; } - sd->npc_pos = run_script(ScriptPointer(nd->is_script()->scr.script.get(), sd->npc_pos), sd->bl_id, id); + sd->npc_pos = run_script(ScriptPointer(borrow(*nd->is_script()->scr.script), sd->npc_pos), sd->bl_id, id); return 0; } @@ -843,8 +846,7 @@ int npc_buylist(dumb_ptr<map_session_data> sd, const uint16_t& item_l_count = item_list[i].count; const ItemNameId& item_l_id = item_list[i].name_id; - struct item_data *item_data; - if ((item_data = itemdb_exists(item_l_id)) != nullptr) + P<struct item_data> item_data = TRY_UNWRAP(itemdb_exists(item_l_id), continue); { int amount = item_l_count; Item item_tmp {}; diff --git a/src/map/npc.hpp b/src/map/npc.hpp index 3bd64af..67a62a9 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -52,7 +52,7 @@ int npc_event_dequeue(dumb_ptr<map_session_data> sd); int npc_event(dumb_ptr<map_session_data> sd, NpcEvent npcname, int); void npc_timer_event(NpcEvent eventname); // Added by RoVeRT int npc_command(dumb_ptr<map_session_data> sd, NpcName npcname, XString command); -int npc_touch_areanpc(dumb_ptr<map_session_data>, map_local *, int, int); +int npc_touch_areanpc(dumb_ptr<map_session_data>, Borrowed<map_local>, int, int); int npc_click(dumb_ptr<map_session_data>, BlockId); int npc_scriptcont(dumb_ptr<map_session_data>, BlockId); int npc_buysellsel(dumb_ptr<map_session_data>, BlockId, int); diff --git a/src/map/party.cpp b/src/map/party.cpp index 8713c60..45c406a 100644 --- a/src/map/party.cpp +++ b/src/map/party.cpp @@ -66,32 +66,30 @@ void do_init_party(void) } // 検索 -PartyPair party_search(PartyId party_id) +Option<PartyPair> party_search(PartyId party_id) { - PartyPair p; - p.party_most = party_db.search(party_id); - if (p) - p.party_id = party_id; - return p; + Option<P<PartyMost>> party_most_ = party_db.search(party_id); + return party_most_.map([party_id](P<PartyMost> party_most) + { + return PartyPair{party_id, party_most}; + }); } static -void party_searchname_sub(PartyPair p, PartyName str, PartyPair *dst) +void party_searchname_sub(PartyPair p, PartyName str, Borrowed<Option<PartyPair>> dst) { if (p->name == str) - *dst = p; + *dst = Some(p); } // パーティ名検索 -PartyPair party_searchname(PartyName str) +Option<PartyPair> party_searchname(PartyName str) { - PartyPair p; + Option<PartyPair> p = None; for (auto& pair : party_db) { - PartyPair tmp; - tmp.party_id = pair.first; - tmp.party_most = &pair.second; - party_searchname_sub(tmp, str, &p); + PartyPair tmp{pair.first, borrow(pair.second)}; + party_searchname_sub(tmp, str, borrow(p)); } return p; } @@ -129,15 +127,13 @@ void party_created(AccountId account_id, int fail, PartyId party_id, PartyName n { sd->status.party_id = party_id; - PartyPair p = party_search(party_id); - if (p) + if (party_search(party_id).is_some()) { PRINTF("party_created(): ID already exists!\n"_fmt); exit(1); } - p.party_most = party_db.init(party_id); - p.party_id = party_id; + Borrowed<PartyMost> p = party_db.init(party_id); p->name = name; /* The party was created successfully. */ @@ -158,8 +154,6 @@ void party_request_info(PartyId party_id) static int party_check_member(PartyPair p) { - nullpo_retz(p); - for (io::FD i : iter_fds()) { Session *s = get_session(i); @@ -215,24 +209,31 @@ int party_recv_noinfo(PartyId party_id) return 0; } -// 情報所得 -int party_recv_info(const PartyPair sp) +static +PartyPair handle_info(const PartyPair sp) { - int i; - - nullpo_retz(sp); - - PartyPair p = party_search(sp.party_id); - if (!p) + Option<PartyPair> p_ = party_search(sp.party_id); + if OPTION_IS_SOME(p, p_) { - p.party_most = party_db.init(sp.party_id); + *p.party_most = *sp.party_most; + return p; + } + { + PartyPair p{sp.party_id, party_db.init(sp.party_id)}; // 最初のロードなのでユーザーのチェックを行う *p.party_most = *sp.party_most; party_check_member(p); + return p; } - else - *p.party_most = *sp.party_most; +} + +// 情報所得 +int party_recv_info(const PartyPair sp) +{ + int i; + + PartyPair p = handle_info(sp); for (i = 0; i < MAX_PARTY; i++) { // sdの設定 @@ -261,13 +262,13 @@ int party_recv_info(const PartyPair sp) int party_invite(dumb_ptr<map_session_data> sd, AccountId account_id) { dumb_ptr<map_session_data> tsd = map_id2sd(account_to_block(account_id)); - PartyPair p = party_search(sd->status.party_id); + PartyPair p = TRY_UNWRAP(party_search(sd->status.party_id), return 0); int i; int full = 1; /* Indicates whether or not there's room for one more. */ nullpo_retz(sd); - if (!tsd || !p || !tsd->sess) + if (!tsd || !tsd->sess) return 0; if (!battle_config.invite_request_check) @@ -359,7 +360,6 @@ int party_reply_invite(dumb_ptr<map_session_data> sd, AccountId account_id, int int party_member_added(PartyId party_id, AccountId account_id, int flag) { dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(account_id)), sd2; - PartyPair p = party_search(party_id); if (sd == nullptr) { @@ -376,12 +376,12 @@ int party_member_added(PartyId party_id, AccountId account_id, int flag) sd->party_invite = PartyId(); sd->party_invite_account = AccountId(); - if (!p) + PartyPair p = TRY_UNWRAP(party_search(party_id), { PRINTF("party_member_added: party %d not found.\n"_fmt, party_id); intif_party_leave(party_id, account_id); return 0; - } + }); if (flag == 1) { // 失敗 @@ -408,13 +408,11 @@ int party_member_added(PartyId party_id, AccountId account_id, int flag) // パーティ除名要求 int party_removemember(dumb_ptr<map_session_data> sd, AccountId account_id) { - PartyPair p; int i; nullpo_retz(sd); - if (!(p = party_search(sd->status.party_id))) - return 0; + PartyPair p = TRY_UNWRAP(party_search(sd->status.party_id), return 0); for (i = 0; i < MAX_PARTY; i++) { // リーダーかどうかチェック @@ -439,13 +437,11 @@ int party_removemember(dumb_ptr<map_session_data> sd, AccountId account_id) // パーティ脱退要求 int party_leave(dumb_ptr<map_session_data> sd) { - PartyPair p; int i; nullpo_retz(sd); - if (!(p = party_search(sd->status.party_id))) - return 0; + PartyPair p = TRY_UNWRAP(party_search(sd->status.party_id), return 0); for (i = 0; i < MAX_PARTY; i++) { // 所属しているか @@ -462,8 +458,8 @@ int party_leave(dumb_ptr<map_session_data> sd) int party_member_leaved(PartyId party_id, AccountId account_id, CharName name) { dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(account_id)); - PartyPair p = party_search(party_id); - if (p) + Option<PartyPair> p_ = party_search(party_id); + if OPTION_IS_SOME(p, p_) { int i; for (i = 0; i < MAX_PARTY; i++) @@ -485,10 +481,8 @@ int party_member_leaved(PartyId party_id, AccountId account_id, CharName name) // パーティ解散通知 int party_broken(PartyId party_id) { - PartyPair p; int i; - if (!(p = party_search(party_id))) - return 0; + PartyPair p = TRY_UNWRAP(party_search(party_id), return 0); for (i = 0; i < MAX_PARTY; i++) { @@ -508,12 +502,11 @@ int party_broken(PartyId party_id) // パーティの設定変更要求 int party_changeoption(dumb_ptr<map_session_data> sd, int exp, int item) { - PartyPair p; - nullpo_retz(sd); - if (!sd->status.party_id - || !(p = party_search(sd->status.party_id))) + if (!sd->status.party_id) + return 0; + if (party_search(sd->status.party_id).is_none()) return 0; intif_party_changeoption(sd->status.party_id, sd->status_key.account_id, exp, item); @@ -524,10 +517,8 @@ int party_changeoption(dumb_ptr<map_session_data> sd, int exp, int item) int party_optionchanged(PartyId party_id, AccountId account_id, int exp, int item, int flag) { - PartyPair p; dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(account_id)); - if (!(p = party_search(party_id))) - return 0; + PartyPair p = TRY_UNWRAP(party_search(party_id), return 0); if (!(flag & 0x01)) p->exp = exp; @@ -541,10 +532,8 @@ int party_optionchanged(PartyId party_id, AccountId account_id, int exp, int ite void party_recv_movemap(PartyId party_id, AccountId account_id, MapName mapname, int online, int lv) { - PartyPair p; int i; - if (!(p = party_search(party_id))) - return; + PartyPair p = TRY_UNWRAP(party_search(party_id), return); for (i = 0; i < MAX_PARTY; i++) { PartyMember *m = &p->member[i]; @@ -584,8 +573,6 @@ void party_recv_movemap(PartyId party_id, AccountId account_id, MapName mapname, // パーティメンバの移動 int party_send_movemap(dumb_ptr<map_session_data> sd) { - PartyPair p; - nullpo_retz(sd); if (!sd->status.party_id) @@ -599,7 +586,7 @@ int party_send_movemap(dumb_ptr<map_session_data> sd) party_check_conflict(sd); // あるならパーティ情報送信 - if ((p = party_search(sd->status.party_id))) + PartyPair p = TRY_UNWRAP(party_search(sd->status.party_id), return 0); { party_check_member(p); // 所属を確認する if (sd->status.party_id == p.party_id) @@ -616,15 +603,13 @@ int party_send_movemap(dumb_ptr<map_session_data> sd) // パーティメンバのログアウト int party_send_logout(dumb_ptr<map_session_data> sd) { - PartyPair p; - nullpo_retz(sd); if (sd->status.party_id) intif_party_changemap(sd, 0); // sdが無効になるのでパーティ情報から削除 - if ((p = party_search(sd->status.party_id))) + PartyPair p = TRY_UNWRAP(party_search(sd->status.party_id), return 0); { int i; for (i = 0; i < MAX_PARTY; i++) @@ -646,9 +631,7 @@ void party_send_message(dumb_ptr<map_session_data> sd, XString mes) // パーティメッセージ受信 void party_recv_message(PartyId party_id, AccountId account_id, XString mes) { - PartyPair p; - if (!(p = party_search(party_id))) - return; + PartyPair p = TRY_UNWRAP(party_search(party_id), return); clif_party_message(p, account_id, mes); } @@ -667,8 +650,6 @@ void party_send_xyhp_timer_sub(PartyPair p) { int i; - nullpo_retv(p); - for (i = 0; i < MAX_PARTY; i++) { dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(p->member[i].sd); @@ -697,9 +678,7 @@ void party_send_xyhp_timer(TimerData *, tick_t) { for (auto& pair : party_db) { - PartyPair tmp; - tmp.party_id = pair.first; - tmp.party_most = &pair.second; + PartyPair tmp{pair.first, borrow(pair.second)}; party_send_xyhp_timer_sub(tmp); } } @@ -709,8 +688,6 @@ void party_send_xy_clear(PartyPair p) { int i; - nullpo_retv(p); - for (i = 0; i < MAX_PARTY; i++) { dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(p->member[i].sd); @@ -739,13 +716,11 @@ void party_send_hp_check(dumb_ptr<block_list> bl, PartyId party_id, int *flag) } // 経験値公平分配 -int party_exp_share(PartyPair p, map_local *mapid, int base_exp, int job_exp) +int party_exp_share(PartyPair p, Borrowed<map_local> mapid, int base_exp, int job_exp) { dumb_ptr<map_session_data> sd; int i, c; - nullpo_retz(p); - for (i = c = 0; i < MAX_PARTY; i++) { sd = dumb_ptr<map_session_data>(p->member[i].sd); @@ -770,7 +745,6 @@ int party_exp_share(PartyPair p, map_local *mapid, int base_exp, int job_exp) void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, dumb_ptr<map_session_data> sd, int type) { - PartyPair p; int i; int x0, y0, x1, y1; dumb_ptr<map_session_data> list[MAX_PARTY]; @@ -778,8 +752,7 @@ void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, nullpo_retv(sd); - if (!(p = party_search(sd->status.party_id))) - return; + PartyPair p = TRY_UNWRAP(party_search(sd->status.party_id), return); x0 = sd->bl_x - AREA_SIZE; y0 = sd->bl_y - AREA_SIZE; diff --git a/src/map/party.hpp b/src/map/party.hpp index 01a8125..466ee6a 100644 --- a/src/map/party.hpp +++ b/src/map/party.hpp @@ -24,6 +24,8 @@ #include <functional> +#include "../compat/fwd.hpp" + #include "../strings/fwd.hpp" #include "../generic/fwd.hpp" @@ -34,8 +36,8 @@ namespace tmwa { void do_init_party(void); -PartyPair party_search(PartyId party_id); -PartyPair party_searchname(PartyName str); +Option<PartyPair> party_search(PartyId party_id); +Option<PartyPair> party_searchname(PartyName str); int party_create(dumb_ptr<map_session_data> sd, PartyName name); void party_created(AccountId account_id, int fail, PartyId party_id, PartyName name); @@ -65,7 +67,7 @@ void party_recv_message(PartyId party_id, AccountId account_id, XString mes); void party_send_xy_clear(PartyPair p); void party_send_hp_check(dumb_ptr<block_list> bl, PartyId party_id, int *flag); -int party_exp_share(PartyPair p, map_local *map, int base_exp, int job_exp); +int party_exp_share(PartyPair p, Borrowed<map_local> map, int base_exp, int job_exp); void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, dumb_ptr<map_session_data> sd, int type); diff --git a/src/map/path.cpp b/src/map/path.cpp index 6950797..7f9a657 100644 --- a/src/map/path.cpp +++ b/src/map/path.cpp @@ -212,10 +212,8 @@ int add_path(int *heap, struct tmp_path *tp, int x, int y, int dist, *------------------------------------------ */ static -bool can_place(struct map_local *m, int x, int y) +bool can_place(Borrowed<struct map_local> m, int x, int y) { - nullpo_retz(m); - return !bool(read_gatp(m, x, y) & MapCell::UNWALKABLE); } @@ -224,10 +222,8 @@ bool can_place(struct map_local *m, int x, int y) *------------------------------------------ */ static -int can_move(struct map_local *m, int x0, int y0, int x1, int y1) +int can_move(Borrowed<struct map_local> m, int x0, int y0, int x1, int y1) { - nullpo_retz(m); - if (x0 - x1 < -1 || x0 - x1 > 1 || y0 - y1 < -1 || y0 - y1 > 1) return 0; if (x1 < 0 || y1 < 0 || x1 >= m->xs || y1 >= m->ys) @@ -247,7 +243,7 @@ int can_move(struct map_local *m, int x0, int y0, int x1, int y1) * path探索 (x0,y0)->(x1,y1) *------------------------------------------ */ -int path_search(struct walkpath_data *wpd, map_local *m, int x0, int y0, int x1, int y1, int flag) +int path_search(struct walkpath_data *wpd, Borrowed<map_local> m, int x0, int y0, int x1, int y1, int flag) { int heap[MAX_HEAP + 1]; int i, rp, x, y; @@ -256,7 +252,7 @@ int path_search(struct walkpath_data *wpd, map_local *m, int x0, int y0, int x1, nullpo_retz(wpd); assert (m->gat); - map_local *md = m; + P<map_local> md = m; if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || bool(read_gatp(md, x1, y1) & MapCell::UNWALKABLE)) return -1; diff --git a/src/map/path.hpp b/src/map/path.hpp index 3619e2e..a588f1b 100644 --- a/src/map/path.hpp +++ b/src/map/path.hpp @@ -22,8 +22,10 @@ #include "fwd.hpp" +#include "../compat/fwd.hpp" + namespace tmwa { -int path_search(struct walkpath_data *, map_local *, int, int, int, int, int); +int path_search(struct walkpath_data *, Borrowed<map_local>, int, int, int, int, int); } // namespace tmwa diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 3c0fce5..0497e5b 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -464,7 +464,7 @@ void pc_makesavestatus(dumb_ptr<map_session_data> sd) // セーブ禁止マップだったので指定位置に移動 if (sd->bl_m->flag.get(MapFlag::NOSAVE)) { - map_local *m = sd->bl_m; + P<map_local> m = sd->bl_m; if (m->save.map_ == "SavePoint"_s) sd->status.last_point = sd->status.save_point; else @@ -505,12 +505,7 @@ EPOS pc_equippoint(dumb_ptr<map_session_data> sd, IOff0 n) { nullpo_retr(EPOS::ZERO, sd); - if (!sd->inventory_data[n]) - return EPOS::ZERO; - - EPOS ep = sd->inventory_data[n]->equip; - - return ep; + return sd->inventory_data[n].pmd_pget(&item_data::equip).copy_or(EPOS::ZERO); } static @@ -521,7 +516,11 @@ int pc_setinventorydata(dumb_ptr<map_session_data> sd) for (IOff0 i : IOff0::iter()) { ItemNameId id = sd->status.inventory[i].nameid; - sd->inventory_data[i] = itemdb_search(id); + // If you think you understand this line, you're wrong. + // It does not do what you think it does. Rather, you need to + // understand it in the context in which it is used. Despite this, + // it is quite common for elements to be None. + sd->inventory_data[i] = Some(itemdb_search(id)); } return 0; } @@ -556,16 +555,16 @@ int pc_setequipindex(dumb_ptr<map_session_data> sd) sd->equip_index_maybe[j] = i; if (bool(sd->status.inventory[i].equip & EPOS::WEAPON)) { - if (sd->inventory_data[i]) - sd->weapontype1 = sd->inventory_data[i]->look; + if OPTION_IS_SOME(sdidi, sd->inventory_data[i]) + sd->weapontype1 = sdidi->look; else sd->weapontype1 = ItemLook::NONE; } if (bool(sd->status.inventory[i].equip & EPOS::SHIELD)) { - if (sd->inventory_data[i]) + if OPTION_IS_SOME(sdidi, sd->inventory_data[i]) { - if (sd->inventory_data[i]->type == ItemType::WEAPON) + if (sdidi->type == ItemType::WEAPON) { if (sd->status.inventory[i].equip == EPOS::SHIELD) assert(0 && "unreachable - offhand weapons are not supported"); @@ -582,21 +581,18 @@ int pc_setequipindex(dumb_ptr<map_session_data> sd) static int pc_isequip(dumb_ptr<map_session_data> sd, IOff0 n) { - struct item_data *item; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; //転生や養子の場合の元の職業を算出する nullpo_retz(sd); - item = sd->inventory_data[n]; sc_data = battle_get_sc_data(sd); GmLevel gm_all_equipment = GmLevel::from(static_cast<uint32_t>(battle_config.gm_all_equipment)); if (gm_all_equipment && pc_isGM(sd).satisfies(gm_all_equipment)) return 1; - if (item == nullptr) - return 0; + P<struct item_data> item = TRY_UNWRAP(sd->inventory_data[n], return 0); if (item->sex != SEX::NEUTRAL && sd->status.sex != item->sex) return 0; if (item->elv > 0 && sd->status.base_level < item->elv) @@ -615,7 +611,6 @@ int pc_authok(AccountId id, int login_id2, TimeT connect_until_time, { dumb_ptr<map_session_data> sd = nullptr; - PartyPair p; tick_t tick = gettick(); sd = map_id2sd(account_to_block(id)); @@ -721,7 +716,7 @@ int pc_authok(AccountId id, int login_id2, TimeT connect_until_time, // パーティ、ギルドデータの要求 if (sd->status.party_id - && !(p = party_search(sd->status.party_id))) + && party_search(sd->status.party_id).is_none()) party_request_info(sd->status.party_id); // pvpの設定 @@ -938,11 +933,11 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->weight = 0; for (IOff0 i : IOff0::iter()) { - if (!sd->status.inventory[i].nameid - || sd->inventory_data[i] == nullptr) + if (!sd->status.inventory[i].nameid) continue; + P<struct item_data> sdidi = TRY_UNWRAP(sd->inventory_data[i], continue); sd->weight += - sd->inventory_data[i]->weight * + sdidi->weight * sd->status.inventory[i].amount; } // used to fill cart @@ -1012,10 +1007,10 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) || sd->equip_index_maybe[EQUIP::LEGS] == index)) continue; - if (sd->inventory_data[index]) + if OPTION_IS_SOME(sdidi, sd->inventory_data[index]) { sd->spellpower_bonus_target += - sd->inventory_data[index]->magic_bonus; + sdidi->magic_bonus; // used to apply cards } @@ -1047,10 +1042,10 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) && (sd->equip_index_maybe[EQUIP::TORSO] == index || sd->equip_index_maybe[EQUIP::LEGS] == index)) continue; - if (sd->inventory_data[index]) + if OPTION_IS_SOME(sdidi, sd->inventory_data[index]) { - sd->def += sd->inventory_data[index]->def; - if (sd->inventory_data[index]->type == ItemType::WEAPON) + sd->def += sdidi->def; + if (sdidi->type == ItemType::WEAPON) { if (i == EQUIP::SHIELD && sd->status.inventory[index].equip == EPOS::SHIELD) @@ -1063,25 +1058,25 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) argrec_t arg[2] = { {"@slotId"_s, static_cast<int>(i)}, - {"@itemId"_s, unwrap<ItemNameId>(sd->inventory_data[index]->nameid)}, + {"@itemId"_s, unwrap<ItemNameId>(sdidi->nameid)}, }; - sd->watk += sd->inventory_data[index]->atk; + sd->watk += sdidi->atk; - sd->attackrange += sd->inventory_data[index]->range; - run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), + sd->attackrange += sdidi->range; + run_script_l(ScriptPointer(borrow(*sdidi->equip_script), 0), sd->bl_id, BlockId(), arg); } } - else if (sd->inventory_data[index]->type == ItemType::ARMOR) + else if (sdidi->type == ItemType::ARMOR) { argrec_t arg[2] = { {"@slotId"_s, static_cast<int>(i)}, - {"@itemId"_s, unwrap<ItemNameId>(sd->inventory_data[index]->nameid)}, + {"@itemId"_s, unwrap<ItemNameId>(sdidi->nameid)}, }; - sd->watk += sd->inventory_data[index]->atk; - run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), + sd->watk += sdidi->atk; + run_script_l(ScriptPointer(borrow(*sdidi->equip_script), 0), sd->bl_id, BlockId(), arg); } @@ -1098,19 +1093,19 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (aidx.ok()) { IOff0 index = aidx; - if (sd->inventory_data[index]) + if OPTION_IS_SOME(sdidi, sd->inventory_data[index]) { //まだ属性が入っていない argrec_t arg[2] = { {"@slotId"_s, static_cast<int>(EQUIP::ARROW)}, - {"@itemId"_s, unwrap<ItemNameId>(sd->inventory_data[index]->nameid)}, + {"@itemId"_s, unwrap<ItemNameId>(sdidi->nameid)}, }; sd->state.lr_flag_is_arrow_2 = 1; - run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), + run_script_l(ScriptPointer(borrow(*sdidi->equip_script), 0), sd->bl_id, BlockId(), arg); sd->state.lr_flag_is_arrow_2 = 0; - sd->arrow_atk += sd->inventory_data[index]->atk; + sd->arrow_atk += sdidi->atk; } } sd->def += (refinedef + 50) / 100; @@ -1877,7 +1872,6 @@ int pc_remove_items(dumb_ptr<map_session_data> player, ItemNameId item_id, int c PickupFail pc_additem(dumb_ptr<map_session_data> sd, Item *item_data, int amount) { - struct item_data *data; int w; MAP_LOG_PC(sd, "PICKUP %d %d"_fmt, item_data->nameid, amount); @@ -1887,7 +1881,7 @@ PickupFail pc_additem(dumb_ptr<map_session_data> sd, Item *item_data, if (!item_data->nameid || amount <= 0) return PickupFail::BAD_ITEM; - data = itemdb_search(item_data->nameid); + P<struct item_data> data = itemdb_search(item_data->nameid); if ((w = data->weight * amount) + sd->weight > sd->max_weight) return PickupFail::TOO_HEAVY; @@ -1919,7 +1913,7 @@ PickupFail pc_additem(dumb_ptr<map_session_data> sd, Item *item_data, sd->status.inventory[i].equip = EPOS::ZERO; sd->status.inventory[i].amount = amount; - sd->inventory_data[i] = data; + sd->inventory_data[i] = Some(data); clif_additem(sd, i, amount, PickupFail::OKAY); } else @@ -1943,18 +1937,18 @@ int pc_delitem(dumb_ptr<map_session_data> sd, IOff0 n, int amount, int type) trade_tradecancel(sd); if (!sd->status.inventory[n].nameid || amount <= 0 - || sd->status.inventory[n].amount < amount - || sd->inventory_data[n] == nullptr) + || sd->status.inventory[n].amount < amount) return 1; + P<struct item_data> sdidn = TRY_UNWRAP(sd->inventory_data[n], return 1); sd->status.inventory[n].amount -= amount; - sd->weight -= sd->inventory_data[n]->weight * amount; + sd->weight -= sdidn->weight * amount; if (sd->status.inventory[n].amount <= 0) { if (bool(sd->status.inventory[n].equip)) pc_unequipitem(sd, n, CalcStatus::NOW); sd->status.inventory[n] = Item{}; - sd->inventory_data[n] = nullptr; + sd->inventory_data[n] = None; } if (!(type & 1)) clif_delitem(sd, n, amount); @@ -2003,8 +1997,6 @@ int pc_dropitem(dumb_ptr<map_session_data> sd, IOff0 n, int amount) static int can_pick_item_up_from(dumb_ptr<map_session_data> self, BlockId other_id) { - PartyPair p = party_search(self->status.party_id); - /* From ourselves or from no-one? */ if (!self || self->bl_id == other_id || !other_id) return 1; @@ -2020,9 +2012,10 @@ int can_pick_item_up_from(dumb_ptr<map_session_data> self, BlockId other_id) return 1; /* From a party member? */ + Option<PartyPair> p = party_search(self->status.party_id); if (self->status.party_id && self->status.party_id == other->status.party_id - && p && p->item != 0) + && p.pmd_pget(&PartyMost::item).copy_or(0) != 0) return 1; /* From someone who is far away? */ @@ -2098,16 +2091,13 @@ int pc_takeitem(dumb_ptr<map_session_data> sd, dumb_ptr<flooritem_data> fitem) static int pc_isUseitem(dumb_ptr<map_session_data> sd, IOff0 n) { - struct item_data *item; ItemNameId nameid; nullpo_retz(sd); - item = sd->inventory_data[n]; + P<struct item_data> item = TRY_UNWRAP(sd->inventory_data[n], return 0); nameid = sd->status.inventory[n].nameid; - if (item == nullptr) - return 0; if (itemdb_type(nameid) != ItemType::USE) return 0; @@ -2129,7 +2119,9 @@ int pc_useitem(dumb_ptr<map_session_data> sd, IOff0 n) nullpo_retr(1, sd); - if (n.ok() && sd->inventory_data[n]) + if (!n.ok()) + return 0; + if OPTION_IS_SOME(sdidn, sd->inventory_data[n]) { amount = sd->status.inventory[n].amount; if (!sd->status.inventory[n].nameid @@ -2140,7 +2132,7 @@ int pc_useitem(dumb_ptr<map_session_data> sd, IOff0 n) return 1; } - const ScriptBuffer *script = sd->inventory_data[n]->use_script.get(); + P<const ScriptBuffer> script = borrow(*sdidn->use_script); clif_useitemack(sd, n, amount - 1, 1); pc_delitem(sd, n, 1, 1); @@ -2183,18 +2175,19 @@ int pc_setpos(dumb_ptr<map_session_data> sd, mapname_ = mapname_org; - map_local *m = map_mapname2mapid(mapname_); - if (!m) + Option<P<map_local>> m_ = map_mapname2mapid(mapname_); + if (m_.is_none()) { if (sd->mapname_) { IP4Address ip; int port; - if (map_mapname2ipport(mapname_, &ip, &port) == 0) + if (map_mapname2ipport(mapname_, borrow(ip), borrow(port)) == 0) { skill_stop_dancing(sd, 1); clif_clearchar(sd, clrtype); map_delblock(sd); + // *cringe* sd->mapname_ = mapname_; sd->bl_x = x; sd->bl_y = y; @@ -2216,6 +2209,7 @@ int pc_setpos(dumb_ptr<map_session_data> sd, #endif return 1; } + P<map_local> m = TRY_UNWRAP(m_, abort()); if (x < 0 || x >= m->xs || y < 0 || y >= m->ys) x = y = 0; @@ -2268,7 +2262,7 @@ int pc_randomwarp(dumb_ptr<map_session_data> sd, BeingRemoveWhy type) nullpo_retz(sd); - map_local *m = sd->bl_m; + P<map_local> m = sd->bl_m; if (sd->bl_m->flag.get(MapFlag::NOTELEPORT)) // テレポート禁止 return 0; @@ -2410,8 +2404,8 @@ void pc_walk(TimerData *, tick_t tick, BlockId id, unsigned char data) if (sd->status.party_id) { // パーティのHP情報通知検査 - PartyPair p = party_search(sd->status.party_id); - if (p) + Option<PartyPair> p = party_search(sd->status.party_id); + if (p.is_some()) { int p_flag = 0; map_foreachinmovearea(std::bind(party_send_hp_check, ph::_1, sd->status.party_id, &p_flag), @@ -2584,8 +2578,8 @@ int pc_movepos(dumb_ptr<map_session_data> sd, int dst_x, int dst_y) if (sd->status.party_id) { // パーティのHP情報通知検査 - PartyPair p = party_search(sd->status.party_id); - if (p) + Option<PartyPair> p = party_search(sd->status.party_id); + if (p.is_some()) { int flag = 0; map_foreachinmovearea(std::bind(party_send_hp_check, ph::_1, sd->status.party_id, &flag), @@ -3341,8 +3335,8 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, if (sd->status.party_id) { // on-the-fly party hp updates [Valaris] - PartyPair p = party_search(sd->status.party_id); - if (p) + Option<PartyPair> p_ = party_search(sd->status.party_id); + if OPTION_IS_SOME(p, p_) clif_party_hp(p, sd); } // end addition [Valaris] @@ -3709,8 +3703,8 @@ int pc_heal(dumb_ptr<map_session_data> sd, int hp, int sp) if (sd->status.party_id) { // on-the-fly party hp updates [Valaris] - PartyPair p = party_search(sd->status.party_id); - if (p) + Option<PartyPair> p_ = party_search(sd->status.party_id); + if OPTION_IS_SOME(p, p_) clif_party_hp(p, sd); } // end addition [Valaris] @@ -3994,11 +3988,8 @@ ZString pc_readregstr(dumb_ptr<map_session_data> sd, SIR reg) { nullpo_retr(ZString(), sd); - RString *s = sd->regstrm.search(reg); - if (s) - return *s; - - return ZString(); + Option<P<RString>> s = sd->regstrm.search(reg); + return s.map([](P<RString> s_) -> ZString { return *s_; }).copy_or(""_s); } /*========================================== @@ -4306,7 +4297,6 @@ int pc_signal_advanced_equipment_change(dumb_ptr<map_session_data> sd, IOff0 n) int pc_equipitem(dumb_ptr<map_session_data> sd, IOff0 n, EPOS) { ItemNameId nameid; - struct item_data *id; //ソス]ソスソスソスソスソス{ソスqソスフ場合ソスフ鯉ソスソスフ職ソスニゑソスソスZソスoソスソスソスソス nullpo_retz(sd); @@ -4318,9 +4308,8 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, IOff0 n, EPOS) } nameid = sd->status.inventory[n].nameid; - id = sd->inventory_data[n]; - if (!id) // can't actually happen - the only caller checks this. - return 0; + // can't actually happen - the only caller checks this. + P<struct item_data> id = TRY_UNWRAP(sd->inventory_data[n], return 0); EPOS pos = pc_equippoint(sd, n); if (battle_config.battle_log) @@ -4381,16 +4370,16 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, IOff0 n, EPOS) ItemNameId view_i; ItemLook view_l = ItemLook::NONE; // TODO: This is ugly. - if (sd->inventory_data[n]) + if OPTION_IS_SOME(sdidn, sd->inventory_data[n]) { - bool look_not_weapon = sd->inventory_data[n]->look == ItemLook::NONE; + bool look_not_weapon = sdidn->look == ItemLook::NONE; bool equip_is_weapon = bool(sd->status.inventory[n].equip & EPOS::WEAPON); assert (look_not_weapon != equip_is_weapon); if (look_not_weapon) - view_i = sd->inventory_data[n]->nameid; + view_i = sdidn->nameid; else - view_l = sd->inventory_data[n]->look; + view_l = sdidn->look; } if (bool(sd->status.inventory[n].equip & EPOS::WEAPON)) @@ -4401,15 +4390,15 @@ int pc_equipitem(dumb_ptr<map_session_data> sd, IOff0 n, EPOS) } if (bool(sd->status.inventory[n].equip & EPOS::SHIELD)) { - if (sd->inventory_data[n]) + if OPTION_IS_SOME(sdidn, sd->inventory_data[n]) { - if (sd->inventory_data[n]->type == ItemType::WEAPON) + if (sdidn->type == ItemType::WEAPON) { sd->status.shield = ItemNameId(); if (sd->status.inventory[n].equip == EPOS::SHIELD) assert(0 && "unreachable - offhand weapons are not supported"); } - else if (sd->inventory_data[n]->type == ItemType::ARMOR) + else if (sdidn->type == ItemType::ARMOR) { sd->status.shield = view_i; } @@ -4632,8 +4621,7 @@ void pc_calc_pvprank_sub(dumb_ptr<block_list> bl, dumb_ptr<map_session_data> sd2 int pc_calc_pvprank(dumb_ptr<map_session_data> sd) { nullpo_retz(sd); - map_local *m = sd->bl_m; - nullpo_retz(m); + P<map_local> m = sd->bl_m; if (!(m->flag.get(MapFlag::PVP))) return 0; diff --git a/src/map/script-call-internal.hpp b/src/map/script-call-internal.hpp index 72e1e46..e10a859 100644 --- a/src/map/script-call-internal.hpp +++ b/src/map/script-call-internal.hpp @@ -79,14 +79,14 @@ RString conv_str(ScriptState *st, struct script_data *data); __attribute__((warn_unused_result)) int conv_num(ScriptState *st, struct script_data *data); __attribute__((warn_unused_result)) -const ScriptBuffer *conv_script(ScriptState *st, struct script_data *data); +Borrowed<const ScriptBuffer> conv_script(ScriptState *st, struct script_data *data); template<class T> void push_int(struct script_stack *stack, int val); template<class T> void push_reg(struct script_stack *stack, SIR reg); template<class T> -void push_script(struct script_stack *stack, const ScriptBuffer *code); +void push_script(struct script_stack *stack, Borrowed<const ScriptBuffer> code); template<class T> void push_str(struct script_stack *stack, RString str); diff --git a/src/map/script-call-internal.tcc b/src/map/script-call-internal.tcc index cc5c2a4..d77d491 100644 --- a/src/map/script-call-internal.tcc +++ b/src/map/script-call-internal.tcc @@ -57,7 +57,7 @@ void push_reg(struct script_stack *stack, SIR reg) } template<class T> -void push_script(struct script_stack *stack, const ScriptBuffer *code) +void push_script(struct script_stack *stack, Borrowed<const ScriptBuffer> code) { static_assert(first_type_is_any<T, ScriptDataRetInfo>(), "not scriptbuf type"); diff --git a/src/map/script-call.cpp b/src/map/script-call.cpp index f889e4b..6d3e6f2 100644 --- a/src/map/script-call.cpp +++ b/src/map/script-call.cpp @@ -106,8 +106,8 @@ void get_val(dumb_ptr<map_session_data> sd, struct script_data *data) } else if (prefix == '$') { - RString *s = mapregstr_db.search(u.reg); - if (s) + Option<P<RString>> s_ = mapregstr_db.search(u.reg); + if OPTION_IS_SOME(s, s_) str = *s; } else @@ -289,7 +289,7 @@ int conv_num(ScriptState *st, struct script_data *data) return rv; } -const ScriptBuffer *conv_script(ScriptState *st, struct script_data *data) +Borrowed<const ScriptBuffer> conv_script(ScriptState *st, struct script_data *data) { get_val(st, data); return data->get_if<ScriptDataRetInfo>()->script; @@ -603,7 +603,7 @@ void run_func(ScriptState *st) } CASE (const ScriptDataRetInfo&, u) { - PRINTF(" retinfo(%p)"_fmt, static_cast<const void *>(u.script)); + PRINTF(" retinfo(%p)"_fmt, static_cast<const void *>(&*u.script)); } CASE (const ScriptDataParam&, u) { @@ -655,7 +655,7 @@ void run_func(ScriptState *st) return; } assert (olddefsp == st->defsp); // pretty sure it hasn't changed yet - st->scriptp.code = conv_script(st, &st->stack->stack_datav[olddefsp - 1]); // スクリプトを復元 + st->scriptp.code = Some(conv_script(st, &st->stack->stack_datav[olddefsp - 1])); // スクリプトを復元 st->scriptp.pos = conv_num(st, &st->stack->stack_datav[olddefsp - 2]); // スクリプト位置の復元 st->defsp = conv_num(st, &st->stack->stack_datav[olddefsp - 3]); // 基準スタックポインタを復元 // Number of arguments. @@ -669,11 +669,11 @@ void run_func(ScriptState *st) } // pretend it's external so this can be called in the debugger -void dump_script(const ScriptBuffer *script); -void dump_script(const ScriptBuffer *script) +void dump_script(Borrowed<const ScriptBuffer> script); +void dump_script(Borrowed<const ScriptBuffer> script) { ScriptPointer scriptp(script, 0); - while (scriptp.pos < reinterpret_cast<const std::vector<ByteCode> *>(script)->size()) + while (scriptp.pos < reinterpret_cast<const std::vector<ByteCode> *>(&*script)->size()) { PRINTF("%6zu: "_fmt, scriptp.pos); switch (ByteCode c = get_com(&scriptp)) @@ -803,7 +803,7 @@ void dump_script(const ScriptBuffer *script) *------------------------------------------ */ static -void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) +void run_script_main(ScriptState *st, Borrowed<const ScriptBuffer> rootscript) { int cmdcount = script_config.check_cmdcount; int gotocount = script_config.check_gotocount; @@ -936,7 +936,7 @@ void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) case ScriptEndState::END: { dumb_ptr<map_session_data> sd = map_id2sd(st->rid); - st->scriptp.code = nullptr; + st->scriptp.code = None; st->scriptp.pos = -1; if (sd && sd->npc_id == st->oid) npc_event_dequeue(sd); @@ -956,7 +956,7 @@ void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) sd->npc_stackbuf = stack->stack_datav; sd->npc_script = st->scriptp.code; // sd->npc_pos is set later ... ??? - sd->npc_scriptroot = rootscript; + sd->npc_scriptroot = Some(rootscript); } } } @@ -976,12 +976,12 @@ int run_script_l(ScriptPointer sp, BlockId rid, BlockId oid, struct script_stack stack; ScriptState st; dumb_ptr<map_session_data> sd = map_id2sd(rid); - const ScriptBuffer *rootscript = sp.code; + P<const ScriptBuffer> rootscript = TRY_UNWRAP(sp.code, return -1); int i; - if (sp.code == nullptr || sp.pos >> 24) + if (sp.pos >> 24) return -1; - if (sd && !sd->npc_stackbuf.empty() && sd->npc_scriptroot == rootscript) + if (sd && !sd->npc_stackbuf.empty() && sd->npc_scriptroot == Some(rootscript)) { // 前回のスタックを復帰 sp.code = sd->npc_script; diff --git a/src/map/script-call.hpp b/src/map/script-call.hpp index da9d03f..89cadb8 100644 --- a/src/map/script-call.hpp +++ b/src/map/script-call.hpp @@ -24,6 +24,8 @@ #include "fwd.hpp" +#include "../compat/borrow.hpp" + #include "../range/fwd.hpp" #include "../generic/fwd.hpp" @@ -38,16 +40,15 @@ enum class ByteCode : uint8_t; // implemented in script-parse.cpp because reasons struct ScriptPointer { - const ScriptBuffer *code; + Option<Borrowed<const ScriptBuffer>> code; size_t pos; ScriptPointer() - : code() + : code(None) , pos() {} - - ScriptPointer(const ScriptBuffer *c, size_t p) - : code(c) + ScriptPointer(Borrowed<const ScriptBuffer> c, size_t p) + : code(Some(c)) , pos(p) {} diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index 5caf060..4c6d7b5 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -117,9 +117,9 @@ static void builtin_callfunc(ScriptState *st) { RString str = conv_str(st, &AARG(0)); - const ScriptBuffer *scr = userfunc_db.get(str); + Option<P<const ScriptBuffer>> scr_ = userfunc_db.get(str); - if (scr) + if OPTION_IS_SOME(scr, scr_) { int j = 0; assert (st->start + 3 == st->end); @@ -131,7 +131,7 @@ void builtin_callfunc(ScriptState *st) push_int<ScriptDataInt>(st->stack, j); // 引数の数をプッシュ push_int<ScriptDataInt>(st->stack, st->defsp); // 現在の基準スタックポインタをプッシュ push_int<ScriptDataInt>(st->stack, st->scriptp.pos); // 現在のスクリプト位置をプッシュ - push_script<ScriptDataRetInfo>(st->stack, st->scriptp.code); // 現在のスクリプトをプッシュ + push_script<ScriptDataRetInfo>(st->stack, TRY_UNWRAP(st->scriptp.code, abort())); // 現在のスクリプトをプッシュ st->scriptp = ScriptPointer(scr, 0); st->defsp = st->start + 4 + j; @@ -162,7 +162,7 @@ void builtin_callsub(ScriptState *st) push_int<ScriptDataInt>(st->stack, j); // 引数の数をプッシュ push_int<ScriptDataInt>(st->stack, st->defsp); // 現在の基準スタックポインタをプッシュ push_int<ScriptDataInt>(st->stack, st->scriptp.pos); // 現在のスクリプト位置をプッシュ - push_script<ScriptDataRetInfo>(st->stack, st->scriptp.code); // 現在のスクリプトをプッシュ + push_script<ScriptDataRetInfo>(st->stack, TRY_UNWRAP(st->scriptp.code, abort())); // 現在のスクリプトをプッシュ st->scriptp.pos = pos_; st->defsp = st->start + 4 + j; @@ -373,9 +373,7 @@ void builtin_areawarp(ScriptState *st) x = conv_num(st, &AARG(6)); y = conv_num(st, &AARG(7)); - map_local *m = map_mapname2mapid(mapname); - if (m == nullptr) - return; + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return); map_foreachinarea(std::bind(builtin_areawarp_sub, ph::_1, str, x, y), m, @@ -718,8 +716,8 @@ void builtin_countitem(ScriptState *st) if (data->is<ScriptDataStr>()) { ZString name = ZString(conv_str(st, data)); - struct item_data *item_data = itemdb_searchname(name); - if (item_data != nullptr) + Option<P<struct item_data>> item_data_ = itemdb_searchname(name); + if OPTION_IS_SOME(item_data, item_data_) nameid = item_data->nameid; } else @@ -761,8 +759,8 @@ void builtin_checkweight(ScriptState *st) if (data->is<ScriptDataStr>()) { ZString name = ZString(conv_str(st, data)); - struct item_data *item_data = itemdb_searchname(name); - if (item_data) + Option<P<struct item_data>> item_data_ = itemdb_searchname(name); + if OPTION_IS_SOME(item_data, item_data_) nameid = item_data->nameid; } else @@ -806,8 +804,8 @@ void builtin_getitem(ScriptState *st) if (data->is<ScriptDataStr>()) { ZString name = ZString(conv_str(st, data)); - struct item_data *item_data = itemdb_searchname(name); - if (item_data != nullptr) + Option<P<struct item_data>> item_data_ = itemdb_searchname(name); + if OPTION_IS_SOME(item_data, item_data_) nameid = item_data->nameid; } else @@ -859,8 +857,8 @@ void builtin_makeitem(ScriptState *st) if (data->is<ScriptDataStr>()) { ZString name = ZString(conv_str(st, data)); - struct item_data *item_data = itemdb_searchname(name); - if (item_data) + Option<P<struct item_data>> item_data_ = itemdb_searchname(name); + if OPTION_IS_SOME(item_data, item_data_) nameid = item_data->nameid; } else @@ -871,11 +869,9 @@ void builtin_makeitem(ScriptState *st) x = conv_num(st, &AARG(3)); y = conv_num(st, &AARG(4)); - map_local *m; - if (sd && mapname == MOB_THIS_MAP) - m = sd->bl_m; - else - m = map_mapname2mapid(mapname); + P<map_local> m = ((sd && mapname == MOB_THIS_MAP) + ? sd->bl_m + : TRY_UNWRAP(map_mapname2mapid(mapname), return)); if (nameid) { @@ -905,8 +901,8 @@ void builtin_delitem(ScriptState *st) if (data->is<ScriptDataStr>()) { ZString name = ZString(conv_str(st, data)); - struct item_data *item_data = itemdb_searchname(name); - if (item_data) + Option<P<struct item_data>> item_data_ = itemdb_searchname(name); + if OPTION_IS_SOME(item_data, item_data_) nameid = item_data->nameid; } else @@ -1004,12 +1000,9 @@ void builtin_getcharid(ScriptState *st) static RString builtin_getpartyname_sub(PartyId party_id) { - PartyPair p = party_search(party_id); + Option<PartyPair> p = party_search(party_id); - if (p) - return p->name; - - return RString(); + return p.pmd_pget(&PartyMost::name).copy_or(PartyName()); } /*========================================== @@ -1072,7 +1065,6 @@ void builtin_getequipid(ScriptState *st) { int num; dumb_ptr<map_session_data> sd; - struct item_data *item; sd = script_rid2sd(st); if (sd == nullptr) @@ -1084,8 +1076,8 @@ void builtin_getequipid(ScriptState *st) IOff0 i = pc_checkequip(sd, equip[num - 1]); if (i.ok()) { - item = sd->inventory_data[i]; - if (item) + Option<P<struct item_data>> item_ = sd->inventory_data[i]; + if OPTION_IS_SOME(item, item_) push_int<ScriptDataInt>(st->stack, unwrap<ItemNameId>(item->nameid)); else push_int<ScriptDataInt>(st->stack, 0); @@ -1105,7 +1097,6 @@ void builtin_getequipname(ScriptState *st) { int num; dumb_ptr<map_session_data> sd; - struct item_data *item; AString buf; @@ -1114,8 +1105,8 @@ void builtin_getequipname(ScriptState *st) IOff0 i = pc_checkequip(sd, equip[num - 1]); if (i.ok()) { - item = sd->inventory_data[i]; - if (item) + Option<P<struct item_data>> item_ = sd->inventory_data[i]; + if OPTION_IS_SOME(item, item_) buf = STRPRINTF("%s-[%s]"_fmt, pos_str[num - 1], item->jname); else buf = STRPRINTF("%s-[%s]"_fmt, pos_str[num - 1], pos_str[10]); @@ -1494,9 +1485,7 @@ void builtin_killmonster(ScriptState *st) if (event_ != "All"_s) extract(event_, &event); - map_local *m = map_mapname2mapid(mapname); - if (m == nullptr) - return; + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return); map_foreachinarea(std::bind(builtin_killmonster_sub, ph::_1, event), m, 0, 0, @@ -1515,9 +1504,7 @@ void builtin_killmonsterall(ScriptState *st) { MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); - map_local *m = map_mapname2mapid(mapname); - if (m == nullptr) - return; + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return); map_foreachinarea(builtin_killmonsterall_sub, m, 0, 0, @@ -1701,9 +1688,7 @@ void builtin_mapannounce(ScriptState *st) ZString str = ZString(conv_str(st, &AARG(1))); flag = conv_num(st, &AARG(2)); - map_local *m = map_mapname2mapid(mapname); - if (m == nullptr) - return; + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return); map_foreachinarea(std::bind(builtin_mapannounce_sub, ph::_1, str, flag & 0x10), m, 0, 0, @@ -1741,12 +1726,11 @@ static void builtin_getmapusers(ScriptState *st) { MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); - map_local *m = map_mapname2mapid(str); - if (m == nullptr) + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(str), { push_int<ScriptDataInt>(st->stack, -1); return; - } + }); push_int<ScriptDataInt>(st->stack, m->users); } @@ -1786,12 +1770,11 @@ void builtin_getareausers(ScriptState *st) { living = conv_num(st, &AARG(5)); } - map_local *m = map_mapname2mapid(str); - if (m == nullptr) + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(str), { push_int<ScriptDataInt>(st->stack, -1); return; - } + }); map_foreachinarea(std::bind(living ? builtin_getareausers_living_sub: builtin_getareausers_sub, ph::_1, &users), m, x0, y0, @@ -1845,8 +1828,8 @@ void builtin_getareadropitem(ScriptState *st) if (data->is<ScriptDataStr>()) { ZString name = ZString(conv_str(st, data)); - struct item_data *item_data = itemdb_searchname(name); - if (item_data) + Option<P<struct item_data>> item_data_ = itemdb_searchname(name); + if OPTION_IS_SOME(item_data, item_data_) item = item_data->nameid; } else @@ -1855,12 +1838,11 @@ void builtin_getareadropitem(ScriptState *st) if (HARG(6)) delitems = conv_num(st, &AARG(6)); - map_local *m = map_mapname2mapid(str); - if (m == nullptr) + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(str), { push_int<ScriptDataInt>(st->stack, -1); return; - } + }); if (delitems) map_foreachinarea(std::bind(builtin_getareadropitem_sub_anddelete, ph::_1, item, &amount), m, @@ -2027,8 +2009,8 @@ void builtin_setmapflag(ScriptState *st) MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); int i = conv_num(st, &AARG(1)); MapFlag mf = map_flag_from_int(i); - map_local *m = map_mapname2mapid(str); - if (m != nullptr) + Option<P<map_local>> m_ = map_mapname2mapid(str); + if OPTION_IS_SOME(m, m_) { m->flag.set(mf, 1); } @@ -2040,8 +2022,8 @@ void builtin_removemapflag(ScriptState *st) MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); int i = conv_num(st, &AARG(1)); MapFlag mf = map_flag_from_int(i); - map_local *m = map_mapname2mapid(str); - if (m != nullptr) + Option<P<map_local>> m_ = map_mapname2mapid(str); + if OPTION_IS_SOME(m, m_) { m->flag.set(mf, 0); } @@ -2055,8 +2037,8 @@ void builtin_getmapflag(ScriptState *st) MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); int i = conv_num(st, &AARG(1)); MapFlag mf = map_flag_from_int(i); - map_local *m = map_mapname2mapid(str); - if (m != nullptr) + Option<P<map_local>> m_ = map_mapname2mapid(str); + if OPTION_IS_SOME(m, m_) { r = m->flag.get(mf); } @@ -2068,8 +2050,8 @@ static void builtin_pvpon(ScriptState *st) { MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); - map_local *m = map_mapname2mapid(str); - if (m != nullptr && !m->flag.get(MapFlag::PVP) && !m->flag.get(MapFlag::NOPVP)) + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(str), return); + if (!m->flag.get(MapFlag::PVP) && !m->flag.get(MapFlag::NOPVP)) { m->flag.set(MapFlag::PVP, 1); @@ -2095,15 +2077,14 @@ void builtin_pvpon(ScriptState *st) } } } - } static void builtin_pvpoff(ScriptState *st) { MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); - map_local *m = map_mapname2mapid(str); - if (m != nullptr && m->flag.get(MapFlag::PVP) && m->flag.get(MapFlag::NOPVP)) + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(str), return); + if (m->flag.get(MapFlag::PVP) && m->flag.get(MapFlag::NOPVP)) { m->flag.set(MapFlag::PVP, 0); @@ -2125,7 +2106,6 @@ void builtin_pvpoff(ScriptState *st) } } } - } /*========================================== @@ -2152,16 +2132,13 @@ void builtin_mapwarp(ScriptState *st) // Added by RoVeRT MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); x0 = 0; y0 = 0; - map_local *m = map_mapname2mapid(mapname); + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return); x1 = m->xs; y1 = m->ys; MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(1)))); x = conv_num(st, &AARG(2)); y = conv_num(st, &AARG(3)); - if (m == nullptr) - return; - map_foreachinarea(std::bind(builtin_areawarp_sub, ph::_1, str, x, y), m, x0, y0, @@ -2194,12 +2171,11 @@ void builtin_mobcount(ScriptState *st) // Added by RoVeRT NpcEvent event; extract(event_, &event); - map_local *m = map_mapname2mapid(mapname); - if (m == nullptr) + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), { push_int<ScriptDataInt>(st->stack, -1); return; - } + }); map_foreachinarea(std::bind(builtin_mobcount_sub, ph::_1, event, &c), m, 0, 0, @@ -2250,7 +2226,7 @@ void builtin_divorce(ScriptState *st) static void builtin_getitemname(ScriptState *st) { - struct item_data *i_data; + Option<P<struct item_data>> i_data = None; struct script_data *data; data = &AARG(0); @@ -2263,14 +2239,10 @@ void builtin_getitemname(ScriptState *st) else { ItemNameId item_id = wrap<ItemNameId>(conv_num(st, data)); - i_data = itemdb_search(item_id); + i_data = Some(itemdb_search(item_id)); } - RString item_name; - if (i_data) - item_name = i_data->jname; - else - item_name = "Unknown Item"_s; + RString item_name = i_data.pmd_pget(&item_data::jname).copy_or(stringish<ItemName>("Unknown Item"_s)); push_str<ScriptDataStr>(st->stack, item_name); } @@ -2585,10 +2557,10 @@ void builtin_npcwarp(ScriptState *st) return; } - map_local *m = nd->bl_m; + P<map_local> m = nd->bl_m; /* Crude sanity checks. */ - if (m == nullptr || !nd->bl_prev + if (!nd->bl_prev || x < 0 || x > m->xs -1 || y < 0 || y > m->ys - 1) return; @@ -2740,9 +2712,7 @@ void builtin_areatimer(ScriptState *st) NpcEvent event; extract(event_, &event); - map_local *m = map_mapname2mapid(mapname); - if (m == nullptr) - return; + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return); map_foreachinarea(std::bind(builtin_areatimer_sub, ph::_1, tick, event), m, diff --git a/src/map/script-parse-internal.hpp b/src/map/script-parse-internal.hpp index f01317a..f7e153b 100644 --- a/src/map/script-parse-internal.hpp +++ b/src/map/script-parse-internal.hpp @@ -23,6 +23,8 @@ #include "script-parse.hpp" #include "fwd.hpp" +#include "../compat/fwd.hpp" + #include "../strings/rstring.hpp" @@ -64,6 +66,6 @@ Map<RString, str_data_t> str_datam; extern InternPool variable_names; -str_data_t *search_strp(XString p); -str_data_t *add_strp(XString p); +Option<Borrowed<str_data_t>> search_strp(XString p); +Borrowed<str_data_t> add_strp(XString p); } // namespace tmwa diff --git a/src/map/script-parse.cpp b/src/map/script-parse.cpp index 0c93477..10d1582 100644 --- a/src/map/script-parse.cpp +++ b/src/map/script-parse.cpp @@ -54,8 +54,8 @@ public: void add_scriptc(ByteCode a); void add_scriptb(uint8_t a); void add_scripti(uint32_t a); - void add_scriptl(str_data_t *a); - void set_label(str_data_t *ld, int pos_); + void add_scriptl(Borrowed<str_data_t> a); + void set_label(Borrowed<str_data_t> ld, int pos_); ZSit parse_simpleexpr(ZSit p); ZSit parse_subexpr(ZSit p, int limit); ZSit parse_expr(ZSit p); @@ -79,11 +79,11 @@ void std::default_delete<const tmwa::ScriptBuffer>::operator()(const tmwa::Scrip namespace tmwa { // implemented for script-call.hpp because reasons -ByteCode ScriptPointer::peek() const { return (*code)[pos]; } -ByteCode ScriptPointer::pop() { return (*code)[pos++]; } +ByteCode ScriptPointer::peek() const { return (*TRY_UNWRAP(code, abort()))[pos]; } +ByteCode ScriptPointer::pop() { return (*TRY_UNWRAP(code, abort()))[pos++]; } ZString ScriptPointer::pops() { - ZString rv = code->get_str(pos); + ZString rv = TRY_UNWRAP(code, abort())->get_str(pos); pos += rv.size(); ++pos; return rv; @@ -114,22 +114,23 @@ struct ScriptConfigParse static int parse_cmd_if = 0; static -str_data_t *parse_cmdp; +Option<Borrowed<str_data_t>> parse_cmdp = None; InternPool variable_names; -str_data_t *search_strp(XString p) +Option<Borrowed<str_data_t>> search_strp(XString p) { return str_datam.search(p); } -str_data_t *add_strp(XString p) +Borrowed<str_data_t> add_strp(XString p) { - if (str_data_t *rv = search_strp(p)) + Option<P<str_data_t>> rv_ = search_strp(p); + if OPTION_IS_SOME(rv, rv_) return rv; RString p2 = p; - str_data_t *datum = str_datam.init(p2); + P<str_data_t> datum = str_datam.init(p2); datum->type = StringCode::NOP; datum->strs = p2; datum->backpatch = -1; @@ -174,7 +175,7 @@ void ScriptBuffer::add_scripti(uint32_t a) *------------------------------------------ */ // 最大16Mまで -void ScriptBuffer::add_scriptl(str_data_t *ld) +void ScriptBuffer::add_scriptl(P<str_data_t> ld) { int backpatch = ld->backpatch; @@ -218,7 +219,7 @@ void ScriptBuffer::add_scriptl(str_data_t *ld) * ラベルを解決する *------------------------------------------ */ -void ScriptBuffer::set_label(str_data_t *ld, int pos_) +void ScriptBuffer::set_label(Borrowed<str_data_t> ld, int pos_) { int next; @@ -408,18 +409,18 @@ ZString::iterator ScriptBuffer::parse_simpleexpr(ZString::iterator p) { disp_error_message("Sorry, callsub/callfunc/return have never worked properly in an if statement."_s, p); } - str_data_t *ld = add_strp(word); + P<str_data_t> ld = add_strp(word); - parse_cmdp = ld; // warn_*_mismatch_paramnumのために必要 + parse_cmdp = Some(ld); // warn_*_mismatch_paramnumのために必要 // why not just check l->str == "if"_s or std::string(p, p2) == "if"_s? - if (ld == search_strp("if"_s)) // warn_cmd_no_commaのために必要 + if (Some(ld) == search_strp("if"_s)) // warn_cmd_no_commaのために必要 parse_cmd_if++; p = p2; if (ld->type != StringCode::FUNC && *p == '[') { // array(name[i] => getelementofarray(name,i) ) - add_scriptl(search_strp("getelementofarray"_s)); + add_scriptl(TRY_UNWRAP(search_strp("getelementofarray"_s), abort())); add_scriptc(ByteCode::ARG); add_scriptl(ld); p = parse_subexpr(p + 1, -1); @@ -457,7 +458,7 @@ ZString::iterator ScriptBuffer::parse_subexpr(ZString::iterator p, int limit) if (*tmpp == ';' || *tmpp == ',') { --script_errors; disp_error_message("deprecated: implicit 'next statement' label"_s, p); - add_scriptl(&LABEL_NEXTLINE_); + add_scriptl(borrow(LABEL_NEXTLINE_)); p++; return p; } @@ -496,7 +497,7 @@ ZString::iterator ScriptBuffer::parse_subexpr(ZString::iterator p, int limit) if (op == ByteCode::FUNC) { int i = 0; - str_data_t *funcp = parse_cmdp; + P<str_data_t> funcp = TRY_UNWRAP(parse_cmdp, abort()); ZString::iterator plist[128]; if (funcp->type != StringCode::FUNC) @@ -600,7 +601,7 @@ ZString::iterator ScriptBuffer::parse_line(ZString::iterator p, bool *can_step) p = parse_simpleexpr(p); p = skip_space(p); - str_data_t *cmd = parse_cmdp; + P<str_data_t> cmd = TRY_UNWRAP(parse_cmdp, abort()); if (cmd->type != StringCode::FUNC) { disp_error_message("expect command"_s, p2); @@ -680,7 +681,7 @@ void add_builtin_functions(void) { for (int i = 0; builtin_functions[i].func; i++) { - str_data_t *n = add_strp(builtin_functions[i].name); + P<str_data_t> n = add_strp(builtin_functions[i].name); n->type = StringCode::FUNC; n->val = i; } @@ -749,7 +750,7 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) ZString::iterator tmpp = skip_word(p); XString str(&*p, &*tmpp, nullptr); - str_data_t *ld = add_strp(str); + P<str_data_t> ld = add_strp(str); bool e1 = ld->type != StringCode::NOP; bool e2 = ld->type == StringCode::POS; bool e3 = ld->label_ != -1; @@ -774,7 +775,7 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) p = skip_space(p); add_scriptc(ByteCode::EOL); - set_label(&LABEL_NEXTLINE_, script_buf.size()); + set_label(borrow(LABEL_NEXTLINE_), script_buf.size()); LABEL_NEXTLINE_.type = StringCode::NOP; LABEL_NEXTLINE_.backpatch = -1; LABEL_NEXTLINE_.label_ = -1; @@ -820,7 +821,7 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) } for (ScriptLabel used : probable_labels) { - if (!scriptlabel_db.search(used)) + if (scriptlabel_db.search(used).is_none()) PRINTF("Warning: no such label: %s\n"_fmt, used); } probable_labels.clear(); diff --git a/src/map/script-persist.hpp b/src/map/script-persist.hpp index 35cd2d0..3d9f22b 100644 --- a/src/map/script-persist.hpp +++ b/src/map/script-persist.hpp @@ -22,6 +22,8 @@ #include "fwd.hpp" +#include "../compat/borrow.hpp" + #include "../strings/rstring.hpp" #include "../sexpr/variant.hpp" @@ -81,7 +83,7 @@ struct ScriptDataRetInfo { // Not a ScriptPointer - pos is stored in a separate slot, // to avoid exploding the struct for everyone. - const ScriptBuffer *script; + Borrowed<const ScriptBuffer> script; }; struct ScriptDataFuncRef { diff --git a/src/map/script-persist.py b/src/map/script-persist.py index a5010cd..454c828 100644 --- a/src/map/script-persist.py +++ b/src/map/script-persist.py @@ -3,6 +3,7 @@ class script_data(object): test_extra = ''' using tmwa::operator "" _s; + #include "../map/script-parse.hpp" ''' tests = [ @@ -18,8 +19,10 @@ class script_data(object): '{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = {(tmwa::ScriptDataArg) = {numi = 0}}, <No data fields>}'), ('tmwa::script_data(tmwa::ScriptDataVariable{tmwa::SIR()})', '{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = {(tmwa::ScriptDataVariable) = {reg = {impl = 0}}}, <No data fields>}'), - ('tmwa::script_data(tmwa::ScriptDataRetInfo{static_cast<const tmwa::ScriptBuffer *>(nullptr)})', - '{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = {(tmwa::ScriptDataRetInfo) = {script = 0x0}}, <No data fields>}'), + # the {script = } is almost certainly a bug in gdb's 'set print address' + # but the most I can do is check for changes. + ('tmwa::script_data(tmwa::ScriptDataRetInfo{tmwa::borrow(*tmwa::parse_script("{}"_s, 1, true).release())})', + 'regex:\{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = \{\(tmwa::ScriptDataRetInfo\) = \{script = \}\}, <No data fields>\}'), ('tmwa::script_data(tmwa::ScriptDataFuncRef{404})', '{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = {(tmwa::ScriptDataFuncRef) = {numi = 404}}, <No data fields>}'), ] diff --git a/src/map/script-startup.cpp b/src/map/script-startup.cpp index 1aa63aa..27ec903 100644 --- a/src/map/script-startup.cpp +++ b/src/map/script-startup.cpp @@ -102,7 +102,7 @@ bool read_constdb(ZString filename) rv = false; continue; } - str_data_t *n = add_strp(name); + P<str_data_t> n = add_strp(name); n->type = type ? StringCode::PARAM : StringCode::INT; n->val = val; } diff --git a/src/map/storage.cpp b/src/map/storage.cpp index a6e6a0d..295eff0 100644 --- a/src/map/storage.cpp +++ b/src/map/storage.cpp @@ -47,19 +47,15 @@ void do_final_storage(void) storage_db.clear(); } -Storage *account2storage(AccountId account_id) +Borrowed<Storage> account2storage(AccountId account_id) { - Storage *stor = storage_db.search(account_id); - if (stor == nullptr) - { - stor = storage_db.init(account_id); - stor->account_id = account_id; - } + P<Storage> stor = storage_db.init(account_id); + stor->account_id = account_id; return stor; } // Just to ask storage, without creation -Storage *account2storage2(AccountId account_id) +Option<Borrowed<Storage>> account2storage2(AccountId account_id) { return storage_db.search(account_id); } @@ -81,12 +77,11 @@ int storage_storageopen(dumb_ptr<map_session_data> sd) if (sd->state.storage_open) return 1; //Already open? - Storage *stor = storage_db.search(sd->status_key.account_id); - if (stor == nullptr) + P<Storage> stor = TRY_UNWRAP(storage_db.search(sd->status_key.account_id), { //Request storage. intif_request_storage(sd->status_key.account_id); return 1; - } + }); if (stor->storage_status) return 1; //Already open/player already has it open... @@ -104,15 +99,13 @@ int storage_storageopen(dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -int storage_additem(dumb_ptr<map_session_data> sd, Storage *stor, +int storage_additem(dumb_ptr<map_session_data> sd, P<Storage> stor, Item *item_data, int amount) { - struct item_data *data; - if (!item_data->nameid || amount <= 0) return 1; - data = itemdb_search(item_data->nameid); + P<struct item_data> data = itemdb_search(item_data->nameid); if (!itemdb_isequip2(data)) { //Stackable @@ -152,7 +145,7 @@ int storage_additem(dumb_ptr<map_session_data> sd, Storage *stor, *------------------------------------------ */ static -int storage_delitem(dumb_ptr<map_session_data> sd, Storage *stor, +int storage_delitem(dumb_ptr<map_session_data> sd, P<Storage> stor, SOff0 n, int amount) { @@ -178,11 +171,8 @@ int storage_delitem(dumb_ptr<map_session_data> sd, Storage *stor, */ int storage_storageadd(dumb_ptr<map_session_data> sd, IOff0 index, int amount) { - Storage *stor; - nullpo_retz(sd); - stor = account2storage2(sd->status_key.account_id); - nullpo_retz(stor); + P<Storage> stor = TRY_UNWRAP(account2storage2(sd->status_key.account_id), return 0); if ((stor->storage_amount > MAX_STORAGE) || !stor->storage_status) return 0; // storage full / storage closed @@ -213,12 +203,10 @@ int storage_storageadd(dumb_ptr<map_session_data> sd, IOff0 index, int amount) */ int storage_storageget(dumb_ptr<map_session_data> sd, SOff0 index, int amount) { - Storage *stor; PickupFail flag; nullpo_retz(sd); - stor = account2storage2(sd->status_key.account_id); - nullpo_retz(stor); + P<Storage> stor = TRY_UNWRAP(account2storage2(sd->status_key.account_id), return 0); if (!index.ok()) return 0; @@ -243,11 +231,8 @@ int storage_storageget(dumb_ptr<map_session_data> sd, SOff0 index, int amount) */ int storage_storageclose(dumb_ptr<map_session_data> sd) { - Storage *stor; - nullpo_retz(sd); - stor = account2storage2(sd->status_key.account_id); - nullpo_retz(stor); + P<Storage> stor = TRY_UNWRAP(account2storage2(sd->status_key.account_id), return 0); clif_storageclose(sd); if (stor->storage_status) @@ -275,12 +260,9 @@ int storage_storageclose(dumb_ptr<map_session_data> sd) */ int storage_storage_quit(dumb_ptr<map_session_data> sd) { - Storage *stor; - nullpo_retz(sd); - stor = account2storage2(sd->status_key.account_id); - if (stor) + P<Storage> stor = TRY_UNWRAP(account2storage2(sd->status_key.account_id), return 0); { chrif_save(sd); //Invokes the storage saving as well. stor->storage_status = 0; @@ -292,11 +274,7 @@ int storage_storage_quit(dumb_ptr<map_session_data> sd) int storage_storage_save(AccountId account_id, int final) { - Storage *stor; - - stor = account2storage2(account_id); - if (!stor) - return 0; + P<Storage> stor = TRY_UNWRAP(account2storage2(account_id), return 0); if (stor->dirty) { @@ -320,9 +298,8 @@ int storage_storage_save(AccountId account_id, int final) //Ack from Char-server indicating the storage was saved. [Skotlex] int storage_storage_saved(AccountId account_id) { - Storage *stor = account2storage2(account_id); + P<Storage> stor = TRY_UNWRAP(account2storage2(account_id), return 0); - if (stor) { //Only mark it clean if it's not in use. [Skotlex] if (stor->dirty && stor->storage_status == 0) diff --git a/src/map/storage.hpp b/src/map/storage.hpp index f3875c8..6874ca8 100644 --- a/src/map/storage.hpp +++ b/src/map/storage.hpp @@ -22,6 +22,8 @@ #include "fwd.hpp" +#include "../compat/fwd.hpp" + #include "../generic/fwd.hpp" #include "../mmo/fwd.hpp" @@ -36,8 +38,8 @@ int storage_storageadd(dumb_ptr<map_session_data> sd, IOff0 index, int amount); int storage_storageget(dumb_ptr<map_session_data> sd, SOff0 index, int amount); int storage_storageclose(dumb_ptr<map_session_data> sd); void do_final_storage(void); -Storage *account2storage(AccountId account_id); -Storage *account2storage2(AccountId account_id); +Borrowed<Storage> account2storage(AccountId account_id); +Option<Borrowed<Storage>> account2storage2(AccountId account_id); int storage_storage_quit(dumb_ptr<map_session_data> sd); int storage_storage_save(AccountId account_id, int final); int storage_storage_saved(AccountId account_id); diff --git a/src/map/trade.cpp b/src/map/trade.cpp index c52377d..b5e19be 100644 --- a/src/map/trade.cpp +++ b/src/map/trade.cpp @@ -129,7 +129,6 @@ void trade_tradeack(dumb_ptr<map_session_data> sd, int type) void trade_tradeadditem(dumb_ptr<map_session_data> sd, IOff2 index, int amount) { dumb_ptr<map_session_data> target_sd; - struct item_data *id; int trade_i; int trade_weight = 0; int free_ = 0; @@ -156,7 +155,7 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, IOff2 index, int amount) for (IOff0 i : IOff0::iter()) { if (!target_sd->status.inventory[i].nameid - && target_sd->inventory_data[i] == nullptr) + && target_sd->inventory_data[i].is_none()) free_++; } for (trade_i = 0; trade_i < TRADE_MAX; trade_i++) @@ -164,17 +163,19 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, IOff2 index, int amount) if (sd->deal_item_amount[trade_i] == 0) { // calculate trade weight + // note: 'abort' branch is protected by 'amount' check above trade_weight += - sd->inventory_data[index.unshift()]->weight * amount; + TRY_UNWRAP(sd->inventory_data[index.unshift()], abort())->weight * amount; // determine if item is a stackable already in receivers inventory, and up free count for (IOff0 i : IOff0::iter()) { - if (target_sd->status.inventory[i].nameid == - sd->status.inventory[index.unshift()].nameid - && target_sd->inventory_data[i] != nullptr) + if (target_sd->status.inventory[i].nameid != + sd->status.inventory[index.unshift()].nameid) + continue; + + if OPTION_IS_SOME(id, target_sd->inventory_data[i]) { - id = target_sd->inventory_data[i]; if (id->type != ItemType::WEAPON && id->type != ItemType::ARMOR && id->type != ItemType::_7 @@ -218,19 +219,20 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, IOff2 index, int amount) else { // calculate weight for stored deal + // note: 'abort' branch is protected by 'amount' check above trade_weight += - sd->inventory_data[sd->deal_item_index[trade_i].unshift() - ]->weight * + TRY_UNWRAP(sd->inventory_data[sd->deal_item_index[trade_i].unshift() + ], abort())->weight * sd->deal_item_amount[trade_i]; // count free stackables in stored deal for (IOff0 i : IOff0::iter()) { - if (target_sd->status.inventory[i].nameid == + if (target_sd->status.inventory[i].nameid != sd->status. - inventory[sd->deal_item_index[trade_i].unshift()].nameid - && target_sd->inventory_data[i] != nullptr) + inventory[sd->deal_item_index[trade_i].unshift()].nameid) + continue; + if OPTION_IS_SOME(id, target_sd->inventory_data[i]) { - id = target_sd->inventory_data[i]; if (id->type != ItemType::WEAPON && id->type != ItemType::ARMOR && id->type != ItemType::_7 diff --git a/src/mmo/mmo.hpp b/src/mmo/mmo.hpp index e3cf0e4..d627c90 100644 --- a/src/mmo/mmo.hpp +++ b/src/mmo/mmo.hpp @@ -22,6 +22,7 @@ #include "fwd.hpp" +#include "../compat/borrow.hpp" #include "../compat/memory.hpp" #include "../proto2/types.hpp" @@ -58,13 +59,10 @@ struct GM_Account struct PartyPair { - PartyId party_id = {}; - PartyMost *party_most = {}; + PartyId party_id; + Borrowed<PartyMost> party_most; - explicit - operator bool() const { return party_most; } - bool operator !() const { return !party_most; } - PartyMost *operator->() { return party_most; } - const PartyMost *operator->() const { return party_most; } + PartyMost& operator *() const { return *party_most; } + Borrowed<PartyMost> operator->() const { return party_most; } }; } // namespace tmwa diff --git a/src/sexpr/variant.tcc b/src/sexpr/variant.tcc index 1f7df03..c370fa4 100644 --- a/src/sexpr/variant.tcc +++ b/src/sexpr/variant.tcc @@ -120,6 +120,9 @@ namespace sexpr } catch (...) { + // TODO switch from requiring nothrow default construct, to + // instead require nothrow moves, and offer the strong exception + // guarantee (which is actually easier that the basic one) #if GCC != 407 // apparent compiler bug, not reduced // 4.7.2 from wheezy is bad // 4.7.3 from jessie is good diff --git a/tools/protocol.py b/tools/protocol.py index 2c3ebce..a423722 100755 --- a/tools/protocol.py +++ b/tools/protocol.py @@ -1251,6 +1251,7 @@ def main(): size=None, ) + # TODO move 'account id' out somehow. storage = ctx.struct( 'Storage', [ |