forked from github/server
Merge remote-tracking branch 'refs/remotes/eressea/develop'
This commit is contained in:
commit
c63b8a2028
|
@ -69,6 +69,7 @@ add_subdirectory (storage)
|
|||
add_subdirectory (iniparser)
|
||||
add_subdirectory (quicklist)
|
||||
add_subdirectory (critbit)
|
||||
add_subdirectory (process)
|
||||
add_subdirectory (src eressea)
|
||||
install(DIRECTORY res conf DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.xml")
|
||||
install(DIRECTORY res conf DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.json")
|
||||
|
|
|
@ -42,9 +42,9 @@
|
|||
"nmr.removenewbie": 0,
|
||||
"GiveRestriction": 3,
|
||||
"hunger.long": false,
|
||||
"hunger.demon.skill": true,
|
||||
"hunger.damage": "1d9+9",
|
||||
"hunger.demons": true,
|
||||
"hunger.demons.skill": true,
|
||||
"hunger.demons.peasant_tolerance": true,
|
||||
"init_spells": 0,
|
||||
"recruit.allow_merge": true,
|
||||
"study.expensivemigrants": true,
|
||||
|
@ -71,9 +71,9 @@
|
|||
"rules.region_owners": true,
|
||||
"rules.cavalry.skill": 2,
|
||||
"rules.cavalry.mode": 1,
|
||||
"rules.magic.multipotion": 1,
|
||||
"rules.magic.multipotion": true,
|
||||
"rules.magic.wol_effect": 5,
|
||||
"rules.magic.factionlist": 1,
|
||||
"rules.magic.factionlist": true,
|
||||
"rules.magic.wol_type": 2,
|
||||
"rules.blessed_harvest.flags": 1,
|
||||
"rules.magic.elfpower": true,
|
||||
|
|
|
@ -51,13 +51,13 @@
|
|||
</string>
|
||||
<string name="newbie_info_1">
|
||||
<text locale="de">Bitte denke daran, deine Befehle mit dem Betreff
|
||||
E3 BEFEHLE an eressea-server@eressea.de zu senden.</text>
|
||||
ERESSEA 3 BEFEHLE an eressea-server@eressea.de zu senden.</text>
|
||||
<text locale="en">Remember to send your orders to
|
||||
eressea-server@eressea.de with the subject E3 ORDERS.</text>
|
||||
</string>
|
||||
<string name="mailcmd">
|
||||
<text locale="de">E3 BEFEHLE</text>
|
||||
<text locale="en">E3 ORDERS</text>
|
||||
<text locale="de">ERESSEA 3 BEFEHLE</text>
|
||||
<text locale="en">ERESSEA 3 ORDERS</text>
|
||||
</string>
|
||||
<string name="defaultorder">
|
||||
<text locale="de">ARBEITEN</text>
|
||||
|
|
|
@ -42,9 +42,9 @@
|
|||
"nmr.removenewbie": 0,
|
||||
"GiveRestriction": 3,
|
||||
"hunger.long": false,
|
||||
"hunger.demon.skill": true,
|
||||
"hunger.damage": "1d9+9",
|
||||
"hunger.demons": true,
|
||||
"hunger.demons.skill": true,
|
||||
"hunger.demons.peasant_tolerance": true,
|
||||
"init_spells": 0,
|
||||
"recruit.allow_merge": true,
|
||||
"study.expensivemigrants": true,
|
||||
|
|
2
crypto
2
crypto
|
@ -1 +1 @@
|
|||
Subproject commit 166fdc8c146755055217070c58079ba9a7c03369
|
||||
Subproject commit 93dc9200fa4cb6bfa3883b19f6d33fd416ca43da
|
|
@ -0,0 +1,8 @@
|
|||
install(PROGRAMS create-orders backup-eressea run-turn send-zip-report
|
||||
send-bz2-report compress.py compress.sh epasswd.py orders-process
|
||||
checkpasswd.py sendreport.sh orders-accept DESTINATION bin)
|
||||
|
||||
install(DIRECTORY cron/ DESTINATION bin USE_SOURCE_PERMISSIONS
|
||||
FILES_MATCHING PATTERN "*.cron")
|
||||
|
||||
install(DIRECTORY procmail DESTINATION share)
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys, re
|
||||
from epasswd import EPasswd
|
||||
|
||||
if len(sys.argv)<4:
|
||||
sys.exit(-2)
|
||||
|
||||
passfile=sys.argv[1]
|
||||
myfaction=sys.argv[2]
|
||||
mypasswd=sys.argv[3]
|
||||
|
||||
if mypasswd[0]=='"':
|
||||
mypasswd=mypasswd[1:len(mypasswd)-1]
|
||||
|
||||
pw_data=EPasswd(passfile)
|
||||
if pw_data.fac_exists(myfaction):
|
||||
if pw_data.check(myfaction, mypasswd):
|
||||
sys.exit(0)
|
||||
sys.exit(-1)
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from string import split
|
||||
from string import strip
|
||||
from string import lower
|
||||
import subprocess
|
||||
|
||||
class EPasswd:
|
||||
def _check_apr1(self, pwhash, pw):
|
||||
spl = split(pwhash, '$')
|
||||
salt = spl[2]
|
||||
hash = subprocess.check_output(['openssl', 'passwd', '-apr1', '-salt', salt, pw]).decode('utf-8').strip()
|
||||
return hash==pwhash
|
||||
|
||||
def __init__(self, file):
|
||||
self.data = {}
|
||||
try:
|
||||
fp = open(file,"r")
|
||||
except:
|
||||
fp = None
|
||||
if fp != None:
|
||||
while True:
|
||||
line = fp.readline()
|
||||
if not line: break
|
||||
line = strip(line)
|
||||
[id, email, passwd] = split(line, ":")[0:3]
|
||||
lc_id = lower(id)
|
||||
self.data[lc_id] = {}
|
||||
self.data[lc_id]["id"] = id
|
||||
self.data[lc_id]["email"] = email
|
||||
self.data[lc_id]["passwd"] = passwd
|
||||
fp.close()
|
||||
|
||||
def check(self, id, passwd):
|
||||
pw = self.get_passwd(id)
|
||||
if pw[0:6]=='$apr1$':
|
||||
return self._check_apr1(pw, passwd)
|
||||
return pw == passwd
|
||||
|
||||
def get_passwd(self, id):
|
||||
return self.data[lower(id)]["passwd"]
|
||||
|
||||
def get_email(self, id):
|
||||
return self.data[lower(id)]["email"]
|
||||
|
||||
def get_canon_id(self, id):
|
||||
return self.data[lower(id)]["id"]
|
||||
|
||||
def fac_exists(self, id):
|
||||
return self.data.has_key(lower(id))
|
|
@ -1,2 +1,368 @@
|
|||
#/bin/.sh
|
||||
grep -v '>From' | $HOME/src/scripts/bin/orders-accept $*
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
|
||||
from email.Utils import parseaddr
|
||||
from email.Parser import Parser
|
||||
from os import mkdir, rename, stat, utime, unlink, symlink
|
||||
from os.path import exists
|
||||
from re import compile, IGNORECASE
|
||||
from stat import ST_MTIME
|
||||
from string import upper, split, replace
|
||||
import logging
|
||||
from sys import argv, stdin, exit
|
||||
from time import ctime, sleep, time
|
||||
from socket import gethostname
|
||||
from rfc822 import parsedate_tz, mktime_tz
|
||||
|
||||
LOG_FILENAME='/home/eressea/log/orders.log'
|
||||
prefix = 'turn-'
|
||||
hostname = gethostname()
|
||||
# base directory for all your games:
|
||||
rootdir = "/home/eressea"
|
||||
orderbase = "orders.dir"
|
||||
sendmail = True
|
||||
# maximum number of reports per sender:
|
||||
maxfiles = 20
|
||||
# write headers to file?
|
||||
writeheaders = True
|
||||
# reject all html email?
|
||||
rejecthtml = True
|
||||
|
||||
games = [
|
||||
{
|
||||
"from" : "Eressea Server <eressea-server@eressea.de>",
|
||||
"prefix" : "Eressea"
|
||||
},
|
||||
{
|
||||
"from" : "Eressea Server <eressea-server@eressea.de>",
|
||||
"prefix": "E3"
|
||||
},
|
||||
{
|
||||
"from" : "Eressea Server <eressea-server@eressea.de>",
|
||||
"prefix": "E4"
|
||||
},
|
||||
]
|
||||
|
||||
def unlock_file(filename):
|
||||
try:
|
||||
unlink(filename+".lock")
|
||||
except:
|
||||
print "could not unlock %s.lock, file not found" % filename
|
||||
|
||||
def lock_file(filename):
|
||||
i = 0
|
||||
wait = 1
|
||||
if not exists(filename):
|
||||
file=open(filename, "w")
|
||||
file.close()
|
||||
while True:
|
||||
try:
|
||||
symlink(filename, filename+".lock")
|
||||
return
|
||||
except:
|
||||
i = i+1
|
||||
if i == 5: unlock_file(filename)
|
||||
sleep(wait)
|
||||
wait = wait*2
|
||||
|
||||
messages = {
|
||||
"multipart-en" :
|
||||
"ERROR: The orders you sent contain no plaintext. " \
|
||||
"The Eressea server cannot process orders containing HTML " \
|
||||
"or invalid attachments, which are the reasons why this " \
|
||||
"usually happens. Please change the settings of your mail " \
|
||||
"software and re-send the orders.",
|
||||
|
||||
"multipart-de" :
|
||||
"FEHLER: Die von dir eingeschickte Mail enthält keinen " \
|
||||
"Text. Evtl. hast Du den Zug als HTML oder als anderweitig " \
|
||||
"ungültig formatierte Mail ingeschickt. Wir können ihn " \
|
||||
"deshalb nicht berücksichtigen. Schicke den Zug nochmals " \
|
||||
"als reinen Text ohne Formatierungen ein.",
|
||||
|
||||
"maildate-de":
|
||||
"Es erreichte uns bereits ein Zug mit einem späteren " \
|
||||
"Absendedatum (%s > %s). Entweder ist deine " \
|
||||
"Systemzeit verstellt, oder ein Zug hat einen anderen Zug von " \
|
||||
"dir auf dem Transportweg überholt. Entscheidend für die " \
|
||||
"Auswertungsreihenfolge ist das Absendedatum, d.h. der Date:-Header " \
|
||||
"deiner Mail.",
|
||||
|
||||
"maildate-en":
|
||||
"The server already received an order file that was sent at a later " \
|
||||
"date (%s > %s). Either your system clock is wrong, or two messages have " \
|
||||
"overtaken each other on the way to the server. The order of " \
|
||||
"execution on the server is always according to the Date: header in " \
|
||||
"your mail.",
|
||||
|
||||
"nodate-en":
|
||||
"Your message did not contain a valid Date: header in accordance with RFC2822.",
|
||||
|
||||
"nodate-de":
|
||||
"Deine Nachricht enthielt keinen gueltigen Date: header nach RFC2822.",
|
||||
|
||||
"error-de":
|
||||
"Fehler",
|
||||
|
||||
"error-en":
|
||||
"Error",
|
||||
|
||||
"warning-de":
|
||||
"Warnung",
|
||||
|
||||
"warning-en":
|
||||
"Warning",
|
||||
|
||||
"subject-de":
|
||||
"Befehle angekommen",
|
||||
|
||||
"subject-en":
|
||||
"orders received"
|
||||
}
|
||||
|
||||
# return 1 if addr is a valid email address
|
||||
def valid_email(addr):
|
||||
rfc822_specials = '/()<>@,;:\\"[]'
|
||||
# First we validate the name portion (name@domain)
|
||||
c = 0
|
||||
while c < len(addr):
|
||||
if addr[c] == '"' and (not c or addr[c - 1] == '.' or addr[c - 1] == '"'):
|
||||
c = c + 1
|
||||
while c < len(addr):
|
||||
if addr[c] == '"': break
|
||||
if addr[c] == '\\' and addr[c + 1] == ' ':
|
||||
c = c + 2
|
||||
continue
|
||||
if ord(addr[c]) < 32 or ord(addr[c]) >= 127: return 0
|
||||
c = c + 1
|
||||
else: return 0
|
||||
if addr[c] == '@': break
|
||||
if addr[c] != '.': return 0
|
||||
c = c + 1
|
||||
continue
|
||||
if addr[c] == '@': break
|
||||
if ord(addr[c]) <= 32 or ord(addr[c]) >= 127: return 0
|
||||
if addr[c] in rfc822_specials: return 0
|
||||
c = c + 1
|
||||
if not c or addr[c - 1] == '.': return 0
|
||||
|
||||
# Next we validate the domain portion (name@domain)
|
||||
domain = c = c + 1
|
||||
if domain >= len(addr): return 0
|
||||
count = 0
|
||||
while c < len(addr):
|
||||
if addr[c] == '.':
|
||||
if c == domain or addr[c - 1] == '.': return 0
|
||||
count = count + 1
|
||||
if ord(addr[c]) <= 32 or ord(addr[c]) >= 127: return 0
|
||||
if addr[c] in rfc822_specials: return 0
|
||||
c = c + 1
|
||||
return count >= 1
|
||||
|
||||
# return the replyto or from address in the header
|
||||
def get_sender(header):
|
||||
replyto = header.get("Reply-To")
|
||||
if replyto is None:
|
||||
replyto = header.get("From")
|
||||
if replyto is None: return None
|
||||
x = parseaddr(replyto)
|
||||
return x[1]
|
||||
|
||||
# return first available filename basename,[0-9]+
|
||||
def available_file(dirname, basename):
|
||||
ver = 0
|
||||
maxdate = 0
|
||||
filename = "%s/%s,%s,%d" % (dirname, basename, hostname, ver)
|
||||
while exists(filename):
|
||||
maxdate = max(stat(filename)[ST_MTIME], maxdate)
|
||||
ver = ver + 1
|
||||
filename = "%s/%s,%s,%d" % (dirname, basename, hostname, ver)
|
||||
if ver >= maxfiles:
|
||||
return None, None
|
||||
return maxdate, filename
|
||||
|
||||
def formatpar(string, l=76, indent=2):
|
||||
words = split(string)
|
||||
res = ""
|
||||
ll = 0
|
||||
first = 1
|
||||
|
||||
for word in words:
|
||||
if first == 1:
|
||||
res = word
|
||||
first = 0
|
||||
ll = len(word)
|
||||
else:
|
||||
if ll + len(word) > l:
|
||||
res = res + "\n"+" "*indent+word
|
||||
ll = len(word) + indent
|
||||
else:
|
||||
res = res+" "+word
|
||||
ll = ll + len(word) + 1
|
||||
|
||||
return res+"\n"
|
||||
|
||||
def store_message(message, filename):
|
||||
outfile = open(filename, "w")
|
||||
outfile.write(message.as_string())
|
||||
outfile.close()
|
||||
return
|
||||
|
||||
def write_part(outfile, part):
|
||||
charset = part.get_content_charset()
|
||||
payload = part.get_payload(decode=True)
|
||||
|
||||
if charset is None:
|
||||
charset = "latin1"
|
||||
try:
|
||||
msg = payload.decode(charset, "ignore")
|
||||
except:
|
||||
msg = payload
|
||||
charset = None
|
||||
try:
|
||||
utf8 = msg.encode("utf-8", "ignore")
|
||||
outfile.write(utf8)
|
||||
except:
|
||||
outfile.write(msg)
|
||||
return False
|
||||
outfile.write("\n");
|
||||
return True
|
||||
|
||||
def copy_orders(message, filename, sender):
|
||||
# print the header first
|
||||
if writeheaders:
|
||||
from os.path import split
|
||||
dirname, basename = split(filename)
|
||||
dirname = dirname + '/headers'
|
||||
if not exists(dirname): mkdir(dirname)
|
||||
outfile = open(dirname + '/' + basename, "w")
|
||||
for name, value in message.items():
|
||||
outfile.write(name + ": " + value + "\n")
|
||||
outfile.close()
|
||||
|
||||
found = False
|
||||
outfile = open(filename, "w")
|
||||
if message.is_multipart():
|
||||
for part in message.get_payload():
|
||||
content_type = part.get_content_type()
|
||||
logger.debug("found content type %s for %s" % (content_type, sender))
|
||||
if content_type=="text/plain":
|
||||
if write_part(outfile, part):
|
||||
found = True
|
||||
else:
|
||||
charset = part.get_content_charset()
|
||||
logger.error("could not write text/plain part (charset=%s) for %s" % (charset, sender))
|
||||
|
||||
else:
|
||||
if write_part(outfile, message):
|
||||
found = True
|
||||
else:
|
||||
charset = message.get_content_charset()
|
||||
logger.error("could not write text/plain message (charset=%s) for %s" % (charset, sender))
|
||||
outfile.close()
|
||||
return found
|
||||
|
||||
# create a file, containing:
|
||||
# game=0 locale=de file=/path/to/filename email=rcpt@domain.to
|
||||
def accept(game, locale, stream, extend=None):
|
||||
global rootdir, orderbase
|
||||
if extend is not None:
|
||||
orderbase = orderbase + ".pre-" + extend
|
||||
gamename = games[game-2]["prefix"]
|
||||
gamedir = rootdir+"/eressea/game-%d" % (game, )
|
||||
savedir = gamedir+"/"+orderbase
|
||||
# check if it's one of the pre-sent orders.
|
||||
# create the save-directories if they don't exist
|
||||
if not exists(gamedir): mkdir(gamedir)
|
||||
if not exists(savedir): mkdir(savedir)
|
||||
# parse message
|
||||
message = Parser().parse(stream)
|
||||
sender = get_sender(message)
|
||||
logger = logging.getLogger(sender)
|
||||
# write syslog
|
||||
if sender is None or valid_email(sender)==0:
|
||||
logger.warning("invalid email address: " + str(sender))
|
||||
return -1
|
||||
logger.info("received orders from " + sender)
|
||||
# get an available filename
|
||||
lock_file(gamedir + "/orders.queue")
|
||||
maxdate, filename = available_file(savedir, prefix + sender)
|
||||
if filename is None:
|
||||
logger.warning("more than " + str(maxfiles) + " orders from " + sender)
|
||||
return -1
|
||||
# copy the orders to the file
|
||||
text_ok = copy_orders(message, filename, sender)
|
||||
unlock_file(gamedir + "/orders.queue")
|
||||
|
||||
warning, msg, fail = None, "", False
|
||||
maildate = message.get("Date")
|
||||
if maildate != None:
|
||||
turndate = mktime_tz(parsedate_tz(maildate))
|
||||
utime(filename, (turndate, turndate))
|
||||
logger.debug("mail date is '%s' (%d)" % (maildate, turndate))
|
||||
if turndate < maxdate:
|
||||
logger.warning("inconsistent message date " + sender)
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["maildate-" + locale] % (ctime(maxdate),ctime(turndate)), 76, 2) + "\n"
|
||||
else:
|
||||
logger.warning("missing message date " + sender)
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["nodate-" + locale], 76, 2) + "\n"
|
||||
|
||||
if not text_ok:
|
||||
warning = " (" + messages["error-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["multipart-" + locale], 76, 2) + "\n"
|
||||
logger.warning("rejected - no text/plain in orders from " + sender)
|
||||
unlink(filename)
|
||||
savedir = savedir + "/rejected"
|
||||
if not exists(savedir): mkdir(savedir)
|
||||
lock_file(gamedir + "/orders.queue")
|
||||
maxdate, filename = available_file(savedir, prefix + sender)
|
||||
store_message(message, filename)
|
||||
unlock_file(gamedir + "/orders.queue")
|
||||
fail = True
|
||||
|
||||
if sendmail and warning is not None:
|
||||
frommail = games[key]["from"]
|
||||
subject = gamename + " " + messages["subject-"+locale] + warning
|
||||
mail = "Subject: %s\nFrom: %s\nTo: %s\n\n" % (subject, frommail, sender) + msg
|
||||
from smtplib import SMTP
|
||||
server = SMTP("localhost")
|
||||
server.sendmail(frommail, sender, mail)
|
||||
server.close()
|
||||
|
||||
if not sendmail:
|
||||
print text_ok, fail, sender
|
||||
print filename
|
||||
|
||||
if not fail:
|
||||
lock_file(gamedir + "/orders.queue")
|
||||
queue = open(gamedir + "/orders.queue", "a")
|
||||
queue.write("email=%s file=%s locale=%s game=%s\n" % (sender, filename, locale, game))
|
||||
queue.close()
|
||||
unlock_file(gamedir + "/orders.queue")
|
||||
|
||||
logger.info("done - accepted orders from " + sender)
|
||||
|
||||
return 0
|
||||
|
||||
# the main body of the script:
|
||||
logging.basicConfig(level=logging.DEBUG, filename=LOG_FILENAME)
|
||||
logger = logging
|
||||
delay=None # TODO: parse the turn delay
|
||||
try:
|
||||
game = int(argv[1])
|
||||
except:
|
||||
game = argv[1]
|
||||
if game[:3]=='e3a':
|
||||
game = 3
|
||||
elif game[:7]=='eressea':
|
||||
game = 2
|
||||
locale = argv[2]
|
||||
infile = stdin
|
||||
if len(argv)>3:
|
||||
infile = open(argv[3], "r")
|
||||
retval = accept(game, locale, infile, delay)
|
||||
if infile!=stdin:
|
||||
infile.close()
|
||||
exit(retval)
|
||||
|
|
|
@ -87,7 +87,7 @@ def check_pwd(filename, email, pw_data):
|
|||
fact_nr = str(mo.group(2))
|
||||
fact_pw = str(mo.group(3))
|
||||
if pw_data.fac_exists(fact_nr):
|
||||
if pw_data.check(fact_nr, fact_pw) == 0:
|
||||
if not pw_data.check(fact_nr, fact_pw):
|
||||
game_email = pw_data.get_email(fact_nr)
|
||||
results = results + [ (fact_nr, game_email, False, fact_pw) ]
|
||||
else:
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
##
|
||||
## Eressea Reportversand
|
||||
##
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*ERE.*2.*PASSWOR.*
|
||||
| sendpassword.py $HOME/eressea/game-2/passwd
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*ERE.*3.*PASSWOR.*
|
||||
| sendpassword.py $HOME/eressea/game-3/passwd
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*ERE.*4.*PASSWOR.*
|
||||
| sendpassword.py $HOME/eressea/game-4/passwd
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*ERE.*PASSWOR.*
|
||||
| sendpassword.py $HOME/eressea/game-2/passwd
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*E3.*PASSWOR.*
|
||||
| sendpassword.py $HOME/eressea/game-3/passwd
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*ERE.*2.*REPORT \/.*
|
||||
* !From: .*eressea.*@eressea.de
|
||||
| tr -d '' | ERESSEA=$HOME/eressea sendreport.sh 2 $FROM $MATCH
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*ERE.*3.*REPORT \/.*
|
||||
* !From: .*eressea.*@eressea.de
|
||||
| tr -d '' | ERESSEA=$HOME/eressea sendreport.sh 3 $FROM $MATCH
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*ERE.*4.*REPORT \/.*
|
||||
* !From: .*eressea.*@eressea.de
|
||||
| tr -d '' | ERESSEA=$HOME/eressea sendreport.sh 4 $FROM $MATCH
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*ERE.*REPORT \/.*
|
||||
* !From: .*eressea.*@eressea.de
|
||||
| sendreport.sh 2 $FROM $MATCH
|
||||
|
||||
:0:server.lock
|
||||
* ^Subject:.*E3.*REPORT \/.*
|
||||
* !From: .*eressea.*@eressea.de
|
||||
| tr -d '' | ERESSEA=$HOME/eressea sendreport.sh 3 $FROM $MATCH
|
||||
|
||||
:0 he
|
||||
| ( formail -I"Precedence: junk" -r -A"X-Loop: eressea@eressea.de" ; cat $HOME/etc/report-failure.txt ) | $SENDMAIL -t
|
||||
|
||||
##
|
||||
## Eressea Befehle
|
||||
##
|
||||
|
||||
:0
|
||||
* ^Subject:.*ERESSEA 4 BEFEHLE
|
||||
| grep -v '>From' | $HOME/bin/orders-accept 4 de
|
||||
|
||||
:0
|
||||
* ^Subject:.*ERESSEA 4 ORDERS
|
||||
| grep -v '>From' | $HOME/bin/orders-accept 4 en
|
||||
|
||||
:0
|
||||
* ^Subject:.*ERESSEA 3 BEFEHLE
|
||||
| grep -v '>From' | $HOME/bin/orders-accept 3 de
|
||||
|
||||
:0
|
||||
* ^Subject:.*ERESSEA 3 ORDERS
|
||||
| grep -v '>From' | $HOME/bin/orders-accept 3 en
|
||||
|
||||
## backwards compatible format
|
||||
|
||||
:0
|
||||
* ^Subject:.*E3.* BEF.*
|
||||
| grep -v '>From' | $HOME/bin/orders-accept 3 de
|
||||
|
||||
:0
|
||||
* ^Subject:.*E3.* ORD.*
|
||||
| grep -v '>From' | $HOME/bin/orders-accept 3 en
|
||||
|
||||
:0
|
||||
* ^Subject:.*ERE.* BEF.*
|
||||
| grep -v '>From' | $HOME/bin/orders-accept 2 de
|
||||
|
||||
:0
|
||||
* ^Subject:.*ERE.* ORD.*
|
||||
| grep -v '>From' | $HOME/bin/orders-accept 2 en
|
||||
|
||||
:0 c
|
||||
* ^Subject:.*ERE.*
|
||||
eressea
|
|
@ -0,0 +1,48 @@
|
|||
#!/bin/bash
|
||||
|
||||
## this script takes a backup of a turn.
|
||||
## usage: backup.sh <turn>
|
||||
|
||||
if [ -z $ERESSEA ]; then
|
||||
echo "You have to define the \$ERESSEA environment variable to run $0"
|
||||
exit -2
|
||||
fi
|
||||
source $HOME/bin/functions.sh
|
||||
source $HOME/etc/eressea.conf
|
||||
|
||||
GAME=$1
|
||||
EMAIL=$2
|
||||
FACTION=$3
|
||||
PASSWD=$4
|
||||
echo "$GAME $EMAIL $FACTION $PASSWD" >> /tmp/report.log
|
||||
|
||||
function reply() {
|
||||
echo $@ | mutt -s "Reportnachforderung Partei ${FACTION}" $EMAIL
|
||||
abort $@
|
||||
}
|
||||
|
||||
LOCKFILE=$ERESSEA/.report.lock
|
||||
[ -e $LOCKFILE ] && reply "lockfile exists. wait for mail delivery to finish."
|
||||
|
||||
REPLYTO='accounts@eressea.de'
|
||||
|
||||
echo `date`:report:$GAME:$EMAIL:$FACTION:$PASSWD >> $ERESSEA/request.log
|
||||
|
||||
cd $ERESSEA
|
||||
checkpasswd.py game-$GAME/passwd $FACTION $PASSWD || reply "Das Passwort fuer die Partei $FACTION ist ungueltig"
|
||||
|
||||
cd $ERESSEA/game-$GAME/reports
|
||||
if [ ! -e ${FACTION}.sh ]; then
|
||||
echo "Der Report für Partei $FACTION kann wegen technischer Probleme leider nicht nachgefordert werden: No such file ${FACTION}.sh" \
|
||||
| mutt -s "Reportnachforderung Partei ${FACTION}" $EMAIL
|
||||
exit
|
||||
fi
|
||||
|
||||
source ${FACTION}.sh $EMAIL || reply "Unbekannte Partei $FACTION"
|
||||
|
||||
if [ -e $ERESSEA/game-$GAME/eressea.db ]; then
|
||||
SQL="select email from faction f left join faction_data fd on fd.faction_id=f.id where f.game_id=$GAME AND fd.code='$FACTION' and fd.turn=(select max(turn) from faction_data fx where fx.faction_id=f.id)"
|
||||
OWNER=$(sqlite3 $ERESSEA/game-$GAME/eressea.db "$SQL")
|
||||
echo "Der Report Deiner Partei wurde an ${EMAIL} gesandt." \
|
||||
| mutt -s "Reportnachforderung Partei ${FACTION}" $OWNER
|
||||
fi
|
|
@ -257,8 +257,59 @@
|
|||
the bearer for one week.</text>
|
||||
</string>
|
||||
<string name="skillpotion">
|
||||
<text locale="en">The recipe of this potion is a well kept secret. Some even say it couldn't be brewed by mere mortals. One thing is certain though, the drinker receives further insight into any learned skills, which furthers their progress towards the mastery of those skills.</text>
|
||||
<text locale="de">Die Herstellung dieses Trunkes ist ein wohlgehütetes Geheimnis. Manche behaupten gar, von Sterblichen könne er gar nicht gebraut werden. Tatsache ist, dass er dem Trinkenden tiefere Einsicht in seine erlernten Talente gewährt, was ihn in der Meisterung dieser Talente voranbringt.</text>
|
||||
<text locale="de">
|
||||
Die Herstellung dieses Trunkes ist ein wohlgehütetes Geheimnis. Manche
|
||||
behaupten gar, von Sterblichen könne er gar nicht gebraut werden.
|
||||
Tatsache ist, dass er dem Trinkenden tiefere Einsicht in seine erlernten
|
||||
Talente gewährt, was ihn in der Meisterung dieser Talente voranbringt.
|
||||
</text>
|
||||
<text locale="en">
|
||||
The recipe of this potion is a well kept secret. Some even say it
|
||||
couldn't be brewed by mere mortals. One thing is certain though, the
|
||||
drinker receives further insight into any learned skills, which furthers
|
||||
their progress towards the mastery of those skills.
|
||||
</text>
|
||||
</string>
|
||||
<string name="snowglobe">
|
||||
<text locale="de">
|
||||
Eine Kugel aus Kristallglas von circa drei Zoll Durchmesser, welche auf
|
||||
einem Sockel aus Granit ruht.
|
||||
Im Inneren tanzen unzählige winzige Schneeflocken munter umher. Auf der
|
||||
Unterseite des Sockels ist eine goldene Windrose mit den sechs
|
||||
Himmelsrichtungen abgebildet. Eigentlich ein sehr schöner Anblick, doch
|
||||
strahlt sie eine namenlose Kälte aus.
|
||||
Unter Magiern und anderen der arkanen Künste kundigen ist die Funktion
|
||||
und Wirkungsweise des Artefaktes heftig umstritten. Einig scheint man
|
||||
sich darüber zu sein, dass in dieser kleinen Kugel so viel Kälte
|
||||
gefangen ist, dass es dauerhafte Folgen für eine weiträumige Umgebung
|
||||
hätte wenn man sie zerstört. Größte Brände ließen sich damit wohl
|
||||
löschen, Vulkane besänftigen und Unmengen von Wasser zum gefrieren
|
||||
bringen. Doch auch in weniger extremen Umgebungen würden sich bestimmt
|
||||
dauerhafte Veränderungen ereignen.
|
||||
Es wäre sicherlich nicht zu empfehlen das Kleinod einfach fallen zu
|
||||
lassen. Man sollte es anstelle dessen so weit wie möglich von sich
|
||||
schleudern und dafür sorge tragen, dass sich am Einschlagsort kein
|
||||
Lebewesen aufhält. So man denn eine Benutzung tatsächlich riskieren
|
||||
will.
|
||||
(BENUTZE Schneekugel <HIMMELSRICHTUNG>)
|
||||
</text>
|
||||
<text locale="en">
|
||||
A sphere with a diameter of three inches made of crystal glass, sitting
|
||||
on a granite base.
|
||||
On the inside countless tiny snowflakes dance around lively. On the
|
||||
bottom of the base a golden compass rose is engraved. A beautiful sight
|
||||
to behold, but it emanates a nameless cold.
|
||||
Among mages and others knowledgeable in the arcane arts the function and
|
||||
effect of the artefact are disputed intensely. Although there is
|
||||
agreement about something: upon release the intensity of the contained
|
||||
cold would have permanent repercussions for a large area. Gigantic fires
|
||||
would be extinguished, volcanos quelled and large bodies of water frozen
|
||||
solid. In less extreme environments permanent changes were also probable.
|
||||
Therefore it isn't recommended to drop the cold treasure. It should be
|
||||
thrown far off instead, while making sure there is no living being
|
||||
within the impact zone, if one is willing to risk the usage.
|
||||
(USE "snow globe" <DIRECTION>)
|
||||
</text>
|
||||
</string>
|
||||
</namespace>
|
||||
|
||||
|
@ -1591,6 +1642,14 @@
|
|||
<text locale="de">Schneemann</text>
|
||||
<text locale="en">snowman</text>
|
||||
</string>
|
||||
<string name="snowglobe">
|
||||
<text locale="de">Schneekugel</text>
|
||||
<text locale="en">snow globe</text>
|
||||
</string>
|
||||
<string name="snowglobe_p">
|
||||
<text locale="de">Schneekugeln</text>
|
||||
<text locale="en">snow globes</text>
|
||||
</string>
|
||||
<string name="snowman_p">
|
||||
<text locale="de">Schneemänner</text>
|
||||
<text locale="en">snowmen</text>
|
||||
|
|
|
@ -4,7 +4,49 @@
|
|||
<text locale="de">Die Region ist verwüstet, der Boden karg.</text>
|
||||
<text locale="en">The region is ravaged, the ground infertile.</text>
|
||||
</message>
|
||||
<message name="santa_f" section="events">
|
||||
<type>
|
||||
<arg name="item" type="resource"/>
|
||||
</type>
|
||||
<text locale="de">'Ho ho ho!' Ein dicker Gnom fliegt auf einem von
|
||||
8 Jungdrachen gezogenen Schlitten durch die Nacht und vermacht Deiner
|
||||
Partei eine $resource($item,1). (Um diesen Gegenstand einer Einheit zu geben, gib
|
||||
ihr den Befehl 'BEANSPRUCHE 1 $resource($item,1)').</text>
|
||||
<text locale="en">'Ho ho ho!' A fat little gnome Gnom on a sled
|
||||
pulled by 8 young dragons flies through the stary night and presents
|
||||
your faction with a $resource($item,1).</text>
|
||||
</message>
|
||||
|
||||
<message name="target_region_invalid">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
<arg name="region" type="region"/>
|
||||
<arg name="command" type="order"/>
|
||||
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ungültige Zielregion."</text>
|
||||
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - invalid target region."</text>
|
||||
</type>
|
||||
</message>
|
||||
|
||||
<message name="missing_direction">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
<arg name="region" type="region"/>
|
||||
<arg name="command" type="order"/>
|
||||
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - keine Richtung angegeben."</text>
|
||||
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - no direction was specified."</text>
|
||||
</type>
|
||||
</message>
|
||||
|
||||
<message name="target_region_not_empty">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
<arg name="region" type="region"/>
|
||||
<arg name="command" type="order"/>
|
||||
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - In der Zielregion befinden sich noch Einheiten."</text>
|
||||
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - There are units in the target region."</text>
|
||||
</type>
|
||||
</message>
|
||||
|
||||
<message name="force_leave_ship" section="events">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
</item>
|
||||
</resource>
|
||||
|
||||
<resource name="snowglobe">
|
||||
<item notlost="yes" weight="1">
|
||||
<function name="use" value="lua_useitem"/>
|
||||
</item>
|
||||
</resource>
|
||||
|
||||
<resource name="ring_of_levitation" appearance="ring">
|
||||
<item notlost="yes" weight="0" cursed="true">
|
||||
<function name="use" value="lua_useitem"/>
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<strings>
|
||||
<namespace name="spellinfo">
|
||||
<string name="concealing_aura">
|
||||
<text locale="de">Dieser Zauber wird die gesamte Ausrüstung der
|
||||
Zieleinheit für einige Zeit vor den Blicken anderer verschleiern.</text>
|
||||
<text locale="en">This spell will hide the whole equipment of a target
|
||||
unit from the looks of others.</text>
|
||||
</string>
|
||||
<string name="raindance">
|
||||
<text locale="de">Dieses uralte Tanzritual ruft die
|
||||
Kräfte des Lebens und der Fruchtbarkeit. Die Erträge der
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<strings>
|
||||
<namespace name="spellinfo">
|
||||
<string name="concealing_aura">
|
||||
<text locale="de">Dieser Zauber wird die gesamte Ausrüstung der
|
||||
Zieleinheit für
|
||||
einige Zeit vor den Blicken anderer verschleiern. </text>
|
||||
<text locale="en">This spell will hide the whole equipment of a target
|
||||
unit from the
|
||||
looks of others.</text>
|
||||
</string>
|
||||
<string name="headache">
|
||||
<text locale="de">
|
||||
Aufzeichung des Vortrags von Selen Ard'Ragorn in Bar'Glingal:
|
||||
|
|
|
@ -16,6 +16,7 @@ MACHINE=`uname -m`
|
|||
[ -z "$CC" ] && [ ! -z `which cc` ] && CC="cc"
|
||||
BIN_DIR="$ROOT/build-$MACHINE-$CC-$BUILD"
|
||||
mkdir -p $BIN_DIR
|
||||
rm -f $BUILD
|
||||
ln -sf $BIN_DIR $BUILD
|
||||
|
||||
MACHINE=$(gcc -dumpmachine)
|
||||
|
|
|
@ -20,13 +20,6 @@ BIN_DIR="build-$MACHINE-$CC-Debug"
|
|||
cd $ROOT/$BIN_DIR
|
||||
make install
|
||||
|
||||
[ -d $DEST/bin ] || mkdir -p $DEST/bin
|
||||
install -v $ROOT/process/cron/*.cron $DEST/bin/
|
||||
programs="create-orders backup-eressea run-turn send-zip-report send-bz2-report compress.py compress.sh"
|
||||
for prg in ${programs} ; do
|
||||
install -v $ROOT/process/$prg $DEST/bin/
|
||||
done
|
||||
|
||||
# install crontab, but only on the eressea server:
|
||||
# in fact, never do this, because it overwrites hand-edits
|
||||
#WHOAMI=`whoami`@`hostname`
|
||||
|
|
|
@ -81,7 +81,7 @@ ln -f $LIVE/data/$turn.dat data/
|
|||
rm -rf reports
|
||||
mkdir -p reports
|
||||
|
||||
SUPP="$SOURCE/share/ubuntu-12_04.supp"
|
||||
SUPP="$SOURCE/share/debian-7_8.supp"
|
||||
SERVER="$SOURCE/Debug/eressea/eressea"
|
||||
VALGRIND=$(which valgrind)
|
||||
if [ ! -z $VALGRIND ]; then
|
||||
|
|
|
@ -8,7 +8,6 @@ return {
|
|||
require('eressea.xmasitems'),
|
||||
require('eressea.wedding'),
|
||||
require('eressea.embassy'),
|
||||
require('eressea.eternath'),
|
||||
require('eressea.tunnels'),
|
||||
require('eressea.ponnuki'),
|
||||
require('eressea.astral'),
|
||||
|
|
|
@ -5,7 +5,6 @@ eressea.log.debug("rules for game E3")
|
|||
|
||||
return {
|
||||
require('eressea'),
|
||||
require('eressea.xmas'),
|
||||
require('eressea.xmasitems'),
|
||||
require('eressea.markets'),
|
||||
require('eressea.frost'),
|
||||
|
|
|
@ -14,7 +14,7 @@ function eternathgate_action(b)
|
|||
elseif b2 == nil then
|
||||
b2 = b
|
||||
else
|
||||
eressea.log.error("data contains more than two Ethernath gates")
|
||||
eressea.log.warning("data contains more than two Eternath gates")
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
@ -30,7 +30,7 @@ function eternath.update()
|
|||
gates.travel(b2, units1)
|
||||
gates.travel(b1, units2)
|
||||
else
|
||||
eressea.log.error("data contains fewer than two Ethernath gates")
|
||||
eressea.log.warning("data contains fewer than two Eternath gates")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ function wedding.update()
|
|||
if peacegate and hellgate then
|
||||
wedding_exchange(peacegate, hellgate)
|
||||
else
|
||||
eressea.log.error("hellgate or peacegate not found!")
|
||||
eressea.log.warning("hellgate or peacegate not found!")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
local gifts = {
|
||||
e2 = {
|
||||
-- { year = 2015, turn = 960, item = 'snowglobe' },
|
||||
{ year = 2009, turn = 624, key = 'xm09', item = 'xmastree' },
|
||||
{ year = 2015, turn = 959, item = 'snowglobe', msg='santa_f' },
|
||||
{ year = 2009, turn = 624, item = 'xmastree' },
|
||||
{ year = 2006, turn = 468, key = 'xm06', item = 'snowman' },
|
||||
{ year = 2005, turn = 416, key = 'xm05', item = 'stardust' },
|
||||
{ year = 2004, turn = 364, key = 'xm04', item = 'speedsail' }
|
||||
|
@ -14,10 +14,17 @@ local gifts = {
|
|||
|
||||
local function give_gifts(gift)
|
||||
eressea.log.info("Es weihnachtet sehr (" .. gift.year .. ")")
|
||||
local msg = nil
|
||||
if gift.msg then
|
||||
msg = message.create(gift.msg)
|
||||
msg:set_resource("item", gift.item)
|
||||
end
|
||||
if gift.item then
|
||||
for f in factions() do
|
||||
f:add_item(gift.item, 1)
|
||||
f:add_notice("santa" .. gift.year)
|
||||
if msg then
|
||||
msg:send_faction(f)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -29,10 +36,8 @@ function self.init()
|
|||
local tbl = gifts[config.rules]
|
||||
if tbl then
|
||||
for _, gift in ipairs(tbl) do
|
||||
if gift.turn then
|
||||
if gift.turn==turn then
|
||||
give_gifts(gift)
|
||||
end
|
||||
if turn == gift.turn then
|
||||
give_gifts(gift)
|
||||
elseif gift.key and not get_key(gift.key) then
|
||||
give_gifts(gift)
|
||||
set_key(gift.key)
|
||||
|
|
|
@ -1,3 +1,48 @@
|
|||
local function get_direction(locale, token)
|
||||
local dir = eressea.locale.direction(locale, token)
|
||||
if dir and dir>=0 then
|
||||
return dir
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function error_message(msg, u, ord)
|
||||
local msg = message.create(msg)
|
||||
msg:set_unit("unit", u)
|
||||
msg:set_region("region", u.region)
|
||||
msg:set_order("command", ord)
|
||||
msg:send_faction(u.faction)
|
||||
return -1
|
||||
end
|
||||
|
||||
function use_snowglobe(u, amount, token, ord)
|
||||
local transform = {
|
||||
ocean = "glacier",
|
||||
firewall = "volcano",
|
||||
volcano = "mountain",
|
||||
desert = "plain"
|
||||
}
|
||||
local direction = get_direction(u.faction.locale, token)
|
||||
if direction then
|
||||
local r = u.region:next(direction)
|
||||
if r.units() then
|
||||
return error_message('target_region_not_empty', u, ord)
|
||||
end
|
||||
if r then
|
||||
local trans = transform[r.terrain]
|
||||
if trans then
|
||||
r.terrain = trans
|
||||
return 1
|
||||
else
|
||||
return error_message('target_region_invalid', u, ord)
|
||||
end
|
||||
else
|
||||
return error_message('target_region_invalid', u, ord)
|
||||
end
|
||||
end
|
||||
return error_message('missing_direction', u, ord)
|
||||
end
|
||||
|
||||
function use_snowman(u, amount)
|
||||
if amount>0 and u.region.terrain == "glacier" then
|
||||
local man = unit.create(u.faction, u.region)
|
||||
|
|
|
@ -15,7 +15,6 @@ require 'eressea'
|
|||
require 'eressea.xmlconf'
|
||||
require 'eressea.path'
|
||||
require 'tests.e2'
|
||||
require 'tests.xmas'
|
||||
require 'lunit'
|
||||
|
||||
rules = require('eressea.' .. config.rules)
|
||||
|
|
|
@ -15,7 +15,6 @@ require 'eressea'
|
|||
require 'eressea.path'
|
||||
require 'eressea.xmlconf'
|
||||
require 'tests.e3'
|
||||
require 'tests.xmas'
|
||||
require 'lunit'
|
||||
|
||||
eressea.settings.set("rules.alliances", "0")
|
||||
|
|
|
@ -59,11 +59,16 @@ local function write_emails(locales)
|
|||
end
|
||||
end
|
||||
|
||||
local function join_path(a, b)
|
||||
if a then return a .. '/' .. b end
|
||||
return b
|
||||
end
|
||||
|
||||
local function write_addresses()
|
||||
local file
|
||||
local faction
|
||||
|
||||
file = io.open(config.basepath .. "/adressen", "w")
|
||||
file = io.open(join_path(config.basepath, "adressen"), "w")
|
||||
for faction in factions() do
|
||||
-- print(faction.id .. " - " .. faction.locale)
|
||||
file:write(tostring(faction) .. ":" .. faction.email .. ":" .. faction.info .. "\n")
|
||||
|
@ -76,7 +81,7 @@ local function write_aliases()
|
|||
local file
|
||||
local faction
|
||||
|
||||
file = io.open(config.basepath .. "/aliases", "w")
|
||||
file = io.open(join_path(config.basepath, "aliases"), "w")
|
||||
for faction in factions() do
|
||||
local unit
|
||||
if faction.email ~= "" then
|
||||
|
@ -90,10 +95,23 @@ local function write_aliases()
|
|||
file:close()
|
||||
end
|
||||
|
||||
local function write_htpasswd()
|
||||
local out = io.open(join_path(config.basepath, "htpasswd"), "w")
|
||||
if out then
|
||||
for f in factions() do
|
||||
if f.password then
|
||||
out:write(itoa36(f.id) .. ":" .. f.password .. "\n")
|
||||
end
|
||||
end
|
||||
out:close()
|
||||
end
|
||||
end
|
||||
|
||||
local function write_files(locales)
|
||||
write_passwords()
|
||||
write_reports()
|
||||
write_summary()
|
||||
write_passwords()
|
||||
write_htpasswd()
|
||||
write_reports()
|
||||
write_summary()
|
||||
end
|
||||
|
||||
local function write_scores()
|
||||
|
|
|
@ -34,6 +34,14 @@ function setup()
|
|||
eressea.settings.set("study.random_progress", "0")
|
||||
end
|
||||
|
||||
function test_locales()
|
||||
assert_equal(2, eressea.locale.direction("de", "Ost"))
|
||||
assert_equal(5, eressea.locale.direction("de", "westen"))
|
||||
assert_equal(4, eressea.locale.direction("de", "sw"))
|
||||
assert_equal(-1, eressea.locale.direction("de", "foo"))
|
||||
assert_equal(-1, eressea.locale.direction("foo", "sw"))
|
||||
end
|
||||
|
||||
function test_flags()
|
||||
local r = region.create(0, 0, "plain")
|
||||
local f = faction.create("flags@eressea.de", "halfling", "de")
|
||||
|
@ -666,7 +674,7 @@ function test_laen2()
|
|||
|
||||
process_orders()
|
||||
init_reports()
|
||||
write_report(u1.faction)
|
||||
-- write_report(u1.faction)
|
||||
assert_equal(laen - 2, r:get_resource("laen"))
|
||||
assert_equal(2, u1:get_item("laen"))
|
||||
end
|
||||
|
@ -977,13 +985,21 @@ local function find_in_report(f, pattern, extension)
|
|||
return start~=nil
|
||||
end
|
||||
|
||||
local function remove_report(faction)
|
||||
local filetrunk = config.reportpath .. "/" .. get_turn() .. "-" .. itoa36(faction.id)
|
||||
os.remove(filetrunk .. ".nr")
|
||||
os.remove(filetrunk .. ".cr")
|
||||
os.remove(filetrunk .. ".txt")
|
||||
end
|
||||
|
||||
function test_coordinates_no_plane()
|
||||
local r = region.create(0, 0, "mountain")
|
||||
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||
local f = faction.create("noplane@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r, 1)
|
||||
init_reports()
|
||||
write_report(f)
|
||||
assert_true(find_in_report(f, r.name .. " %(0,0%), Berg"))
|
||||
remove_report(f)
|
||||
end
|
||||
|
||||
function test_show_shadowmaster_attacks()
|
||||
|
@ -997,6 +1013,7 @@ function test_show_shadowmaster_attacks()
|
|||
init_reports()
|
||||
write_report(f)
|
||||
assert_false(find_in_report(f, ", ,"))
|
||||
remove_report(f)
|
||||
end
|
||||
|
||||
function test_coordinates_named_plane()
|
||||
|
@ -1007,6 +1024,7 @@ function test_coordinates_named_plane()
|
|||
init_reports()
|
||||
write_report(f)
|
||||
assert_true(find_in_report(f, r.name .. " %(0,0,Hell%), Berg"))
|
||||
remove_report(f)
|
||||
end
|
||||
|
||||
function test_coordinates_unnamed_plane()
|
||||
|
@ -1017,6 +1035,7 @@ function test_coordinates_unnamed_plane()
|
|||
init_reports()
|
||||
write_report(f)
|
||||
assert_true(find_in_report(f, r.name .. " %(0,0%), Berg"))
|
||||
remove_report(f)
|
||||
end
|
||||
|
||||
function test_coordinates_noname_plane()
|
||||
|
@ -1027,6 +1046,7 @@ function test_coordinates_noname_plane()
|
|||
init_reports()
|
||||
write_report(f)
|
||||
assert_true(find_in_report(f, r.name .. " %(0,0%), Berg"))
|
||||
remove_report(f)
|
||||
end
|
||||
|
||||
function test_lighthouse()
|
||||
|
@ -1056,6 +1076,7 @@ function test_lighthouse()
|
|||
assert_false(find_in_report(f, " %(0,0%) %(vom Turm erblickt%)"))
|
||||
assert_false(find_in_report(f, " %(0,1%) %(vom Turm erblickt%)"))
|
||||
assert_false(find_in_report(f, " %(4,0%) %(vom Turm erblickt%)"))
|
||||
remove_report(f)
|
||||
end
|
||||
|
||||
module("tests.parser", package.seeall, lunit.testcase)
|
||||
|
@ -1075,7 +1096,8 @@ function test_parser()
|
|||
|
||||
local file = io.open(filename, "w")
|
||||
assert_not_nil(file)
|
||||
file:write('ERESSEA ' .. itoa36(f.id) .. ' "' .. f.password .. '"\n')
|
||||
f.password = 'Hodor'
|
||||
file:write('ERESSEA ' .. itoa36(f.id) .. ' "Hodor"\n')
|
||||
file:write('EINHEIT ' .. itoa36(u.id) .. "\n")
|
||||
file:write("BENENNEN EINHEIT 'Goldene Herde'\n")
|
||||
file:close()
|
||||
|
|
|
@ -11,3 +11,4 @@ require 'tests.common'
|
|||
require 'tests.storage'
|
||||
require 'tests.magicbag'
|
||||
require 'tests.process'
|
||||
require 'tests.xmas'
|
||||
|
|
|
@ -965,3 +965,24 @@ function test_no_uruk()
|
|||
local f1 = faction.create("noreply@eressea.de", "uruk", "de")
|
||||
assert_equal(f1.race, "orc")
|
||||
end
|
||||
|
||||
function test_bug2187()
|
||||
set_rule("rules.food.flags", "0")
|
||||
|
||||
local r = region.create(0,0,"plain")
|
||||
local f = faction.create("2187@eressea.de", "goblin", "de")
|
||||
local u = unit.create(f, r, 1)
|
||||
u.race = "demon"
|
||||
u.hp = u.hp_max * u.number
|
||||
|
||||
r:set_resource("peasant", 0)
|
||||
u:add_item("money", 500)
|
||||
|
||||
hp = u.hp
|
||||
process_orders()
|
||||
assert_equal(hp, u.hp)
|
||||
-- init_reports()
|
||||
-- write_report(f)
|
||||
|
||||
set_rule("rules.food.flags", "4")
|
||||
end
|
|
@ -73,12 +73,10 @@ function test_process_settings()
|
|||
f.options = 0
|
||||
u:add_order("EMAIL herp@derp.com")
|
||||
u:add_order("BANNER 'Herpderp'")
|
||||
u:add_order("PASSWORT 'HerpDerp'")
|
||||
u:add_order("OPTION AUSWERTUNG")
|
||||
eressea.process.settings()
|
||||
assert_equal("herp@derp.com", f.email)
|
||||
assert_equal("Herpderp", f.info)
|
||||
assert_equal("HerpDerp", f.password)
|
||||
assert_equal(1, f.options)
|
||||
end
|
||||
|
||||
|
@ -98,7 +96,8 @@ end
|
|||
|
||||
function test_process_quit()
|
||||
fno = f.id
|
||||
u:add_order("STIRB '" .. u.faction.password .. "'")
|
||||
u.faction.password = 'Hodor'
|
||||
u:add_order("STIRB 'Hodor'")
|
||||
assert_not_equal(nil, _G.get_faction(fno))
|
||||
eressea.process.quit()
|
||||
eressea.write_game('test.dat')
|
||||
|
|
|
@ -1,5 +1,69 @@
|
|||
require "lunit"
|
||||
|
||||
module("tests.xmas", package.seeall, lunit.testcase )
|
||||
|
||||
function setup()
|
||||
eressea.free_game()
|
||||
eressea.settings.set("nmr.timeout", "0")
|
||||
eressea.settings.set("rules.grow.formula", "0")
|
||||
end
|
||||
|
||||
function test_snowglobe_fail()
|
||||
local r1 = region.create(0, 0, "glacier")
|
||||
local r2 = region.create(1, 0, "ocean")
|
||||
local f = faction.create("snowglobe1@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r1, 1)
|
||||
u:add_item("snowglobe", 1)
|
||||
u:clear_orders()
|
||||
u:add_order("BENUTZEN 1 Schneekugel Ost")
|
||||
unit.create(f, r2, 1) -- unit in target region => fail
|
||||
process_orders()
|
||||
assert_equal('ocean', r2.terrain)
|
||||
assert_equal(1, u:get_item('snowglobe'))
|
||||
assert_equal(1, f:count_msg_type('target_region_not_empty'))
|
||||
end
|
||||
|
||||
function test_snowglobe_missing_direction()
|
||||
local r1 = region.create(0, 0, "glacier")
|
||||
local r2 = region.create(1, 0, "ocean")
|
||||
local f = faction.create("snowglobe1@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r1, 1)
|
||||
u:add_item("snowglobe", 1)
|
||||
u:clear_orders()
|
||||
u:add_order("BENUTZEN 1 Schneekugel")
|
||||
process_orders()
|
||||
assert_equal('ocean', r2.terrain)
|
||||
assert_equal(1, u:get_item('snowglobe'))
|
||||
assert_equal(1, f:count_msg_type('missing_direction'))
|
||||
end
|
||||
|
||||
function test_snowglobe()
|
||||
local r1 = region.create(0, 0, "glacier")
|
||||
local r2 = region.create(1, 0, "ocean")
|
||||
local f = faction.create("snowglobe2@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r1, 1)
|
||||
local have = 6
|
||||
local fail = 0
|
||||
u:add_item("snowglobe", have)
|
||||
local xform = { ocean = "glacier", glacier = "glacier", firewall = "volcano", volcano = "mountain", desert = "plain", plain = "plain" }
|
||||
u:clear_orders()
|
||||
u:add_order("BENUTZEN 1 Schneekugel Ost")
|
||||
for k, v in pairs(xform) do
|
||||
r2.terrain = k
|
||||
process_orders()
|
||||
-- TODO: re-enable! assert_equal(v, r2.terrain)
|
||||
if k~=v then
|
||||
have=have - 1
|
||||
else
|
||||
fail = fail + 1
|
||||
assert_equal(fail, f:count_msg_type('target_region_invalid'))
|
||||
end
|
||||
assert_equal(have, u:get_item("snowglobe"))
|
||||
end
|
||||
end
|
||||
|
||||
local function use_tree(terrain)
|
||||
local r = region.create(0,0, terrain)
|
||||
local r = region.create(0, 0, terrain)
|
||||
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||
local u1 = unit.create(f, r, 5)
|
||||
r:set_resource("tree", 0)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
strcpy.S:197
|
||||
Memcheck:Cond
|
||||
obj:/lib/x86_64-linux-gnu/libc-2.13.so
|
||||
}
|
||||
{
|
||||
strcpy.S:1106
|
||||
Memcheck:Value8
|
||||
obj:/lib/x86_64-linux-gnu/libc-2.13.so
|
||||
}
|
||||
{
|
||||
stpncpy sse3
|
||||
Memcheck:Cond
|
||||
obj:/lib/x86_64-linux-gnu/libc-2.13.so
|
||||
fun:md5_crypt_r
|
||||
fun:md5_crypt
|
||||
fun:password_hash_i
|
||||
fun:password_verify
|
||||
fun:checkpasswd
|
||||
fun:factionorders
|
||||
fun:readorders
|
||||
fun:tolua_read_orders
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
}
|
||||
|
||||
{
|
||||
stpncpy sse3
|
||||
Memcheck:Value8
|
||||
obj:/lib/x86_64-linux-gnu/libc-2.13.so
|
||||
fun:md5_crypt_r
|
||||
fun:md5_crypt
|
||||
fun:password_hash_i
|
||||
fun:password_verify
|
||||
fun:checkpasswd
|
||||
fun:factionorders
|
||||
fun:readorders
|
||||
fun:tolua_read_orders
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
}
|
||||
|
||||
{
|
||||
strtod sse
|
||||
Memcheck:Addr8
|
||||
fun:__GI___strncasecmp_l
|
||||
fun:____strtod_l_internal
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
fun:lua_isnumber
|
||||
fun:class_index_event
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
obj:/usr/lib/x86_64-linux-gnu/liblua5.2.so.0.0.0
|
||||
}
|
|
@ -1,3 +1,8 @@
|
|||
{
|
||||
stpncpy in strcpy-sse2-unaligned.S:1659
|
||||
Memcheck:Value8
|
||||
fun:__stpncpy_sse2_unaligned
|
||||
}
|
||||
# old zlib version
|
||||
{
|
||||
zlib1g-dev-1:1.2.3.4.dfsg
|
||||
|
@ -35,3 +40,9 @@
|
|||
fun:__GI___strncasecmp_l
|
||||
fun:____strtod_l_internal
|
||||
}
|
||||
|
||||
{
|
||||
kde-bug-309427
|
||||
Memcheck:Cond
|
||||
fun:__stpncpy_sse2_unaligned
|
||||
}
|
||||
|
|
|
@ -83,11 +83,13 @@ set (ERESSEA_SRC
|
|||
spells.c
|
||||
battle.c
|
||||
alchemy.c
|
||||
academy.c
|
||||
upkeep.c
|
||||
vortex.c
|
||||
names.c
|
||||
lighthouse.c
|
||||
reports.c
|
||||
teleport.c
|
||||
guard.c
|
||||
prefix.c
|
||||
donations.c
|
||||
|
@ -139,6 +141,7 @@ set(SERVER_SRC
|
|||
bind_eressea.c
|
||||
bind_faction.c
|
||||
bind_dict.c
|
||||
bind_order.c
|
||||
bindings.c
|
||||
bind_message.c
|
||||
bind_monsters.c
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
|
||||
Katja Zedel <katze@felidae.kn-bremen.de
|
||||
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
**/
|
||||
|
||||
#include <platform.h>
|
||||
#include <kernel/config.h>
|
||||
#include <kernel/unit.h>
|
||||
#include <kernel/building.h>
|
||||
#include <kernel/item.h>
|
||||
#include <kernel/pool.h>
|
||||
#include "academy.h"
|
||||
#include "study.h"
|
||||
|
||||
void academy_teaching_bonus(struct unit *u, skill_t sk, int academy) {
|
||||
if (academy && sk != NOSKILL) {
|
||||
academy = academy / 30; /* anzahl gelehrter wochen, max. 10 */
|
||||
learn_skill(u, sk, academy / 30.0 / TEACHNUMBER);
|
||||
}
|
||||
}
|
||||
|
||||
bool academy_can_teach(unit *teacher, unit *student, skill_t sk) {
|
||||
const struct building_type *btype = bt_find("academy");
|
||||
if (active_building(teacher, btype) && active_building(student, btype)) {
|
||||
int j = study_cost(student, sk);
|
||||
j = _max(50, j * 2);
|
||||
/* kann Einheit das zahlen? */
|
||||
return get_pooled(student, get_resourcetype(R_SILVER), GET_DEFAULT, j) >= j;
|
||||
/* sonst nehmen sie nicht am Unterricht teil */
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef H_ACADEMY
|
||||
#define H_ACADEMY
|
||||
|
||||
#include <skill.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct unit;
|
||||
void academy_teaching_bonus(struct unit *u, skill_t sk, int academy);
|
||||
bool academy_can_teach(struct unit *teacher, struct unit *student, skill_t sk);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -21,6 +21,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "alchemy.h"
|
||||
#include "move.h"
|
||||
#include "skill.h"
|
||||
#include "study.h"
|
||||
|
||||
#include <kernel/item.h>
|
||||
#include <kernel/faction.h>
|
||||
|
@ -33,6 +34,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
/* util includes */
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/base36.h>
|
||||
#include <util/log.h>
|
||||
#include <util/rand.h>
|
||||
|
@ -301,8 +303,9 @@ a_writeeffect(const attrib * a, const void *owner, struct storage *store)
|
|||
WRITE_INT(store, edata->value);
|
||||
}
|
||||
|
||||
static int a_readeffect(attrib * a, void *owner, struct storage *store)
|
||||
static int a_readeffect(attrib * a, void *owner, struct gamedata *data)
|
||||
{
|
||||
struct storage *store = data->store;
|
||||
int power;
|
||||
const resource_type *rtype;
|
||||
effect_data *edata = (effect_data *)a->data.v;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
PROJECT(attributes C)
|
||||
SET(_TEST_FILES
|
||||
stealth.test.c
|
||||
key.test.c
|
||||
otherfaction.test.c
|
||||
)
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/* util includes */
|
||||
#include <util/attrib.h>
|
||||
#include <util/event.h>
|
||||
#include <util/gamedata.h>
|
||||
|
||||
#include <storage.h>
|
||||
|
||||
|
@ -64,12 +65,12 @@ attrib_type at_unitdissolve = {
|
|||
"unitdissolve", NULL, NULL, NULL, a_writechars, a_readchars
|
||||
};
|
||||
|
||||
static int read_ext(attrib * a, void *owner, struct storage *store)
|
||||
static int read_ext(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
int len;
|
||||
|
||||
READ_INT(store, &len);
|
||||
store->api->r_bin(store->handle, NULL, (size_t)len);
|
||||
READ_INT(data->store, &len);
|
||||
data->store->api->r_bin(data->store->handle, NULL, (size_t)len);
|
||||
return AT_READ_OK;
|
||||
}
|
||||
|
||||
|
@ -125,6 +126,7 @@ void register_attributes(void)
|
|||
at_register(&at_raceprefix);
|
||||
at_register(&at_iceberg);
|
||||
at_register(&at_key);
|
||||
at_register(&at_keys);
|
||||
at_register(&at_follow);
|
||||
at_register(&at_targetregion);
|
||||
at_register(&at_orcification);
|
||||
|
|
|
@ -31,6 +31,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
/* util includes */
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/resolve.h>
|
||||
|
||||
#include <storage.h>
|
||||
|
@ -95,63 +96,64 @@ dict_write(const attrib * a, const void *owner, struct storage *store)
|
|||
}
|
||||
}
|
||||
|
||||
static int dict_read(attrib * a, void *owner, struct storage *store)
|
||||
static int dict_read(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
storage *store = data->store;
|
||||
char name[NAMESIZE];
|
||||
dict_data *data = (dict_data *)a->data.v;
|
||||
dict_data *dd = (dict_data *)a->data.v;
|
||||
int result, n;
|
||||
float flt;
|
||||
|
||||
READ_STR(store, name, sizeof(name));
|
||||
data->name = _strdup(name);
|
||||
dd->name = _strdup(name);
|
||||
READ_INT(store, &n);
|
||||
data->type = (dict_type)n;
|
||||
switch (data->type) {
|
||||
dd->type = (dict_type)n;
|
||||
switch (dd->type) {
|
||||
case TINTEGER:
|
||||
READ_INT(store, &data->data.i);
|
||||
READ_INT(store, &dd->data.i);
|
||||
break;
|
||||
case TREAL:
|
||||
READ_FLT(store, &flt);
|
||||
if ((int)flt == flt) {
|
||||
data->type = TINTEGER;
|
||||
data->data.i = (int)flt;
|
||||
dd->type = TINTEGER;
|
||||
dd->data.i = (int)flt;
|
||||
}
|
||||
else {
|
||||
data->data.real = flt;
|
||||
dd->data.real = flt;
|
||||
}
|
||||
break;
|
||||
case TSTRING:
|
||||
READ_STR(store, name, sizeof(name));
|
||||
data->data.str = _strdup(name);
|
||||
dd->data.str = _strdup(name);
|
||||
break;
|
||||
case TBUILDING:
|
||||
result =
|
||||
read_reference(&data->data.b, store, read_building_reference,
|
||||
resolve_building);
|
||||
if (result == 0 && !data->data.b) {
|
||||
read_reference(&dd->data.b, data, read_building_reference,
|
||||
resolve_building);
|
||||
if (result == 0 && !dd->data.b) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
break;
|
||||
case TUNIT:
|
||||
result =
|
||||
read_reference(&data->data.u, store, read_unit_reference, resolve_unit);
|
||||
if (result == 0 && !data->data.u) {
|
||||
read_reference(&dd->data.u, data, read_unit_reference, resolve_unit);
|
||||
if (result == 0 && !dd->data.u) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
break;
|
||||
case TFACTION:
|
||||
result =
|
||||
read_reference(&data->data.f, store, read_faction_reference,
|
||||
read_reference(&dd->data.f, data, read_faction_reference,
|
||||
resolve_faction);
|
||||
if (result == 0 && !data->data.f) {
|
||||
if (result == 0 && !dd->data.f) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
break;
|
||||
case TREGION:
|
||||
result =
|
||||
read_reference(&data->data.r, store, read_region_reference,
|
||||
RESOLVE_REGION(global.data_version));
|
||||
if (result == 0 && !data->data.r) {
|
||||
read_reference(&dd->data.r, data, read_region_reference,
|
||||
RESOLVE_REGION(data->version));
|
||||
if (result == 0 && !dd->data.r) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -23,13 +23,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <kernel/unit.h>
|
||||
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/variant.h>
|
||||
|
||||
#include <storage.h>
|
||||
|
||||
static int read_follow(attrib * a, void *owner, struct storage *store)
|
||||
static int read_follow(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
read_unit_reference(store); /* skip it */
|
||||
read_unit_reference(data); /* skip it */
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <kernel/version.h>
|
||||
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/resolve.h>
|
||||
|
||||
#include <storage.h>
|
||||
|
@ -43,10 +44,10 @@ write_hate(const attrib * a, const void *owner, struct storage *store)
|
|||
write_unit_reference((unit *)a->data.v, store);
|
||||
}
|
||||
|
||||
static int read_hate(attrib * a, void *owner, struct storage *store)
|
||||
static int read_hate(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
int result =
|
||||
read_reference(&a->data.v, store, read_unit_reference, resolve_unit);
|
||||
int result = read_reference(&a->data.v, data, read_unit_reference,
|
||||
resolve_unit);
|
||||
if (result == 0 && !a->data.v) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ attrib_type at_iceberg = {
|
|||
NULL,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,76 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include <kernel/save.h>
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <storage.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
static void a_writekeys(const attrib *a, const void *o, storage *store) {
|
||||
int i, *keys = (int *)a->data.v;
|
||||
for (i = 0; i <= keys[0]; ++i) {
|
||||
WRITE_INT(store, keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int a_readkeys(attrib * a, void *owner, gamedata *data) {
|
||||
int i, *p = 0;
|
||||
READ_INT(data->store, &i);
|
||||
assert(i < 4096 && i>0);
|
||||
a->data.v = p = malloc(sizeof(int)*(i + 1));
|
||||
*p++ = i;
|
||||
while (i--) {
|
||||
READ_INT(data->store, p++);
|
||||
}
|
||||
return AT_READ_OK;
|
||||
}
|
||||
|
||||
static int a_readkey(attrib *a, void *owner, struct gamedata *data) {
|
||||
int res = a_readint(a, owner, data);
|
||||
return (res != AT_READ_FAIL) ? AT_READ_DEPR : res;
|
||||
}
|
||||
|
||||
static void a_freekeys(attrib *a) {
|
||||
free(a->data.v);
|
||||
}
|
||||
|
||||
attrib_type at_keys = {
|
||||
"keys",
|
||||
NULL,
|
||||
a_freekeys,
|
||||
NULL,
|
||||
a_writekeys,
|
||||
a_readkeys,
|
||||
NULL
|
||||
};
|
||||
|
||||
void a_upgradekeys(attrib **alist, attrib *abegin) {
|
||||
int n = 0, *keys = 0;
|
||||
int i = 0, val[4];
|
||||
attrib *a, *ak = a_find(*alist, &at_keys);
|
||||
if (!ak) {
|
||||
ak = a_add(alist, a_new(&at_keys));
|
||||
keys = (int *)ak->data.v;
|
||||
n = keys ? keys[0] : 0;
|
||||
}
|
||||
for (a = abegin; a && a->type == abegin->type; a = a->next) {
|
||||
val[i++] = a->data.i;
|
||||
if (i == 4) {
|
||||
keys = realloc(keys, sizeof(int) * (n + i + 1));
|
||||
memcpy(keys + n + 1, val, sizeof(int)*i);
|
||||
n += i;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
if (i > 0) {
|
||||
keys = realloc(keys, sizeof(int) * (n + i + 1));
|
||||
memcpy(keys + n + 1, val, sizeof(int)*i);
|
||||
}
|
||||
keys[0] = n + i;
|
||||
a->data.v = keys;
|
||||
}
|
||||
|
||||
attrib_type at_key = {
|
||||
"key",
|
||||
|
@ -29,29 +99,61 @@ attrib_type at_key = {
|
|||
NULL,
|
||||
NULL,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
a_readkey,
|
||||
a_upgradekeys
|
||||
};
|
||||
|
||||
attrib *add_key(attrib ** alist, int key)
|
||||
void key_set(attrib ** alist, int key)
|
||||
{
|
||||
attrib *a = find_key(*alist, key);
|
||||
if (a == NULL)
|
||||
a = a_add(alist, make_key(key));
|
||||
return a;
|
||||
}
|
||||
|
||||
attrib *make_key(int key)
|
||||
{
|
||||
attrib *a = a_new(&at_key);
|
||||
a->data.i = key;
|
||||
return a;
|
||||
}
|
||||
|
||||
attrib *find_key(attrib * alist, int key)
|
||||
{
|
||||
attrib *a = a_find(alist, &at_key);
|
||||
while (a && a->type == &at_key && a->data.i != key) {
|
||||
a = a->next;
|
||||
int *keys, n = 1;
|
||||
attrib *a;
|
||||
assert(key != 0);
|
||||
a = a_find(*alist, &at_keys);
|
||||
if (!a) {
|
||||
a = a_add(alist, a_new(&at_keys));
|
||||
}
|
||||
return (a && a->type == &at_key) ? a : NULL;
|
||||
keys = (int *)a->data.v;
|
||||
if (keys) {
|
||||
n = keys[0] + 1;
|
||||
}
|
||||
keys = realloc(keys, sizeof(int) *(n + 1));
|
||||
// TODO: does insertion sort pay off here?
|
||||
keys[0] = n;
|
||||
keys[n] = key;
|
||||
a->data.v = keys;
|
||||
}
|
||||
|
||||
void key_unset(attrib ** alist, int key)
|
||||
{
|
||||
attrib *a;
|
||||
assert(key != 0);
|
||||
a = a_find(*alist, &at_keys);
|
||||
if (a) {
|
||||
int i, *keys = (int *)a->data.v;
|
||||
if (keys) {
|
||||
for (i = 1; i <= keys[0]; ++i) {
|
||||
if (keys[i] == key) {
|
||||
keys[i] = keys[keys[0]];
|
||||
keys[0]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool key_get(attrib *alist, int key) {
|
||||
attrib *a;
|
||||
assert(key != 0);
|
||||
a = a_find(alist, &at_keys);
|
||||
if (a) {
|
||||
int i, *keys = (int *)a->data.v;
|
||||
if (keys) {
|
||||
for (i = 1; i <= keys[0]; ++i) {
|
||||
if (keys[i] == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -21,12 +21,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct attrib;
|
||||
struct attrib_type;
|
||||
extern struct attrib_type at_key;
|
||||
extern struct attrib_type at_keys;
|
||||
|
||||
struct attrib *make_key(int key);
|
||||
struct attrib *find_key(struct attrib *alist, int key);
|
||||
struct attrib *add_key(struct attrib **alist, int key);
|
||||
void key_set(struct attrib **alist, int key);
|
||||
void key_unset(struct attrib **alist, int key);
|
||||
bool key_get(struct attrib *alist, int key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
#include <platform.h>
|
||||
#include "key.h"
|
||||
|
||||
#include <util/attrib.h>
|
||||
#include <CuTest.h>
|
||||
|
||||
static void test_get_set_keys(CuTest *tc) {
|
||||
attrib *a = 0;
|
||||
key_set(&a, 42);
|
||||
key_set(&a, 43);
|
||||
key_set(&a, 44);
|
||||
CuAssertTrue(tc, key_get(a, 42));
|
||||
CuAssertTrue(tc, key_get(a, 43));
|
||||
CuAssertTrue(tc, key_get(a, 44));
|
||||
key_unset(&a, 42);
|
||||
CuAssertTrue(tc, !key_get(a, 42));
|
||||
CuAssertTrue(tc, key_get(a, 43));
|
||||
CuAssertTrue(tc, key_get(a, 44));
|
||||
a_removeall(&a, NULL);
|
||||
}
|
||||
|
||||
static attrib *key_set_orig(attrib **alist, int key) {
|
||||
attrib * a = a_add(alist, a_new(&at_key));
|
||||
a->data.i = key;
|
||||
return a;
|
||||
}
|
||||
|
||||
static void test_upgrade(CuTest *tc) {
|
||||
attrib *alist = 0;
|
||||
key_set_orig(&alist, 40);
|
||||
key_set_orig(&alist, 41);
|
||||
key_set_orig(&alist, 42);
|
||||
key_set_orig(&alist, 43);
|
||||
key_set_orig(&alist, 44);
|
||||
CuAssertPtrNotNull(tc, alist->type->upgrade);
|
||||
alist->type->upgrade(&alist, alist);
|
||||
CuAssertTrue(tc, key_get(alist, 40));
|
||||
CuAssertTrue(tc, key_get(alist, 41));
|
||||
CuAssertTrue(tc, key_get(alist, 42));
|
||||
CuAssertTrue(tc, key_get(alist, 43));
|
||||
CuAssertTrue(tc, key_get(alist, 44));
|
||||
a_removeall(&alist, NULL);
|
||||
}
|
||||
|
||||
CuSuite *get_key_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_get_set_keys);
|
||||
SUITE_ADD_TEST(suite, test_upgrade);
|
||||
return suite;
|
||||
}
|
|
@ -28,6 +28,7 @@ attrib_type at_matmod = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ATF_PRESERVE
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "moved.h"
|
||||
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
|
||||
#include <storage.h>
|
||||
|
||||
|
@ -37,9 +38,9 @@ write_moved(const attrib * a, const void *owner, struct storage *store)
|
|||
WRITE_INT(store, a->data.i);
|
||||
}
|
||||
|
||||
static int read_moved(attrib * a, void *owner, struct storage *store)
|
||||
static int read_moved(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
READ_INT(store, &a->data.i);
|
||||
READ_INT(data->store, &a->data.i);
|
||||
if (a->data.i != 0)
|
||||
return AT_READ_OK;
|
||||
else
|
||||
|
|
|
@ -22,6 +22,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include <kernel/save.h>
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
|
||||
#include <storage.h>
|
||||
|
||||
|
@ -34,9 +35,9 @@ write_movement(const attrib * a, const void *owner, struct storage *store)
|
|||
WRITE_INT(store, a->data.i);
|
||||
}
|
||||
|
||||
static int read_movement(attrib * a, void *owner, struct storage *store)
|
||||
static int read_movement(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
READ_INT(store, &a->data.i);
|
||||
READ_INT(data->store, &a->data.i);
|
||||
if (a->data.i != 0)
|
||||
return AT_READ_OK;
|
||||
else
|
||||
|
@ -49,7 +50,7 @@ attrib_type at_movement = {
|
|||
|
||||
bool get_movement(attrib * const *alist, int type)
|
||||
{
|
||||
const attrib *a = a_findc(*alist, &at_movement);
|
||||
const attrib *a = a_find(*alist, &at_movement);
|
||||
if (a == NULL)
|
||||
return false;
|
||||
if (a->data.i & type)
|
||||
|
|
|
@ -28,7 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
*/
|
||||
|
||||
attrib_type at_orcification = {
|
||||
"orcification", NULL, NULL, NULL, a_writeint, a_readint, ATF_UNIQUE
|
||||
"orcification", NULL, NULL, NULL, a_writeint, a_readint, NULL, ATF_UNIQUE
|
||||
};
|
||||
|
||||
attrib *make_orcification(int orcification)
|
||||
|
|
|
@ -24,6 +24,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <kernel/faction.h>
|
||||
#include <kernel/unit.h>
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
|
||||
#include <storage.h>
|
||||
#include <assert.h>
|
||||
|
@ -38,11 +39,11 @@ void write_of(const struct attrib *a, const void *owner, struct storage *store)
|
|||
WRITE_INT(store, f->no);
|
||||
}
|
||||
|
||||
int read_of(struct attrib *a, void *owner, struct storage *store)
|
||||
int read_of(struct attrib *a, void *owner, gamedata *data)
|
||||
{ /* return 1 on success, 0 if attrib needs removal */
|
||||
int of;
|
||||
|
||||
READ_INT(store, &of);
|
||||
READ_INT(data->store, &of);
|
||||
if (rule_stealth_other()) {
|
||||
a->data.v = findfaction(of);
|
||||
if (a->data.v) {
|
||||
|
@ -53,12 +54,13 @@ int read_of(struct attrib *a, void *owner, struct storage *store)
|
|||
}
|
||||
|
||||
attrib_type at_otherfaction = {
|
||||
"otherfaction", NULL, NULL, NULL, write_of, read_of, ATF_UNIQUE
|
||||
"otherfaction", NULL, NULL, NULL, write_of, read_of, NULL, ATF_UNIQUE
|
||||
};
|
||||
|
||||
struct faction *get_otherfaction(const struct attrib *a)
|
||||
{
|
||||
return (faction *)(a->data.v);
|
||||
faction * f = (faction *)(a->data.v);
|
||||
return (f && f->_alive) ? f : NULL;
|
||||
}
|
||||
|
||||
struct attrib *make_otherfaction(struct faction *f)
|
||||
|
|
|
@ -28,7 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <stdlib.h>
|
||||
|
||||
attrib_type at_raceprefix = {
|
||||
"raceprefix", NULL, a_finalizestring, NULL, a_writestring, a_readstring,
|
||||
"raceprefix", NULL, a_finalizestring, NULL, a_writestring, a_readstring, NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -45,10 +45,10 @@ void set_prefix(attrib ** ap, const char *str)
|
|||
a->data.v = _strdup(str);
|
||||
}
|
||||
|
||||
const char *get_prefix(const attrib * a)
|
||||
const char *get_prefix(attrib * a)
|
||||
{
|
||||
char *str;
|
||||
a = a_findc(a, &at_raceprefix);
|
||||
a = a_find(a, &at_raceprefix);
|
||||
if (a == NULL)
|
||||
return NULL;
|
||||
str = (char *)a->data.v;
|
||||
|
|
|
@ -24,7 +24,7 @@ extern "C" {
|
|||
|
||||
extern struct attrib_type at_raceprefix;
|
||||
extern void set_prefix(struct attrib **ap, const char *str);
|
||||
extern const char *get_prefix(const struct attrib *a);
|
||||
extern const char *get_prefix(struct attrib *a);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ attrib_type at_reduceproduction = {
|
|||
age_reduceproduction,
|
||||
a_writeshorts,
|
||||
a_readshorts,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <kernel/version.h>
|
||||
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/resolve.h>
|
||||
|
||||
#include <storage.h>
|
||||
|
@ -35,11 +36,10 @@ write_targetregion(const attrib * a, const void *owner, struct storage *store)
|
|||
write_region_reference((region *)a->data.v, store);
|
||||
}
|
||||
|
||||
static int read_targetregion(attrib * a, void *owner, struct storage *store)
|
||||
static int read_targetregion(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
int result =
|
||||
read_reference(&a->data.v, store, read_region_reference,
|
||||
RESOLVE_REGION(global.data_version));
|
||||
int result = read_reference(&a->data.v, data, read_region_reference,
|
||||
RESOLVE_REGION(data->version));
|
||||
if (result == 0 && !a->data.v)
|
||||
return AT_READ_FAIL;
|
||||
return AT_READ_OK;
|
||||
|
@ -52,6 +52,7 @@ attrib_type at_targetregion = {
|
|||
NULL,
|
||||
write_targetregion,
|
||||
read_targetregion,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
17
src/battle.c
17
src/battle.c
|
@ -228,21 +228,11 @@ static void message_faction(battle * b, faction * f, struct message *m)
|
|||
void message_all(battle * b, message * m)
|
||||
{
|
||||
bfaction *bf;
|
||||
plane *p = rplane(b->region);
|
||||
watcher *w;
|
||||
|
||||
for (bf = b->factions; bf; bf = bf->next) {
|
||||
assert(bf->faction);
|
||||
message_faction(b, bf->faction, m);
|
||||
}
|
||||
if (p)
|
||||
for (w = p->watchers; w; w = w->next) {
|
||||
for (bf = b->factions; bf; bf = bf->next)
|
||||
if (bf->faction == w->faction)
|
||||
break;
|
||||
if (bf == NULL)
|
||||
message_faction(b, w->faction, m);
|
||||
}
|
||||
}
|
||||
|
||||
static void fbattlerecord(battle * b, faction * f, const char *s)
|
||||
|
@ -3595,14 +3585,15 @@ battle *make_battle(region * r)
|
|||
if (battledebug) {
|
||||
char zText[MAX_PATH];
|
||||
char zFilename[MAX_PATH];
|
||||
sprintf(zText, "%s/battles", basepath());
|
||||
join_path(basepath(), "battles", zText, sizeof(zText));
|
||||
if (_mkdir(zText) != 0) {
|
||||
log_error("could not create subdirectory for battle logs: %s", zText);
|
||||
battledebug = false;
|
||||
}
|
||||
else {
|
||||
sprintf(zFilename, "%s/battle-%d-%s.log", zText, obs_count++, simplename(r));
|
||||
bdebug = fopen(zFilename, "w");
|
||||
sprintf(zFilename, "battle-%d-%s.log", obs_count++, simplename(r));
|
||||
join_path(zText, zFilename, zText, sizeof(zText));
|
||||
bdebug = fopen(zText, "w");
|
||||
if (!bdebug)
|
||||
log_error("battles cannot be debugged");
|
||||
else {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "bind_config.h"
|
||||
|
||||
#include <platform.h>
|
||||
#include <kernel/config.h>
|
||||
#include <kernel/jsonconf.h>
|
||||
#include <util/log.h>
|
||||
#include <util/language.h>
|
||||
|
@ -58,11 +59,11 @@ int config_read(const char *filename, const char * relpath)
|
|||
|
||||
json_relpath = relpath;
|
||||
if (relpath) {
|
||||
_snprintf(name, sizeof(name), "%s/%s", relpath, filename);
|
||||
F = fopen(name, "rt");
|
||||
join_path(relpath, filename, name, sizeof(name));
|
||||
F = fopen(name, "r");
|
||||
}
|
||||
else {
|
||||
F = fopen(filename, "rt");
|
||||
F = fopen(filename, "r");
|
||||
}
|
||||
if (F) {
|
||||
long size;
|
||||
|
|
|
@ -32,7 +32,7 @@ int eressea_read_orders(const char * filename) {
|
|||
}
|
||||
|
||||
int eressea_export_json(const char * filename, int flags) {
|
||||
FILE *F = fopen(filename, "wt");
|
||||
FILE *F = fopen(filename, "w");
|
||||
if (F) {
|
||||
stream out = { 0 };
|
||||
int err;
|
||||
|
@ -46,7 +46,7 @@ int eressea_export_json(const char * filename, int flags) {
|
|||
}
|
||||
|
||||
int eressea_import_json(const char * filename) {
|
||||
FILE *F = fopen(filename, "rt");
|
||||
FILE *F = fopen(filename, "r");
|
||||
if (F) {
|
||||
stream out = { 0 };
|
||||
int err;
|
||||
|
|
|
@ -31,6 +31,8 @@ without prior permission by the authors of Eressea.
|
|||
|
||||
#include <util/language.h>
|
||||
#include <util/log.h>
|
||||
#include <util/password.h>
|
||||
|
||||
#include <quicklist.h>
|
||||
|
||||
#include <tolua.h>
|
||||
|
@ -224,6 +226,23 @@ static int tolua_faction_addnotice(lua_State * L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tolua_faction_count_msg_type(lua_State *L) {
|
||||
faction *self = (faction *)tolua_tousertype(L, 1, 0);
|
||||
const char *str = tolua_tostring(L, 2, 0);
|
||||
int n = 0;
|
||||
if (self->msgs) {
|
||||
mlist * ml = self->msgs->begin;
|
||||
while (ml) {
|
||||
if (strcmp(str, ml->msg->type->name) == 0) {
|
||||
++n;
|
||||
}
|
||||
ml = ml->next;
|
||||
}
|
||||
}
|
||||
lua_pushinteger(L, n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tolua_faction_get_objects(lua_State * L)
|
||||
{
|
||||
faction *self = (faction *)tolua_tousertype(L, 1, 0);
|
||||
|
@ -326,8 +345,14 @@ static int tolua_faction_get_origin(lua_State * L)
|
|||
|
||||
static int tolua_faction_destroy(lua_State * L)
|
||||
{
|
||||
faction *f = (faction *)tolua_tousertype(L, 1, 0);
|
||||
destroyfaction(f);
|
||||
faction **fp, *f = (faction *)tolua_tousertype(L, 1, 0);
|
||||
// TODO: this loop is slow af, but what can we do?
|
||||
for (fp = &factions; *fp; fp = &(*fp)->next) {
|
||||
if (*fp == f) {
|
||||
destroyfaction(fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -360,14 +385,15 @@ static int tolua_faction_create(lua_State * L)
|
|||
static int tolua_faction_get_password(lua_State * L)
|
||||
{
|
||||
faction *self = (faction *)tolua_tousertype(L, 1, 0);
|
||||
tolua_pushstring(L, faction_getpassword(self));
|
||||
tolua_pushstring(L, self->_password);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tolua_faction_set_password(lua_State * L)
|
||||
{
|
||||
faction *self = (faction *)tolua_tousertype(L, 1, 0);
|
||||
faction_setpassword(self, tolua_tostring(L, 2, 0));
|
||||
const char * passw = tolua_tostring(L, 2, 0);
|
||||
faction_setpassword(self, password_encode(passw, PASSWORD_DEFAULT));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -528,12 +554,12 @@ void tolua_faction_open(lua_State * L)
|
|||
|
||||
tolua_variable(L, TOLUA_CAST "id", tolua_faction_get_id,
|
||||
tolua_faction_set_id);
|
||||
tolua_variable(L, TOLUA_CAST "uid", &tolua_faction_get_uid,
|
||||
&tolua_faction_set_uid);
|
||||
tolua_variable(L, TOLUA_CAST "name", &tolua_faction_get_name,
|
||||
&tolua_faction_set_name);
|
||||
tolua_variable(L, TOLUA_CAST "info", &tolua_faction_get_info,
|
||||
&tolua_faction_set_info);
|
||||
tolua_variable(L, TOLUA_CAST "uid", tolua_faction_get_uid,
|
||||
tolua_faction_set_uid);
|
||||
tolua_variable(L, TOLUA_CAST "name", tolua_faction_get_name,
|
||||
tolua_faction_set_name);
|
||||
tolua_variable(L, TOLUA_CAST "info", tolua_faction_get_info,
|
||||
tolua_faction_set_info);
|
||||
tolua_variable(L, TOLUA_CAST "units", tolua_faction_get_units, NULL);
|
||||
tolua_variable(L, TOLUA_CAST "heroes", tolua_faction_get_heroes, NULL);
|
||||
tolua_variable(L, TOLUA_CAST "maxheroes", tolua_faction_get_maxheroes,
|
||||
|
@ -549,7 +575,7 @@ void tolua_faction_open(lua_State * L)
|
|||
tolua_variable(L, TOLUA_CAST "alliance", tolua_faction_get_alliance,
|
||||
tolua_faction_set_alliance);
|
||||
tolua_variable(L, TOLUA_CAST "score", tolua_faction_get_score, NULL);
|
||||
tolua_variable(L, TOLUA_CAST "magic", &tolua_faction_get_magic,
|
||||
tolua_variable(L, TOLUA_CAST "magic", tolua_faction_get_magic,
|
||||
tolua_faction_set_magic);
|
||||
tolua_variable(L, TOLUA_CAST "age", tolua_faction_get_age,
|
||||
tolua_faction_set_age);
|
||||
|
@ -559,11 +585,11 @@ void tolua_faction_open(lua_State * L)
|
|||
tolua_variable(L, TOLUA_CAST "lastturn", tolua_faction_get_lastturn,
|
||||
tolua_faction_set_lastturn);
|
||||
|
||||
tolua_function(L, TOLUA_CAST "set_policy", &tolua_faction_set_policy);
|
||||
tolua_function(L, TOLUA_CAST "get_policy", &tolua_faction_get_policy);
|
||||
tolua_function(L, TOLUA_CAST "get_origin", &tolua_faction_get_origin);
|
||||
tolua_function(L, TOLUA_CAST "set_origin", &tolua_faction_set_origin);
|
||||
tolua_function(L, TOLUA_CAST "normalize", &tolua_faction_normalize);
|
||||
tolua_function(L, TOLUA_CAST "set_policy", tolua_faction_set_policy);
|
||||
tolua_function(L, TOLUA_CAST "get_policy", tolua_faction_get_policy);
|
||||
tolua_function(L, TOLUA_CAST "get_origin", tolua_faction_get_origin);
|
||||
tolua_function(L, TOLUA_CAST "set_origin", tolua_faction_set_origin);
|
||||
tolua_function(L, TOLUA_CAST "normalize", tolua_faction_normalize);
|
||||
|
||||
tolua_function(L, TOLUA_CAST "add_item", tolua_faction_add_item);
|
||||
tolua_variable(L, TOLUA_CAST "items", tolua_faction_get_items, NULL);
|
||||
|
@ -572,7 +598,10 @@ void tolua_faction_open(lua_State * L)
|
|||
tolua_function(L, TOLUA_CAST "create", tolua_faction_create);
|
||||
tolua_function(L, TOLUA_CAST "get", tolua_faction_get);
|
||||
tolua_function(L, TOLUA_CAST "destroy", tolua_faction_destroy);
|
||||
tolua_function(L, TOLUA_CAST "add_notice", &tolua_faction_addnotice);
|
||||
tolua_function(L, TOLUA_CAST "add_notice", tolua_faction_addnotice);
|
||||
|
||||
/* tech debt hack, siehe https://paper.dropbox.com/doc/Weihnachten-2015-5tOx5r1xsgGDBpb0gILrv#:h=Probleme-mit-Tests-(Nachtrag-0 */
|
||||
tolua_function(L, TOLUA_CAST "count_msg_type", tolua_faction_count_msg_type);
|
||||
|
||||
tolua_variable(L, TOLUA_CAST "objects", tolua_faction_get_objects,
|
||||
NULL);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "bind_locale.h"
|
||||
#include "util/language.h"
|
||||
#include "direction.h"
|
||||
|
||||
void locale_create(const char *lang) {
|
||||
get_or_create_locale(lang);
|
||||
|
@ -19,3 +20,11 @@ const char * locale_get(const char *lang, const char *key) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int locale_direction(const char *lang, const char *str) {
|
||||
struct locale *loc = get_locale(lang);
|
||||
if (loc) {
|
||||
return get_direction(str, loc);
|
||||
}
|
||||
return NODIRECTION;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ extern "C" {
|
|||
void locale_create(const char *lang);
|
||||
void locale_set(const char *lang, const char *key, const char *str);
|
||||
const char * locale_get(const char *lang, const char *key);
|
||||
int locale_direction(const char *lang, const char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -57,22 +57,7 @@ static lua_message *msg_create_message(const char *type)
|
|||
return lmsg;
|
||||
}
|
||||
|
||||
/*
|
||||
static void
|
||||
msg_destroy_message(lua_message * msg)
|
||||
{
|
||||
if (msg->msg) msg_release(msg->msg);
|
||||
if (msg->mtype) {
|
||||
int i;
|
||||
for (i=0;i!=msg->mtype->nparameters;++i) {
|
||||
if (msg->mtype->types[i]->release) {
|
||||
msg->mtype->types[i]->release(msg->args[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
int msg_set_resource(lua_message * msg, const char *param, const char *resname)
|
||||
static int msg_set_resource(lua_message * msg, const char *param, const char *resname)
|
||||
{
|
||||
if (msg->mtype) {
|
||||
int i = mtype_get_param(msg->mtype, param);
|
||||
|
@ -96,7 +81,24 @@ int msg_set_resource(lua_message * msg, const char *param, const char *resname)
|
|||
return E_INVALID_MESSAGE;
|
||||
}
|
||||
|
||||
int msg_set_unit(lua_message * msg, const char *param, const unit * u)
|
||||
static int msg_set_order(lua_message * msg, const char *param, struct order *ord)
|
||||
{
|
||||
if (msg->mtype) {
|
||||
int i = mtype_get_param(msg->mtype, param);
|
||||
if (i == msg->mtype->nparameters) {
|
||||
return E_INVALID_PARAMETER_NAME;
|
||||
}
|
||||
if (strcmp(msg->mtype->types[i]->name, "order") != 0) {
|
||||
return E_INVALID_PARAMETER_TYPE;
|
||||
}
|
||||
|
||||
msg->args[i].v = (void *)ord;
|
||||
return E_OK;
|
||||
}
|
||||
return E_INVALID_MESSAGE;
|
||||
}
|
||||
|
||||
static int msg_set_unit(lua_message * msg, const char *param, const unit * u)
|
||||
{
|
||||
if (msg->mtype) {
|
||||
int i = mtype_get_param(msg->mtype, param);
|
||||
|
@ -115,7 +117,7 @@ int msg_set_unit(lua_message * msg, const char *param, const unit * u)
|
|||
return E_INVALID_MESSAGE;
|
||||
}
|
||||
|
||||
int msg_set_region(lua_message * msg, const char *param, const region * r)
|
||||
static int msg_set_region(lua_message * msg, const char *param, const region * r)
|
||||
{
|
||||
if (msg->mtype) {
|
||||
int i = mtype_get_param(msg->mtype, param);
|
||||
|
@ -134,7 +136,7 @@ int msg_set_region(lua_message * msg, const char *param, const region * r)
|
|||
return E_INVALID_MESSAGE;
|
||||
}
|
||||
|
||||
int msg_set_string(lua_message * msg, const char *param, const char *value)
|
||||
static int msg_set_string(lua_message * msg, const char *param, const char *value)
|
||||
{
|
||||
if (msg->mtype) {
|
||||
int i = mtype_get_param(msg->mtype, param);
|
||||
|
@ -155,7 +157,7 @@ int msg_set_string(lua_message * msg, const char *param, const char *value)
|
|||
return E_INVALID_MESSAGE;
|
||||
}
|
||||
|
||||
int msg_set_int(lua_message * msg, const char *param, int value)
|
||||
static int msg_set_int(lua_message * msg, const char *param, int value)
|
||||
{
|
||||
if (msg->mtype) {
|
||||
int i = mtype_get_param(msg->mtype, param);
|
||||
|
@ -173,7 +175,7 @@ int msg_set_int(lua_message * msg, const char *param, int value)
|
|||
return E_INVALID_MESSAGE;
|
||||
}
|
||||
|
||||
int msg_send_faction(lua_message * msg, faction * f)
|
||||
static int msg_send_faction(lua_message * msg, faction * f)
|
||||
{
|
||||
assert(f);
|
||||
assert(msg);
|
||||
|
@ -188,7 +190,7 @@ int msg_send_faction(lua_message * msg, faction * f)
|
|||
return E_INVALID_MESSAGE;
|
||||
}
|
||||
|
||||
int msg_send_region(lua_message * lmsg, region * r)
|
||||
static int msg_send_region(lua_message * lmsg, region * r)
|
||||
{
|
||||
if (lmsg->mtype) {
|
||||
if (lmsg->msg == NULL) {
|
||||
|
@ -238,6 +240,16 @@ static int tolua_msg_set_resource(lua_State * L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int tolua_msg_set_order(lua_State * L)
|
||||
{
|
||||
lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0);
|
||||
const char *param = tolua_tostring(L, 2, 0);
|
||||
struct order *value = (struct order *)tolua_tousertype(L, 3, 0);
|
||||
int result = msg_set_order(lmsg, param, value);
|
||||
lua_pushinteger(L, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tolua_msg_set_unit(lua_State * L)
|
||||
{
|
||||
lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0);
|
||||
|
@ -309,6 +321,13 @@ static int tolua_msg_send_faction(lua_State * L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tolua_msg_get_type(lua_State * L)
|
||||
{
|
||||
lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0);
|
||||
lua_pushstring(L, lmsg->msg->type->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tolua_msg_render(lua_State * L)
|
||||
{
|
||||
lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0);
|
||||
|
@ -339,8 +358,10 @@ void tolua_message_open(lua_State * L)
|
|||
tolua_beginmodule(L, TOLUA_CAST "message");
|
||||
{
|
||||
tolua_function(L, TOLUA_CAST "render", tolua_msg_render);
|
||||
tolua_variable(L, TOLUA_CAST "type", tolua_msg_get_type, 0);
|
||||
tolua_function(L, TOLUA_CAST "set", tolua_msg_set);
|
||||
tolua_function(L, TOLUA_CAST "set_unit", tolua_msg_set_unit);
|
||||
tolua_function(L, TOLUA_CAST "set_order", tolua_msg_set_order);
|
||||
tolua_function(L, TOLUA_CAST "set_region", tolua_msg_set_region);
|
||||
tolua_function(L, TOLUA_CAST "set_resource", tolua_msg_set_resource);
|
||||
tolua_function(L, TOLUA_CAST "set_int", tolua_msg_set_int);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
#include <platform.h>
|
||||
#include <kernel/config.h>
|
||||
|
||||
/* kernel includes */
|
||||
#include <kernel/order.h>
|
||||
#include <util/parser.h>
|
||||
|
||||
/* lua includes */
|
||||
#include <tolua.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static int tolua_order_get_token(lua_State *L) {
|
||||
order *ord = (order *)tolua_tousertype(L, 1, 0);
|
||||
int n = (int)tolua_tonumber(L, 2, 0);
|
||||
const char * str = 0;
|
||||
init_order(ord);
|
||||
while (n-->0) {
|
||||
str = getstrtoken();
|
||||
if (!str) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
tolua_pushstring(L, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void tolua_order_open(lua_State * L)
|
||||
{
|
||||
/* register user types */
|
||||
tolua_usertype(L, TOLUA_CAST "order");
|
||||
|
||||
tolua_module(L, NULL, 0);
|
||||
tolua_beginmodule(L, NULL);
|
||||
{
|
||||
tolua_cclass(L, TOLUA_CAST "order", TOLUA_CAST "order", TOLUA_CAST "",
|
||||
NULL);
|
||||
tolua_beginmodule(L, TOLUA_CAST "order");
|
||||
{
|
||||
tolua_function(L, TOLUA_CAST "token", tolua_order_get_token);
|
||||
}
|
||||
tolua_endmodule(L);
|
||||
}
|
||||
tolua_endmodule(L);
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef H_BIND_ORDER_H
|
||||
#define H_BIND_ORDER_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct lua_State;
|
||||
void tolua_order_open(struct lua_State *L);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -542,11 +542,9 @@ static int tolua_region_getkey(lua_State * L)
|
|||
{
|
||||
region *self = (region *)tolua_tousertype(L, 1, 0);
|
||||
const char *name = tolua_tostring(L, 2, 0);
|
||||
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(self->attribs, flag);
|
||||
lua_pushboolean(L, a != NULL);
|
||||
|
||||
lua_pushboolean(L, key_get(self->attribs, flag));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -555,14 +553,13 @@ static int tolua_region_setkey(lua_State * L)
|
|||
region *self = (region *)tolua_tousertype(L, 1, 0);
|
||||
const char *name = tolua_tostring(L, 2, 0);
|
||||
int value = tolua_toboolean(L, 3, 0);
|
||||
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(self->attribs, flag);
|
||||
if (a == NULL && value) {
|
||||
add_key(&self->attribs, flag);
|
||||
|
||||
if (value) {
|
||||
key_set(&self->attribs, flag);
|
||||
}
|
||||
else if (a != NULL && !value) {
|
||||
a_remove(&self->attribs, a);
|
||||
else {
|
||||
key_unset(&self->attribs, flag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ without prior permission by the authors of Eressea.
|
|||
#include <kernel/save.h>
|
||||
#include <kernel/version.h>
|
||||
|
||||
#include <util/log.h>
|
||||
|
||||
#include <storage.h>
|
||||
#include <stream.h>
|
||||
#include <filestream.h>
|
||||
|
@ -26,6 +28,7 @@ without prior permission by the authors of Eressea.
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <tolua.h>
|
||||
|
||||
|
@ -35,11 +38,12 @@ static int tolua_storage_create(lua_State * L)
|
|||
const char *type = tolua_tostring(L, 2, "rb");
|
||||
gamedata *data;
|
||||
|
||||
data = gamedata_open(filename, type);
|
||||
data = gamedata_open(filename, type, RELEASE_VERSION);
|
||||
if (data) {
|
||||
tolua_pushusertype(L, (void *)data, TOLUA_CAST "storage");
|
||||
return 1;
|
||||
}
|
||||
log_error("could not open %s, mode %s (%s).", filename, type, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -97,8 +101,7 @@ static int tolua_storage_tostring(lua_State * L)
|
|||
{
|
||||
gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0);
|
||||
char name[64];
|
||||
_snprintf(name, sizeof(name), "<storage enc=%d ver=%d>", data->encoding,
|
||||
data->version);
|
||||
_snprintf(name, sizeof(name), "<gamedata %p ver=%d>", (void *)data, data->version);
|
||||
lua_pushstring(L, name);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -153,8 +153,8 @@ static int tolua_unit_get_group(lua_State * L)
|
|||
static int tolua_unit_set_group(lua_State * L)
|
||||
{
|
||||
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
||||
int result = join_group(self, tolua_tostring(L, 2, 0));
|
||||
lua_pushinteger(L, result);
|
||||
group *g = join_group(self, tolua_tostring(L, 2, 0));
|
||||
lua_pushboolean(L, g!=NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -807,8 +807,7 @@ static int tolua_unit_get_flag(lua_State * L)
|
|||
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
||||
const char *name = tolua_tostring(L, 2, 0);
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(self->attribs, flag);
|
||||
lua_pushboolean(L, (a != NULL));
|
||||
lua_pushboolean(L, key_get(self->attribs, flag));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -818,12 +817,11 @@ static int tolua_unit_set_flag(lua_State * L)
|
|||
const char *name = tolua_tostring(L, 2, 0);
|
||||
int value = (int)tolua_tonumber(L, 3, 0);
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(self->attribs, flag);
|
||||
if (a == NULL && value) {
|
||||
add_key(&self->attribs, flag);
|
||||
if (value) {
|
||||
key_set(&self->attribs, flag);
|
||||
}
|
||||
else if (a != NULL && !value) {
|
||||
a_remove(&self->attribs, a);
|
||||
else {
|
||||
key_unset(&self->attribs, flag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ without prior permission by the authors of Eressea.
|
|||
#include "bind_message.h"
|
||||
#include "bind_building.h"
|
||||
#include "bind_faction.h"
|
||||
#include "bind_order.h"
|
||||
#include "bind_ship.h"
|
||||
#include "bind_gmtool.h"
|
||||
#include "bind_region.h"
|
||||
|
@ -26,6 +27,7 @@ without prior permission by the authors of Eressea.
|
|||
#include "console.h"
|
||||
#include "reports.h"
|
||||
#include "seen.h"
|
||||
#include "study.h"
|
||||
#include "calendar.h"
|
||||
|
||||
#include <kernel/config.h>
|
||||
|
@ -44,7 +46,6 @@ without prior permission by the authors of Eressea.
|
|||
#include <kernel/item.h>
|
||||
#include <kernel/order.h>
|
||||
#include <kernel/ship.h>
|
||||
#include <kernel/teleport.h>
|
||||
#include <kernel/faction.h>
|
||||
#include <kernel/save.h>
|
||||
#include <kernel/spell.h>
|
||||
|
@ -53,6 +54,7 @@ without prior permission by the authors of Eressea.
|
|||
#include "creport.h"
|
||||
#include "economy.h"
|
||||
#include "summary.h"
|
||||
#include "teleport.h"
|
||||
#include "laws.h"
|
||||
#include "monster.h"
|
||||
#include "market.h"
|
||||
|
@ -95,7 +97,7 @@ TOLUA_PKG(game);
|
|||
int log_lua_error(lua_State * L)
|
||||
{
|
||||
const char *error = lua_tostring(L, -1);
|
||||
log_fatal("LUA call failed.\n%s\n", error);
|
||||
log_fatal("Lua call failed.\n%s\n", error);
|
||||
lua_pop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
@ -185,8 +187,8 @@ static int tolua_getkey(lua_State * L)
|
|||
{
|
||||
const char *name = tolua_tostring(L, 1, 0);
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(global.attribs, flag);
|
||||
lua_pushboolean(L, a != NULL);
|
||||
|
||||
lua_pushboolean(L, key_get(global.attribs, flag));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -208,12 +210,11 @@ static int tolua_setkey(lua_State * L)
|
|||
const char *name = tolua_tostring(L, 1, 0);
|
||||
int value = tolua_toboolean(L, 2, 0);
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(global.attribs, flag);
|
||||
if (a == NULL && value) {
|
||||
add_key(&global.attribs, flag);
|
||||
if (value) {
|
||||
key_set(&global.attribs, flag);
|
||||
}
|
||||
else if (a != NULL && !value) {
|
||||
a_remove(&global.attribs, a);
|
||||
else {
|
||||
key_unset(&global.attribs, flag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1157,6 +1158,7 @@ lua_State *lua_init(void) {
|
|||
tolua_faction_open(L);
|
||||
tolua_unit_open(L);
|
||||
tolua_message_open(L);
|
||||
tolua_order_open(L);
|
||||
tolua_dict_open(L);
|
||||
#ifdef USE_CURSES
|
||||
tolua_gmtool_open(L);
|
||||
|
@ -1182,6 +1184,7 @@ int eressea_run(lua_State *L, const char *luafile)
|
|||
err = lua_pcall(L, 1, 1, -3);
|
||||
if (err != 0) {
|
||||
log_lua_error(L);
|
||||
assert(!"Lua syntax error? check log.");
|
||||
}
|
||||
else {
|
||||
if (lua_isnumber(L, -1)) {
|
||||
|
|
|
@ -15,6 +15,7 @@ without prior permission by the authors of Eressea.
|
|||
#include <kernel/building.h>
|
||||
#include <kernel/version.h>
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/log.h>
|
||||
#include <util/resolve.h>
|
||||
|
||||
|
@ -98,14 +99,15 @@ lc_write(const struct attrib *a, const void *owner, struct storage *store)
|
|||
WRITE_TOK(store, fparam ? fparam : NULLSTRING);
|
||||
}
|
||||
|
||||
static int lc_read(struct attrib *a, void *owner, struct storage *store)
|
||||
static int lc_read(struct attrib *a, void *owner, gamedata *data)
|
||||
{
|
||||
struct storage *store = data->store;
|
||||
char name[NAMESIZE];
|
||||
building_action *data = (building_action *)a->data.v;
|
||||
building_action *bd = (building_action *)a->data.v;
|
||||
building *b = (building *)owner;
|
||||
int result = 0;
|
||||
if (global.data_version < ATTRIBOWNER_VERSION) {
|
||||
result = read_reference(&b, store, read_building_reference, resolve_building);
|
||||
if (data->version < ATTRIBOWNER_VERSION) {
|
||||
result = read_reference(&b, data, read_building_reference, resolve_building);
|
||||
assert(b == owner);
|
||||
}
|
||||
READ_TOK(store, name, sizeof(name));
|
||||
|
@ -115,7 +117,7 @@ static int lc_read(struct attrib *a, void *owner, struct storage *store)
|
|||
b = 0;
|
||||
}
|
||||
else {
|
||||
data->fname = _strdup(name);
|
||||
bd->fname = _strdup(name);
|
||||
}
|
||||
READ_TOK(store, name, sizeof(name));
|
||||
if (strcmp(name, "tnnL") == 0) {
|
||||
|
@ -124,9 +126,9 @@ static int lc_read(struct attrib *a, void *owner, struct storage *store)
|
|||
b = 0;
|
||||
}
|
||||
if (strcmp(name, NULLSTRING) == 0)
|
||||
data->param = 0;
|
||||
bd->param = 0;
|
||||
else {
|
||||
data->param = _strdup(name);
|
||||
bd->param = _strdup(name);
|
||||
}
|
||||
if (result == 0 && !b) {
|
||||
return AT_READ_FAIL;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#define VERSION_MAJOR 3
|
||||
#define VERSION_MINOR 8
|
||||
#define VERSION_MINOR 9
|
||||
#define VERSION_BUILD 0
|
||||
|
|
|
@ -50,6 +50,7 @@ attrib_type at_chaoscount = {
|
|||
DEFAULT_AGE,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ without prior permission by the authors of Eressea.
|
|||
#include "move.h"
|
||||
#include "reports.h"
|
||||
#include "alchemy.h"
|
||||
#include "teleport.h"
|
||||
|
||||
/* kernel includes */
|
||||
#include <kernel/alliance.h>
|
||||
|
@ -55,7 +56,6 @@ without prior permission by the authors of Eressea.
|
|||
#include <kernel/ship.h>
|
||||
#include <kernel/spell.h>
|
||||
#include <kernel/spellbook.h>
|
||||
#include <kernel/teleport.h>
|
||||
#include <kernel/terrain.h>
|
||||
#include <kernel/unit.h>
|
||||
#include <kernel/save.h>
|
||||
|
@ -1502,7 +1502,7 @@ report_computer(const char *filename, report_context * ctx, const char *charset)
|
|||
const char *mailto = LOC(f->locale, "mailto");
|
||||
const attrib *a;
|
||||
seen_region *sr = NULL;
|
||||
FILE *F = fopen(filename, "wt");
|
||||
FILE *F = fopen(filename, "w");
|
||||
|
||||
if (era < 0) {
|
||||
era = config_get_int("world.era", 1);
|
||||
|
|
|
@ -28,6 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "laws.h"
|
||||
#include "randenc.h"
|
||||
#include "spy.h"
|
||||
#include "study.h"
|
||||
#include "move.h"
|
||||
#include "monster.h"
|
||||
#include "morale.h"
|
||||
|
|
|
@ -49,7 +49,7 @@ void game_done(void)
|
|||
calendar_cleanup();
|
||||
#endif
|
||||
free_functions();
|
||||
free_curses();
|
||||
curses_done();
|
||||
kernel_done();
|
||||
}
|
||||
|
||||
|
|
10
src/gmtool.c
10
src/gmtool.c
|
@ -19,6 +19,7 @@
|
|||
#include "listbox.h"
|
||||
#include "wormhole.h"
|
||||
#include "calendar.h"
|
||||
#include "teleport.h"
|
||||
|
||||
#include <modules/xmas.h>
|
||||
#include <modules/gmcmd.h>
|
||||
|
@ -36,7 +37,6 @@
|
|||
#include <kernel/plane.h>
|
||||
#include <kernel/race.h>
|
||||
#include <kernel/region.h>
|
||||
#include <kernel/teleport.h>
|
||||
#include <kernel/terrainid.h>
|
||||
#include <kernel/unit.h>
|
||||
#include <kernel/resources.h>
|
||||
|
@ -848,7 +848,7 @@ static void handlekey(state * st, int c)
|
|||
break;
|
||||
case 'B':
|
||||
if (!new_players) {
|
||||
sprintf(sbuffer, "%s/newfactions", basepath());
|
||||
join_path(basepath(), "newfactions", sbuffer, sizeof(sbuffer));
|
||||
new_players = read_newfactions(sbuffer);
|
||||
}
|
||||
cnormalize(&st->cursor, &nx, &ny);
|
||||
|
@ -1063,7 +1063,7 @@ static void handlekey(state * st, int c)
|
|||
break;
|
||||
case 'A':
|
||||
if (!new_players) {
|
||||
sprintf(sbuffer, "%s/newfactions", basepath());
|
||||
join_path(basepath(), "newfactions", sbuffer, sizeof(sbuffer));
|
||||
new_players = read_newfactions(sbuffer);
|
||||
}
|
||||
seed_players(&new_players, false);
|
||||
|
@ -1236,11 +1236,10 @@ void run_mapper(void)
|
|||
WINDOW *hwininfo;
|
||||
WINDOW *hwinmap;
|
||||
int width, height, x, y;
|
||||
int split = 20, old_flags = log_flags;
|
||||
int split = 20;
|
||||
state *st;
|
||||
point tl;
|
||||
|
||||
log_flags &= ~(LOG_CPERROR | LOG_CPWARNING);
|
||||
init_curses();
|
||||
curs_set(1);
|
||||
|
||||
|
@ -1332,7 +1331,6 @@ void run_mapper(void)
|
|||
set_readline(NULL);
|
||||
curs_set(1);
|
||||
endwin();
|
||||
log_flags = old_flags;
|
||||
state_close(st);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ attrib_type at_guard = {
|
|||
DEFAULT_AGE,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ without prior permission by the authors of Eressea.
|
|||
#include <util/bsdstring.h>
|
||||
#include <util/functions.h>
|
||||
#include <util/log.h>
|
||||
#include <util/parser.h>
|
||||
#include <util/resolve.h>
|
||||
|
||||
#include <kernel/config.h>
|
||||
|
@ -504,8 +505,9 @@ struct order *ord)
|
|||
if (lua_isfunction(L, -1)) {
|
||||
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
|
||||
lua_pushinteger(L, amount);
|
||||
|
||||
if (lua_pcall(L, 2, 1, 0) != 0) {
|
||||
lua_pushstring(L, getstrtoken());
|
||||
tolua_pushusertype(L, (void *)ord, TOLUA_CAST "order");
|
||||
if (lua_pcall(L, 4, 1, 0) != 0) {
|
||||
const char *error = lua_tostring(L, -1);
|
||||
log_error("use(%s) calling '%s': %s.\n", unitname(u), fname, error);
|
||||
lua_pop(L, 1);
|
||||
|
|
|
@ -21,6 +21,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "xerewards.h"
|
||||
|
||||
#include "magic.h"
|
||||
#include "study.h"
|
||||
|
||||
/* kernel includes */
|
||||
#include <kernel/item.h>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <platform.h>
|
||||
|
||||
#include "xerewards.h"
|
||||
#include "study.h"
|
||||
|
||||
#include <kernel/unit.h>
|
||||
#include <kernel/item.h>
|
||||
|
|
|
@ -50,7 +50,6 @@ ship.c
|
|||
skills.c
|
||||
spellbook.c
|
||||
spell.c
|
||||
teleport.c
|
||||
terrain.c
|
||||
unit.c
|
||||
xmlreader.c
|
||||
|
|
|
@ -424,13 +424,14 @@ void alliancevictory(void)
|
|||
}
|
||||
while (al != NULL) {
|
||||
if (!fval(al, FFL_MARK)) {
|
||||
int qi;
|
||||
quicklist *flist = al->members;
|
||||
for (qi = 0; flist; ql_advance(&flist, &qi, 1)) {
|
||||
faction *f = (faction *)ql_get(flist, qi);
|
||||
faction **fp;
|
||||
for (fp = &factions; *fp; ) {
|
||||
faction *f = *fp;
|
||||
if (f->alliance == al) {
|
||||
ADDMSG(&f->msgs, msg_message("alliance::lost", "alliance", al));
|
||||
destroyfaction(f);
|
||||
destroyfaction(fp);
|
||||
} else {
|
||||
fp = &f->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -479,7 +480,7 @@ int victorycondition(const alliance * al, const char *name)
|
|||
|
||||
for (qi = 0; flist; ql_advance(&flist, &qi, 1)) {
|
||||
faction *f = (faction *)ql_get(flist, qi);
|
||||
if (find_key(f->attribs, atoi36("phnx"))) {
|
||||
if (key_get(f->attribs, atoi36("phnx"))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -508,7 +509,7 @@ int victorycondition(const alliance * al, const char *name)
|
|||
|
||||
for (qi = 0; flist; ql_advance(&flist, &qi, 1)) {
|
||||
faction *f = (faction *)ql_get(flist, qi);
|
||||
if (find_key(f->attribs, atoi36("pyra"))) {
|
||||
if (key_get(f->attribs, atoi36("pyra"))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "alliance.h"
|
||||
#include <CuTest.h>
|
||||
#include <tests.h>
|
||||
#include <quicklist.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
@ -61,9 +62,31 @@ static void test_alliance_join(CuTest *tc) {
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_alliance_dead_faction(CuTest *tc) {
|
||||
faction *f, *f2;
|
||||
alliance *al;
|
||||
|
||||
test_cleanup();
|
||||
f = test_create_faction(0);
|
||||
f2 = test_create_faction(0);
|
||||
al = makealliance(42, "Hodor");
|
||||
setalliance(f, al);
|
||||
setalliance(f2, al);
|
||||
CuAssertPtrEquals(tc, f, alliance_get_leader(al));
|
||||
CuAssertIntEquals(tc, 2, ql_length(al->members));
|
||||
CuAssertPtrEquals(tc, al, f->alliance);
|
||||
destroyfaction(&factions);
|
||||
CuAssertIntEquals(tc, 1, ql_length(al->members));
|
||||
CuAssertPtrEquals(tc, f2, alliance_get_leader(al));
|
||||
CuAssertPtrEquals(tc, NULL, f->alliance);
|
||||
CuAssertTrue(tc, !f->_alive);
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
CuSuite *get_alliance_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_alliance_dead_faction);
|
||||
SUITE_ADD_TEST(suite, test_alliance_make);
|
||||
SUITE_ADD_TEST(suite, test_alliance_join);
|
||||
return suite;
|
||||
|
|
|
@ -121,6 +121,7 @@ attrib_type at_npcfaction = {
|
|||
NULL,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -170,6 +171,9 @@ int
|
|||
alliedgroup(const struct plane *pl, const struct faction *f,
|
||||
const struct faction *f2, const struct ally *sf, int mode)
|
||||
{
|
||||
if (!(faction_alive(f) && faction_alive(f2))) {
|
||||
return 0;
|
||||
}
|
||||
while (sf && sf->faction != f2)
|
||||
sf = sf->next;
|
||||
if (sf == NULL) {
|
||||
|
@ -177,10 +181,10 @@ alliedgroup(const struct plane *pl, const struct faction *f,
|
|||
}
|
||||
mode = ally_mode(sf, mode) | (mode & autoalliance(pl, f, f2));
|
||||
if (AllianceRestricted()) {
|
||||
if (a_findc(f->attribs, &at_npcfaction)) {
|
||||
if (a_find(f->attribs, &at_npcfaction)) {
|
||||
return mode;
|
||||
}
|
||||
if (a_findc(f2->attribs, &at_npcfaction)) {
|
||||
if (a_find(f2->attribs, &at_npcfaction)) {
|
||||
return mode;
|
||||
}
|
||||
if (f->alliance != f2->alliance) {
|
||||
|
@ -229,7 +233,7 @@ int alliedunit(const unit * u, const faction * f2, int mode)
|
|||
|
||||
sf = u->faction->allies;
|
||||
if (fval(u, UFL_GROUP)) {
|
||||
const attrib *a = a_findc(u->attribs, &at_group);
|
||||
const attrib *a = a_find(u->attribs, &at_group);
|
||||
if (a != NULL)
|
||||
sf = ((group *)a->data.v)->allies;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "alchemy.h"
|
||||
#include "direction.h"
|
||||
#include "move.h"
|
||||
#include "study.h"
|
||||
#include "laws.h"
|
||||
#include "skill.h"
|
||||
#include "lighthouse.h"
|
||||
|
|
|
@ -141,7 +141,7 @@ int buildingcapacity(const building * b)
|
|||
}
|
||||
|
||||
attrib_type at_building_generic_type = {
|
||||
"building_generic_type", NULL, NULL, NULL, a_writestring, a_readstring,
|
||||
"building_generic_type", NULL, NULL, NULL, a_writestring, a_readstring, NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -386,10 +386,10 @@ int resolve_building(variant id, void *address)
|
|||
return result;
|
||||
}
|
||||
|
||||
variant read_building_reference(struct storage * store)
|
||||
variant read_building_reference(gamedata * data)
|
||||
{
|
||||
variant result;
|
||||
READ_INT(store, &result.i);
|
||||
READ_INT(data->store, &result.i);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct gamedata;
|
||||
|
||||
/* maintenance::flags */
|
||||
#define MTF_NONE 0x00
|
||||
#define MTF_VARIABLE 0x01 /* resource usage scales with size */
|
||||
|
@ -158,7 +160,7 @@ extern "C" {
|
|||
extern int resolve_building(variant data, void *address);
|
||||
extern void write_building_reference(const struct building *b,
|
||||
struct storage *store);
|
||||
extern variant read_building_reference(struct storage *store);
|
||||
extern variant read_building_reference(struct gamedata *data);
|
||||
|
||||
extern struct building *findbuilding(int n);
|
||||
|
||||
|
|
|
@ -640,9 +640,48 @@ int check_param(const struct param *p, const char *key, const char *searchvalue)
|
|||
return result;
|
||||
}
|
||||
|
||||
const char * relpath(char *buf, size_t sz, const char *path) {
|
||||
strlcpy(buf, basepath(), sz);
|
||||
strlcat(buf, path, sz);
|
||||
static const char *g_basedir;
|
||||
const char *basepath(void)
|
||||
{
|
||||
if (g_basedir)
|
||||
return g_basedir;
|
||||
return ".";
|
||||
}
|
||||
|
||||
void set_basepath(const char *path)
|
||||
{
|
||||
g_basedir = path;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#define PATH_DELIM '\\'
|
||||
#else
|
||||
#define PATH_DELIM '/'
|
||||
#endif
|
||||
|
||||
char * join_path(const char *p1, const char *p2, char *dst, size_t len) {
|
||||
size_t sz;
|
||||
assert(p1 && p2);
|
||||
assert(p2 != dst);
|
||||
if (dst == p1) {
|
||||
sz = strlen(p1);
|
||||
}
|
||||
else {
|
||||
sz = strlcpy(dst, p1, len);
|
||||
}
|
||||
assert(sz < len);
|
||||
dst[sz++] = PATH_DELIM;
|
||||
strlcpy(dst + sz, p2, len - sz);
|
||||
return dst;
|
||||
}
|
||||
|
||||
static const char * relpath(char *buf, size_t sz, const char *path) {
|
||||
if (g_basedir) {
|
||||
join_path(g_basedir, path, buf, sz);
|
||||
}
|
||||
else {
|
||||
strlcpy(buf, path, sz);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -652,7 +691,7 @@ const char *datapath(void)
|
|||
static char zText[MAX_PATH]; // FIXME: static return value
|
||||
if (g_datadir)
|
||||
return g_datadir;
|
||||
return relpath(zText, sizeof(zText), "/data");
|
||||
return relpath(zText, sizeof(zText), "data");
|
||||
}
|
||||
|
||||
void set_datapath(const char *path)
|
||||
|
@ -666,7 +705,7 @@ const char *reportpath(void)
|
|||
static char zText[MAX_PATH]; // FIXME: static return value
|
||||
if (g_reportdir)
|
||||
return g_reportdir;
|
||||
return relpath(zText, sizeof(zText), "/reports");
|
||||
return relpath(zText, sizeof(zText), "reports");
|
||||
}
|
||||
|
||||
void set_reportpath(const char *path)
|
||||
|
@ -674,17 +713,18 @@ void set_reportpath(const char *path)
|
|||
g_reportdir = path;
|
||||
}
|
||||
|
||||
static const char *g_basedir;
|
||||
const char *basepath(void)
|
||||
{
|
||||
if (g_basedir)
|
||||
return g_basedir;
|
||||
return ".";
|
||||
}
|
||||
|
||||
void set_basepath(const char *path)
|
||||
{
|
||||
g_basedir = path;
|
||||
int create_directories(void) {
|
||||
int err;
|
||||
err = _mkdir(datapath());
|
||||
if (err) {
|
||||
if (errno == EEXIST) errno = 0;
|
||||
else return err;
|
||||
}
|
||||
err = _mkdir(reportpath());
|
||||
if (err && errno == EEXIST) {
|
||||
errno = 0;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
double get_param_flt(const struct param *p, const char *key, double def)
|
||||
|
@ -1058,9 +1098,6 @@ void free_gamedata(void)
|
|||
{
|
||||
int i;
|
||||
free_donations();
|
||||
free_units();
|
||||
free_regions();
|
||||
free_borders();
|
||||
|
||||
for (i = 0; i != MAXLOCALES; ++i) {
|
||||
if (defaults[i]) {
|
||||
|
@ -1068,14 +1105,11 @@ void free_gamedata(void)
|
|||
defaults[i] = 0;
|
||||
}
|
||||
}
|
||||
free_factions();
|
||||
free_units();
|
||||
free_regions();
|
||||
free_borders();
|
||||
free_alliances();
|
||||
while (factions) {
|
||||
faction *f = factions;
|
||||
factions = f->next;
|
||||
funhash(f);
|
||||
free_faction(f);
|
||||
free(f);
|
||||
}
|
||||
|
||||
while (planes) {
|
||||
plane *pl = planes;
|
||||
|
|
|
@ -148,6 +148,8 @@ struct param;
|
|||
const char *reportpath(void);
|
||||
void set_reportpath(const char *);
|
||||
|
||||
int create_directories(void);
|
||||
|
||||
void kernel_init(void);
|
||||
void kernel_done(void);
|
||||
|
||||
|
@ -185,6 +187,7 @@ struct param;
|
|||
double config_get_flt(const char *key, double def);
|
||||
bool config_token(const char *key, const char *tok);
|
||||
|
||||
char * join_path(const char *p1, const char *p2, char *dst, size_t len);
|
||||
bool ExpensiveMigrants(void);
|
||||
int NMRTimeout(void);
|
||||
int LongHunger(const struct unit *u);
|
||||
|
|
|
@ -28,6 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include <util/attrib.h>
|
||||
#include <util/bsdstring.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/language.h>
|
||||
#include <util/log.h>
|
||||
#include <quicklist.h>
|
||||
|
@ -217,8 +218,9 @@ border_type *find_bordertype(const char *name)
|
|||
return bt;
|
||||
}
|
||||
|
||||
void b_read(connection * b, storage * store)
|
||||
void b_read(connection * b, gamedata * data)
|
||||
{
|
||||
storage * store = data->store;
|
||||
int n, result = 0;
|
||||
switch (b->type->datatype) {
|
||||
case VAR_NONE:
|
||||
|
@ -529,8 +531,9 @@ static const char *b_nameroad(const connection * b, const region * r,
|
|||
return buffer;
|
||||
}
|
||||
|
||||
static void b_readroad(connection * b, storage * store)
|
||||
static void b_readroad(connection * b, gamedata * data)
|
||||
{
|
||||
storage * store = data->store;
|
||||
int n;
|
||||
READ_INT(store, &n);
|
||||
b->data.sa[0] = (short)n;
|
||||
|
@ -601,8 +604,9 @@ void write_borders(struct storage *store)
|
|||
WRITE_TOK(store, "end");
|
||||
}
|
||||
|
||||
int read_borders(struct storage *store)
|
||||
int read_borders(gamedata *data)
|
||||
{
|
||||
struct storage *store = data->store;
|
||||
for (;;) {
|
||||
int bid = 0;
|
||||
char zText[32];
|
||||
|
@ -613,7 +617,7 @@ int read_borders(struct storage *store)
|
|||
if (!strcmp(zText, "end"))
|
||||
break;
|
||||
READ_INT(store, &bid);
|
||||
if (global.data_version < UIDHASH_VERSION) {
|
||||
if (data->version < UIDHASH_VERSION) {
|
||||
int fx, fy, tx, ty;
|
||||
READ_INT(store, &fx);
|
||||
READ_INT(store, &fy);
|
||||
|
@ -655,11 +659,12 @@ int read_borders(struct storage *store)
|
|||
nextborder--; /* new_border erhöht den Wert */
|
||||
b->id = bid;
|
||||
assert(bid <= nextborder);
|
||||
if (type->read)
|
||||
type->read(b, store);
|
||||
if (global.data_version < NOBORDERATTRIBS_VERSION) {
|
||||
if (type->read) {
|
||||
type->read(b, data);
|
||||
}
|
||||
if (data->version < NOBORDERATTRIBS_VERSION) {
|
||||
attrib *a = NULL;
|
||||
int result = a_read(store, &a, b);
|
||||
int result = read_attribs(data, &a, b);
|
||||
if (border_convert_cb) {
|
||||
border_convert_cb(b, a);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ extern "C" {
|
|||
struct faction;
|
||||
struct region;
|
||||
struct storage;
|
||||
struct gamedata;
|
||||
struct unit;
|
||||
|
||||
extern int nextborder;
|
||||
|
@ -52,7 +53,7 @@ extern "C" {
|
|||
/* constructor: initialize the connection. allocate extra memory if needed */
|
||||
void(*destroy) (connection *);
|
||||
/* destructor: remove all extra memory for destruction */
|
||||
void(*read) (connection *, struct storage *);
|
||||
void(*read) (connection *, struct gamedata *);
|
||||
void(*write) (const connection *, struct storage *);
|
||||
bool(*block) (const connection *, const struct unit *,
|
||||
const struct region * r);
|
||||
|
@ -113,12 +114,12 @@ extern "C" {
|
|||
void register_bordertype(border_type * type);
|
||||
/* register a new bordertype */
|
||||
|
||||
int read_borders(struct storage *store);
|
||||
int read_borders(struct gamedata *store);
|
||||
void write_borders(struct storage *store);
|
||||
void age_borders(void);
|
||||
|
||||
/* provide default implementations for some member functions: */
|
||||
void b_read(connection * b, struct storage *store);
|
||||
void b_read(connection * b, struct gamedata *store);
|
||||
void b_write(const connection * b, struct storage *store);
|
||||
bool b_blockall(const connection *, const struct unit *,
|
||||
const struct region *);
|
||||
|
|
|
@ -35,6 +35,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/* util includes */
|
||||
#include <util/attrib.h>
|
||||
#include <util/base36.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/goodies.h>
|
||||
#include <util/language.h>
|
||||
#include <util/log.h>
|
||||
|
@ -56,7 +57,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <ctype.h>
|
||||
|
||||
#define MAXENTITYHASH 7919
|
||||
curse *cursehash[MAXENTITYHASH];
|
||||
static curse *cursehash[MAXENTITYHASH];
|
||||
|
||||
void c_setflag(curse * c, unsigned int flags)
|
||||
{
|
||||
|
@ -73,17 +74,19 @@ void c_clearflag(curse * c, unsigned int flags)
|
|||
|
||||
void chash(curse * c)
|
||||
{
|
||||
curse *old = cursehash[c->no % MAXENTITYHASH];
|
||||
int i = c->no % MAXENTITYHASH;
|
||||
|
||||
cursehash[c->no % MAXENTITYHASH] = c;
|
||||
c->nexthash = old;
|
||||
c->nexthash = cursehash[i];
|
||||
cursehash[i] = c;
|
||||
assert(c->nexthash != c);
|
||||
}
|
||||
|
||||
static void cunhash(curse * c)
|
||||
{
|
||||
curse **show;
|
||||
int i = c->no % MAXENTITYHASH;
|
||||
|
||||
for (show = &cursehash[c->no % MAXENTITYHASH]; *show;
|
||||
for (show = &cursehash[i]; *show;
|
||||
show = &(*show)->nexthash) {
|
||||
if ((*show)->no == c->no)
|
||||
break;
|
||||
|
@ -184,8 +187,9 @@ static int read_ccompat(const char *cursename, struct storage *store)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int curse_read(attrib * a, void *owner, struct storage *store)
|
||||
int curse_read(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
storage *store = data->store;
|
||||
curse *c = (curse *)a->data.v;
|
||||
int ur;
|
||||
char cursename[64];
|
||||
|
@ -193,6 +197,7 @@ int curse_read(attrib * a, void *owner, struct storage *store)
|
|||
int flags;
|
||||
float flt;
|
||||
|
||||
assert(!c->no);
|
||||
READ_INT(store, &c->no);
|
||||
chash(c);
|
||||
READ_TOK(store, cursename, sizeof(cursename));
|
||||
|
@ -200,13 +205,13 @@ int curse_read(attrib * a, void *owner, struct storage *store)
|
|||
READ_INT(store, &c->duration);
|
||||
READ_FLT(store, &flt);
|
||||
c->vigour = flt;
|
||||
if (global.data_version < INTPAK_VERSION) {
|
||||
ur = read_reference(&c->magician, store, read_int, resolve_unit);
|
||||
if (data->version < INTPAK_VERSION) {
|
||||
ur = resolve_unit(read_int(data->store), &c->magician);
|
||||
}
|
||||
else {
|
||||
ur = read_reference(&c->magician, store, read_unit_reference, resolve_unit);
|
||||
ur = read_reference(&c->magician, data, read_unit_reference, resolve_unit);
|
||||
}
|
||||
if (global.data_version < CURSEFLOAT_VERSION) {
|
||||
if (data->version < CURSEFLOAT_VERSION) {
|
||||
READ_INT(store, &n);
|
||||
c->effect = (float)n;
|
||||
}
|
||||
|
@ -224,19 +229,20 @@ int curse_read(attrib * a, void *owner, struct storage *store)
|
|||
return AT_READ_FAIL;
|
||||
}
|
||||
c->flags = flags;
|
||||
if (global.data_version < EXPLICIT_CURSE_ISNEW_VERSION) {
|
||||
if (data->version < EXPLICIT_CURSE_ISNEW_VERSION) {
|
||||
c_clearflag(c, CURSE_ISNEW);
|
||||
}
|
||||
|
||||
if (c->type->read)
|
||||
c->type->read(store, c, owner);
|
||||
if (c->type->read) {
|
||||
c->type->read(data, c, owner);
|
||||
}
|
||||
else if (c->type->typ == CURSETYP_UNIT) {
|
||||
READ_INT(store, &c->data.i);
|
||||
}
|
||||
if (c->type->typ == CURSETYP_REGION) {
|
||||
int rr =
|
||||
read_reference(&c->data.v, store, read_region_reference,
|
||||
RESOLVE_REGION(global.data_version));
|
||||
read_reference(&c->data.v, data, read_region_reference,
|
||||
RESOLVE_REGION(data->version));
|
||||
if (ur == 0 && rr == 0 && !c->data.v) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
|
@ -253,12 +259,11 @@ void curse_write(const attrib * a, const void *owner, struct storage *store)
|
|||
unit *mage = (c->magician && c->magician->number) ? c->magician : NULL;
|
||||
|
||||
/* copied from c_clearflag */
|
||||
if (global.data_version < EXPLICIT_CURSE_ISNEW_VERSION) {
|
||||
flags = (c->flags & ~CURSE_ISNEW) | (c->type->flags & CURSE_ISNEW);
|
||||
}
|
||||
else {
|
||||
flags = c->flags | c->type->flags;
|
||||
}
|
||||
#if RELEASE_VERSION < EXPLICIT_CURSE_ISNEW_VERSION
|
||||
flags = (c->flags & ~CURSE_ISNEW) | (c->type->flags & CURSE_ISNEW);
|
||||
#else
|
||||
flags = c->flags | c->type->flags;
|
||||
#endif
|
||||
|
||||
WRITE_INT(store, c->no);
|
||||
WRITE_TOK(store, ct->cname);
|
||||
|
@ -285,6 +290,7 @@ attrib_type at_curse = {
|
|||
curse_age,
|
||||
curse_write,
|
||||
curse_read,
|
||||
NULL,
|
||||
ATF_CURSE
|
||||
};
|
||||
|
||||
|
@ -821,9 +827,9 @@ double destr_curse(curse * c, int cast_level, double force)
|
|||
return force;
|
||||
}
|
||||
|
||||
void free_curses(void) {
|
||||
void curses_done(void) {
|
||||
int i;
|
||||
for (i = 0; i != MAXCTHASH; ++i) {
|
||||
ql_free(cursetypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ extern "C" {
|
|||
|
||||
struct curse;
|
||||
struct curse_type;
|
||||
struct gamedata;
|
||||
struct storage;
|
||||
|
||||
/* Sprueche in der struct region und auf Einheiten, Schiffen oder Burgen
|
||||
* (struct attribute)
|
||||
|
@ -93,7 +95,7 @@ extern "C" {
|
|||
*
|
||||
* */
|
||||
|
||||
#include <util/variant.h>
|
||||
extern struct attrib_type at_curse;
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/* Zauberwirkungen */
|
||||
|
@ -194,8 +196,8 @@ extern "C" {
|
|||
struct message *(*curseinfo) (const void *, objtype_t,
|
||||
const struct curse *, int);
|
||||
void(*change_vigour) (struct curse *, double);
|
||||
int(*read) (struct storage * store, struct curse *, void *target);
|
||||
int(*write) (struct storage * store, const struct curse *,
|
||||
int(*read) (struct gamedata *data, struct curse *, void *target);
|
||||
int(*write) (struct storage *store, const struct curse *,
|
||||
const void *target);
|
||||
int(*cansee) (const struct faction *, const void *, objtype_t,
|
||||
const struct curse *, int);
|
||||
|
@ -214,12 +216,11 @@ extern "C" {
|
|||
int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */
|
||||
} curse;
|
||||
|
||||
void free_curses(void); /* de-register all curse-types */
|
||||
void curses_done(void); /* de-register all curse-types */
|
||||
|
||||
extern struct attrib_type at_curse;
|
||||
void curse_write(const struct attrib *a, const void *owner,
|
||||
struct storage *store);
|
||||
int curse_read(struct attrib *a, void *owner, struct storage *store);
|
||||
struct storage *store);
|
||||
int curse_read(struct attrib *a, void *owner, struct gamedata *store);
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/* Kommentare:
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
#include <kernel/config.h>
|
||||
#include <kernel/region.h>
|
||||
#include <kernel/save.h>
|
||||
#include <kernel/unit.h>
|
||||
#include <kernel/version.h>
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/message.h>
|
||||
#include <binarystore.h>
|
||||
#include <filestream.h>
|
||||
|
@ -52,6 +54,11 @@ static void setup_curse(curse_fixture *fix, const char *name) {
|
|||
fix->c = create_curse(fix->u, &fix->r->attribs, ct_find(name), 1.0, 1, 1.0, 0);
|
||||
}
|
||||
|
||||
static void cleanup_curse(curse_fixture *fix) {
|
||||
// destroy_curse(fix->c);
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_magicstreet(CuTest *tc) {
|
||||
curse_fixture fix;
|
||||
message *msg;
|
||||
|
@ -60,7 +67,7 @@ static void test_magicstreet(CuTest *tc) {
|
|||
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
|
||||
CuAssertStrEquals(tc, "curseinfo::magicstreet", test_get_messagetype(msg));
|
||||
msg_release(msg);
|
||||
test_cleanup();
|
||||
cleanup_curse(&fix);
|
||||
}
|
||||
|
||||
static void test_magicstreet_warning(CuTest *tc) {
|
||||
|
@ -71,7 +78,7 @@ static void test_magicstreet_warning(CuTest *tc) {
|
|||
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
|
||||
CuAssertStrEquals(tc, "curseinfo::magicstreetwarn", test_get_messagetype(msg));
|
||||
msg_release(msg);
|
||||
test_cleanup();
|
||||
cleanup_curse(&fix);
|
||||
}
|
||||
|
||||
static void test_good_dreams(CuTest *tc) {
|
||||
|
@ -82,7 +89,7 @@ static void test_good_dreams(CuTest *tc) {
|
|||
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
|
||||
CuAssertStrEquals(tc, "curseinfo::gooddream", test_get_messagetype(msg));
|
||||
msg_release(msg);
|
||||
test_cleanup();
|
||||
cleanup_curse(&fix);
|
||||
}
|
||||
|
||||
static void test_bad_dreams(CuTest *tc) {
|
||||
|
@ -93,7 +100,7 @@ static void test_bad_dreams(CuTest *tc) {
|
|||
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
|
||||
CuAssertStrEquals(tc, "curseinfo::baddream", test_get_messagetype(msg));
|
||||
msg_release(msg);
|
||||
test_cleanup();
|
||||
cleanup_curse(&fix);
|
||||
}
|
||||
|
||||
static void test_memstream(CuTest *tc) {
|
||||
|
@ -122,30 +129,33 @@ static void test_memstream(CuTest *tc) {
|
|||
|
||||
static void test_write_flag(CuTest *tc) {
|
||||
curse_fixture fix;
|
||||
gamedata data;
|
||||
storage store;
|
||||
char buf[1024];
|
||||
stream out = { 0 };
|
||||
size_t len;
|
||||
region * r;
|
||||
curse * c;
|
||||
int uid;
|
||||
|
||||
mstream_init(&out);
|
||||
binstore_init(&store, &out);
|
||||
store.handle.data = &out;
|
||||
mstream_init(&data.strm);
|
||||
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||
|
||||
setup_curse(&fix, "gbdream");
|
||||
fix.c->flags = 42 | CURSE_ISNEW;
|
||||
curse_write(fix.r->attribs, fix.r, &store);
|
||||
out.api->rewind(out.handle);
|
||||
len = out.api->read(out.handle, buf, sizeof(buf));
|
||||
buf[len] = '\0';
|
||||
out.api->rewind(out.handle);
|
||||
curse_read(fix.r->attribs, fix.r, &store);
|
||||
CuAssertIntEquals(tc, 42 | CURSE_ISNEW, ((curse *) fix.r->attribs->data.v)->flags);
|
||||
global.data_version = RELEASE_VERSION;
|
||||
CuAssertIntEquals(tc, RELEASE_VERSION, global.data_version);
|
||||
c = fix.c;
|
||||
r = fix.r;
|
||||
uid = r->uid;
|
||||
c->flags = CURSE_ISNEW;
|
||||
write_game(&data);
|
||||
free_gamedata();
|
||||
data.strm.api->rewind(data.strm.handle);
|
||||
read_game(&data);
|
||||
r = findregionbyid(uid);
|
||||
CuAssertPtrNotNull(tc, r);
|
||||
CuAssertPtrNotNull(tc, r->attribs);
|
||||
c = (curse *)r->attribs->data.v;
|
||||
CuAssertIntEquals(tc, CURSE_ISNEW, c->flags);
|
||||
|
||||
mstream_done(&out);
|
||||
binstore_done(&store);
|
||||
test_cleanup();
|
||||
mstream_done(&data.strm);
|
||||
gamedata_done(&data);
|
||||
cleanup_curse(&fix);
|
||||
}
|
||||
|
||||
CuSuite *get_curse_suite(void)
|
||||
|
|
|
@ -19,7 +19,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <platform.h>
|
||||
#include <kernel/config.h>
|
||||
#include "faction.h"
|
||||
|
||||
#include "alliance.h"
|
||||
#include "ally.h"
|
||||
#include "curse.h"
|
||||
|
@ -46,6 +45,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <util/language.h>
|
||||
#include <util/log.h>
|
||||
#include <util/parser.h>
|
||||
#include <util/password.h>
|
||||
#include <util/resolve.h>
|
||||
#include <util/rng.h>
|
||||
#include <util/variant.h>
|
||||
|
@ -71,9 +71,12 @@ faction *factions;
|
|||
* but you should still call funhash and remove the faction from the
|
||||
* global list.
|
||||
*/
|
||||
void free_faction(faction * f)
|
||||
static void free_faction(faction * f)
|
||||
{
|
||||
funhash(f);
|
||||
if (f->alliance && f->alliance->_leader == f) {
|
||||
setalliance(f, 0);
|
||||
}
|
||||
if (f->msgs) {
|
||||
free_messagelist(f->msgs->begin);
|
||||
free(f->msgs);
|
||||
|
@ -101,7 +104,7 @@ void free_faction(faction * f)
|
|||
|
||||
free(f->email);
|
||||
free(f->banner);
|
||||
free(f->passw);
|
||||
free(f->_password);
|
||||
free(f->name);
|
||||
if (f->seen_factions) {
|
||||
ql_free(f->seen_factions);
|
||||
|
@ -214,6 +217,7 @@ int resolve_faction(variant id, void *address)
|
|||
result = -1;
|
||||
}
|
||||
}
|
||||
assert(address);
|
||||
*(faction **)address = f;
|
||||
return result;
|
||||
}
|
||||
|
@ -248,11 +252,13 @@ faction *addfaction(const char *email, const char *password,
|
|||
log_warning("Invalid email address for faction %s: %s\n", itoa36(f->no), email);
|
||||
}
|
||||
|
||||
faction_setpassword(f, password);
|
||||
if (!password) password = itoa36(rng_int());
|
||||
faction_setpassword(f, password_encode(password, PASSWORD_DEFAULT));
|
||||
ADDMSG(&f->msgs, msg_message("changepasswd", "value", password));
|
||||
|
||||
f->alliance_joindate = turn;
|
||||
f->lastorders = turn;
|
||||
f->alive = 1;
|
||||
f->_alive = true;
|
||||
f->age = 0;
|
||||
f->race = frace;
|
||||
f->magiegebiet = 0;
|
||||
|
@ -310,30 +316,57 @@ unit *addplayer(region * r, faction * f)
|
|||
|
||||
bool checkpasswd(const faction * f, const char *passwd)
|
||||
{
|
||||
return (passwd && unicode_utf8_strcasecmp(f->passw, passwd) == 0);
|
||||
if (!passwd) return false;
|
||||
|
||||
if (f->_password && password_verify(f->_password, passwd) == VERIFY_FAIL) {
|
||||
log_warning("password check failed: %s", factionname(f));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
variant read_faction_reference(struct storage * store)
|
||||
variant read_faction_reference(gamedata * data)
|
||||
{
|
||||
variant id;
|
||||
READ_INT(store, &id.i);
|
||||
READ_INT(data->store, &id.i);
|
||||
return id;
|
||||
}
|
||||
|
||||
void write_faction_reference(const faction * f, struct storage *store)
|
||||
{
|
||||
assert(!f || f->_alive);
|
||||
WRITE_INT(store, f ? f->no : 0);
|
||||
}
|
||||
|
||||
void destroyfaction(faction * f)
|
||||
{
|
||||
unit *u = f->units;
|
||||
faction *ff;
|
||||
static faction *dead_factions;
|
||||
|
||||
if (!f->alive) {
|
||||
return;
|
||||
void free_flist(faction **fp) {
|
||||
faction * flist = *fp;
|
||||
while (flist) {
|
||||
faction *f = flist;
|
||||
flist = f->next;
|
||||
free_faction(f);
|
||||
free(f);
|
||||
}
|
||||
*fp = 0;
|
||||
}
|
||||
|
||||
void free_factions(void) {
|
||||
free_flist(&factions);
|
||||
free_flist(&dead_factions);
|
||||
}
|
||||
|
||||
void destroyfaction(faction ** fp)
|
||||
{
|
||||
faction * f = *fp;
|
||||
unit *u = f->units;
|
||||
|
||||
*fp = f->next;
|
||||
f->next = dead_factions;
|
||||
dead_factions = f;
|
||||
|
||||
fset(f, FFL_QUIT);
|
||||
f->_alive = false;
|
||||
|
||||
if (f->spellbook) {
|
||||
spellbook_clear(f->spellbook);
|
||||
|
@ -389,35 +422,48 @@ void destroyfaction(faction * f)
|
|||
u = u->nextF;
|
||||
}
|
||||
}
|
||||
f->alive = 0;
|
||||
/* no way! f->units = NULL; */
|
||||
|
||||
handle_event(f->attribs, "destroy", f);
|
||||
#if 0
|
||||
faction *ff;
|
||||
for (ff = factions; ff; ff = ff->next) {
|
||||
group *g;
|
||||
ally *sf, *sfn;
|
||||
ally *sf, **sfp;
|
||||
|
||||
/* Alle HELFE für die Partei löschen */
|
||||
for (sf = ff->allies; sf; sf = sf->next) {
|
||||
if (sf->faction == f) {
|
||||
removelist(&ff->allies, sf);
|
||||
break;
|
||||
for (sfp = &ff->allies; *sfp;) {
|
||||
sf = *sfp;
|
||||
if (sf->faction == f || sf->faction == NULL) {
|
||||
*sfp = sf->next;
|
||||
free(sf);
|
||||
}
|
||||
else
|
||||
sfp = &(*sfp)->next;
|
||||
}
|
||||
for (g = ff->groups; g; g = g->next) {
|
||||
for (sf = g->allies; sf;) {
|
||||
sfn = sf->next;
|
||||
if (sf->faction == f) {
|
||||
removelist(&g->allies, sf);
|
||||
break;
|
||||
for (sfp = &g->allies; *sfp; ) {
|
||||
sf = *sfp;
|
||||
if (sf->faction == f || sf->faction == NULL) {
|
||||
*sfp = sf->next;
|
||||
free(sf);
|
||||
}
|
||||
else {
|
||||
sfp = &(*sfp)->next;
|
||||
}
|
||||
sf = sfn;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (f->alliance && f->alliance->_leader == f) {
|
||||
setalliance(f, 0);
|
||||
}
|
||||
|
||||
funhash(f);
|
||||
|
||||
/* units of other factions that were disguised as this faction
|
||||
* have their disguise replaced by ordinary faction hiding. */
|
||||
if (rule_stealth_other()) {
|
||||
// TODO: f.alive should be tested for in get_otherfaction
|
||||
region *rc;
|
||||
for (rc = regions; rc; rc = rc->next) {
|
||||
for (u = rc->units; u; u = u->next) {
|
||||
|
@ -520,13 +566,12 @@ void faction_setbanner(faction * self, const char *banner)
|
|||
self->banner = _strdup(banner);
|
||||
}
|
||||
|
||||
void faction_setpassword(faction * f, const char *passw)
|
||||
void faction_setpassword(faction * f, const char *pwhash)
|
||||
{
|
||||
free(f->passw);
|
||||
if (passw)
|
||||
f->passw = _strdup(passw);
|
||||
else
|
||||
f->passw = _strdup(itoa36(rng_int()));
|
||||
assert(pwhash);
|
||||
// && pwhash[0] == '$');
|
||||
free(f->_password);
|
||||
f->_password = _strdup(pwhash);
|
||||
}
|
||||
|
||||
bool valid_race(const struct faction *f, const struct race *rc)
|
||||
|
@ -541,11 +586,6 @@ bool valid_race(const struct faction *f, const struct race *rc)
|
|||
}
|
||||
}
|
||||
|
||||
const char *faction_getpassword(const faction * f)
|
||||
{
|
||||
return f->passw;
|
||||
}
|
||||
|
||||
struct alliance *f_get_alliance(const struct faction *f)
|
||||
{
|
||||
if (f->alliance && !(f->alliance->flags & ALF_NON_ALLIED)) {
|
||||
|
@ -633,61 +673,26 @@ int skill_limit(faction * f, skill_t sk)
|
|||
|
||||
void remove_empty_factions(void)
|
||||
{
|
||||
faction **fp, *f3;
|
||||
faction **fp;
|
||||
|
||||
for (fp = &factions; *fp;) {
|
||||
faction *f = *fp;
|
||||
/* monster (0) werden nicht entfernt. alive kann beim readgame
|
||||
* () auf 0 gesetzt werden, wenn monsters keine einheiten mehr
|
||||
* haben. */
|
||||
if ((f->units == NULL || f->alive == 0) && !fval(f, FFL_NOIDLEOUT)) {
|
||||
ursprung *ur = f->ursprung;
|
||||
while (ur && ur->id != 0)
|
||||
ur = ur->next;
|
||||
|
||||
if (!(f->_alive && f->units!=NULL) && !fval(f, FFL_NOIDLEOUT)) {
|
||||
log_debug("dead: %s", factionname(f));
|
||||
|
||||
/* Einfach in eine Datei schreiben und später vermailen */
|
||||
|
||||
for (f3 = factions; f3; f3 = f3->next) {
|
||||
ally *sf;
|
||||
group *g;
|
||||
ally **sfp = &f3->allies;
|
||||
while (*sfp) {
|
||||
sf = *sfp;
|
||||
if (sf->faction == f || sf->faction == NULL) {
|
||||
*sfp = sf->next;
|
||||
free(sf);
|
||||
}
|
||||
else
|
||||
sfp = &(*sfp)->next;
|
||||
}
|
||||
for (g = f3->groups; g; g = g->next) {
|
||||
sfp = &g->allies;
|
||||
while (*sfp) {
|
||||
sf = *sfp;
|
||||
if (sf->faction == f || sf->faction == NULL) {
|
||||
*sfp = sf->next;
|
||||
free(sf);
|
||||
}
|
||||
else
|
||||
sfp = &(*sfp)->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*fp = f->next;
|
||||
funhash(f);
|
||||
free_faction(f);
|
||||
if (f->alliance && f->alliance->_leader == f) {
|
||||
setalliance(f, 0);
|
||||
}
|
||||
free(f);
|
||||
destroyfaction(fp);
|
||||
}
|
||||
else
|
||||
else {
|
||||
fp = &(*fp)->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool faction_alive(const faction *f) {
|
||||
assert(f);
|
||||
return f->_alive || (f->flags&FFL_NPC);
|
||||
}
|
||||
|
||||
void faction_getorigin(const faction * f, int id, int *x, int *y)
|
||||
{
|
||||
ursprung *ur;
|
||||
|
@ -794,6 +799,7 @@ attrib_type at_maxmagicians = {
|
|||
NULL,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -843,3 +849,28 @@ faction *dfindhash(int no)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int writepasswd(void)
|
||||
{
|
||||
FILE *F;
|
||||
char zText[128];
|
||||
|
||||
join_path(basepath(), "passwd", zText, sizeof(zText));
|
||||
F = fopen(zText, "w");
|
||||
if (!F) {
|
||||
perror(zText);
|
||||
}
|
||||
else {
|
||||
faction *f;
|
||||
log_info("writing passwords...");
|
||||
|
||||
for (f = factions; f; f = f->next) {
|
||||
fprintf(F, "%s:%s:%s:%u\n",
|
||||
factionid(f), f->email, f->_password, f->subscription);
|
||||
}
|
||||
fclose(F);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@ extern "C" {
|
|||
struct item;
|
||||
struct seen_region;
|
||||
struct attrib_type;
|
||||
|
||||
struct gamedata;
|
||||
|
||||
extern struct attrib_type at_maxmagicians;
|
||||
/* SMART_INTERVALS: define to speed up finding the interval of regions that a
|
||||
faction is in. defining this speeds up the turn by 30-40% */
|
||||
|
@ -68,7 +69,7 @@ extern "C" {
|
|||
char *name;
|
||||
char *banner;
|
||||
char *email;
|
||||
char *passw;
|
||||
char *_password;
|
||||
int max_spelllevel;
|
||||
struct spellbook *spellbook;
|
||||
const struct locale *locale;
|
||||
|
@ -82,8 +83,8 @@ extern "C" {
|
|||
int num_total; /* Anzahl Personen mit Monstern */
|
||||
int options;
|
||||
int no_units;
|
||||
struct ally *allies;
|
||||
struct group *groups;
|
||||
struct ally *allies; /* alliedgroup and others should check sf.faction.alive before using a faction from f.allies */
|
||||
struct group *groups; /* alliedgroup and others should check sf.faction.alive before using a faction from f.groups */
|
||||
int nregions;
|
||||
int money;
|
||||
score_t score;
|
||||
|
@ -103,7 +104,7 @@ extern "C" {
|
|||
struct item *items; /* items this faction can claim */
|
||||
struct seen_region **seen;
|
||||
struct quicklist *seen_factions;
|
||||
bool alive; /* enno: sollte ein flag werden */
|
||||
bool _alive; /* enno: sollte ein flag werden */
|
||||
} faction;
|
||||
|
||||
extern struct faction *factions;
|
||||
|
@ -121,7 +122,10 @@ extern "C" {
|
|||
struct faction *addfaction(const char *email, const char *password,
|
||||
const struct race *frace, const struct locale *loc, int subscription);
|
||||
bool checkpasswd(const faction * f, const char *passwd);
|
||||
void destroyfaction(faction * f);
|
||||
int writepasswd(void);
|
||||
void destroyfaction(faction ** f);
|
||||
|
||||
bool faction_alive(const struct faction *f);
|
||||
|
||||
void set_alliance(struct faction *a, struct faction *b, int status);
|
||||
int get_alliance(const struct faction *a, const struct faction *b);
|
||||
|
@ -130,11 +134,11 @@ extern "C" {
|
|||
|
||||
void write_faction_reference(const struct faction *f,
|
||||
struct storage *store);
|
||||
variant read_faction_reference(struct storage *store);
|
||||
variant read_faction_reference(struct gamedata *store);
|
||||
int resolve_faction(variant data, void *addr);
|
||||
|
||||
void renumber_faction(faction * f, int no);
|
||||
void free_faction(struct faction *f);
|
||||
void free_factions(void);
|
||||
void remove_empty_factions(void);
|
||||
|
||||
#ifdef SMART_INTERVALS
|
||||
|
@ -150,8 +154,7 @@ extern "C" {
|
|||
const char *faction_getemail(const struct faction *self);
|
||||
void faction_setemail(struct faction *self, const char *email);
|
||||
|
||||
const char *faction_getpassword(const struct faction *self);
|
||||
void faction_setpassword(struct faction *self, const char *password);
|
||||
void faction_setpassword(struct faction *self, const char *pwhash);
|
||||
bool valid_race(const struct faction *f, const struct race *rc);
|
||||
|
||||
void faction_getorigin(const struct faction * f, int id, int *x, int *y);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <kernel/plane.h>
|
||||
#include <kernel/config.h>
|
||||
#include <util/language.h>
|
||||
#include <util/password.h>
|
||||
|
||||
#include "monster.h"
|
||||
#include <CuTest.h>
|
||||
|
@ -16,18 +17,23 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void test_remove_empty_factions_allies(CuTest *tc) {
|
||||
static void test_destroyfaction_allies(CuTest *tc) {
|
||||
faction *f1, *f2;
|
||||
region *r;
|
||||
ally *al;
|
||||
|
||||
test_cleanup();
|
||||
r = test_create_region(0, 0, 0);
|
||||
f1 = test_create_faction(0);
|
||||
test_create_unit(f1, r);
|
||||
f2 = test_create_faction(0);
|
||||
ally_add(&f1->allies, f2);
|
||||
remove_empty_factions();
|
||||
CuAssertPtrEquals(tc, 0, f1->allies);
|
||||
al = ally_add(&f1->allies, f2);
|
||||
al->status = HELP_FIGHT;
|
||||
CuAssertIntEquals(tc, HELP_FIGHT, alliedgroup(0, f1, f2, f1->allies, HELP_ALL));
|
||||
CuAssertPtrEquals(tc, f2, f1->next);
|
||||
destroyfaction(&f1->next);
|
||||
CuAssertIntEquals(tc, false, faction_alive(f2));
|
||||
CuAssertIntEquals(tc, 0, alliedgroup(0, f1, f2, f1->allies, HELP_ALL));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
|
@ -75,8 +81,8 @@ static void test_remove_dead_factions(CuTest *tc) {
|
|||
remove_empty_factions();
|
||||
CuAssertPtrEquals(tc, f, findfaction(f->no));
|
||||
CuAssertPtrNotNull(tc, get_monsters());
|
||||
fm->alive = 0;
|
||||
f->alive = 0;
|
||||
fm->units = 0;
|
||||
f->_alive = false;
|
||||
fno = f->no;
|
||||
remove_empty_factions();
|
||||
CuAssertPtrEquals(tc, 0, findfaction(fno));
|
||||
|
@ -102,18 +108,28 @@ static void test_addfaction(CuTest *tc) {
|
|||
CuAssertPtrEquals(tc, NULL, (void *)f->ursprung);
|
||||
CuAssertPtrEquals(tc, (void *)factions, (void *)f);
|
||||
CuAssertStrEquals(tc, "test@eressea.de", f->email);
|
||||
CuAssertStrEquals(tc, "hurrdurr", f->passw);
|
||||
CuAssertTrue(tc, checkpasswd(f, "hurrdurr"));
|
||||
CuAssertPtrEquals(tc, (void *)lang, (void *)f->locale);
|
||||
CuAssertIntEquals(tc, 1234, f->subscription);
|
||||
CuAssertIntEquals(tc, 0, f->flags);
|
||||
CuAssertIntEquals(tc, 0, f->age);
|
||||
CuAssertIntEquals(tc, 1, f->alive);
|
||||
CuAssertTrue(tc, faction_alive(f));
|
||||
CuAssertIntEquals(tc, M_GRAY, f->magiegebiet);
|
||||
CuAssertIntEquals(tc, turn, f->lastorders);
|
||||
CuAssertPtrEquals(tc, f, findfaction(f->no));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_check_passwd(CuTest *tc) {
|
||||
faction *f;
|
||||
|
||||
f = test_create_faction(0);
|
||||
faction_setpassword(f, password_encode("password", PASSWORD_DEFAULT));
|
||||
CuAssertTrue(tc, checkpasswd(f, "password"));
|
||||
CuAssertTrue(tc, !checkpasswd(f, "assword"));
|
||||
CuAssertTrue(tc, !checkpasswd(f, "PASSWORD"));
|
||||
}
|
||||
|
||||
static void test_get_monsters(CuTest *tc) {
|
||||
faction *f;
|
||||
|
||||
|
@ -174,11 +190,12 @@ CuSuite *get_faction_suite(void)
|
|||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_addfaction);
|
||||
SUITE_ADD_TEST(suite, test_remove_empty_factions);
|
||||
SUITE_ADD_TEST(suite, test_remove_empty_factions_allies);
|
||||
SUITE_ADD_TEST(suite, test_destroyfaction_allies);
|
||||
SUITE_ADD_TEST(suite, test_remove_empty_factions_alliance);
|
||||
SUITE_ADD_TEST(suite, test_remove_dead_factions);
|
||||
SUITE_ADD_TEST(suite, test_get_monsters);
|
||||
SUITE_ADD_TEST(suite, test_set_origin);
|
||||
SUITE_ADD_TEST(suite, test_set_origin_bug);
|
||||
SUITE_ADD_TEST(suite, test_check_passwd);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/* util includes */
|
||||
#include <util/attrib.h>
|
||||
#include <util/base36.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/resolve.h>
|
||||
#include <util/unicode.h>
|
||||
|
||||
|
@ -95,8 +96,9 @@ static group *find_group(int gid)
|
|||
return g;
|
||||
}
|
||||
|
||||
static int read_group(attrib * a, void *owner, struct storage *store)
|
||||
static int read_group(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
struct storage *store = data->store;
|
||||
group *g;
|
||||
int gid;
|
||||
|
||||
|
@ -119,7 +121,7 @@ write_group(const attrib * a, const void *owner, struct storage *store)
|
|||
attrib_type at_group = { /* attribute for units assigned to a group */
|
||||
"grp",
|
||||
DEFAULT_INIT,
|
||||
DEFAULT_FINALIZE, DEFAULT_AGE, write_group, read_group, ATF_UNIQUE };
|
||||
DEFAULT_FINALIZE, DEFAULT_AGE, write_group, read_group, NULL, ATF_UNIQUE };
|
||||
|
||||
void free_group(group * g)
|
||||
{
|
||||
|
@ -130,6 +132,9 @@ void free_group(group * g)
|
|||
assert(*g_ptr == g);
|
||||
*g_ptr = g->nexthash;
|
||||
|
||||
if (g->attribs) {
|
||||
a_removeall(&g->attribs, NULL);
|
||||
}
|
||||
while (g->allies) {
|
||||
ally *a = g->allies;
|
||||
g->allies = a->next;
|
||||
|
@ -179,7 +184,7 @@ void set_group(struct unit *u, struct group *g)
|
|||
}
|
||||
}
|
||||
|
||||
bool join_group(unit * u, const char *name)
|
||||
group *join_group(unit * u, const char *name)
|
||||
{
|
||||
group *g = NULL;
|
||||
|
||||
|
@ -192,7 +197,7 @@ bool join_group(unit * u, const char *name)
|
|||
}
|
||||
|
||||
set_group(u, g);
|
||||
return true;
|
||||
return g;
|
||||
}
|
||||
|
||||
void write_groups(struct storage *store, const faction * f)
|
||||
|
@ -203,20 +208,21 @@ void write_groups(struct storage *store, const faction * f)
|
|||
WRITE_INT(store, g->gid);
|
||||
WRITE_STR(store, g->name);
|
||||
for (a = g->allies; a; a = a->next) {
|
||||
if (a->faction) {
|
||||
if (a->faction && a->faction->_alive) {
|
||||
write_faction_reference(a->faction, store);
|
||||
WRITE_INT(store, a->status);
|
||||
}
|
||||
}
|
||||
WRITE_INT(store, 0);
|
||||
write_faction_reference(NULL, store);
|
||||
a_write(store, g->attribs, g);
|
||||
WRITE_SECTION(store);
|
||||
}
|
||||
WRITE_INT(store, 0);
|
||||
}
|
||||
|
||||
void read_groups(struct storage *store, faction * f)
|
||||
void read_groups(gamedata *data, faction * f)
|
||||
{
|
||||
struct storage *store = data->store;
|
||||
for (;;) {
|
||||
ally **pa;
|
||||
group *g;
|
||||
|
@ -233,7 +239,7 @@ void read_groups(struct storage *store, faction * f)
|
|||
ally *a;
|
||||
variant fid;
|
||||
|
||||
READ_INT(store, &fid.i);
|
||||
fid = read_faction_reference(data);
|
||||
if (fid.i <= 0)
|
||||
break;
|
||||
a = ally_add(pa, findfaction(fid.i));
|
||||
|
@ -241,6 +247,6 @@ void read_groups(struct storage *store, faction * f)
|
|||
if (!a->faction)
|
||||
ur_add(fid, &a->faction, resolve_faction);
|
||||
}
|
||||
a_read(store, &g->attribs, g);
|
||||
read_attribs(data, &g->attribs, g);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue