Merge pull request #627 from ennorehling/develop

bug 2270 & changes for culbig
This commit is contained in:
Enno Rehling 2017-01-20 22:52:06 +01:00 committed by GitHub
commit 6c8089d36e
17 changed files with 212 additions and 404 deletions

View File

@ -25,4 +25,5 @@ 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")
install(DIRECTORY scripts DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.lua")
install(DIRECTORY lunit DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.lua")
install(DIRECTORY share DESTINATION ${CMAKE_INSTALL_PREFIX})

View File

@ -1,5 +1,7 @@
[eressea]
[game]
email = eressea-server@kn-bremen.de
sender = Eressea Server
name = Eressea
base = .
report = reports
verbose = 0

View File

@ -3,22 +3,53 @@
from email.Utils import parseaddr
from email.Parser import Parser
from os import mkdir, rename, stat, utime, unlink, symlink
from os.path import exists
import os
import os.path
import ConfigParser
from re import compile, IGNORECASE
from stat import ST_MTIME
from string import upper, split, replace
import logging
from sys import argv, stdin, exit
import sys
from sys import stdin
from time import ctime, sleep, time
from socket import gethostname
from rfc822 import parsedate_tz, mktime_tz
LOG_FILENAME='/home/eressea/log/orders.log'
if 'ERESSEA' in os.environ:
dir = os.environ['ERESSEA']
elif 'HOME' in os.environ:
dir = os.path.join(os.environ['HOME'], '/eressea')
else: # WTF? No HOME?
dir = "/home/eressea/eressea"
if not os.path.isdir(dir):
print "please set the ERESSEA environment variable to the install path"
sys.exit(1)
rootdir = dir
game = int(sys.argv[1])
gamedir = os.path.join(rootdir, "game-%d" % (game, ))
frommail = 'eressea-server@kn-bremen.de'
gamename = 'Eressea'
sender = '%s Server <%s>' % (gamename, frommail)
inifile = os.path.join(gamedir, 'eressea.ini')
if not os.path.exists(inifile):
print "no such file: " . inifile
else:
config = ConfigParser.ConfigParser()
config.read(inifile)
if config.has_option('game', 'email'):
frommail = config.get('game', 'email')
if config.has_option('game', 'name'):
gamename = config.get('game', 'name')
if config.has_option('game', 'sender'):
sender = config.get('game', 'sender')
else:
sender = "%s Server <%s>" % (gamename, frommail)
config = None
prefix = 'turn-'
hostname = gethostname()
# base directory for all your games:
rootdir = "/home/eressea"
orderbase = "orders.dir"
sendmail = True
# maximum number of reports per sender:
@ -28,36 +59,21 @@ writeheaders = True
# reject all html email?
rejecthtml = True
games = [
{
"from" : "Eressea Server <eressea-server@eressea.kn-bremen.de>",
"prefix" : "Eressea"
},
{
"from" : "Eressea Server <eressea-server@eressea.kn-bremen.de>",
"prefix": "E3"
},
{
"from" : "Eressea Server <eressea-server@eressea.kn-bremen.de>",
"prefix": "E4"
},
]
def unlock_file(filename):
try:
unlink(filename+".lock")
os.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):
if not os.path.exists(filename):
file=open(filename, "w")
file.close()
while True:
try:
symlink(filename, filename+".lock")
os.symlink(filename, filename+".lock")
return
except:
i = i+1
@ -74,17 +90,17 @@ messages = {
"software and re-send the orders.",
"multipart-de" :
"FEHLER: Die von dir eingeschickte Mail enthält keinen " \
"FEHLER: Die von dir eingeschickte Mail enth<EFBFBD>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 " \
"ung<EFBFBD>ltig formatierte Mail ingeschickt. Wir k<>nnen ihn " \
"deshalb nicht ber<EFBFBD>cksichtigen. Schicke den Zug nochmals " \
"als reinen Text ohne Formatierungen ein.",
"maildate-de":
"Es erreichte uns bereits ein Zug mit einem späteren " \
"Es erreichte uns bereits ein Zug mit einem sp<EFBFBD>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 " \
"dir auf dem Transportweg <EFBFBD>berholt. Entscheidend f<>r die " \
"Auswertungsreihenfolge ist das Absendedatum, d.h. der Date:-Header " \
"deiner Mail.",
@ -173,8 +189,8 @@ 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)
while os.path.exists(filename):
maxdate = max(os.stat(filename)[ST_MTIME], maxdate)
ver = ver + 1
filename = "%s/%s,%s,%d" % (dirname, basename, hostname, ver)
if ver >= maxfiles:
@ -234,7 +250,7 @@ def copy_orders(message, filename, sender):
from os.path import split
dirname, basename = split(filename)
dirname = dirname + '/headers'
if not exists(dirname): mkdir(dirname)
if not os.path.exists(dirname): os.mkdir(dirname)
outfile = open(dirname + '/' + basename, "w")
for name, value in message.items():
outfile.write(name + ": " + value + "\n")
@ -265,104 +281,94 @@ def copy_orders(message, filename, sender):
# 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
global rootdir, orderbase, gamedir, gamename, sender
if extend is not None:
orderbase = orderbase + ".pre-" + extend
gamename = games[game-2]["prefix"]
gamedir = rootdir+"/eressea/game-%d" % (game, )
savedir = gamedir+"/"+orderbase
savedir = os.path.join(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)
if not os.path.exists(gamedir): os.mkdir(gamedir)
if not os.path.exists(savedir): os.mkdir(savedir)
# parse message
message = Parser().parse(stream)
sender = get_sender(message)
logger = logging.getLogger(sender)
email = get_sender(message)
logger = logging.getLogger(email)
# write syslog
if sender is None or valid_email(sender)==0:
logger.warning("invalid email address: " + str(sender))
if email is None or valid_email(email)==0:
logger.warning("invalid email address: " + str(email))
return -1
logger.info("received orders from " + sender)
logger.info("received orders from " + email)
# get an available filename
lock_file(gamedir + "/orders.queue")
maxdate, filename = available_file(savedir, prefix + sender)
maxdate, filename = available_file(savedir, prefix + email)
if filename is None:
logger.warning("more than " + str(maxfiles) + " orders from " + sender)
logger.warning("more than " + str(maxfiles) + " orders from " + email)
return -1
# copy the orders to the file
text_ok = copy_orders(message, filename, sender)
text_ok = copy_orders(message, filename, email)
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))
os.utime(filename, (turndate, turndate))
logger.debug("mail date is '%s' (%d)" % (maildate, turndate))
if turndate < maxdate:
logger.warning("inconsistent message date " + sender)
logger.warning("inconsistent message date " + email)
warning = " (" + messages["warning-" + locale] + ")"
msg = msg + formatpar(messages["maildate-" + locale] % (ctime(maxdate),ctime(turndate)), 76, 2) + "\n"
else:
logger.warning("missing message date " + sender)
logger.warning("missing message date " + email)
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)
logger.warning("rejected - no text/plain in orders from " + email)
os.unlink(filename)
savedir = savedir + "/rejected"
if not exists(savedir): mkdir(savedir)
if not os.path.exists(savedir): os.mkdir(savedir)
lock_file(gamedir + "/orders.queue")
maxdate, filename = available_file(savedir, prefix + sender)
maxdate, filename = available_file(savedir, prefix + email)
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
mail = "Subject: %s\nFrom: %s\nTo: %s\n\n" % (subject, sender, email) + msg
from smtplib import SMTP
server = SMTP("localhost")
server.sendmail(frommail, sender, mail)
server.sendmail(sender, email, mail)
server.close()
if not sendmail:
print text_ok, fail, sender
print text_ok, fail, email
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.write("email=%s file=%s locale=%s game=%s\n" % (email, filename, locale, game))
queue.close()
unlock_file(gamedir + "/orders.queue")
logger.info("done - accepted orders from " + sender)
logger.info("done - accepted orders from " + email)
return 0
# the main body of the script:
LOG_FILENAME=os.path.join(rootdir, 'log/orders.log')
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]
locale = sys.argv[2]
infile = stdin
if len(argv)>3:
infile = open(argv[3], "r")
if len(sys.argv)>3:
infile = open(sys.argv[3], "r")
retval = accept(game, locale, infile, delay)
if infile!=stdin:
infile.close()
exit(retval)
sys.exit(retval)

View File

@ -2,7 +2,9 @@
# -*- coding: iso-8859-1 -*-
from os import unlink, symlink, rename, popen, tmpfile
from os.path import exists
import os
import os.path
import ConfigParser
from re import compile, IGNORECASE
from string import split, join, upper, strip
from sys import argv, exit
@ -14,9 +16,8 @@ from epasswd import EPasswd
def pwd_get_email(faction, pwd, pwdfile=None):
return None
def splitfilename(filename):
from os.path import split
return split(filename)
def split_filename(filename):
return os.path.split(filename)
def unlock_file(filename):
try:
@ -28,7 +29,7 @@ def unlock_file(filename):
def lock_file(filename):
i = 0
wait = 1
if not exists(filename):
if not os.path.exists(filename):
file=open(filename, "w")
file.close()
while True:
@ -62,17 +63,47 @@ messages = {
"error-en": "Error",
}
game = int(sys.argv[1])
echeck_cmd = "/home/eressea/echeck/echeck.sh"
maxlines = 25
# base directory for all your games:
rootdir = "/home/eressea/eressea"
frommail = "Eressea Server <eressea-server@eressea.kn-bremen.de>"
orderbase = "orders.dir"
sendmail = True
maxlines = 25
echeck_cmd = "/home/eressea/echeck/echeck.sh"
install_dir = "/home/eressea/eressea"
if 'ERESSEA' in os.environ:
install_dir = os.environ['ERESSEA']
elif 'HOME' in os.environ:
install_dir = os.path.join(os.environ['HOME'], '/eressea')
if not os.path.isdir(install_dir):
print "please set the ERESSEA environment variable to the install path"
sys.exit(1)
game_dir = os.path.join(install_dir, "game-%d" % (game, ))
frommail = 'eressea-server@kn-bremen.de'
gamename = 'Eressea'
sender = '%s Server <%s>' % (gamename, frommail)
inifile = os.path.join(gamedir, 'eressea.ini')
if not os.path.exists(inifile):
print "no such file: " . inifile
else:
config = ConfigParser.ConfigParser()
config.read(inifile)
if config.has_option('game', 'email'):
frommail = config.get('game', 'email')
if config.has_option('game', 'name'):
gamename = config.get('game', 'name')
if config.has_option('game', 'sender'):
sender = config.get('game', 'sender')
else:
sender = "%s Server <%s>" % (gamename, frommail)
config = None
queue_file = os.path.join(game_dir, "orders.queue")
if not os.path.exists(queue_file):
exit(0)
# regular expression that finds the start of a faction
fact_re = compile("^\s*(eressea|vinyambar|partei|faction)\s+([a-zA-Z0-9]+)\s+\"?([^\"]*)\"?", IGNORECASE)
fact_re = compile("^\s*(eressea|partei|faction)\s+([a-zA-Z0-9]+)\s+\"?([^\"]*)\"?", IGNORECASE)
def check_pwd(filename, email, pw_data):
results = []
@ -98,7 +129,7 @@ def check_pwd(filename, email, pw_data):
return results
def echeck(filename, locale, rules):
dirname, filename = splitfilename(filename)
dirname, filename = split_filename(filename)
stream = popen("%s %s %s %s %s" % (echeck_cmd, locale, filename, dirname, rules), 'r')
lines = stream.readlines()
if len(lines)==0:
@ -111,14 +142,6 @@ def echeck(filename, locale, rules):
stream.close()
return mail
## the main body of the script
game = int(argv[1])
basedir = rootdir + "/game-%d" % (game, )
queuename = basedir + "/orders.queue"
if not exists(queuename):
exit(0)
# parse the queue file -
#print "connecting to SMTP..."
from smtplib import SMTP
@ -127,16 +150,17 @@ try:
except:
print "could not connect to SMTP server"
exit(0)
#print "reading password file..."
pw_data = EPasswd(basedir + "/passwd")
pw_data = EPasswd(os.path.join(game_dir,"passwd"))
#print "reading orders.queue..."
# move the queue file to a save space while locking it:
try:
lock_file(queuename)
lock_file(queue_file)
except:
exit(0)
queuefile = open(queuename, "r")
queuefile = open(queue_file, "r")
lines = queuefile.readlines()
queuefile.close()
@ -154,9 +178,9 @@ tmpfile.close()
openlog("orders")
unlink(queuename)
unlink(queue_file)
try:
unlock_file(queuename)
unlock_file(queue_file)
except:
pass
@ -170,15 +194,15 @@ for line in lines:
email = dict["email"]
locale = dict["locale"]
game = int(dict["game"])
file = dict["file"]
infile = dict["file"]
gamename='[E%d]' % game
rules='e%d' % game
warning = ""
failed = True
results = check_pwd(file, email, pw_data)
logfile = open(basedir+"/zug.log", "a")
dirname, filename = splitfilename(file)
msg = messages["validate-"+locale] + " " + filename + "\n\n"
results = check_pwd(infile, email, pw_data)
logfile = open(os.path.join(game_dir, "zug.log"), "a")
dirname, filename = split_filename(infile)
msg = messages["validate-"+locale] + " " + infilename + "\n\n"
for faction, game_email, success, pwd in results:
msg = msg + messages["faction-"+locale] + " " + faction + "\n"
if success: failed = False
@ -189,25 +213,24 @@ for line in lines:
if failed:
warning = " (" + messages["warning-" + locale] + ")"
syslog("failed - no valid password in " + file)
syslog("failed - no valid password in " + infile)
else:
result = echeck(file, locale, rules)
if email=='eressea':
print result
continue
elif result is None:
result = None
if os.path.exists(echeck_cmd):
result = echeck(infile, locale, rules)
if result is None:
# echeck did not finish
msg = msg + "Echeck was killed. Your turn was accepted, but could not be verified.\n"
msg = msg + "Echeck is broken. Your turn was accepted, but could not be verified.\n"
warning = " (" + messages["warning-" + locale] + ")"
syslog("process - echeck got killed, " + file)
syslog("process - echeck broken, " + infile)
else:
msg = msg + result
syslog("process - checked orders in " + file)
syslog("process - checked orders in " + infile)
subject = gamename + " " + messages["subject-" + locale] + warning
msg = "Subject: %s\nFrom: %s\nTo: %s\nContent-Type: text/plain; charset=utf-8\n\n" % (subject, frommail, email) + msg
msg = "Subject: %s\nFrom: %s\nTo: %s\nContent-Type: text/plain; charset=utf-8\n\n" % (subject, sender, email) + msg
try:
server.sendmail(frommail, email, msg)
server.sendmail(sender, email, msg)
except:
syslog("failed - cannot send to " + email)

View File

@ -8,7 +8,6 @@ if [ ! -f reports.txt ]; then
exit -2
fi
source $HOME/bin/functions.sh
source $ERESSEA/etc/eressea.conf
TEMPLATE=report-mail.txt
if [ "$1" == "-Lde" ]

View File

@ -8,7 +8,6 @@ if [ -z $ERESSEA ]; then
exit -2
fi
source $HOME/bin/functions.sh
source $HOME/etc/eressea.conf
GAME=$1
EMAIL=$2

View File

@ -8,7 +8,6 @@ if [ -z $ERESSEA ]; then
exit -2
fi
source $HOME/bin/functions.sh
source $ERESSEA/etc/eressea.conf
if [ ! -z $1 ]; then
GAME=$ERESSEA/game-$1

View File

@ -1804,7 +1804,7 @@
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier erschafft ein Traumgebäude."</text>
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician creates an illusionary building."</text>
</message>
<message name="sp_shapeshift_fail" section="magic">
<message name="sp_shapeshift_fail" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -2402,7 +2402,7 @@
<text locale="de">"Eine Botschaft von $unit.dative($unit) in $region($region): 'Ups! Quack, Quack!'"</text>
<text locale="en">"A message from $unit($unit) in $region($region): 'Oops! Croak, Croak!'"</text>
</message>
<message name="familiar_farcast" section="magic">
<message name="familiar_farcast" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -2412,7 +2412,7 @@
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($mage) kann Zauber, die durch $unit($unit) gewirkt werden, nicht zusätzlich in die Ferne richten."</text>
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($mage) cannot direct spells that are channeled through $unit($unit) into distant regions."</text>
</message>
<message name="familiar_toofar" section="magic">
<message name="familiar_toofar" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -2552,13 +2552,6 @@
<text locale="de">"$unit($unit) in $region($region) regeneriert $int($amount) Aura."</text>
<text locale="en">"$unit($unit) regenerates $int($amount) aura in $region($region)."</text>
</message>
<message name="msg_magic" section="magic">
<type>
<arg name="string" type="string"/>
</type>
<text locale="de">"$string"</text>
<text locale="en">"$string"</text>
</message>
<message name="studycost" section="study">
<type>
<arg name="unit" type="unit"/>
@ -2596,13 +2589,6 @@
<text locale="de">"$unit($teacher) lehrt $unit($student) $skill($skill)."</text>
<text locale="en">"$unit($teacher) teaches $unit($student) $skill($skill)."</text>
</message>
<message name="msg_study" section="study">
<type>
<arg name="string" type="string"/>
</type>
<text locale="de">"$string"</text>
<text locale="en">"$string"</text>
</message>
<message name="sellamount" section="economy">
<type>
<arg name="unit" type="unit"/>
@ -2834,13 +2820,6 @@
<text locale="de">"$unit($unit) baut für $int($size) an $ship($ship) weiter."</text>
<text locale="en">"$unit($unit) builds $int($size) more on $ship($ship)."</text>
</message>
<message name="msg_production" section="production">
<type>
<arg name="string" type="string"/>
</type>
<text locale="de">"$string"</text>
<text locale="en">"$string"</text>
</message>
<message name="firewall_death" section="movement">
<type>
<arg name="unit" type="unit"/>
@ -2878,15 +2857,7 @@
<text locale="de">"$unit($unit) $if($eq($mode,1),"reitet", "wandert") von $region($start) nach $region($end).$if($isnull($regions),""," Dabei wurde $trail($regions) durchquert.")"</text>
<text locale="en">"$unit($unit) $if($eq($mode,1),"rides", "walks") from $region($start) to $region($end)$if($isnull($regions),""," by way of $trail($regions)")."</text>
</message>
<message name="detectoceandir" section="movement">
<type>
<arg name="unit" type="unit"/>
<arg name="direction" type="direction"/>
</type>
<text locale="de">"$unit($unit) entdeckt dass im $direction($direction) $terrain($region) ist."</text>
<text locale="en">"$unit($unit) discovered that $terrain($region) lies in the $direction($direction)."</text>
</message>
<message name="detectocean" section="movement">
<message name="detectocean" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -2895,7 +2866,7 @@
<text locale="de">"$unit($unit) entdeckt, dass $region($region) $localize($terrain) ist."</text>
<text locale="en">"$unit($unit) discovered that $region($region) is $localize($terrain)."</text>
</message>
<message name="leftship" section="movement">
<message name="leftship" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -2903,7 +2874,7 @@
<text locale="de">"$unit($unit) ist in dieser Runde gelandet und kann nicht weiter ins Landesinnere nach $region($region) vorstossen."</text>
<text locale="en">"$unit($unit) has just landed and cannot continue moving to $region($region)."</text>
</message>
<message name="sailnolandingstorm" section="movement">
<message name="sailnolandingstorm" section="errors">
<type>
<arg name="ship" type="ship"/>
<arg name="region" type="region"/>
@ -2911,7 +2882,7 @@
<text locale="de">"Die Mannschaft der $ship($ship) kann in letzter Sekunde verhindern, dass das Schiff in $region($region) auf Land aufläuft."</text>
<text locale="en">"At the very last moment, the crew of the $ship($ship) saved the ship from running aground in $region($region)."</text>
</message>
<message name="sailnolanding" section="movement">
<message name="sailnolanding" section="errors">
<type>
<arg name="ship" type="ship"/>
<arg name="region" type="region"/>
@ -2919,7 +2890,7 @@
<text locale="de">"Die $ship($ship) konnte in $region($region) nicht einreisen, die Küste ist zu gefährlich für das Schiff."</text>
<text locale="en">"The $ship($ship) could not berth in $region($region). The coast is too dangerous for the vessel."</text>
</message>
<message name="sailforbiddendir" section="movement">
<message name="sailforbiddendir" section="errors">
<type>
<arg name="ship" type="ship"/>
<arg name="direction" type="direction"/>
@ -2927,7 +2898,7 @@
<text locale="de">"Die Mannschaft der $ship($ship) weigert sich, nach $direction($direction) zu reisen."</text>
<text locale="en">"The crew of the $ship($ship) refuses to travel to the $direction($direction)."</text>
</message>
<message name="sailforbidden" section="movement">
<message name="sailforbidden" section="errors">
<type>
<arg name="ship" type="ship"/>
<arg name="region" type="region"/>
@ -2935,7 +2906,7 @@
<text locale="de">"Die Mannschaft der $ship($ship) weigert sich, nach $region($region) zu reisen."</text>
<text locale="en">"The crew of the $ship($ship) refuses to travel to $region($region)."</text>
</message>
<message name="detectforbiddendir" section="movement">
<message name="detectforbiddendir" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="direction" type="direction"/>
@ -2943,7 +2914,7 @@
<text locale="de">"$unit($unit) weigert sich, nach $direction($direction) zu reisen."</text>
<text locale="en">"$unit($unit) refuses to travel to the $direction($direction)."</text>
</message>
<message name="detectforbidden" section="movement">
<message name="detectforbidden" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -2951,7 +2922,7 @@
<text locale="de">"$unit($unit) weigert sich, nach $region($region) zu reisen."</text>
<text locale="en">"$unit($unit) refuses to travel to $region($region)."</text>
</message>
<message name="sailfail" section="movement">
<message name="sailfail" section="errors">
<type>
<arg name="ship" type="ship"/>
<arg name="region" type="region"/>
@ -2959,7 +2930,7 @@
<text locale="de">"Die $ship($ship) konnte $region($region) nicht verlassen."</text>
<text locale="en">"The $ship($ship) could not leave $region($region)."</text>
</message>
<message name="moveblockedbyguard" section="movement">
<message name="moveblockedbyguard" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -2968,35 +2939,7 @@
<text locale="de">"$unit($unit) wurde in $region($region) von $unit.dative($guard) aufgehalten."</text>
<text locale="en">"$unit($unit) was kept in $region($region) by $unit($guard)."</text>
</message>
<message name="peace_confirm" section="events">
<type>
<arg name="enemy" type="faction"/>
</type>
<text locale="de">"Wir haben den Krieg mit $faction($faction) beendet."</text>
<text locale="en">"We declared peace with $faction($faction)."</text>
</message>
<message name="peace_notify" section="events">
<type>
<arg name="enemy" type="faction"/>
</type>
<text locale="de">"$faction($faction) hat den Krieg mit uns beendet."</text>
<text locale="en">"$faction($faction) has declared peace with us."</text>
</message>
<message name="war_confirm" section="events">
<type>
<arg name="enemy" type="faction"/>
</type>
<text locale="de">"Wir haben $faction($faction) den Krieg erklärt."</text>
<text locale="en">"We declared war on $faction($faction)."</text>
</message>
<message name="war_notify" section="events">
<type>
<arg name="enemy" type="faction"/>
</type>
<text locale="de">"$faction($faction) hat uns den Krieg erklärt."</text>
<text locale="en">"$faction($faction) has declared war on us."</text>
</message>
<message name="regionowned" section="movement">
<message name="regionowned" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -3005,7 +2948,7 @@
<text locale="de">"$unit($unit) konnte nicht von $region($region) nach $region($target) reisen, da der Besitzer der Region es verhinderte."</text>
<text locale="en">"$unit($unit) could not travel from $region($region) to $region($target) because the owner denied entrance."</text>
</message>
<message name="leavefail" section="movement">
<message name="leavefail" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -3029,7 +2972,7 @@
<text locale="de">"$unit($follower) konnte $unit($unit) nicht folgen."</text>
<text locale="en">"$unit($follower) could not follow $unit($unit)."</text>
</message>
<message name="moveblocked" section="movement">
<message name="moveblocked" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="direction" type="direction"/>
@ -3037,7 +2980,7 @@
<text locale="de">"$unit($unit) entdeckt, dass es keinen Weg nach $direction($direction) gibt."</text>
<text locale="en">"$unit($unit) discovers that there is no route going $direction($direction)."</text>
</message>
<message name="fogblock" section="movement">
<message name="fogblock" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -3046,13 +2989,6 @@
<text locale="de">"$unit($unit) konnte von $region($region) nicht nach $direction($direction) ausreisen, der Nebel war zu dicht."</text>
<text locale="en">"$unit($unit) could not travel $direction($direction) from $region($region), the fog was too dense."</text>
</message>
<message name="msg_movement" section="movement">
<type>
<arg name="string" type="string"/>
</type>
<text locale="de">"$string"</text>
<text locale="en">"$string"</text>
</message>
<message name="entrise" section="events">
<type>
<arg name="region" type="region"/>
@ -6945,13 +6881,6 @@
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Man benötigt mindestens $int($minskill) $skill($skill), um $resource($product,0) zu produzieren."</text>
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - You need at least $int($minskill) $skill($skill), to produce $resource($product,0)."</text>
</message>
<message name="msg_errors" section="errors">
<type>
<arg name="string" type="string"/>
</type>
<text locale="de">"$string"</text>
<text locale="en">"$string"</text>
</message>
<message name="msg_event" section="events">
<type>
<arg name="string" type="string"/>
@ -6959,13 +6888,6 @@
<text locale="de">"$string"</text>
<text locale="en">"$string"</text>
</message>
<message name="msg_economy" section="economy">
<type>
<arg name="string" type="string"/>
</type>
<text locale="de">"$string"</text>
<text locale="en">"$string"</text>
</message>
<message name="give_person" section="economy">
<type>
<arg name="unit" type="unit"/>
@ -6997,7 +6919,6 @@
<text locale="de">"$unit($target) erhält $int($amount) $resource($resource,$amount) von $unit($unit)."</text>
<text locale="en">"$unit($target) receives $int($amount) $resource($resource,$amount) from $unit($unit)."</text>
</message>
<message name="give_person_ocean" section="economy">
<type>
<arg name="unit" type="unit"/>
@ -7200,7 +7121,7 @@
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - No pyramids may be build in this region. The closest region to build a pyramid in is between $int($mindist) and $int($maxdist) regions away."</text>
</message>
<message name="wormhole_requirements" section="events">
<message name="wormhole_requirements" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
@ -7621,7 +7542,7 @@
<text locale="de">"Heer $int($index)($abbrev): $int($dead) Tote, $int($fled) Geflohene, $int($survived) Überlebende."</text>
<text locale="en">"Army $int($index)($abbrev): $int($dead) dead, $int($fled) fled, $int($survived) survivors."</text>
</message>
<message name="spellfail::nolevel" section="magic">
<message name="spellfail::nolevel" section="errors">
<type>
<arg name="mage" type="unit"/>
<arg name="region" type="region"/>

View File

@ -35,12 +35,13 @@ if [ -d $HOME/usr ]; then
PREFIX_PATH=$HOME/usr:$HOME/usr/local:$PREFIX_PATH
fi
DEST=$(dirname $ROOT)/server
ARGS=" -DCMAKE_MODULE_PATH=$ROOT/cmake/Modules \
-DCMAKE_BUILD_TYPE=$BUILD \
-DCMAKE_LIBRARY_PATH=$LIBRARY_PATH \
-DCMAKE_INCLUDE_PATH=$INCLUDE_PATH \
-DCMAKE_PREFIX_PATH=$PREFIX_PATH \
-DCMAKE_INSTALL_PREFIX=$HOME/eressea/server"
-DCMAKE_INSTALL_PREFIX=$DEST"
git submodule update --init

View File

@ -8,8 +8,6 @@ while [ ! -d $ROOT/.git ]; do
fi
done
DEST=$(dirname $ROOT)/server
[ -z "$CC" ] && [ ! -z `which clang` ] && CC="clang"
[ -z "$CC" ] && [ ! -z `which gcc` ] && CC="gcc"
[ -z "$CC" ] && [ ! -z `which tcc` ] && CC="tcc"

18
s/setup
View File

@ -1,5 +1,15 @@
#!/bin/bash
ROOT=$(pwd)
while [ ! -d $ROOT/.git ]; do
ROOT=$(dirname $ROOT)
if [ "/" = "$ROOT" ]; then
echo "could not find root, are you in the git repository?"
exit
fi
done
ERESSEA=$(dirname $ROOT)
function abort() {
echo $1
[ -z $2 ] && exit -1
@ -37,7 +47,6 @@ while getopts :d:g:r:s:hfn o; do
done
[ $game -gt 0 ] || abort "must use a positive integer for game id"
[ -d $ERESSEA ] || abort "invalid or missing env variable ERESSEA ($ERESSEA)"
[ -z $SOURCE ] && SOURCE=$ERESSEA/$src
[ -d $SOURCE ] || abort "invalid source directory $SOURCE"
[ -z $rules ] && rules=e$game
@ -46,7 +55,8 @@ done
[ -e $TOOLS ] || TOOLS=$SOURCE/bin
[ -z $INIFILE ] && INIFILE=$TOOLS/inifile
[ -e $INIFILE ] || INIFILE=$TOOLS/iniparser/inifile
#[ -e $INIFILE ] || abort "tool is not installed: $INIFILE"
[ -e $SOURCE/conf/$rules/config.xml ] || abort "cannot find conf/$rules/config.xml"
cd $ERESSEA
if [ -d $dir ] ; then
@ -84,8 +94,8 @@ touch eressea.ini
}
ini_start
ini_sec eressea
ini_add eressea locales de,en
ini_sec game
ini_add game locales de,en
ini_sec lua
ini_add lua install $SOURCE
ini_add lua paths $SOURCE/scripts:$SOURCE/lunit

View File

@ -93,12 +93,6 @@ typedef enum combatmagic {
DO_POSTCOMBATSPELL
} combatmagic_t;
/* globals */
bool battledebug = false;
static int obs_count = 0;
static FILE *bdebug;
#define MINSPELLRANGE 1
#define MAXSPELLRANGE 7
@ -1219,9 +1213,6 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
kritchance = MIN(0.9, kritchance);
while (chance(kritchance)) {
if (bdebug) {
fprintf(bdebug, "%s/%d lands a critical hit\n", itoa36(au->no), at.index);
}
da += dice_rand(damage);
}
}
@ -1302,10 +1293,6 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
}
if (df->person[dt.index].hp > 0) { /* Hat <20>berlebt */
if (bdebug) {
fprintf(bdebug, "Damage %d, armor %d: %d -> %d HP\n",
da, ar, df->person[dt.index].hp + rda, df->person[dt.index].hp);
}
if (u_race(au) == get_race(RC_DAEMON)) {
if (!(df->person[dt.index].flags & (FL_COURAGE | FL_DAZZLED))) {
df->person[dt.index].flags |= FL_DAZZLED;
@ -1334,10 +1321,6 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
}
++at.fighter->kills;
if (bdebug) {
fprintf(bdebug, "Damage %d, armor %d, type %d: %d -> %d HP, tot.\n",
da, ar, type, df->person[dt.index].hp + rda, df->person[dt.index].hp);
}
for (pitm = &du->items; *pitm;) {
item *itm = *pitm;
const item_type *itype = itm->type;
@ -1979,20 +1962,6 @@ int getreload(troop at)
return at.fighter->person[at.index].reload;
}
static void
debug_hit(troop at, const weapon * awp, troop dt, const weapon * dwp,
int skdiff, int dist, bool success)
{
fprintf(bdebug, "%.4s/%d [%6s/%d] %s %.4s/%d [%6s/%d] with %d, distance %d\n",
itoa36(at.fighter->unit->no), at.index,
LOC(default_locale, awp ? resourcename(awp->type->itype->rtype,
0) : "unarmed"), weapon_effskill(at, dt, awp, true, dist > 1),
success ? "hits" : "misses", itoa36(dt.fighter->unit->no), dt.index,
LOC(default_locale, dwp ? resourcename(dwp->type->itype->rtype,
0) : "unarmed"), weapon_effskill(dt, at, dwp, false, dist > 1), skdiff,
dist);
}
int hits(troop at, troop dt, weapon * awp)
{
fighter *af = at.fighter, *df = dt.fighter;
@ -2032,14 +2001,8 @@ int hits(troop at, troop dt, weapon * awp)
shield = select_armor(dt, false);
}
if (contest(skdiff, dt, armor, shield)) {
if (bdebug) {
debug_hit(at, awp, dt, dwp, skdiff, dist, true);
}
return 1;
}
if (bdebug) {
debug_hit(at, awp, dt, dwp, skdiff, dist, false);
}
return 0;
}
@ -2190,11 +2153,7 @@ static void attack(battle * b, troop ta, const att * a, int numattack)
}
}
if (reload && wp && wp->type->reload && !getreload(ta)) {
int i = setreload(ta);
if (bdebug) {
fprintf(bdebug, "%s/%d reloading %d turns\n", itoa36(au->no),
ta.index, i);
}
setreload(ta);
}
}
}
@ -2874,13 +2833,6 @@ static void aftermath(battle * b)
}
reorder_fleeing(r);
if (bdebug) {
fprintf(bdebug, "The battle lasted %d turns, %s and %s.\n",
b->turn,
b->has_tactics_turn ? "had a tactic turn" : "had no tactic turn",
ships_damaged ? "was relevant" : "was not relevant.");
}
}
static void battle_punit(unit * u, battle * b)
@ -2894,10 +2846,6 @@ static void battle_punit(unit * u, battle * b)
spunit(&S, f, u, 4, seen_battle);
for (x = S; x; x = x->next) {
fbattlerecord(b, f, x->s);
if (bdebug && u->faction == f) {
fputs(x->s, bdebug);
fputc('\n', bdebug);
}
}
if (S)
freestrlist(S);
@ -3077,17 +3025,6 @@ static void print_stats(battle * b)
fbattlerecord(b, f, buf);
}
if (bdebug && s->faction) {
if (f_get_alliance(s->faction)) {
fprintf(bdebug, "##### %s (%s/%d)\n", s->faction->name,
itoa36(s->faction->no),
s->faction->alliance ? s->faction->alliance->id : 0);
}
else {
fprintf(bdebug, "##### %s (%s)\n", s->faction->name,
itoa36(s->faction->no));
}
}
print_fighters(b, s);
}
@ -3519,28 +3456,6 @@ static int join_battle(battle * b, unit * u, bool attack, fighter ** cp)
return false;
}
static const char *simplename(region * r)
{
int i;
static char name[17];
const char *cp = rname(r, default_locale);
for (i = 0; *cp && i != 16; ++i, ++cp) {
int c = *(unsigned char *)cp;
while (c && !isalpha(c) && !isspace(c)) {
++cp;
c = *(unsigned char *)cp;
}
if (isspace(c))
name[i] = '_';
else
name[i] = *cp;
if (c == 0)
break;
}
name[i] = 0;
return name;
}
battle *make_battle(region * r)
{
battle *b = (battle *)calloc(1, sizeof(battle));
@ -3552,29 +3467,6 @@ battle *make_battle(region * r)
for (bld = r->buildings; bld != NULL; bld = bld->next)
bld->sizeleft = bld->size;
if (battledebug) {
char zText[4096];
char zFilename[4096];
join_path(basepath(), "battles", zText, sizeof(zText));
if (mkdir(zText, 0777) != 0) {
log_error("could not create subdirectory for battle logs: %s", zText);
battledebug = false;
}
else {
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 {
const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 };
fwrite(utf8_bom, 1, 3, bdebug);
fprintf(bdebug, "In %s findet ein Kampf statt:\n", rname(r,
default_locale));
}
}
}
b->region = r;
b->plane = getplane(r);
/* Finde alle Parteien, die den Kampf beobachten k<>nnen: */
@ -3644,10 +3536,6 @@ static void battle_free(battle * b) {
void free_battle(battle * b)
{
if (bdebug) {
fclose(bdebug);
}
while (b->factions) {
bfaction *bf = b->factions;
b->factions = bf->next;
@ -3812,13 +3700,7 @@ static void join_allies(battle * b)
}
/* keine Einw<6E>nde, also soll er mitmachen: */
if (c == NULL) {
if (join_battle(b, u, false, &c)) {
if (battledebug) {
fprintf(bdebug, "%s joins to help %s against %s.\n",
unitname(u), factionname(s->faction), factionname(se->faction));
}
}
else if (c == NULL) {
if (!join_battle(b, u, false, &c)) {
continue;
}
}
@ -3826,12 +3708,7 @@ static void join_allies(battle * b)
/* the enemy of my friend is my enemy: */
for (se = b->sides; se != s_end; ++se) {
if (se->faction != u->faction && enemy(s, se)) {
if (set_enemy(se, c->side, false) && battledebug) {
fprintf(bdebug,
"%u/%s hates %u/%s because they are enemies with %u/%s.\n",
c->side->index, sidename(c->side), se->index, sidename(se),
s->index, sidename(s));
}
set_enemy(se, c->side, false);
}
}
}
@ -4012,18 +3889,8 @@ static bool start_battle(region * r, battle ** bp)
}
b = make_battle(r);
}
if (join_battle(b, u, true, &c1)) {
if (battledebug) {
fprintf(bdebug, "%s joins by attacking %s.\n",
unitname(u), unitname(u2));
}
}
if (join_battle(b, u2, false, &c2)) {
if (battledebug) {
fprintf(bdebug, "%s joins because of an attack from %s.\n",
unitname(u2), unitname(u));
}
}
join_battle(b, u, true, &c1);
join_battle(b, u2, false, &c2);
/* Hat die attackierte Einheit keinen Noaid-Status,
* wird das Flag von der Faction genommen, andere
@ -4036,11 +3903,7 @@ static bool start_battle(region * r, battle ** bp)
* Pr<EFBFBD>combataura bei kurzem Kampf. */
c1->side->bf->attacker = true;
if (set_enemy(c1->side, c2->side, true) && battledebug) {
fprintf(bdebug, "%u/%s hates %u/%s because they attacked them.\n",
c2->side->index, sidename(c2->side),
c1->side->index, sidename(c1->side));
}
set_enemy(c1->side, c2->side, true);
fighting = true;
}
}
@ -4159,10 +4022,6 @@ static void battle_flee(battle * b)
flee(dt);
}
}
if (bdebug && runners > 0) {
fprintf(bdebug, "Fleeing: %d from %s\n", runners,
itoa36(fig->unit->no));
}
}
}
}
@ -4265,9 +4124,6 @@ void do_battle(region * r)
log_debug("battle in %s (%d, %d) : ", regionname(r, 0), r->x, r->y);
for (; battle_report(b) && b->turn <= max_turns; ++b->turn) {
if (bdebug) {
fprintf(bdebug, "*** Turn: %d\n", b->turn);
}
battle_flee(b);
battle_update(b);
battle_attacks(b);

View File

@ -225,7 +225,6 @@ extern "C" {
} meffect;
extern const troop no_troop;
extern bool battledebug;
/* BEGIN battle interface */
side * find_side(battle * b, const struct faction * f, const struct group * g, unsigned int flags, const struct faction * stealthfaction);

View File

@ -214,29 +214,11 @@ caddmessage(region * r, faction * f, const char *s, msg_t mtype, int level)
UNUSED_ARG(level);
switch (mtype) {
case MSG_INCOME:
assert(f);
m = add_message(&f->msgs, msg_message("msg_economy", "string", s));
break;
case MSG_BATTLE:
assert(0 || !"battle messages must not use addmessage");
break;
case MSG_MOVE:
assert(f);
m = add_message(&f->msgs, msg_message("msg_movement", "string", s));
break;
case MSG_COMMERCE:
assert(f);
m = add_message(&f->msgs, msg_message("msg_economy", "string", s));
break;
case MSG_PRODUCE:
assert(f);
m = add_message(&f->msgs, msg_message("msg_production", "string", s));
break;
case MSG_MAGIC:
case MSG_COMMENT:
case MSG_MESSAGE:
case MSG_ORCVERMEHRUNG:
case MSG_EVENT:
/* Botschaften an REGION oder einzelne PARTEI */
m = msg_message("msg_event", "string", s);

View File

@ -146,9 +146,7 @@ typedef enum { /* Fehler und Meldungen im Report */
MSG_INCOME,
MSG_COMMERCE,
MSG_PRODUCE,
MSG_ORCVERMEHRUNG,
MSG_MESSAGE,
MSG_COMMENT,
MSG_MAGIC,
MAX_MSG
} msg_t;

View File

@ -25,7 +25,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/filereader.h>
#include <util/language.h>
#include "eressea.h"
#include "battle.h"
#ifdef USE_CURSES
#include "gmtool.h"
#endif
@ -55,25 +54,23 @@ static void load_inifile(dictionary * d)
assert(d);
str = iniparser_getstring(d, "eressea:base", basedir);
str = iniparser_getstring(d, "game:base", basedir);
if (str != basedir) {
set_basepath(str);
}
str = iniparser_getstring(d, "eressea:report", reportdir);
str = iniparser_getstring(d, "game:report", reportdir);
if (str != reportdir) {
set_reportpath(str);
}
str = iniparser_getstring(d, "eressea:data", datadir);
str = iniparser_getstring(d, "game:data", datadir);
if (str != datadir) {
set_datapath(str);
}
lomem = iniparser_getint(d, "eressea:lomem", lomem) ? 1 : 0;
lomem = iniparser_getint(d, "game:lomem", lomem) ? 1 : 0;
verbosity = iniparser_getint(d, "eressea:verbose", 2);
battledebug = iniparser_getint(d, "eressea:debug", battledebug) ? 1 : 0;
str = iniparser_getstring(d, "eressea:locales", "de,en");
verbosity = iniparser_getint(d, "game:verbose", 2);
str = iniparser_getstring(d, "game:locales", "de,en");
make_locales(str);
if (global.inifile) iniparser_freedict(global.inifile);
@ -87,7 +84,7 @@ static void parse_config(const char *filename)
load_inifile(d);
log_debug("reading from configuration file %s\n", filename);
memdebug = iniparser_getint(d, "eressea:memcheck", memdebug);
memdebug = iniparser_getint(d, "game:memcheck", memdebug);
#ifdef USE_CURSES
/* only one value in the [editor] section */
force_color = iniparser_getint(d, "editor:color", force_color);

View File

@ -100,9 +100,26 @@ static void test_unicode_utf8_to_ucs(CuTest *tc) {
CuAssertIntEquals(tc, 1, sz);
}
static void test_unicode_bug2262(CuTest *tc) {
char name[7];
ucs4_t ucs;
size_t sz;
strcpy(name, "utende");
CuAssertIntEquals(tc, 0, unicode_utf8_to_ucs4(&ucs, name, &sz));
CuAssertIntEquals(tc, 1, sz);
CuAssertIntEquals(tc, 'u', ucs);
CuAssertIntEquals(tc, 0, unicode_utf8_trim(name));
name[0] = -4; // latin1: &uuml; should fail to decode
CuAssertIntEquals(tc, EILSEQ, unicode_utf8_to_ucs4(&ucs, name, &sz));
CuAssertIntEquals(tc, EILSEQ, unicode_utf8_trim(name));
}
CuSuite *get_unicode_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_unicode_bug2262);
SUITE_ADD_TEST(suite, test_unicode_tolower);
SUITE_ADD_TEST(suite, test_unicode_trim);
SUITE_ADD_TEST(suite, test_unicode_utf8_to_other);