summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHello TMW <hello@themanaworld.org>2025-03-12 12:16:19 +0000
committerHello TMW <hello@themanaworld.org>2025-03-12 12:16:19 +0000
commitb0428330565e92350b002d969c90601f90dc47e5 (patch)
tree1f22af7cf0039ac80e032edad8876ae0e348867c
parent3a0bfe045e24a8d769c60b513ade85505926be70 (diff)
parent88dfbd91ed22ab4ad98b2b9f0243f9d9faa9b49d (diff)
downloadtmwa-b0428330565e92350b002d969c90601f90dc47e5.tar.gz
tmwa-b0428330565e92350b002d969c90601f90dc47e5.tar.bz2
tmwa-b0428330565e92350b002d969c90601f90dc47e5.tar.xz
tmwa-b0428330565e92350b002d969c90601f90dc47e5.zip
Merge branch tmwa:master into masterHEADmaster
-rw-r--r--.gitignore6
-rw-r--r--.gitlab-ci.yml74
-rw-r--r--.gitmodules2
-rw-r--r--CMakeLists.txt188
-rw-r--r--COPYING2
-rw-r--r--Makefile.in88
-rw-r--r--README.md2
-rwxr-xr-xconfigure10
m---------deps/attoconf0
-rw-r--r--generate.mk (renamed from generate.make)0
-rw-r--r--src/char/char.cpp2
-rw-r--r--src/conf/install.hpp.in (renamed from src/conf/install.hpp)7
-rw-r--r--src/conf/version.hpp.in (renamed from src/conf/version.hpp)21
-rw-r--r--src/main-gdb-head.py2
-rw-r--r--src/map/clif.cpp2
-rw-r--r--src/map/mob.cpp173
-rw-r--r--src/map/npc-parse.cpp7
-rw-r--r--src/map/script-fun.cpp241
-rw-r--r--src/map/script-parse.py2
-rw-r--r--src/mmo/version.cpp2
-rw-r--r--src/shared/lib.cpp2
-rwxr-xr-xtools/bs-align2
-rwxr-xr-xtools/colorize4
-rwxr-xr-xtools/config.py10
-rwxr-xr-xtools/debug-debug-scripts9
-rw-r--r--tools/debug-debug.gdb6
-rwxr-xr-xtools/indenter7
-rwxr-xr-xtools/pp-indent2
-rwxr-xr-xtools/protocol.py128
-rw-r--r--version.mk (renamed from version.make)31
30 files changed, 649 insertions, 383 deletions
diff --git a/.gitignore b/.gitignore
index d28b05e..34afd74 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,10 +9,12 @@
/src/proto2/
/src/debug-debug/
/src/*/*_conf.[ch]pp
+/src/conf/version.hpp
# tags file
/tags
# generated by configure
/Makefile
+/src/conf/install.hpp
/config.status
/lib
# generated by python
@@ -32,3 +34,7 @@
# generic build
/build/
+
+# CI build
+/build-atto/
+/build-cmake/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f7c750a..0368723 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -8,6 +8,7 @@ variables: &base_vars
# Depth of clone. If no tag is made after this many commits, then
# the git describe call and version header generation will fail.
GIT_DEPTH: 100 # Will break again eventually.
+ GIT_SUBMODULE_STRATEGY: normal
.prerequisites: &prerequisites
before_script:
@@ -15,21 +16,21 @@ variables: &base_vars
- apt-get update
- apt-get install -y -qq $INSTALL_PACKAGES $DEBIAN_COMMON_PACKAGES
-
# Active server OS?
-re:ubuntu1804:build:
+re:ubuntu1804-attoconf:build:
<<: *prerequisites
stage: build
image: ubuntu:18.04
variables:
<<: *base_vars
- INSTALL_PACKAGES: python
+ INSTALL_PACKAGES: python3
script:
- echo "Building TMW Athena $CI_BUILD_NAME"
- - git submodule update --init
- git fetch -t
- printf "Building TMW Athena version %s\n" "$(git describe --tags HEAD)"
- - ./configure --user
+ - mkdir build-atto
+ - cd build-atto
+ - ../configure --user
- make
- whoami
- make install
@@ -37,23 +38,20 @@ re:ubuntu1804:build:
untracked: true
expire_in: 30 mins
-
-
-
# Next server OS?
-re:ubuntu2204:build:
+re:ubuntu2204-attoconf:build:
<<: *prerequisites
stage: build
image: ubuntu:22.04
variables:
<<: *base_vars
- INSTALL_PACKAGES: python2
+ INSTALL_PACKAGES: python3
script:
- - ln -s /usr/bin/python2 /usr/bin/python
- - git submodule update --init
- git fetch -t
- printf "Building TMW Athena version %s\n" "$(git describe --tags HEAD)"
- - ./configure --user
+ - mkdir build-atto
+ - cd build-atto
+ - ../configure --user
- make
- whoami
- make install
@@ -61,31 +59,69 @@ re:ubuntu2204:build:
untracked: true
expire_in: 30 mins
-
+# Next server OS, with cmake
+re:ubuntu2204:build:
+ <<: *prerequisites
+ stage: build
+ image: ubuntu:22.04
+ variables:
+ <<: *base_vars
+ INSTALL_PACKAGES: python3 cmake
+ script:
+ - git fetch -t
+ - printf "Building TMW Athena version %s\n" "$(git describe --tags HEAD)"
+ - mkdir build-cmake
+ - cd build-cmake
+ - cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local ..
+ - make
+ - whoami
+ - make install
+ artifacts: # required for test stage
+ untracked: true
+ expire_in: 30 mins
# Disabled. fails with:
# (1) GDB failing to resolve a type
# (2) /usr/bin/ld: Dwarf Error: Can't find .debug_ranges section.
-.re:ubuntu1804:test:
+.re:ubuntu1804-attoconf:test:
<<: *prerequisites
stage: test
image: ubuntu:18.04
+ needs: ["ubuntu1804-attoconf:build"]
+ variables:
+ <<: *base_vars
+ INSTALL_PACKAGES: python3 gdb
+ script:
+ - printf "Testing TMW Athena version %s\n" "$(git describe --tags HEAD)"
+ - cd build-atto
+ - make test
+
+
+# Enabled tests
+re:ubuntu2204-attoconf:test:
+ <<: *prerequisites
+ stage: test
+ image: ubuntu:22.04
+ needs: ["re:ubuntu2204-attoconf:build"]
variables:
<<: *base_vars
- INSTALL_PACKAGES: python gdb
+ INSTALL_PACKAGES: python3 gdb
script:
- printf "Testing TMW Athena version %s\n" "$(git describe --tags HEAD)"
+ - cd build-atto
- make test
-re:ubuntu2204:test:
+# Disabled. Tests are not supported yet by the CMake project.
+.re:ubuntu2204:test:
<<: *prerequisites
stage: test
image: ubuntu:22.04
+ needs: ["re:ubuntu2204:build"]
variables:
<<: *base_vars
- INSTALL_PACKAGES: python2 gdb
+ INSTALL_PACKAGES: python3 gdb
script:
- - ln -s /usr/bin/python2 /usr/bin/python
- printf "Testing TMW Athena version %s\n" "$(git describe --tags HEAD)"
+ - cd build-cmake
- make test
diff --git a/.gitmodules b/.gitmodules
index 8197e60..48c5d1f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,6 @@
[submodule "deps/attoconf"]
path = deps/attoconf
- url = https://github.com/o11c/attoconf.git
+ url = https://github.com/Freeyorp/attoconf
[submodule "deps/googletest"]
path = deps/googletest
url = https://github.com/google/googletest.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..5d550f3
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,188 @@
+cmake_minimum_required(VERSION 3.10)
+
+# Function for conveniently capturing git output, used to set version related variables
+find_package(Git REQUIRED)
+function(git_capture_output var)
+ execute_process(COMMAND ${GIT_EXECUTABLE} ${ARGN}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ OUTPUT_VARIABLE ${var}
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET)
+ message(STATUS "${var} = ${${var}}")
+ set(${var} ${${var}} PARENT_SCOPE)
+endfunction()
+
+git_capture_output(VERSION_FULL describe --tags)
+git_capture_output(VERSION_HASH rev-parse HEAD)
+
+# Capture the major.minor.patch part of the version based on the last tag
+string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" VERSION ${VERSION_FULL})
+
+# Capture the tweak part of the version
+if(${VERSION_FULL} MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+-([0-9]+)-g[0-9a-f]+$")
+ set(VERSION "${VERSION}.${CMAKE_MATCH_1}")
+else()
+ set(VERSION "${VERSION}.0")
+endif()
+
+project(tmwAthena VERSION ${VERSION} LANGUAGES CXX)
+
+# Prefer to use G++ as the compiler
+set(CMAKE_CXX_COMPILER g++)
+# Set C++ standard to C++11
+# Note we want -std=c++11, not -std=gnu++11, as we want to avoid GNU extensions
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Some sources and includes are generated, such as the protocol headers.
+# We defer to generate.make for these rules.
+# Note that these are raw Makefile rules, not CMake rules, so a simple
+# add_custom_command() won't work.
+execute_process(COMMAND make -f ${CMAKE_SOURCE_DIR}/generate.mk
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+
+# The generate target must be re-run when the scripts change
+set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
+ "${PROJECT_SOURCE_DIR}/generate.mk"
+ "${PROJECT_SOURCE_DIR}/tools/config.py"
+ "${PROJECT_SOURCE_DIR}/tools/protocol.py"
+)
+
+# Search through the tree for sources
+# For each subfolder in src, add all .cpp, .hpp and .tcc files to a subfolder's SOURCES
+# variable.
+set(ALL_SOURCES "")
+foreach(dir admin ast char compat conf generic high ints io login map mmo net proto-base range sexpr shared strings tests wire)
+ file(GLOB_RECURSE ${dir}_SOURCES CONFIGURE_DEPENDS
+ src/${dir}/*.cpp
+ src/${dir}/*.hpp
+ src/${dir}/*.tcc)
+ # Exclude any _test.cpp files from the build
+ set(ALL_SOURCES ${ALL_SOURCES} ${${dir}_SOURCES})
+ list(FILTER ${dir}_SOURCES EXCLUDE REGEX ".*_test.cpp")
+ message("Adding sources in ${dir}: ${${dir}_SOURCES}")
+endforeach()
+
+# All targets include the include/ directory
+include_directories(include)
+
+# We want -fvisibility=hidden for regular objects, but not shared libraries.
+# CMake provides a helpful preset for this.
+# FIXME this is currently broken
+#set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+# General purpose build flags.
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -fstack-protector -fno-strict-aliasing -flto=auto")
+# Enable link time optimization, and track function and data sections. We let
+# the linker remove unused code.
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=auto -ffunction-sections -fdata-sections -Wl,--gc-sections")
+# Next, add warnings
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
+# Add debug information
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
+
+# Vendor Name: String (no newlines, no parentheses)
+# This is usually one word, and does not (usually) change over time.
+# (Examples: Gentoo, Debian, Fedora, Ubuntu)
+set(VENDOR_NAME Vanilla)
+# Vendor Point: Integer (max value 65535)
+# This is intended to be the "packaging revision number", assuming that's
+# an integer. At a minimum, please try to make it nonzero if you have
+# any non-upstream patches (unconditionally nonzero is also okay).
+# (If your revision 0 package has patches ... please be nicer to upstream)
+set(VENDOR_POINT 0)
+# URL where the source may be found (after searching for version number).
+# See AGPLv3 section 13
+set(VENDOR_SOURCE https://git.themanaworld.org/legacy/tmwa)
+
+# Convenience
+set(VERSION_STRING "TMWA ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} dev${PROJECT_VERSION_TWEAK} +${VENDOR_POINT} (${VENDOR_NAME})")
+set(VERSION_DOTS "${PROJECT_VERSION}.${VENDOR_POINT}")
+
+include(GNUInstallDirs)
+set(PACKAGEDATADIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/tmwa")
+set(LOCALSTATEDIR "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}")
+set(SYSCONFDIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}")
+
+# Generate the install.hpp and version.hpp files.
+configure_file(src/conf/install.hpp.in src/conf/install.hpp @ONLY)
+configure_file(src/conf/version.hpp.in src/conf/version.hpp @ONLY)
+set(conf_SOURCES ${conf_SOURCES} src/conf/install.hpp src/conf/version.hpp)
+# And have the build search for files in the build directory.
+# Note that #includes with generated files should use a path relative to the
+# top level source or build directory.
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+# Add a shared library: libtmwa-shared.so.0
+# When we add_executable later, we need to link against this library.
+add_library(tmwa-shared SHARED ${shared_SOURCES}
+ src/io/dir.cpp
+ src/io/fd.cpp
+ src/io/read.cpp
+ src/io/write.cpp
+ ${strings_SOURCES}
+)
+# SO versioning
+set(ABI_VERSION 0)
+set_target_properties(tmwa-shared PROPERTIES
+ VERSION ${ABI_VERSION}.${VERSION_DOTS}
+ SOVERSION ${ABI_VERSION})
+
+# We have four binaries we want to build: tmwa-{login,char,map,admin}
+add_executable(tmwa-login ${login_SOURCES}
+ ${generic_SOURCES}
+ ${high_SOURCES}
+ ${io_SOURCES}
+ ${mmo_SOURCES}
+ ${net_SOURCES}
+ ${wire_SOURCES}
+)
+target_link_libraries(tmwa-login tmwa-shared)
+
+add_executable(tmwa-char ${char_SOURCES}
+ ${generic_SOURCES}
+ ${high_SOURCES}
+ ${io_SOURCES}
+ ${mmo_SOURCES}
+ ${net_SOURCES}
+ ${wire_SOURCES}
+)
+target_link_libraries(tmwa-char tmwa-shared)
+
+add_executable(tmwa-map ${map_SOURCES}
+ ${ast_SOURCES}
+ ${compat_SOURCES}
+ ${generic_SOURCES}
+ ${high_SOURCES}
+ ${io_SOURCES}
+ ${mmo_SOURCES}
+ ${net_SOURCES}
+ ${wire_SOURCES}
+ )
+target_link_libraries(tmwa-map tmwa-shared)
+
+add_executable(tmwa-admin ${admin_SOURCES}
+ ${generic_SOURCES}
+ ${high_SOURCES}
+ ${io_SOURCES}
+ ${mmo_SOURCES}
+ ${net_SOURCES}
+ ${wire_SOURCES}
+)
+target_link_libraries(tmwa-admin tmwa-shared)
+
+# TODO: Call make -f ${CMAKE_SOURCE_DIR}/generate.mk clean to clean up the
+# generated files. We want this to be run every time we call make clean.
+
+# Install targets
+install(TARGETS tmwa-login tmwa-char tmwa-map tmwa-admin tmwa-shared
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+)
+
+# Install shared configuration and data
+install(FILES etc/tmwa/shared.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/tmwa)
+install(FILES share/tmwa/shared.data DESTINATION ${CMAKE_INSTALL_DATADIR}/tmwa)
+
+# Make sure there is a var directory
+install(DIRECTORY DESTINATION ${CMAKE_INSTALL_LOCALSTATEDIR}/tmwa)
diff --git a/COPYING b/COPYING
index edf98ab..c1c13ff 100644
--- a/COPYING
+++ b/COPYING
@@ -5,7 +5,7 @@ This combination is explicitly allowed by section 13 of the licenses.
See gpl-3.0.txt or agpl-3.0.txt for specific terms.
In order to make life easy for users who run this software publicly,
-please set VENDOR_SOURCE in version.make if you make any modifications.
+please set VENDOR_SOURCE in version.mk if you make any modifications.
History:
diff --git a/Makefile.in b/Makefile.in
index 10f909c..075c107 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -152,7 +152,7 @@ $(info The Road goes ever on and on ...)
endif
endif
-include ${SRC_DIR}/version.make
+include ${SRC_DIR}/version.mk
ifeq (${ENABLE_SHARED},yes)
LIB_SUFFIX_FAKE := so
@@ -184,12 +184,13 @@ export PATH:=$(realpath ${SRC_DIR}/tools):${PATH}
SHELL=bash
# need to generate source files before path lists
-$(shell make -f ${SRC_DIR}/generate.make >&2)
+$(shell make -f ${SRC_DIR}/generate.mk >&2)
stamp/generated.stamp:
# if you get here, the shell above failed
false
# path lists
+GENERATED_FILES := src/conf/version.hpp
REAL_SOURCES := $(shell cd ${SRC_DIR}; find src/ -name '*.cpp')
REAL_HEADERS := $(shell cd ${SRC_DIR}; find include/ src/ -name '*.hpp' -o -name '*.tcc')
PIES := $(shell cd ${SRC_DIR}; find src/ -name '*.py')
@@ -283,9 +284,9 @@ endif
# This needs to edit CXX instead of CXXFLAGS in order to make
# the %.ii rule work.
ifeq (${ENABLE_CYGWIN_HACKS},yes)
-override CXX += -std=gnu++0x
+override CXX += -std=gnu++11
else
-override CXX += -std=c++0x
+override CXX += -std=c++11
endif
CXXFLAGS += -fstack-protector
@@ -333,9 +334,60 @@ include ${DEPENDS}
endif
thisdir := $(abspath .)
+
#$(foreach root,${PATTERN_ROOTS},$(info pre-root: ${root} := $(value ${root}))$(info ))
# can't do $(filter %.hpp yet)
-$(foreach root,${PATTERN_ROOTS},$(eval ${root} := $(sort $(patsubst ${thisdir}/%,%,$(abspath $(patsubst ${SRC_DIR}/%,%,$(wildcard $(value ${root})) $(filter conf-raw/%.h,$(value ${root}))))))))
+
+# Sanitize the dependencies.
+#
+# ${root} has a value like "mmo/version", and ${mmo/version} in turn has the
+# value of all of its dependencies (from the %.d files).
+#
+# This reassigns the *value of the value* of ${root} to be:
+# - sorted
+# - relative and simplified: it's stripped of any absolute path relative to
+# the current directory after being converted to an absolute path.
+# This also converts paths from being relative to the build directory to
+# being relative to the source directory, if they differ.
+# This simplifies any construct such as:
+# ../src/mmo/../strings/zstring.tcc
+# to:
+# src/strings/zstring.tcc
+# - only files which either exist (the purpose of the wildcard function),
+# are in the conf-raw directory (the first filter function), or
+# are listed in the GENERATED_FILES variable (the second filter function).
+# This means that if there are any build-time generated files added, this
+# needs to be modified to not filter them out.
+#
+# The end result for each root will look something like:
+# mmo/version := conf-raw/int-VENDOR_POINT.h conf-raw/int-VERSION_DEVEL.h [...]
+# src/strings/zstring.tcc src/wire/fwd.hpp
+
+# Firstly, make the paths relative and simplified.
+$(foreach root,${PATTERN_ROOTS},$(eval \
+ ${root} := $(sort $(patsubst ${thisdir}/%,%, \
+ $(abspath $(patsubst ${SRC_DIR}/%,%, $(value ${root}))) \
+ )) \
+))
+
+# Secondly, make sure that the files actually exist, or are files we expect to
+# generate ourselves. Sort the result for readability.
+# Note that we re-add and remove the ${SRC_DIR} prefix when first testing for
+# existence, as we need to test for existence relative to our build directory.
+# The second wildcard test doesn't add a ${SRC_DIR} prefix, but does strip it,
+# handling the case where the file is specified relative to the source
+# directory (mostly the case in test sources).
+$(foreach root,${PATTERN_ROOTS},$(eval \
+ ${root} := $(sort \
+ $(patsubst ${SRC_DIR}/%,%,$(wildcard $(addprefix ${SRC_DIR}/, \
+ $(value ${root}) \
+ ))) \
+ $(patsubst ${SRC_DIR}/%,%,$(wildcard ${SRC_DIR})) \
+ $(filter conf-raw/%.h,$(value ${root})) \
+ $(filter ${GENERATED_FILES},$(value ${root})) \
+ ) \
+))
+
# have to redo what we undid to get it as a variable
$(foreach root,${PATTERN_ROOTS},$(eval obj/${root}.ii obj/${root}.ll obj/${root}.bc obj/${root}.s obj/${root}.pdc.o obj/${root}.pic.o obj/${root}.d : $(value ${root})) )
#$(foreach root,${PATTERN_ROOTS},$(info post-root: ${root} := $(value ${root}))$(info ))
@@ -386,6 +438,7 @@ vpath include/%.hpp ${SRC_DIR}
vpath src/%.tcc ${SRC_DIR}
vpath tools/% ${SRC_DIR}
vpath src/%.py ${SRC_DIR}
+vpath src/%.in ${SRC_DIR}
.DELETE_ON_ERROR:
.DEFAULT_GOAL := all
@@ -437,6 +490,10 @@ obj/%.d: src/%.cpp | stamp/generated.stamp
${CXX} ${CPPFLAGS} -DGENERATING_DEPENDENCIES ${CXXFLAGS} -MG -MM \
-MT '$(patsubst obj/%.d,%,$@) := ' \
-MF $@ $<
+# -MG takes the include parameter as-is without prepending the path whenever
+# it's not found, and presumed to be a not-yet generated file.
+# #include statements for generated files should always be relative to the
+# source (or build) directory.
endif
# the above SRC_DIR replacement is not really safe, but it works okayish.
obj/%.ii: src/%.cpp
@@ -508,8 +565,8 @@ obj/gtest%.pdc.o: ${GTEST_DIR}/src/gtest%.cc
DTEST_OBJS := $(filter obj/debug-debug/%.pdc.o,${PDC_OBJECTS})
DTEST_STAMPS := $(patsubst bin/tests/%.elf,stamp/run-%.stamp,${DTEST_BINARIES})
-${DTEST_OBJS}: override CXXFLAGS += -g -O0 -gdwarf-3
-${DTEST_STAMPS}: override TESTER=${GDB} -return-child-result -nx -batch -ex 'python file_to_load = "$<"' -x ${SRC_DIR}/tools/debug-debug.gdb --args false
+${DTEST_OBJS}: override CXXFLAGS += -ggdb -O0
+${DTEST_STAMPS}: override TESTER=LD_LIBRARY_PATH="./lib" ${GDB} -return-child-result -nx -batch -ex 'python file_to_load = "$<"' -x ${SRC_DIR}/tools/debug-debug.gdb --args false
${DTEST_STAMPS}: tools/debug-debug.gdb
test: test-direct
@@ -539,7 +596,7 @@ test: test-rank-fwd
test-rank-fwd: ${CHECK_RANK_FWDS}
stamp/%.rank: src/%
$(MKDIR_FIRST)
- includes=$$(grep '#include.*".*/.*"' $< | sed 's/^[^"]*"//;s/"[^"]*$$//;s:/[^/]*$$::' | sort -u | fgrep -vx -e '..' -e 'conf-raw' -e '../conf'); \
+ includes=$$(grep '#include.*".*/.*"' $< | sed 's/^[^"]*"//;s/"[^"]*$$//;s:/[^/]*$$::' | sort -u | fgrep -vx -e '..' -e 'conf-raw' -e '../conf' -e 'src/conf'); \
for inc in $$includes; do if ! test -f ${<D}/fwd.hpp; then continue; fi; echo fgrep -q $${inc}/fwd.hpp ${<D}/fwd.hpp; fgrep -q $${inc}/fwd.hpp ${<D}/fwd.hpp || { echo ${<D}/fwd.hpp:''23: error: No $${inc}/fwd.hpp; exit 1; }; done
touch $@
@@ -682,21 +739,22 @@ conf-raw/bool-%.h: FORCE
conf-raw/str-%.h: FORCE
$(MKDIR_FIRST)
@echo '#define $* "$(value $*)"_s' | maybe-replace $@
-FORCE: ;
+
+FORCE:: ;
.PHONY: FORCE
-override CPPFLAGS += -I . -I ${SRC_DIR}/include
+override CPPFLAGS += -I. -I${SRC_DIR} -I${SRC_DIR}/include
# distribution tarballs
# this only works from within a git checkout
-dist/%/version.make:
+dist/%/version.mk:
$(MKDIR_FIRST)
- git --git-dir=${SRC_DIR}/.git show HEAD:version.make > $@
+ git --git-dir=${SRC_DIR}/.git show HEAD:version.mk > $@
sed 's/^VERSION_FULL := .*/#&\nVERSION_FULL := ${VERSION_FULL}/' -i $@
sed 's/^VERSION_HASH := .*/#&\nVERSION_HASH := ${VERSION_HASH}/' -i $@
-dist/%-src.tar: dist/%/version.make
+dist/%-src.tar: dist/%/version.mk
git --git-dir=${SRC_DIR}/.git archive --prefix=$*/ -o $@ HEAD
- ( mtime="$$(git --git-dir=${SRC_DIR}/.git log -n1 --pretty=%ci)" && cd dist && tar uf $*-src.tar --mtime="$${mtime}" --mode=664 --owner=root --group=root $*/version.make )
- rm dist/$*/version.make
+ ( mtime="$$(git --git-dir=${SRC_DIR}/.git log -n1 --pretty=%ci)" && cd dist && tar uf $*-src.tar --mtime="$${mtime}" --mode=664 --owner=root --group=root $*/version.mk )
+ rm dist/$*/version.mk
rmdir dist/$*/
dist/%-attoconf-only.tar:
$(MKDIR_FIRST)
diff --git a/README.md b/README.md
index 6ec6a58..8947def 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ The rest of this file contains information relevant to distributors and contribu
## 1. Distributors
### Important notes
-- Please read [version.make](version.make) for important version information.
+- Please read [version.mk](version.mk) for important version information.
- TMWA requires git to build by default. Use 'make dist' to get a tarball.
### Platform dependencies
diff --git a/configure b/configure
index aa1d0fd..468f029 100755
--- a/configure
+++ b/configure
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright 2013 Ben Longbons <b.r.longbons@gmail.com>
#
@@ -17,8 +17,6 @@
# You should have received a copy of the GNU General Public License
# along with attoconf. If not, see <http://www.gnu.org/licenses/>.
-from __future__ import print_function, division, absolute_import
-
import os
import sys
@@ -90,7 +88,7 @@ class Configuration(Cxx, Install, ConfigHash, Templates):
# 2) Modern distros ship gtest-1.13+. It requires C++14+, while
# TMWA is currently a C++0x codebase.
self.add_option('GTEST_DIR',
- init=os.path.join(os.getcwd(), 'deps/googletest/googletest'),
+ init=os.path.join(os.path.abspath(self.srcdir), 'deps/googletest/googletest'),
# http://code.google.com/p/googletest/wiki/FAQ#Why_is_it_not_recommended_to_install_a_pre-compiled_copy_of_Goog
type=filepath, check=lambda build, GTEST_DIR: None,
help='Location of Google Test sources, must contain src/gtest-all.cc (linking to a precompiled library is NOT supported)', hidden=False)
@@ -112,7 +110,9 @@ def main():
srcdir = os.path.dirname(sys.argv[0])
proj = Configuration(
srcdir=srcdir,
- template_files=['Makefile'],
+ # Note that src/conf/version.hpp is made later, by Makefile.
+ # See version.mk (included by Makefile).
+ template_files=['Makefile', 'src/conf/install.hpp'],
)
proj.set_package('tmwa', 'The Mana World (Athena server)');
proj.jiggle()
diff --git a/deps/attoconf b/deps/attoconf
-Subproject 7b939e7e4ce36e8b62b10025e567f871731cbf4
+Subproject 58e75e5f1271363a48c2a3417a2851d3b145b3f
diff --git a/generate.make b/generate.mk
index c32ca8d..c32ca8d 100644
--- a/generate.make
+++ b/generate.mk
diff --git a/src/char/char.cpp b/src/char/char.cpp
index 7ffdd0f..2194ef2 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -777,8 +777,8 @@ void create_online_files(void)
stamp_time(timetemp);
// write heading
FPRINTF(fp2, "<HTML>\n"_fmt);
- FPRINTF(fp2, " <META http-equiv=\"Refresh\" content=\"%d\">\n"_fmt, char_conf.online_refresh_html); // update on client explorer every x seconds
FPRINTF(fp2, " <HEAD>\n"_fmt);
+ FPRINTF(fp2, " <META http-equiv=\"refresh\" content=\"%d\">\n"_fmt, char_conf.online_refresh_html); // update on client explorer every x seconds
FPRINTF(fp2, " <TITLE>Online Players on %s</TITLE>\n"_fmt,
char_conf.server_name);
FPRINTF(fp2, " </HEAD>\n"_fmt);
diff --git a/src/conf/install.hpp b/src/conf/install.hpp.in
index 42fd125..e63164a 100644
--- a/src/conf/install.hpp
+++ b/src/conf/install.hpp.in
@@ -20,10 +20,9 @@
// just mention "fwd.hpp" to make formatter happy
-#include "conf-raw/str-PACKAGESYSCONFDIR.h"
-#include "conf-raw/str-PACKAGELOCALSTATEDIR.h"
-#include "conf-raw/str-PACKAGEDATADIR.h"
-
+#define PACKAGESYSCONFDIR "@SYSCONFDIR@/tmwa"_s
+#define PACKAGELOCALSTATEDIR "@LOCALSTATEDIR@/tmwa"_s
+#define PACKAGEDATADIR "@PACKAGEDATADIR@"_s
namespace tmwa
{
diff --git a/src/conf/version.hpp b/src/conf/version.hpp.in
index df8a8b6..126fae2 100644
--- a/src/conf/version.hpp
+++ b/src/conf/version.hpp.in
@@ -20,20 +20,19 @@
// just mention "fwd.hpp" to make formatter happy
-#include "conf-raw/str-VERSION_FULL.h"
-#include "conf-raw/str-VERSION_HASH.h"
+#define VERSION_FULL "@VERSION_FULL@"_s
+#define VERSION_HASH "@VERSION_HASH@"_s
-#include "conf-raw/int-VERSION_MAJOR.h"
-#include "conf-raw/int-VERSION_MINOR.h"
-#include "conf-raw/int-VERSION_PATCH.h"
-#include "conf-raw/int-VERSION_DEVEL.h"
+#define VERSION_MAJOR @PROJECT_VERSION_MAJOR@
+#define VERSION_MINOR @PROJECT_VERSION_MINOR@
+#define VERSION_PATCH @PROJECT_VERSION_PATCH@
+#define VERSION_DEVEL @PROJECT_VERSION_TWEAK@
-#include "conf-raw/str-VENDOR_NAME.h"
-#include "conf-raw/int-VENDOR_POINT.h"
-#include "conf-raw/str-VENDOR_SOURCE.h"
-
-#include "conf-raw/str-VERSION_STRING.h"
+#define VENDOR_NAME "@VENDOR_NAME@"_s
+#define VENDOR_POINT @VENDOR_POINT@
+#define VENDOR_SOURCE "@VENDOR_SOURCE@"_s
+#define VERSION_STRING "@VERSION_STRING@"_s
namespace tmwa
{
diff --git a/src/main-gdb-head.py b/src/main-gdb-head.py
index a465c97..09e22fe 100644
--- a/src/main-gdb-head.py
+++ b/src/main-gdb-head.py
@@ -5,7 +5,7 @@
# gdb sticks everything in one scope.
# This lets us enumerate what *we* added.
-initial_globals = {id(v):v for v in globals().values()}
+initial_globals = {id(v):v for v in list(globals().values())}
import re
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 4d36f17..1b77be6 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -4020,7 +4020,7 @@ RecvResult clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data>
dumb_ptr<mob_data> md = bl->is_mob();
nullpo_retr(rv, md);
- if (md->name != MobName() && md->name != get_mob_db(md->mob_class).name && md->name.size() >= 4)
+ if (md->name.size() >= 4)
fixed_95.char_name = stringish<CharName>(md->name);
else
fixed_95.char_name = stringish<CharName>(get_mob_db(md->mob_class).name);
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index 996e2bb..fc41d19 100644
--- a/src/map/mob.cpp
+++ b/src/map/mob.cpp
@@ -355,24 +355,25 @@ void mob_init(dumb_ptr<mob_data> md)
{
int i;
const Species mob_class = md->mob_class;
- const int mutations_nr = get_mob_db(mob_class).mutations_nr;
- const int mutation_power = get_mob_db(mob_class).mutation_power;
-
- md->stats[mob_stat::LV] = get_mob_db(mob_class).lv;
- md->stats[mob_stat::MAX_HP] = get_mob_db(mob_class).max_hp;
- md->stats[mob_stat::STR] = get_mob_db(mob_class).attrs[ATTR::STR];
- md->stats[mob_stat::AGI] = get_mob_db(mob_class).attrs[ATTR::AGI];
- md->stats[mob_stat::VIT] = get_mob_db(mob_class).attrs[ATTR::VIT];
- md->stats[mob_stat::INT] = get_mob_db(mob_class).attrs[ATTR::INT];
- md->stats[mob_stat::DEX] = get_mob_db(mob_class).attrs[ATTR::DEX];
- md->stats[mob_stat::LUK] = get_mob_db(mob_class).attrs[ATTR::LUK];
- md->stats[mob_stat::ATK1] = get_mob_db(mob_class).atk1;
- md->stats[mob_stat::ATK2] = get_mob_db(mob_class).atk2;
- md->stats[mob_stat::ADELAY] = get_mob_db(mob_class).adelay.count();
- md->stats[mob_stat::DEF] = get_mob_db(mob_class).def;
- md->stats[mob_stat::MDEF] = get_mob_db(mob_class).mdef;
- md->stats[mob_stat::CRITICAL_DEF] = get_mob_db(mob_class).critical_def;
- md->stats[mob_stat::SPEED] = get_mob_db(mob_class).speed.count();
+ const mob_db_& mob_info = get_mob_db(mob_class);
+ const int mutations_nr = mob_info.mutations_nr;
+ const int mutation_power = mob_info.mutation_power;
+
+ md->stats[mob_stat::LV] = mob_info.lv;
+ md->stats[mob_stat::MAX_HP] = mob_info.max_hp;
+ md->stats[mob_stat::STR] = mob_info.attrs[ATTR::STR];
+ md->stats[mob_stat::AGI] = mob_info.attrs[ATTR::AGI];
+ md->stats[mob_stat::VIT] = mob_info.attrs[ATTR::VIT];
+ md->stats[mob_stat::INT] = mob_info.attrs[ATTR::INT];
+ md->stats[mob_stat::DEX] = mob_info.attrs[ATTR::DEX];
+ md->stats[mob_stat::LUK] = mob_info.attrs[ATTR::LUK];
+ md->stats[mob_stat::ATK1] = mob_info.atk1;
+ md->stats[mob_stat::ATK2] = mob_info.atk2;
+ md->stats[mob_stat::ADELAY] = mob_info.adelay.count();
+ md->stats[mob_stat::DEF] = mob_info.def;
+ md->stats[mob_stat::MDEF] = mob_info.mdef;
+ md->stats[mob_stat::CRITICAL_DEF] = mob_info.critical_def;
+ md->stats[mob_stat::SPEED] = mob_info.speed.count();
md->stats[mob_stat::XP_BONUS] = MOB_XP_BONUS_BASE;
for (i = 0; i < mutations_nr; i++)
@@ -2596,6 +2597,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
);
{
+ const mob_db_& mob_info = get_mob_db(md->mob_class);
struct DmgLogParty
{
PartyPair p;
@@ -2660,23 +2662,23 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
per = 1;
base_exp =
- ((get_mob_db(md->mob_class).base_exp *
+ ((mob_info.base_exp *
md->stats[mob_stat::XP_BONUS]) >> MOB_XP_BONUS_SHIFT) * per / 256;
if (base_exp < 1)
base_exp = 1;
- if (sd && md && battle_config.pk_mode == 1
- && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20))
+ if (sd && battle_config.pk_mode == 1
+ && (mob_info.lv - sd->status.base_level >= 20))
{
base_exp *= 1.15; // pk_mode additional exp if monster >20 levels [Valaris]
}
if (md->state.special_mob_ai >= 1
&& battle_config.alchemist_summon_reward != 1)
base_exp = 0; // Added [Valaris]
- job_exp = get_mob_db(md->mob_class).job_exp * per / 256;
+ job_exp = mob_info.job_exp * per / 256;
if (job_exp < 1)
job_exp = 1;
- if (sd && md && battle_config.pk_mode == 1
- && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20))
+ if (sd && battle_config.pk_mode == 1
+ && (mob_info.lv - sd->status.base_level >= 20))
{
job_exp *= 1.15; // pk_mode additional exp if monster >20 levels [Valaris]
}
@@ -2730,13 +2732,14 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris]
break; // End
- if (!get_mob_db(md->mob_class).dropitem[i].nameid)
+ const auto& drop_info = mob_info.dropitem[i];
+ if (!drop_info.nameid)
continue;
- random_::Fixed<int, 10000> drop_rate = get_mob_db(md->mob_class).dropitem[i].p;
- if (battle_config.drops_by_luk > 0 && sd && md)
+ random_::Fixed<int, 10000> drop_rate = drop_info.p;
+ if (sd && battle_config.drops_by_luk > 0)
drop_rate.num += (sd->status.attrs[ATTR::LUK] * battle_config.drops_by_luk) / 100; // drops affected by luk [Valaris]
- if (sd && md && battle_config.pk_mode == 1
- && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20))
+ if (sd && battle_config.pk_mode == 1
+ && (mob_info.lv - sd->status.base_level >= 20))
drop_rate.num *= 1.25; // pk_mode increase drops if 20 level difference [Valaris]
// server-wide drop rate scaling
@@ -2745,7 +2748,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
continue;
struct delay_item_drop ditem {};
- ditem.nameid = get_mob_db(md->mob_class).dropitem[i].nameid;
+ ditem.nameid = drop_info.nameid;
ditem.amount = 1;
ditem.m = md->bl_m;
ditem.x = md->bl_x;
@@ -2796,9 +2799,11 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
npc_event(sd, md->npc_event, 0);
// TODO: in the future, OnPCKillEvent, OnMobKillEvent and OnPCDieEvent should be combined
- argrec_t arg[1] =
+ argrec_t arg[3] =
{
{"@mobID"_s, static_cast<int32_t>(unwrap<Species>(md->mob_class))},
+ {"@mobX"_s, static_cast<int32_t>(md->bl_x)},
+ {"@mobY"_s, static_cast<int32_t>(md->bl_y)},
};
npc_event_doall_l(stringish<ScriptLabel>("OnMobKillEvent"_s), sd->bl_id, arg);
}
@@ -3501,40 +3506,39 @@ int mobskill_event(dumb_ptr<mob_data> md, BF flag)
static
int mob_makedummymobdb(Species mob_class)
{
- int i;
-
- SNPRINTF(get_mob_db(mob_class).name, 24, "mob%d"_fmt, mob_class);
- SNPRINTF(get_mob_db(mob_class).jname, 24, "mob%d"_fmt, mob_class);
- get_mob_db(mob_class).lv = 1;
- get_mob_db(mob_class).max_hp = 1000;
- get_mob_db(mob_class).max_sp = 1;
- get_mob_db(mob_class).base_exp = 2;
- get_mob_db(mob_class).job_exp = 1;
- get_mob_db(mob_class).range = 1;
- get_mob_db(mob_class).atk1 = 7;
- get_mob_db(mob_class).atk2 = 10;
- get_mob_db(mob_class).def = 0;
- get_mob_db(mob_class).mdef = 0;
- get_mob_db(mob_class).attrs[ATTR::STR] = 1;
- get_mob_db(mob_class).attrs[ATTR::AGI] = 1;
- get_mob_db(mob_class).attrs[ATTR::VIT] = 1;
- get_mob_db(mob_class).attrs[ATTR::INT] = 1;
- get_mob_db(mob_class).attrs[ATTR::DEX] = 6;
- get_mob_db(mob_class).attrs[ATTR::LUK] = 2;
- get_mob_db(mob_class).range2 = 10;
- get_mob_db(mob_class).range3 = 10;
- get_mob_db(mob_class).size = 0; // 1
- get_mob_db(mob_class).race = Race::formless;
- get_mob_db(mob_class).element = LevelElement{0, Element::neutral};
- get_mob_db(mob_class).mode = MobMode::ZERO;
- get_mob_db(mob_class).speed = 300_ms;
- get_mob_db(mob_class).adelay = 1000_ms;
- get_mob_db(mob_class).amotion = 500_ms;
- get_mob_db(mob_class).dmotion = 500_ms;
- for (i = 0; i < MaxDrops; i++)
- {
- get_mob_db(mob_class).dropitem[i].nameid = ItemNameId();
- get_mob_db(mob_class).dropitem[i].p.num = 0;
+ mob_db_& mob_info = get_mob_db(mob_class);
+ SNPRINTF(mob_info.name, 24, "mob%d"_fmt, mob_class);
+ SNPRINTF(mob_info.jname, 24, "mob%d"_fmt, mob_class);
+ mob_info.lv = 1;
+ mob_info.max_hp = 1000;
+ mob_info.max_sp = 1;
+ mob_info.base_exp = 2;
+ mob_info.job_exp = 1;
+ mob_info.range = 1;
+ mob_info.atk1 = 7;
+ mob_info.atk2 = 10;
+ mob_info.def = 0;
+ mob_info.mdef = 0;
+ mob_info.attrs[ATTR::STR] = 1;
+ mob_info.attrs[ATTR::AGI] = 1;
+ mob_info.attrs[ATTR::VIT] = 1;
+ mob_info.attrs[ATTR::INT] = 1;
+ mob_info.attrs[ATTR::DEX] = 6;
+ mob_info.attrs[ATTR::LUK] = 2;
+ mob_info.range2 = 10;
+ mob_info.range3 = 10;
+ mob_info.size = 0; // 1
+ mob_info.race = Race::formless;
+ mob_info.element = LevelElement{0, Element::neutral};
+ mob_info.mode = MobMode::ZERO;
+ mob_info.speed = 300_ms;
+ mob_info.adelay = 1000_ms;
+ mob_info.amotion = 500_ms;
+ mob_info.dmotion = 500_ms;
+ for (int i = 0; i < MaxDrops; i++)
+ {
+ mob_info.dropitem[i].nameid = ItemNameId();
+ mob_info.dropitem[i].p.num = 0;
}
return 0;
}
@@ -3654,56 +3658,55 @@ bool mob_readdb(ZString filename)
continue;
}
- if (get_mob_db(mob_class).base_exp < 0)
+ if (mdbv.base_exp < 0)
{
PRINTF("bad mob line: Xp needs to be greater than 0. %s\n"_fmt, line);
rv = false;
continue;
}
- if (get_mob_db(mob_class).base_exp > 1000000000)
+ if (mdbv.base_exp > 1000000000)
{
PRINTF("bad mob line: Xp needs to be less than 1000000000. %s\n"_fmt, line);
rv = false;
continue;
}
- if (get_mob_db(mob_class).job_exp < 0)
+ if (mdbv.job_exp < 0)
{
PRINTF("bad mob line: Job Xp needs to be greater than 0. %s\n"_fmt, line);
rv = false;
continue;
}
- if (get_mob_db(mob_class).job_exp > 1000000000)
+ if (mdbv.job_exp > 1000000000)
{
PRINTF("bad mob line: Job Xp needs to be less than 1000000000. %s\n"_fmt, line);
rv = false;
continue;
}
- // TODO move this lower
- get_mob_db(mob_class) = std::move(mdbv);
-
for (int i = 0; i < MaxDrops; i++)
{
- int rate = get_mob_db(mob_class).dropitem[i].p.num;
+ int rate = mdbv.dropitem[i].p.num;
if (rate < 1) rate = 1;
if (rate > 10000) rate = 10000;
- get_mob_db(mob_class).dropitem[i].p.num = rate;
+ mdbv.dropitem[i].p.num = rate;
}
- get_mob_db(mob_class).skills.clear();
+ mdbv.skills.clear();
+
+ mdbv.hair = 0;
+ mdbv.hair_color = 0;
+ mdbv.weapon = 0;
+ mdbv.shield = ItemNameId();
+ mdbv.head_top = ItemNameId();
+ mdbv.head_mid = ItemNameId();
+ mdbv.head_buttom = ItemNameId();
+ mdbv.clothes_color = 0; //Add for player monster dye - Valaris
- get_mob_db(mob_class).hair = 0;
- get_mob_db(mob_class).hair_color = 0;
- get_mob_db(mob_class).weapon = 0;
- get_mob_db(mob_class).shield = ItemNameId();
- get_mob_db(mob_class).head_top = ItemNameId();
- get_mob_db(mob_class).head_mid = ItemNameId();
- get_mob_db(mob_class).head_buttom = ItemNameId();
- get_mob_db(mob_class).clothes_color = 0; //Add for player monster dye - Valaris
+ if (mdbv.base_exp == 0)
+ mdbv.base_exp = mob_gen_exp(&mdbv);
- if (get_mob_db(mob_class).base_exp == 0)
- get_mob_db(mob_class).base_exp = mob_gen_exp(&get_mob_db(mob_class));
+ get_mob_db(mob_class) = std::move(mdbv);
}
PRINTF("read %s done\n"_fmt, filename);
}
diff --git a/src/map/npc-parse.cpp b/src/map/npc-parse.cpp
index df1a09a..8865ea6 100644
--- a/src/map/npc-parse.cpp
+++ b/src/map/npc-parse.cpp
@@ -273,15 +273,16 @@ bool npc_load_monster(ast::npc::Monster& monster)
md->bl_m = m;
md->bl_x = x;
md->bl_y = y;
- MobName expected = get_mob_db(mob_class).jname;
+ const mob_db_& mob_info = get_mob_db(mob_class);
+ MobName expected = mob_info.jname;
if (monster.name.data != expected)
{
monster.name.span.warning(STRPRINTF("Visible label/jname should match: %s"_fmt, expected));
}
if (monster.name.data == ENGLISH_NAME)
- md->name = get_mob_db(mob_class).name;
+ md->name = mob_info.name;
else if (monster.name.data == JAPANESE_NAME)
- md->name = get_mob_db(mob_class).jname;
+ md->name = mob_info.jname;
else
md->name = monster.name.data;
diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp
index fee39d6..c471da1 100644
--- a/src/map/script-fun.cpp
+++ b/src/map/script-fun.cpp
@@ -2683,6 +2683,22 @@ void builtin_getexp(ScriptState *st)
*------------------------------------------
*/
static
+int get_mob_drop_nameid(Species mob_id, int index)
+{
+ return unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[index].nameid);
+}
+static
+int get_mob_drop_percent(Species mob_id, int index)
+{
+ return get_mob_db(mob_id).dropitem[index].p.num;
+}
+static
+AString get_mob_drop_name(Species mob_id, int index)
+{
+ Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[index].nameid));
+ return i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
+}
+static
void builtin_mobinfo(ScriptState *st)
{
Species mob_id = wrap<Species>(conv_num(st, &AARG(0)));
@@ -2697,6 +2713,19 @@ void builtin_mobinfo(ScriptState *st)
return;
}
+#define CASE_MobInfo_DROPID(index) \
+ MobInfo::DROPID##index: info = get_mob_drop_nameid(mob_id, index)
+
+#define CASE_MobInfo_DROPPERCENT(index) \
+ MobInfo::DROPPERCENT##index: info = get_mob_drop_percent(mob_id, index)
+
+#define CASE_MobInfo_DROPNAME(index) \
+ MobInfo::DROPNAME##index: \
+ { \
+ info_str = get_mob_drop_name(mob_id, index); \
+ mode = 1; \
+ }
+
switch (request)
{
case MobInfo::ID:
@@ -2800,142 +2829,57 @@ void builtin_mobinfo(ScriptState *st)
case MobInfo::MUTATION_POWER:
info = get_mob_db(mob_id).mutation_power;
break;
- case MobInfo::DROPID0:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[0].nameid);
- break;
- case MobInfo::DROPNAME0:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[0].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT0:
- info = get_mob_db(mob_id).dropitem[0].p.num;
- break;
- case MobInfo::DROPID1:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[0].nameid);
- break;
- case MobInfo::DROPNAME1:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[0].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT1:
- info = get_mob_db(mob_id).dropitem[0].p.num;
- break;
- case MobInfo::DROPID2:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[1].nameid);
- break;
- case MobInfo::DROPNAME2:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[1].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT2:
- info = get_mob_db(mob_id).dropitem[1].p.num;
- break;
- case MobInfo::DROPID3:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[2].nameid);
- break;
- case MobInfo::DROPNAME3:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[2].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT3:
- info = get_mob_db(mob_id).dropitem[2].p.num;
- break;
- case MobInfo::DROPID4:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[3].nameid);
- break;
- case MobInfo::DROPNAME4:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[3].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT4:
- info = get_mob_db(mob_id).dropitem[3].p.num;
- break;
- case MobInfo::DROPID5:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[4].nameid);
- break;
- case MobInfo::DROPNAME5:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[4].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT5:
- info = get_mob_db(mob_id).dropitem[4].p.num;
- break;
- case MobInfo::DROPID6:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[5].nameid);
- break;
- case MobInfo::DROPNAME6:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[5].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT6:
- info = get_mob_db(mob_id).dropitem[5].p.num;
- break;
- case MobInfo::DROPID7:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[6].nameid);
- break;
- case MobInfo::DROPNAME7:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[6].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT7:
- info = get_mob_db(mob_id).dropitem[6].p.num;
- break;
- case MobInfo::DROPID8:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[7].nameid);
- break;
- case MobInfo::DROPNAME8:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[7].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT8:
- info = get_mob_db(mob_id).dropitem[7].p.num;
- break;
- case MobInfo::DROPID9:
- info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[7].nameid);
- break;
- case MobInfo::DROPNAME9:
- {
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[7].nameid));
- info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
- mode = 1;
- }
- break;
- case MobInfo::DROPPERCENT9:
- info = get_mob_db(mob_id).dropitem[7].p.num;
- break;
+
+ case CASE_MobInfo_DROPID(0); break;
+ case CASE_MobInfo_DROPNAME(0); break;
+ case CASE_MobInfo_DROPPERCENT(0); break;
+
+ case CASE_MobInfo_DROPID(1); break;
+ case CASE_MobInfo_DROPNAME(1); break;
+ case CASE_MobInfo_DROPPERCENT(1); break;
+
+ case CASE_MobInfo_DROPID(2); break;
+ case CASE_MobInfo_DROPNAME(2); break;
+ case CASE_MobInfo_DROPPERCENT(2); break;
+
+ case CASE_MobInfo_DROPID(3); break;
+ case CASE_MobInfo_DROPNAME(3); break;
+ case CASE_MobInfo_DROPPERCENT(3); break;
+
+ case CASE_MobInfo_DROPID(4); break;
+ case CASE_MobInfo_DROPNAME(4); break;
+ case CASE_MobInfo_DROPPERCENT(4); break;
+
+ case CASE_MobInfo_DROPID(5); break;
+ case CASE_MobInfo_DROPNAME(5); break;
+ case CASE_MobInfo_DROPPERCENT(5); break;
+
+ case CASE_MobInfo_DROPID(6); break;
+ case CASE_MobInfo_DROPNAME(6); break;
+ case CASE_MobInfo_DROPPERCENT(6); break;
+
+ case CASE_MobInfo_DROPID(7); break;
+ case CASE_MobInfo_DROPNAME(7); break;
+ case CASE_MobInfo_DROPPERCENT(7); break;
+
+ case CASE_MobInfo_DROPID(8); break;
+ case CASE_MobInfo_DROPNAME(8); break;
+ case CASE_MobInfo_DROPPERCENT(8); break;
+
+ case CASE_MobInfo_DROPID(9); break;
+ case CASE_MobInfo_DROPNAME(9); break;
+ case CASE_MobInfo_DROPPERCENT(9); break;
+
default:
PRINTF("builtin_mobinfo: unknown request\n"_fmt);
push_int<ScriptDataInt>(st->stack, -1);
return;
break;
}
+#undef CASE_MobInfo_DROPID
+#undef CASE_MobInfo_DROPPERCENT
+#undef CASE_MobInfo_DROPNAME
+
if (!mode)
push_int<ScriptDataInt>(st->stack, info);
else
@@ -3022,7 +2966,9 @@ void builtin_mobinfo_droparrays(ScriptState *st)
}
for (int i = 0; i < MaxDrops; ++i)
- if (get_mob_db(mob_id).dropitem[i].nameid)
+ {
+ auto& dropitem = get_mob_db(mob_id).dropitem[i];
+ if (dropitem.nameid)
{
status = 1;
switch (request)
@@ -3030,15 +2976,15 @@ void builtin_mobinfo_droparrays(ScriptState *st)
case MobInfo_DropArrays::IDS:
if (name.startswith(".@"_s))
{
- struct script_data vd = script_data(ScriptDataInt{unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[i].nameid)});
+ struct script_data vd = script_data(ScriptDataInt{unwrap<ItemNameId>(dropitem.nameid)});
set_scope_reg(st, reg.iplus(i), &vd);
}
else
- set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[i].nameid));
+ set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), unwrap<ItemNameId>(dropitem.nameid));
break;
case MobInfo_DropArrays::NAMES:
{
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[i].nameid));
+ Option<P<struct item_data>> i_data = Some(itemdb_search(dropitem.nameid));
RString item_name = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
if (name.startswith(".@"_s))
@@ -3053,11 +2999,11 @@ void builtin_mobinfo_droparrays(ScriptState *st)
case MobInfo_DropArrays::PERCENTS:
if (name.startswith(".@"_s))
{
- struct script_data vd = script_data(ScriptDataInt{get_mob_db(mob_id).dropitem[i].p.num});
+ struct script_data vd = script_data(ScriptDataInt{dropitem.p.num});
set_scope_reg(st, reg.iplus(i), &vd);
}
else
- set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), get_mob_db(mob_id).dropitem[i].p.num);
+ set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), dropitem.p.num);
break;
}
}
@@ -3067,7 +3013,7 @@ void builtin_mobinfo_droparrays(ScriptState *st)
status = 2;
break;
}
-
+ }
push_int<ScriptDataInt>(st->stack, status);
}
@@ -3097,16 +3043,19 @@ void builtin_getmobdrops(ScriptState *st)
status = 1;
+ const mob_db_& mob_info = get_mob_db(mob_id);
for (; i < MaxDrops; ++i)
- if (get_mob_db(mob_id).dropitem[i].nameid)
+ {
+ auto& dropitem = mob_info.dropitem[i];
+ if (dropitem.nameid)
{
- set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_item"_s), i), get_mob_db(mob_id).dropitem[i].p.num);
+ set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_item"_s), i), dropitem.p.num);
- Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[i].nameid));
+ Option<P<struct item_data>> i_data = Some(itemdb_search(dropitem.nameid));
RString item_name = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_name$"_s), i), item_name);
- set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_rate"_s), i), get_mob_db(mob_id).dropitem[i].p.num);
+ set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_rate"_s), i), dropitem.p.num);
}
else
{
@@ -3114,6 +3063,7 @@ void builtin_getmobdrops(ScriptState *st)
status = 2;
break;
}
+ }
if (status == 1)
set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_count"_s), 0), i);
@@ -4366,9 +4316,14 @@ void builtin_getitemlink(ScriptState *st)
struct script_data *data;
AString buf;
data = &AARG(0);
- ZString name = conv_str(st, data);
+ Option<P<struct item_data>> item_data_ = None;
+
+ get_val(st, data);
+ if (data->is<ScriptDataStr>())
+ item_data_ = itemdb_searchname(conv_str(st, data));
+ else
+ item_data_ = itemdb_exists(wrap<ItemNameId>(conv_num(st, data)));
- Option<P<struct item_data>> item_data_ = itemdb_searchname(name);
OMATCH_BEGIN (item_data_)
{
OMATCH_CASE_SOME (item_data)
diff --git a/src/map/script-parse.py b/src/map/script-parse.py
index 199e348..3346b92 100644
--- a/src/map/script-parse.py
+++ b/src/map/script-parse.py
@@ -106,7 +106,7 @@ class ScriptBuffer(object):
code_begin = code['_M_impl']['_M_start']
code_end = code['_M_impl']['_M_finish']
code_size = int(code_end - code_begin)
- r = iter(range(code_size))
+ r = iter(list(range(code_size)))
for i in r:
buf = []
for label in labels_dict.get(i, []):
diff --git a/src/mmo/version.cpp b/src/mmo/version.cpp
index f91b748..c75c25c 100644
--- a/src/mmo/version.cpp
+++ b/src/mmo/version.cpp
@@ -20,7 +20,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-#include "../conf/version.hpp"
+#include "src/conf/version.hpp"
#include "../strings/xstring.hpp"
diff --git a/src/shared/lib.cpp b/src/shared/lib.cpp
index c0a4371..37b2e93 100644
--- a/src/shared/lib.cpp
+++ b/src/shared/lib.cpp
@@ -18,7 +18,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-#include "../conf/install.hpp"
+#include "src/conf/install.hpp"
#include "../strings/literal.hpp"
#include "../strings/astring.hpp"
diff --git a/tools/bs-align b/tools/bs-align
index 6582298..0caf649 100755
--- a/tools/bs-align
+++ b/tools/bs-align
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# -*- encoding: utf-8
## bs-align.py - Filter to align trailing line continuations
##
diff --git a/tools/colorize b/tools/colorize
index ce6f410..205a1bc 100755
--- a/tools/colorize
+++ b/tools/colorize
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
+#!/usr/bin/env python3
import os
import sys
diff --git a/tools/config.py b/tools/config.py
index f87fe77..22ece0b 100755
--- a/tools/config.py
+++ b/tools/config.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# coding: utf-8
# config.py - generator for config file parsers
@@ -20,8 +20,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from __future__ import print_function
-
import glob
import os
@@ -259,7 +257,7 @@ class Group(object):
short_cpp_name = '%s.cpp' % var_name
cpp_name = os.path.join(path, short_cpp_name)
- values = sorted(self.options.values(), key=lambda o: o.name)
+ values = sorted(list(self.options.values()), key=lambda o: o.name)
desc = 'Config for %s::%s' % (namespace_name, self.name)
with OpenWrite(hpp_name) as hpp, \
@@ -384,7 +382,7 @@ class Realm(object):
return rv
def dump(self):
- for g in self.groups.values():
+ for g in list(self.groups.values()):
g.dump_in(self.path, self.path.split('/')[-1])
class Everything(object):
@@ -401,7 +399,7 @@ class Everything(object):
def dump(self):
for g in glob.glob('src/*/*_conf.[ch]pp'):
os.rename(g, g + '.old')
- for v in self.realms.values():
+ for v in list(self.realms.values()):
v.dump()
for g in glob.glob('src/*/*_conf.[ch]pp.old'):
print('Obsolete: %s' % g)
diff --git a/tools/debug-debug-scripts b/tools/debug-debug-scripts
index 2112a6e..5ba7ecb 100755
--- a/tools/debug-debug-scripts
+++ b/tools/debug-debug-scripts
@@ -1,6 +1,5 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# encoding: utf-8
-from __future__ import print_function
copyright = '''
// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com>
@@ -35,6 +34,12 @@ error = False
def eprint(s):
print('Error:', s, file=sys.stderr)
+# Implement an equivalent to Python 2's execfile for Python 3
+def execfile(filename, globals=None, locals=None):
+ with open(filename, 'r') as f:
+ code = compile(f.read(), filename, 'exec')
+ exec(code, globals, locals)
+
def get_classes_from_file(a):
global error
d = {}
diff --git a/tools/debug-debug.gdb b/tools/debug-debug.gdb
index b50a49b..5bf3a57 100644
--- a/tools/debug-debug.gdb
+++ b/tools/debug-debug.gdb
@@ -9,7 +9,7 @@ gdb.execute('file %s' % file_to_load)
end
set logging file /dev/null
set logging redirect on
-set logging off
+set logging enabled off
python
import re
@@ -41,7 +41,7 @@ set print elements 9999
set print frame-arguments none
set python print-stack full
-set logging on
+set logging enabled on
# Workaround "Function... not defined in.." (breakpoints not found) (GDB bug)
# https://sourceware.org/bugzilla/show_bug.cgi?id=15962
# In some gdb versions rbreak works, in some break does.
@@ -55,7 +55,7 @@ if bpoint.pending:
gdb.execute("rbreak do_breakpoint")
end
-set logging off
+set logging enabled off
commands
silent
diff --git a/tools/indenter b/tools/indenter
index 0d93543..ee000da 100755
--- a/tools/indenter
+++ b/tools/indenter
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# -*- encoding: utf-8
## indenter.py - Top-level indenter for all files
##
@@ -20,10 +20,9 @@
## along with this program. If not, see <http://www.gnu.org/licenses/>.
-from __future__ import print_function
from collections import namedtuple
-import cStringIO
+import io
import string
import subprocess
import sys
@@ -114,7 +113,7 @@ class Reader(object):
self._column += 1
def string_reader(s, name='<string>', line=1, column=1):
- return Reader(name, cStringIO.StringIO(s), line, column)
+ return Reader(name, io.StringIO(s), line, column)
def take_while(b, r, s):
assert isinstance(b, bytearray)
diff --git a/tools/pp-indent b/tools/pp-indent
index 9be9a03..622614a 100755
--- a/tools/pp-indent
+++ b/tools/pp-indent
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# -*- encoding: utf-8
## pp-indent - Filter to apply indentation to preprocessor statements
##
diff --git a/tools/protocol.py b/tools/protocol.py
index cf89a16..d278884 100755
--- a/tools/protocol.py
+++ b/tools/protocol.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# coding: utf-8
# protocol.py - generator for entire TMWA network protocol
@@ -20,20 +20,12 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from __future__ import print_function
-
import glob
-import itertools
import os
-from pipes import quote
+from shlex import quote
from posixpath import relpath
from weakref import ref as wr
-try:
- unicode
-except NameError:
- unicode = str
-
## For various reasons this is all one file, so let's navigate with a
##
## Table of Contents
@@ -91,7 +83,7 @@ class OpenWrite(object):
self.filename = filename
def __enter__(self):
- self.handle = open(self.filename + '.tmp', 'w')
+ self.handle = open(self.filename + '.tmp', 'w', encoding='utf-8')
return self.handle
def __exit__(self, ty, v, tb):
@@ -116,30 +108,30 @@ class OpenWrite(object):
# TOC_
def gvq(s):
- return u'"%s"' % s.replace(u'"', u'\\"')
+ return '"%s"' % s.replace('"', '\\"')
def gva(d):
if d:
- return u' [%s]' % u', '.join(u'%s=%s' % (ak, gvq(av)) for (ak, av) in sorted(d.items()))
- return u''
+ return ' [%s]' % ', '.join('%s=%s' % (ak, gvq(av)) for (ak, av) in sorted(d.items()))
+ return ''
class Attributes(object):
- __slots__ = (u'_attributes')
+ __slots__ = ('_attributes')
def __init__(self):
self._attributes = {}
def __getitem__(self, k):
- assert isinstance(k, unicode)
+ assert isinstance(k, str)
return self._attributes[k]
def __setitem__(self, k, v):
- assert isinstance(k, unicode)
- assert isinstance(v, unicode)
+ assert isinstance(k, str)
+ assert isinstance(v, str)
self._attributes[k] = v
def __delitem__(self, k):
- assert isinstance(k, unicode)
+ assert isinstance(k, str)
del self._attributes[k]
def merge(self, *others):
@@ -150,7 +142,7 @@ class Attributes(object):
self._attributes.update(other._attributes)
class Graph(Attributes):
- __slots__ = (u'default_vertex', u'default_edge', u'_vertices', u'_edges', u'_vertex_lookup')
+ __slots__ = ('default_vertex', 'default_edge', '_vertices', '_edges', '_vertex_lookup')
def __init__(self):
Attributes.__init__(self)
@@ -161,7 +153,7 @@ class Graph(Attributes):
self._vertex_lookup = {}
def vertex(self, name, insert=True):
- assert isinstance(name, unicode)
+ assert isinstance(name, str)
vert = self._vertex_lookup.get(name)
if insert and vert is None:
vert = Vertex(name)
@@ -238,21 +230,21 @@ class Graph(Attributes):
def p(*args):
for x in args:
- out.write(unicode(x))
- out.write(u'\n')
- p(u'digraph')
- p(u'{')
+ out.write(str(x))
+ out.write('\n')
+ p('digraph')
+ p('{')
for ak, av in sorted(self._attributes.items()):
- p(u' ', ak, u'=', gvq(av), u';')
+ p(' ', ak, '=', gvq(av), ';')
for ak, av in sorted(self.default_vertex._attributes.items()):
- p(u' node [', ak, u'=', gvq(av), u'];')
+ p(' node [', ak, '=', gvq(av), '];')
for ak, av in sorted(self.default_edge._attributes.items()):
- p(u' edge [', ak, u'=', gvq(av), u'];')
+ p(' edge [', ak, '=', gvq(av), '];')
for n in sorted(self._vertices):
- p(u' ', n)
+ p(' ', n)
for _, e in sorted(self._edges.items()):
- p(u' ', e)
- p(u'}')
+ p(' ', e)
+ p('}')
def dot_str(self):
from io import StringIO
@@ -261,18 +253,18 @@ class Graph(Attributes):
return out.getvalue()
def dot_file(self, name):
- with open(name, u'w') as f:
+ with open(name, 'w') as f:
self.dot(f, False)
def preview(self, block):
from subprocess import Popen, PIPE
- proc = Popen([u'dot', u'-Txlib', u'/dev/stdin'], stdin=PIPE, universal_newlines=True)
+ proc = Popen(['dot', '-Txlib', '/dev/stdin'], stdin=PIPE, universal_newlines=True)
self.dot(proc.stdin, True)
if block:
proc.wait()
class Vertex(Attributes):
- __slots__ = (u'_key', u'_post', u'_pre', u'__weakref__')
+ __slots__ = ('_key', '_post', '_pre', '__weakref__')
def __init__(self, key):
Attributes.__init__(self)
@@ -281,13 +273,13 @@ class Vertex(Attributes):
self._pre = set()
def __str__(self):
- return u'%s%s;' % (gvq(self._key), gva(self._attributes))
+ return '%s%s;' % (gvq(self._key), gva(self._attributes))
def __lt__(self, other):
return self._key < other._key
class Edge(Attributes):
- __slots__ = (u'_from', u'_to')
+ __slots__ = ('_from', '_to')
def __init__(self, f, t):
Attributes.__init__(self)
@@ -295,7 +287,7 @@ class Edge(Attributes):
self._to = t
def __str__(self):
- return u'%s -> %s%s;' % (gvq(self._from._key), gvq(self._to._key), gva(self._attributes))
+ return '%s -> %s%s;' % (gvq(self._from._key), gvq(self._to._key), gva(self._attributes))
# TOC_TYPES
@@ -7091,7 +7083,7 @@ def partition(d):
changed = True
while changed:
changed = False
- for k, vlist in d.items():
+ for k, vlist in list(d.items()):
if vlist:
m = min(leaders[v] for v in vlist)
if m < leaders[k]:
@@ -7107,9 +7099,9 @@ def partition(d):
leaders[v] = m
followers = {}
- for k, v in leaders.items():
+ for k, v in list(leaders.items()):
followers.setdefault(v, []).append(k)
- return [set(v) for v in followers.values()]
+ return [set(v) for v in list(followers.values())]
def ids_only(vpost):
rv = [e for e in vpost if not isinstance(e, SpecialEventOrigin)]
@@ -7124,7 +7116,7 @@ def make_dots(ctx):
#p = partition({k: ids_only(v.post) for (k, v) in d.items()})
if not os.path.exists('doc-gen'):
- # generate.make will succeed if missing the wiki repo
+ # generate.mk will succeed if missing the wiki repo
# but 'make doc' will fail
return
for g in glob.glob('doc-gen/*.gv'):
@@ -7132,7 +7124,7 @@ def make_dots(ctx):
for g in glob.glob('doc-gen/Packet-*.md'):
os.rename(g, g + '.old')
- for (id, p) in d.items():
+ for (id, p) in list(d.items()):
md = 'doc-gen/Packet-0x%04x.md' % id
dot = 'doc-gen/packets-around-0x%04x.gv' % id
with OpenWrite(md) as f:
@@ -7179,16 +7171,16 @@ def make_dots(ctx):
covered_nodes = sorted(p.pre_set(d, 2) | p.post_set(d, 2))
covered_edges = [(a, b) for a in covered_nodes for b in covered_nodes if b in d[a].post]
g = Graph()
- g.default_vertex[u'shape'] = u'box'
- # g[u'layout'] = u'twopi'
- # g[u'root'] = u'0x%04x' % id
+ g.default_vertex['shape'] = 'box'
+ # g['layout'] = 'twopi'
+ # g['root'] = '0x%04x' % id
for n in covered_nodes:
- v = g.vertex(u'0x%04x' % n)
- v[u'label'] = u'Packet \\N: %s' % d[n].name
+ v = g.vertex('0x%04x' % n)
+ v['label'] = 'Packet \\N: %s' % d[n].name
if n == id:
- v[u'style'] = u'filled'
+ v['style'] = 'filled'
for (a, b) in covered_edges:
- g.edge(u'0x%04x' % a, u'0x%04x' % b)
+ g.edge('0x%04x' % a, '0x%04x' % b)
for n in covered_nodes:
# the center node will be covered specially below
if n == id:
@@ -7206,10 +7198,10 @@ def make_dots(ctx):
# don't show mere siblings unless also ancestor/descendent
count += 1
if count:
- v = g.vertex(u'0x%04x...pre' % n)
- v[u'label'] = u'%d more' % count
- v[u'style'] = u'dashed'
- g.edge(v, u'0x%04x' % n)
+ v = g.vertex('0x%04x...pre' % n)
+ v['label'] = '%d more' % count
+ v['style'] = 'dashed'
+ g.edge(v, '0x%04x' % n)
# strong forward links
count = 0
for p in d[n].post:
@@ -7218,36 +7210,36 @@ def make_dots(ctx):
elif p not in covered_nodes:
count += 1
if count:
- v = g.vertex(u'0x%04x...post' % n)
- v[u'label'] = u'%d more' % count
- v[u'style'] = u'dashed'
- g.edge(u'0x%04x' % n, v)
+ v = g.vertex('0x%04x...post' % n)
+ v['label'] = '%d more' % count
+ v['style'] = 'dashed'
+ g.edge('0x%04x' % n, v)
# for the immediate node, also cover specials and weaks
for p in d[id].pre:
# (there are no weak backward specials)
# strong backward specials
if isinstance(p, SpecialEventOrigin):
- g.edge(unicode(p.name), u'0x%04x' % id)
+ g.edge(str(p.name), '0x%04x' % id)
# weak backward nodes
elif id in d[p].xpost:
- e = g.edge(u'0x%04x' % p, u'0x%04x' % id)
- e[u'style']=u'dashed'
- e[u'weight'] = u'0'
+ e = g.edge('0x%04x' % p, '0x%04x' % id)
+ e['style']='dashed'
+ e['weight'] = '0'
for p in d[id].post:
# strong forward specials
if isinstance(p, SpecialEventOrigin):
- g.edge(u'0x%04x' % id, unicode(p.name))
+ g.edge('0x%04x' % id, str(p.name))
for p in d[id].xpost:
# weak forward specials
if isinstance(p, SpecialEventOrigin):
- e = g.edge(u'0x%04x' % id, unicode(p.name))
- e[u'style'] = u'dashed'
- e[u'weight'] = u'0'
+ e = g.edge('0x%04x' % id, str(p.name))
+ e['style'] = 'dashed'
+ e['weight'] = '0'
# weak forward nodes
elif p not in covered_nodes:
- e = g.edge(u'0x%04x' % id, u'0x%04x' % p)
- e[u'style'] = u'dashed'
- e[u'weight'] = u'0'
+ e = g.edge('0x%04x' % id, '0x%04x' % p)
+ e['style'] = 'dashed'
+ e['weight'] = '0'
g.dot(f, False)
diff --git a/version.make b/version.mk
index 73ecc83..23bd071 100644
--- a/version.make
+++ b/version.mk
@@ -39,7 +39,7 @@ VENDOR_NAME := Vanilla
VENDOR_POINT := 0
# URL where the source may be found (after searching for version number).
# See AGPLv3 section 13
-VENDOR_SOURCE := https://github.com/themanaworld/tmwa
+VENDOR_SOURCE := https://git.themanaworld.org/legacy/tmwa
# Convenience
VERSION_STRING := TMWA ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} dev${VERSION_DEVEL} +${VENDOR_POINT} (${VENDOR_NAME})
@@ -50,9 +50,38 @@ SO_SHORT := so.${ABI_VERSION}
SO_LONG := ${SO_SHORT}.${VERSION_DOTS}
# and thanks for all the fish
+# This is a phony target, so that it always runs.
+# Targets which depend on this will always have their recipes run.
+FORCE:: ;
+.PHONY: FORCE
+
+# Fully generate version.hpp here, where we have all the relevant information.
+# version.mk is included by the top level Makefile, so simply explaning how to
+# make it here will let it be built later, when needed.
+# Note that some variable substitutions are slightly different here to use the
+# name used by standard CMake macros, such as PROJECT_VERSION_TWEAK instead of
+# VERSION_DEVEL.
+src/conf/version.hpp: src/conf/version.hpp.in FORCE
+ sed -e 's/@VERSION_FULL@/${VERSION_FULL}/g' \
+ -e 's/@VERSION_HASH@/${VERSION_HASH}/g' \
+ -e 's/@VERSION_STRING@/${VERSION_STRING}/g' \
+ -e 's/@PROJECT_VERSION_MAJOR@/${VERSION_MAJOR}/g' \
+ -e 's/@PROJECT_VERSION_MINOR@/${VERSION_MINOR}/g' \
+ -e 's/@PROJECT_VERSION_PATCH@/${VERSION_PATCH}/g' \
+ -e 's/@PROJECT_VERSION_TWEAK@/${VERSION_DEVEL}/g' \
+ -e 's/@VENDOR_NAME@/${VENDOR_NAME}/g' \
+ -e 's/@VENDOR_POINT@/${VENDOR_POINT}/g' \
+ -e 's|@VENDOR_SOURCE@|${VENDOR_SOURCE}|g' \
+ -e 's/@ABI_VERSION@/${ABI_VERSION}/g' \
+ -e 's/@SO_SHORT@/${SO_SHORT}/g' \
+ -e 's/@SO_LONG@/${SO_LONG}/g' \
+ $< > $@
+
+
version:
@echo version '${VERSION_STRING}'
@echo based on commit ${VERSION_FULL} aka ${VERSION_HASH}
@echo source ${VENDOR_SOURCE}
@echo abi version ${ABI_VERSION}
@echo 'lib so -> ${SO_SHORT} -> ${SO_LONG}'
+.PHONY: version