Skip to content

Commit

Permalink
Merge branch 'dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
WeirdYunus authored Nov 30, 2024
2 parents 07c3765 + e7f91cc commit a03bf37
Show file tree
Hide file tree
Showing 531 changed files with 4,741 additions and 25,733 deletions.
23 changes: 9 additions & 14 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
if: "!contains(github.event.head_commit.message, 'ci skip')"

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Checkout submodules
run: |
Expand All @@ -28,32 +28,27 @@ jobs:
# Install dependencies
- name: Update apt repositories
run: sudo apt-get update

- name: Install GCC12
shell: bash
run: |
sudo apt update
sudo apt install gcc-12 g++-12
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 110 --slave /usr/bin/g++ g++ /usr/bin/g++-12 --slave /usr/bin/gcov gcov /usr/bin/gcov-12

# Install xmake
- name: Setup xmake
uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: '2.9.3'
xmake-version: '2.9.5'

# Update xmake repository (in order to have the file that will be cached)
- name: Update xmake repository
run: xmake repo --update

# Setup compilation mode and install project dependencies
# (continue-on-error + timeout is a temporary solution until sentry-native is fixed; shouldn't affect the building step)
- name: Configure xmake and install dependencies
run: xmake config --arch=${{ matrix.arch }} --mode=${{ matrix.mode }} --yes
continue-on-error: true
run: timeout 15m xmake config --arch=${{ matrix.arch }} --mode=${{ matrix.mode }} --yes

# Build the game
# Build the server
- name: Build
run: xmake
run: xmake -y

# Create install
#- name: Install
# run: xmake install -o packaged
Expand Down
100 changes: 100 additions & 0 deletions .github/workflows/windows-playable-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: Playable Skyrim Together Build

on:
workflow_dispatch:
schedule:
# Every Friday at 1:00 p.m. UTC
- cron: '0 13 * * 5'
push:
branches:
- master
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'

jobs:
build:
strategy:
matrix:
os: [windows-latest]
arch: [x64]
mode: [release]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
with:
# We need full history in order to create a build version string (BuildInfo.h)
fetch-depth: 0

- name: Checkout submodules
run: |
git submodule sync --recursive
git submodule update --init --force --recursive --depth=1
- name: Cache xmake dependencies
uses: actions/cache@v4
with:
path: ~/AppData/Local/.xmake/packages
key: ${{ runner.os }}-xmake-${{ hashFiles('**/xmake.lua') }}

# Install xmake
- name: Setup xmake
uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: 2.9.5
actions-cache-folder: '.xmake-cache' # This doesn't cache dependencies, only xmake itself
actions-cache-key: ${{ matrix.os }}

- name: Configure xmake and install dependencies
run: xmake config --arch=${{ matrix.arch }} --mode=${{ matrix.mode }} --yes -vD

# Build the game
- name: Build with xmake
run: xmake -y

# Create distrib
- name: Output STR binaries via xmake
run: xmake install -o distrib

# Building the Together UI
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: lts/iron
cache-dependency-path: Code/skyrim_ui/pnpm-lock.yaml
cache: 'pnpm'

- name: Build the UI
run: |
pnpm --prefix Code/skyrim_ui/ install
pnpm --prefix Code/skyrim_ui/ deploy:production
# Package everything, organize directories

- name: Package binaries and assets
run: |
mkdir -p str-build/SkyrimTogetherReborn
mv build/windows/${{ matrix.arch }}/${{ matrix.mode }}/* str-build/SkyrimTogetherReborn
cp -Force -Recurse distrib/bin/* str-build/SkyrimTogetherReborn
cp -r Code/skyrim_ui/dist/UI str-build/SkyrimTogetherReborn
cp -r GameFiles/Skyrim/* str-build/
- name: Remove unnecessary build files
run: rm str-build/SkyrimTogetherReborn/*.pdb, str-build/SkyrimTogetherReborn/*.lib

# Upload artifact

- name: Store version string
run: echo "STR_VERSION=$(git describe --tags)" >> $env:GITHUB_ENV

- name: Upload playable build
uses: actions/upload-artifact@v4
with:
name: Skyrim Together Build (${{ env.STR_VERSION }})
path: str-build/
2 changes: 1 addition & 1 deletion .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Setup xmake
uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: '2.9.3'
xmake-version: '2.9.5'

# Install node
#- name: Setup nodejs
Expand Down
147 changes: 105 additions & 42 deletions Code/client/CrashHandler.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <BranchInfo.h>
#include "CrashHandler.h"
#include <DbgHelp.h>
#include <Windows.h>
Expand All @@ -22,58 +23,120 @@ std::string SerializeTimePoint(const time_point& time, const std::string& format

LONG WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{
static int alreadycrashed = 0;
static int alreadyCrashed = 0;
auto retval = EXCEPTION_CONTINUE_SEARCH;

if (pExceptionInfo->ExceptionRecord->ExceptionCode == 0xC0000005 && alreadycrashed++ == 0)
{
spdlog::error("Crash occurred!");
MINIDUMP_EXCEPTION_INFORMATION M;
char dumpPath[MAX_PATH];

M.ThreadId = GetCurrentThreadId();
M.ExceptionPointers = pExceptionInfo;
M.ClientPointers = 0;

std::ostringstream oss;
oss << "crash_" << SerializeTimePoint(std::chrono::system_clock::now(), "UTC_%Y-%m-%d_%H-%M-%S") << ".dmp";

GetModuleFileNameA(NULL, dumpPath, sizeof(dumpPath));
std::filesystem::path modulePath(dumpPath);
auto subPath = modulePath.parent_path();

CrashHandler::RemovePreviousDump(subPath);

subPath /= oss.str();

auto hDumpFile = CreateFileA(subPath.string().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

// baseline settings from https://stackoverflow.com/a/63123214/5273909
auto dumpSettings = MiniDumpWithDataSegs | MiniDumpWithProcessThreadData | MiniDumpWithHandleData | MiniDumpWithThreadInfo |
/*
//MiniDumpWithPrivateReadWriteMemory | // this one gens bad dump
MiniDumpWithUnloadedModules |
MiniDumpWithFullMemoryInfo |
MiniDumpWithTokenInformation |
MiniDumpWithPrivateWriteCopyMemory |
*/
0;
// Serialize
static std::mutex singleThreaded;
const std::lock_guard lock{singleThreaded};

MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, (MINIDUMP_TYPE)dumpSettings, (pExceptionInfo) ? &M : NULL, NULL, NULL);

CloseHandle(hDumpFile);
// Check for severe, not continuable and not software-originated exception
if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
alreadyCrashed++ == 0)
{
spdlog::critical (__FUNCTION__ ": crash occurred!");

spdlog::error(__FUNCTION__ ": exception code is {:x}, at address {}, flags {:x} ",
pExceptionInfo->ExceptionRecord->ExceptionCode,
pExceptionInfo->ExceptionRecord->ExceptionAddress,
pExceptionInfo->ExceptionRecord->ExceptionFlags);

#if (IS_MASTER)
volatile static bool bMiniDump = false;
#else
volatile static bool bMiniDump = true;
#endif
if (bMiniDump)
{
HANDLE hDumpFile = NULL;
try
{
MINIDUMP_EXCEPTION_INFORMATION M;
char dumpPath[MAX_PATH];

M.ThreadId = GetCurrentThreadId();
M.ExceptionPointers = pExceptionInfo;
M.ClientPointers = 0;

std::ostringstream oss;
oss << "crash_" << SerializeTimePoint(std::chrono::system_clock::now(), "UTC_%Y-%m-%d_%H-%M-%S")
<< ".dmp";

GetModuleFileNameA(NULL, dumpPath, sizeof(dumpPath));
std::filesystem::path modulePath(dumpPath);
auto subPath = modulePath.parent_path();

CrashHandler::RemovePreviousDump(subPath);

subPath /= oss.str();

hDumpFile = CreateFileA(subPath.string().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);

// baseline settings from https://stackoverflow.com/a/63123214/5273909
auto dumpSettings = MiniDumpWithDataSegs | MiniDumpWithProcessThreadData | MiniDumpWithHandleData |
MiniDumpWithThreadInfo |
/*
//MiniDumpWithPrivateReadWriteMemory | // this one gens bad dump
MiniDumpWithUnloadedModules |
MiniDumpWithFullMemoryInfo |
MiniDumpWithTokenInformation |
MiniDumpWithPrivateWriteCopyMemory |
*/
0;

MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, (MINIDUMP_TYPE)dumpSettings,
(pExceptionInfo) ? &M : NULL, NULL, NULL);
}
catch (...) // Mini-dump is best effort only.
{
}

if (!hDumpFile)
spdlog::critical(__FUNCTION__ ": coredump may have failed.");
else
{
CloseHandle(hDumpFile);
spdlog::critical(__FUNCTION__ ": coredump created -> flush logs.");
}
}

spdlog::error("Coredump created -> flush logs.");
spdlog::default_logger()->flush();

return EXCEPTION_EXECUTE_HANDLER;
}
// Something in STR breaks top-level unhandled exception filters.
// The Win API for them is pretty clunky (non-atomic, not chainable),
// but they can do some important things. If someone actually set one
// they probably meant it; make sure it actually runs.
// This will make more CrashLogger mods work with STR.

// Get the current unhandled exception filter. If it has changed
// from when STR started up, invoke it here.
LPTOP_LEVEL_EXCEPTION_FILTER pCurrentUnhandledExceptionFilter = SetUnhandledExceptionFilter(CrashHandler::GetOriginalUnhandledExceptionFilter());
SetUnhandledExceptionFilter(pCurrentUnhandledExceptionFilter);
if (pCurrentUnhandledExceptionFilter != CrashHandler::GetOriginalUnhandledExceptionFilter())
{
spdlog::critical(__FUNCTION__ ": UnhandledExceptionFilter() workaround triggered.");

return EXCEPTION_CONTINUE_SEARCH;
singleThreaded.unlock(); // Might reenter, but is safe at this point.
if ((*pCurrentUnhandledExceptionFilter)(pExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION)
retval = EXCEPTION_CONTINUE_EXECUTION;
singleThreaded.lock();
}
}
return retval;
}

LPTOP_LEVEL_EXCEPTION_FILTER CrashHandler::m_pUnhandled;
CrashHandler::CrashHandler()
{
AddVectoredExceptionHandler(1, &VectoredExceptionHandler);
// Record the original (or as close as we can get) top-level unhandled exception handler.
// We grab this so we can see if it is changed, presumably by a mod or even graphics drivers.
// Something in STR breaks unhandled exception handling, so we'll fake it if necessary.
// This is the only way to get the current setting, but the race is small.
m_pUnhandled = SetUnhandledExceptionFilter(NULL);
SetUnhandledExceptionFilter(m_pUnhandled);

m_handler = AddVectoredExceptionHandler(1, &VectoredExceptionHandler);
}

CrashHandler::~CrashHandler()
Expand Down
9 changes: 8 additions & 1 deletion Code/client/CrashHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@

class CrashHandler
{
public:
PVOID m_handler;
static LPTOP_LEVEL_EXCEPTION_FILTER m_pUnhandled; // For remembering "original" UnhandledExceptionFilter

public:
CrashHandler();
~CrashHandler();

static void RemovePreviousDump(std::filesystem::path path);
static inline LPTOP_LEVEL_EXCEPTION_FILTER GetOriginalUnhandledExceptionFilter()
{
return m_pUnhandled;
}
};
20 changes: 0 additions & 20 deletions Code/client/Events/ActivateEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,6 @@ struct TESBoundObject;
*/
struct ActivateEvent
{
#if TP_FALLOUT4
ActivateEvent(TESObjectREFR* apObject, Actor* apActivator, TESBoundObject* apObjectToGet, int32_t aCount, bool aDefaultProcessing, bool aFromScript, bool aIsLooping, bool aActivateFlag = false)
: pObject(apObject)
, pActivator(apActivator)
, pObjectToGet(apObjectToGet)
, Count(aCount)
, DefaultProcessing(aDefaultProcessing)
, FromScript(aFromScript)
, IsLooping(aIsLooping)
, ActivateFlag(aActivateFlag)
{
}
#elif TP_SKYRIM64
ActivateEvent(TESObjectREFR* apObject, Actor* apActivator, TESBoundObject* apObjectToGet, int32_t aCount, bool aDefaultProcessing, uint8_t aUnk1, TESObjectREFR::OpenState aPreActivationOpenState, bool aActivateFlag = false)
: pObject(apObject)
, pActivator(apActivator)
Expand All @@ -33,20 +20,13 @@ struct ActivateEvent
, ActivateFlag(aActivateFlag)
{
}
#endif

TESObjectREFR* pObject;
Actor* pActivator;
TESBoundObject* pObjectToGet;
int32_t Count;
bool DefaultProcessing;
#if TP_FALLOUT4
bool FromScript;
bool IsLooping;
#elif TP_SKYRIM64
uint8_t Unk1;
#endif

TESObjectREFR::OpenState PreActivationOpenState;
bool ActivateFlag;
};
Loading

0 comments on commit a03bf37

Please sign in to comment.