summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-10-13 13:16:34 -0700
committerBen Longbons <b.r.longbons@gmail.com>2014-10-13 14:03:46 -0700
commit780a0d771edbe21dcfa3405163ffbdf7f7fa4604 (patch)
treeac202254d015d2a2a28ab5bca60c3f5474d168ba
parenta5e0fe8204a8b3299507a645f3479e9ead6c6110 (diff)
downloadtmwa-780a0d771edbe21dcfa3405163ffbdf7f7fa4604.tar.gz
tmwa-780a0d771edbe21dcfa3405163ffbdf7f7fa4604.tar.bz2
tmwa-780a0d771edbe21dcfa3405163ffbdf7f7fa4604.tar.xz
tmwa-780a0d771edbe21dcfa3405163ffbdf7f7fa4604.zip
Convert container lookups to use Option<Borrowed<T>>
-rw-r--r--src/char/char.cpp3
-rw-r--r--src/char/int_party.cpp84
-rw-r--r--src/char/int_storage.cpp15
-rw-r--r--src/char/int_storage.hpp4
-rw-r--r--src/char/inter.cpp12
-rw-r--r--src/compat/borrow.hpp9
-rw-r--r--src/compat/borrow.py18
-rw-r--r--src/compat/fwd.hpp1
-rw-r--r--src/compat/nullpo.hpp2
-rw-r--r--src/compat/option.hpp54
-rw-r--r--src/compat/option.py37
-rw-r--r--src/compat/option_test.cpp37
-rw-r--r--src/generic/db.hpp38
-rw-r--r--src/login/login.cpp7
-rw-r--r--src/map/atcommand.cpp234
-rw-r--r--src/map/battle.cpp20
-rw-r--r--src/map/chrif.cpp8
-rw-r--r--src/map/clif.cpp117
-rw-r--r--src/map/clif.hpp8
-rw-r--r--src/map/intif.cpp10
-rw-r--r--src/map/intif.hpp4
-rw-r--r--src/map/itemdb.cpp28
-rw-r--r--src/map/itemdb.hpp10
-rw-r--r--src/map/magic-expr.cpp45
-rw-r--r--src/map/magic-expr.hpp4
-rw-r--r--src/map/magic-interpreter.hpp8
-rw-r--r--src/map/magic-interpreter.py8
-rw-r--r--src/map/magic-stmt.cpp17
-rw-r--r--src/map/magic-v2.cpp12
-rw-r--r--src/map/map.cpp118
-rw-r--r--src/map/map.hpp52
-rw-r--r--src/map/mob.cpp56
-rw-r--r--src/map/mob.hpp2
-rw-r--r--src/map/npc-parse.cpp61
-rw-r--r--src/map/npc-parse.hpp4
-rw-r--r--src/map/npc.cpp62
-rw-r--r--src/map/npc.hpp2
-rw-r--r--src/map/party.cpp131
-rw-r--r--src/map/party.hpp8
-rw-r--r--src/map/path.cpp12
-rw-r--r--src/map/path.hpp4
-rw-r--r--src/map/pc.cpp156
-rw-r--r--src/map/script-call-internal.hpp4
-rw-r--r--src/map/script-call-internal.tcc2
-rw-r--r--src/map/script-call.cpp28
-rw-r--r--src/map/script-call.hpp11
-rw-r--r--src/map/script-fun.cpp138
-rw-r--r--src/map/script-parse-internal.hpp6
-rw-r--r--src/map/script-parse.cpp47
-rw-r--r--src/map/script-persist.hpp4
-rw-r--r--src/map/script-persist.py7
-rw-r--r--src/map/script-startup.cpp2
-rw-r--r--src/map/storage.cpp53
-rw-r--r--src/map/storage.hpp6
-rw-r--r--src/map/trade.cpp28
-rw-r--r--src/mmo/mmo.hpp12
-rw-r--r--src/sexpr/variant.tcc3
-rwxr-xr-xtools/protocol.py1
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 = &pm;
+ 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 = &pm;
+ 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',
[