A node.js based server emulator replacing official server for the Hitman 2016 series:
- Hitman (2016)
- Hitman Sniper Assassin
- Hitman 2
- Hitman 3 / World of Assassination
Download latest release (regular has Windows Node.js binaries bundled in, -linux
doesn't).
Copy PeacockPatcher.exe
into game directory (not strictly necessary, as it will patch a running process, not the executable next to it, but it's most convenient to call it from there in scripts)
To launch patcher together with the game, some adjustments are necessary.
First, copying patcher into game's dir is now mandatory for this method to work.
Also create the following Batch script WineLaunch.bat
in the game's dir:
@echo off
start Launcher.exe %*
start PeacockPatcher.exe
This will make Proton launch both the game and the patcher at the same time
[!info] This will have patcher be launched interactively, and hang around after the game exists, keeping the "game" process alive in the Steam's eyes. [[#Non-interactive patcher|See alternative below]]
Change Steam's launch option to
bash -c 'exec "${@/Launcher.exe/WineLaunch.bat}"' -- %command%
This will substitute Launcher.exe
with the script above in the chain of commands Steam normally executes to start the game through the Proton
If something else needs to be done before/after starting the game (such as starting/stopping the Peacock server), an alternative wrapper script could be used.
Change Steam's launch option to
bash -c './wrapper.sh %command%'
Create the executable wrapper.sh
in the game's directory:
#! /bin/bash
# comamnds before game starts, for example:
systemctl --user start peacock.service
# DO NOTE that any commands used here must either exit, or be forked, for script to actually reach the line below and start the game
$("${@/Launcher.exe/WineLaunch.bat}")
# commands after game (and patcher, if run interactively) exits, for example:
systemctl --user stop peacock.service
Start server (without specifying, it tries to run on port 80)
PORT=3000 node chunk0.js
When launching server for the first time, one should ideally download all assets from official servers (see [[#Tools]])
Start patcher. Enter the server address (default is localhost
, on port 80 =_="). Patcher will save the last address used, but only the last one used. If you switch to IOI servers - address will need to be re-entered.
Start game.
Patcher should log that it has replaced server with specified.
Patcher can also be started in one-off headless mode from command line as
PeacockPatcher.exe --headless --domain "ip:port"
This will cause patcher to use the server provided to patch currently running Hitman process once, and exit, instead of hanging around (this option also doesn't allow re-patching for official servers!).
[!warning] Potential issues This will only patch the game once and exit. If no game process is available when patcher starts - it will just exit after doing nothing. Game should be launched with
-skip_launcher
option to avoid that happening
When game has changes to owned content (such as when just purchased or when a DLC is added) - the actual installed game will know nothing about it (great job, IOI, fucking up a basic Steam feature) and game must be launched with stock IOI server once, fully logged in (for owned content proof to be saved locally), and then quit. After that it can be restarted and used with Peacock normally
There are two "tools": CLI and WebUI
CLI tool is for getting debug info, downloading official contracts, and pre-caching assets:
node chunk0.js tools
WebUI is available on the same port server is running on, without authentication. It allows starting escalation from specific level, creating loadouts, and importing official progress (but it seems to be broken right now)
FROM node:18.18.2-alpine
ARG VERSION
ARG PORT=3000
WORKDIR /app
RUN mkdir userdata
RUN mkdir contractSessions
RUN mkdir contracts
RUN mkdir plugins
RUN mkdir images
RUN wget -q -O server.zip https://github.com/thepeacockproject/Peacock/releases/download/v${VERSION}/Peacock-v${VERSION}-linux.zip
RUN unzip -qd server server.zip \
&& mv server/Peacock-*/* ./ \
&& rm -rf server.zip server
RUN echo "#! /bin/sh" >> run.sh \
&& echo "export PORT=${PORT}" >> run.sh \
&& echo "node chunk0.js" >> run.sh \
&& chmod a+x run.sh
VOLUME /app/userdata
VOLUME /app/contractSessions
VOLUME /app/contracts
VOLUME /app/plugins
VOLUME /app/images
EXPOSE ${PORT}/tcp
EXPOSE ${PORT}/udp
CMD ["./run.sh"]
This will download a selected version from Github releases (alternatively, replace downloading with COPY
as the same server.zip
file from local storage), extracts it, and sets up a launcher fir the image.
Uses build args:
PORT
- which port it will run onVERSION
- which version will be downloaded
userdata
andcontractSessions
contain important user data and must always be persisted.contracts
contains automatically and manually downloaded contracts, andplugins
- Peacock plugins to be added by the user. They are less important, but should probably still persisted.images
contains cached images for the various game menus. They are not necessary to persist, but would be nice to keep to increase autonomyoptions.ini
file must be placed in the working dir of the server, so it can't be made into a volume like the rest of the data.
After the container is initially started, it must be copied out of the container withdocker cp peacock-server:/app/options.ini ./
. After that it must be mounted into a container from now on.
The patcher can later be obtained from the running container with docker cp peacock-server:/app/PeacockPatcher.exe ./
And tools accessed with docker exec -it peacock-server node chuck0.js tools
name: "peacock"
services:
server:
image: peacock:7.3.1
restart: unless-stopped
ports:
- 8450:3000
volumes:
- ./data/options.ini:/app/options.ini
- ./data/userdata:/app/userdata
- ./data/contracts:/app/contracts
- ./data/plugins:/app/plugins
- ./data/contractSessions:/app/contractSessions
- ./data/images:/app/images
The last volume may be omitted, to cache into an automatically created volume.
server:
image: peacock:7.3.1
pull_policy: never
build:
context: .
dockerfile: Dockerfile
args:
VERSION: "7.3.1"
PORT: 3000
Before docker compose up
one should also do docker compose build
, just in case. pull_policy: never
is there to prevent docker from trying to download this image from the dockerhub (which will either not exist, or be a completely wrong image) first, and only then attempt to build it