Compare commits

...

4 Commits

Author SHA1 Message Date
Aaron Kimbrell
8e09ffd6e8 feat: enhance CI/CD workflows with Docker support and artifact management (#1977)
* feat: enhance CI/CD workflows with Docker support and artifact management

* chore: update GitHub Actions workflows with version pinning and permission adjustments

* feat: update CI workflows to support new OS versions and improve artifact handling

* chore: remove macOS-specific installation of libssl and XCode switching

* fix: update artifact zipping logic to target build directories in canary and release workflows

* chore: update actions/checkout to version 6.0.2 in CI workflow

* fix: update continue-on-error condition in CI workflow and add macOS RelWithDebInfo build preset

* fix: rename step to accurately reflect Docker image signing process

* don't ignore pdb's
2026-06-06 01:30:12 -05:00
David Markowitz
0c1808686c fix: tac arc absolute value bug (#1979)
Tested that tac arc correctly checks the full range
2026-06-06 01:17:00 -05:00
Johntor
4d6a624da2 docs: Refine command documentation (#1978)
* Refine command documentation

Updated command descriptions From dGame/dUtilities/SlashCommandHandler.cpp. Added aliases and improved formatting for better readability.

* fix: grammatical feedback

---------

Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2026-06-02 00:00:13 -07:00
David Markowitz
4ab09cf1aa Remove non-functioning saving of gm invis, re-add gm invis as a feature (#1976)
Does not save, only works for this world.  Fixed an issue where the incorrect comparison was used to make players invisible again (the same check that makes then INvisible needs to make them visible.)
2026-05-27 04:35:00 -05:00
12 changed files with 486 additions and 144 deletions

View File

@@ -1,14 +1,14 @@
name: CI
name: Docker
on:
push:
branches:
- "main"
- main
tags:
- "v*.*.*"
pull_request:
branches:
- "main"
- main
env:
REGISTRY: ghcr.io
@@ -20,15 +20,21 @@ jobs:
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: recursive
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Log in to the Container registry
uses: docker/login-action@v3
if: github.event_name != 'pull_request'
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -36,21 +42,32 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=ref,event=pr
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
type=raw,value=canary,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
id: push
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Sign Docker image
if: github.event_name != 'pull_request'
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true

View File

@@ -3,6 +3,8 @@ name: CI
on:
push:
branches: [ main ]
tags:
- "v*.*.*"
pull_request:
branches: [ main ]
@@ -10,38 +12,51 @@ jobs:
build-and-test:
name: Build & Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
continue-on-error: true
continue-on-error: ${{ github.event_name == 'pull_request' }}
strategy:
matrix:
os: [ windows-2022, ubuntu-22.04, macos-15-intel ]
include:
- os: windows-2025
artifact: windows
debug_preset: windows-msvc-relwithdebinfo
- os: ubuntu-24.04
artifact: linux
debug_preset: linux-gnu-relwithdebinfo
- os: macos-15-intel
artifact: macos
debug_preset: macos-relwithdebinfo
steps:
- uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
- name: Add msbuild to PATH (Windows only)
if: ${{ matrix.os == 'windows-2022' }}
uses: microsoft/setup-msbuild@767f00a3f09872d96a0cb9fcd5e6a4ff33311330
if: ${{ matrix.os == 'windows-2025' }}
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3
with:
vs-version: '[17,18)'
msbuild-architecture: x64
- name: Install libssl and switch to XCode 15.2 (Mac Only)
if: ${{ matrix.os == 'macos-13' }}
run: |
brew install openssl@3
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
- name: Get CMake 3.x
uses: lukka/get-cmake@28983e0d3955dba2bb0a6810caae0c6cf268ec0c
uses: lukka/get-cmake@591817e96fcad43505fb4eae36172462abb3a42e # v4.3.3
with:
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
cmakeVersion: "~3.25.0"
- name: cmake
uses: lukka/run-cmake@67c73a83a46f86c4e0b96b741ac37ff495478c38
uses: lukka/run-cmake@5d55ea7949e25f69f0ecb516d8d572297e03a956 # v10.9
with:
workflowPreset: "ci-${{matrix.os}}"
workflowPreset: "${{ matrix.debug_preset }}"
- name: Extract Linux debug symbols
if: matrix.os == 'ubuntu-24.04'
run: |
find build -type f -name '*Server' | while read bin; do
objcopy --only-keep-debug "$bin" "${bin}.debug"
objcopy --strip-debug --add-gnu-debuglink="${bin}.debug" "$bin"
done
- name: artifacts
uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: build-${{matrix.os}}
name: build-${{matrix.artifact}}
path: |
build/*/*Server*
build/*/*.ini
@@ -52,5 +67,30 @@ jobs:
build/*/navmeshes/
build/*/migrations/
build/*/*.dcf
!build/*/*.pdb
!build/*/d*/
!build/*/*.dSYM/
!build/**/*.debug
- name: debug symbols (Windows)
if: matrix.os == 'windows-2025'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: debug-${{matrix.artifact}}
path: |
build/*/*.pdb
build/*/d*/
retention-days: 30
- name: debug symbols (Linux)
if: matrix.os == 'ubuntu-24.04'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: debug-${{matrix.artifact}}
path: build/**/*.debug
retention-days: 30
- name: debug symbols (macOS)
if: matrix.os == 'macos-15-intel'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: debug-${{matrix.artifact}}
path: build/**/*.dSYM/
retention-days: 30

93
.github/workflows/canary.yml vendored Normal file
View File

@@ -0,0 +1,93 @@
name: Canary
on:
workflow_run:
workflows: ["CI"]
branches: [main]
types: [completed]
permissions:
contents: write
actions: read
jobs:
canary-release:
name: Publish Canary Release
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
ref: ${{ github.event.workflow_run.head_sha }}
- name: Get last release tag
id: last_tag
run: |
tag=$(git describe --tags --abbrev=0 --match "v*.*.*" 2>/dev/null || echo "none")
echo "tag=$tag" >> "$GITHUB_OUTPUT"
- name: Generate changelog since last release tag
uses: orhun/git-cliff-action@f50e11560dce63f7c33227798f90b924471a88b5 # v4.8.0
id: cliff
with:
config: cliff.toml
args: --unreleased --strip header
env:
OUTPUT: CHANGES.md
GITHUB_REPO: ${{ github.repository }}
- name: Prepend header to changelog
run: |
last="${{ steps.last_tag.outputs.tag }}"
sha="${{ github.event.workflow_run.head_sha }}"
short="${sha:0:7}"
if [ "$last" != "none" ]; then
header="Changes since **$last** ([full diff](https://github.com/${{ github.repository }}/compare/${last}...${sha}))\n\n"
else
header="Changes up to \`${short}\`\n\n"
fi
printf "%b" "$header" | cat - CHANGES.md > CHANGES.tmp && mv CHANGES.tmp CHANGES.md
- name: Download artifacts from CI run
uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
with:
run_id: ${{ github.event.workflow_run.id }}
path: artifacts/
- name: Package artifacts
run: |
declare -A platform_map=(
["build-windows"]="darkflame-universe-windows"
["build-linux"]="darkflame-universe-linux"
["build-macos"]="darkflame-universe-macos"
)
cd artifacts
for dir in build-*/; do
name="${dir%/}"
out="${platform_map[$name]:-$name}"
zip -r "../${out}.zip" "$dir"
done
cd ..
ls -lh *.zip
- name: Delete existing canary release
run: gh release delete canary --yes --cleanup-tag 2>/dev/null || true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create canary pre-release
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
with:
tag: canary
name: "Canary ${{ steps.last_tag.outputs.tag }}+${{ github.event.workflow_run.head_sha }}"
bodyFile: CHANGES.md
artifacts: "*.zip"
artifactContentType: application/zip
token: ${{ secrets.GITHUB_TOKEN }}
prerelease: true
draft: false
allowUpdates: true
removeArtifacts: true
commit: ${{ github.event.workflow_run.head_sha }}

37
.github/workflows/pr-title-check.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: PR Title Check
on:
pull_request_target:
types: [opened, edited, synchronize, reopened]
permissions:
pull-requests: write
jobs:
check-title:
name: Conventional Commit Title
runs-on: ubuntu-latest
steps:
- name: Check PR title follows Conventional Commits
uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
perf
refactor
docs
chore
test
ci
revert
requireScope: false
subjectPattern: ^.+$
subjectPatternError: |
The PR title "{title}" must have a description after the type/scope prefix.
Example: "feat: add new login flow" or "fix(auth): handle null token"
wip: true
validateSingleCommit: false

70
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,70 @@
name: Release
on:
workflow_run:
workflows: ["CI"]
types: [completed]
permissions:
contents: write
actions: read
jobs:
release:
name: Create Release
# Only run when CI completed successfully on a tag push (not a PR branch named like a version)
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
startsWith(github.event.workflow_run.head_branch, 'v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
ref: ${{ github.event.workflow_run.head_sha }}
- name: Generate changelog
uses: orhun/git-cliff-action@f50e11560dce63f7c33227798f90b924471a88b5 # v4.8.0
id: cliff
with:
config: cliff.toml
args: --latest --strip header
env:
OUTPUT: CHANGES.md
GITHUB_REPO: ${{ github.repository }}
- name: Download artifacts from CI run
uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
with:
run_id: ${{ github.event.workflow_run.id }}
path: artifacts/
- name: Package artifacts
run: |
declare -A platform_map=(
["build-windows"]="darkflame-universe-windows"
["build-linux"]="darkflame-universe-linux"
["build-macos"]="darkflame-universe-macos"
)
cd artifacts
for dir in build-*/; do
name="${dir%/}"
out="${platform_map[$name]:-$name}"
zip -r "../${out}.zip" "$dir"
done
cd ..
ls -lh *.zip
- name: Create GitHub Release
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
with:
tag: ${{ github.event.workflow_run.head_branch }}
name: ${{ github.event.workflow_run.head_branch }}
bodyFile: CHANGES.md
artifacts: "*.zip"
artifactContentType: application/zip
token: ${{ secrets.GITHUB_TOKEN }}
prerelease: false
draft: false

2
.gitignore vendored
View File

@@ -126,3 +126,5 @@ docker-compose.override.yml
# CMake scripts
!cmake/*
!cmake/toolchains/*
.mcp.json
.claude/

View File

@@ -162,6 +162,13 @@
"rhs": "Darwin"
},
"binaryDir": "${sourceDir}/build/macos"
},
{
"name": "macos-relwithdebinfo",
"inherits": ["macos", "relwithdebinfo-config"],
"displayName": "[RelWithDebInfo] MacOS",
"description": "Create a RelWithDebInfo build for MacOS",
"binaryDir": "${sourceDir}/build/macos-relwithdebinfo"
}
],
"buildPresets": [
@@ -255,7 +262,7 @@
{
"name": "macos-relwithdebinfo",
"inherits": "default",
"configurePreset": "macos",
"configurePreset": "macos-relwithdebinfo",
"displayName": "[RelWithDebInfo] MacOS",
"description": "This preset is used to build in release mode with debug info on MacOS",
"configuration": "RelWithDebInfo"
@@ -374,7 +381,7 @@
{
"name": "macos-relwithdebinfo",
"inherits": "default",
"configurePreset": "macos",
"configurePreset": "macos-relwithdebinfo",
"displayName": "[RelWithDebInfo] MacOS",
"description": "Runs all tests on a MacOS configuration",
"configuration": "RelWithDebInfo"
@@ -603,7 +610,7 @@
"steps": [
{
"type": "configure",
"name": "macos"
"name": "macos-relwithdebinfo"
},
{
"type": "build",

35
cliff.toml Normal file
View File

@@ -0,0 +1,35 @@
[changelog]
header = ""
body = """
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {% if commit.scope %}**{{ commit.scope }}**: {% endif %}{{ commit.message }} ([{{ commit.id | truncate(length=7, end="") }}](https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}/commit/{{ commit.id }}))\
{% if commit.github.username %} by [@{{ commit.github.username }}](https://github.com/{{ commit.github.username }}){% endif %}
{% endfor %}
{% endfor %}
"""
footer = ""
trim = true
[git]
conventional_commits = true
filter_unconventional = true
split_commits = false
commit_parsers = [
{ message = "^feat", group = "Features" },
{ message = "^fix", group = "Bug Fixes" },
{ message = "^perf", group = "Performance" },
{ message = "^refactor", group = "Refactoring" },
{ message = "^docs", group = "Documentation" },
{ message = "^chore", group = "Chores" },
{ message = "^test", group = "Testing" },
{ message = "^ci", group = "CI/CD" },
{ message = "^revert", group = "Reverts" },
]
filter_commits = false
tag_pattern = "v[0-9].*"
skip_tags = "canary"
ignore_tags = ""
topo_order = false
sort_commits = "oldest"

View File

@@ -208,8 +208,8 @@ void TacArcBehavior::Load() {
GetFloat("offset_z", 0.0f)
);
this->m_method = GetInt("method", 1);
this->m_upperBound = std::abs(GetFloat("upper_bound", 4.4f));
this->m_lowerBound = std::abs(GetFloat("lower_bound", 0.4f)) - 5.0f; // Makes it so players and objects can still be targetted when slightly below the caster. FIXME: use bounding spheres at some point
this->m_upperBound = GetFloat("upper_bound", 4.4f);
this->m_lowerBound = GetFloat("lower_bound", 0.4f) - 5.0f; // Makes it so players and objects can still be targetted when slightly below the caster. FIXME: use bounding spheres at some point
this->m_usePickedTarget = GetBoolean("use_picked_target", false);
this->m_useTargetPostion = GetBoolean("use_target_position", false);
this->m_checkEnv = GetBoolean("check_env", false);

View File

@@ -29,26 +29,6 @@ GhostComponent::~GhostComponent() {
}
}
void GhostComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* objElement = doc.FirstChildElement("obj");
if (!objElement) return;
auto* ghstElement = objElement->FirstChildElement("ghst");
if (!ghstElement) return;
m_IsGMInvisible = ghstElement->BoolAttribute("i");
}
void GhostComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
auto* objElement = doc.FirstChildElement("obj");
if (!objElement) return;
auto* ghstElement = objElement->FirstChildElement("ghst");
if (ghstElement) objElement->DeleteChild(ghstElement);
// Only save if GM invisible
const auto* const user = UserManager::Instance()->GetUser(m_Parent->GetSystemAddress());
if (!m_IsGMInvisible || !user || user->GetMaxGMLevel() < eGameMasterLevel::FORUM_MODERATOR) return;
ghstElement = objElement->InsertNewChildElement("ghst");
if (ghstElement) ghstElement->SetAttribute("i", m_IsGMInvisible);
}
void GhostComponent::SetGhostReferencePoint(const NiPoint3& value) {
m_GhostReferencePoint = value;
}
@@ -107,7 +87,7 @@ bool GhostComponent::OnToggleGMInvis(GameMessages::ToggleGMInvis& gmInvisMsg) {
Game::entityManager->DestructEntity(m_Parent, player->GetSystemAddress());
}
} else {
if (toUser->GetMaxGMLevel() >= thisUser->GetMaxGMLevel()) {
if (toUser->GetMaxGMLevel() < thisUser->GetMaxGMLevel()) {
Game::entityManager->ConstructEntity(m_Parent, player->GetSystemAddress());
auto* controllableComp = m_Parent->GetComponent<ControllablePhysicsComponent>();
controllableComp->SetDirtyPosition(true);
@@ -121,11 +101,8 @@ bool GhostComponent::OnToggleGMInvis(GameMessages::ToggleGMInvis& gmInvisMsg) {
bool GhostComponent::OnGetGMInvis(GameMessages::GetGMInvis& gmInvisMsg) {
LOG_DEBUG("GM Invisibility requested: %s", m_IsGMInvisible ? "true" : "false");
// TODO: disabled for now while bugs are fixed
// gmInvisMsg.bGMInvis = m_IsGMInvisible;
// return gmInvisMsg.bGMInvis;
gmInvisMsg.bGMInvis = false;
return false;
gmInvisMsg.bGMInvis = m_IsGMInvisible;
return gmInvisMsg.bGMInvis;
}
bool GhostComponent::MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportMsg) {

View File

@@ -16,8 +16,6 @@ public:
static inline const eReplicaComponentType ComponentType = eReplicaComponentType::GHOST;
GhostComponent(Entity* parent, const int32_t componentID);
~GhostComponent() override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
void SetGhostOverride(bool value) { m_GhostOverride = value; };

View File

@@ -1,51 +1,115 @@
# In-game commands
* All commands are prefixed by `/` and typed in the in-game chat window. Some commands require elevated gmlevel privileges. Operands within `<>` are required, operands within `()` are not.
* All commands are prefixed by `/` and typed in the in-game chat window. Some commands require elevated gmlevel privileges. Operands within `<>` are required, operands within `()` are optional.
## General Commands
|Command|Usage|Description|Admin Level Requirement|
|--- |--- |--- |--- |
|help|`/help (command/page)`|If a command is given, display detailed info on that command. Otherwise display a list of commands with short descriptions. Aliases: `/h`.|0|
|credits|`/credits`|Displays the names of the people behind Darkflame Universe.|0|
|die|`/die`|Smashes the player.|0|
|info|`/info`|Displays server info to the user, including where to find the server's source code.|0|
|instanceinfo|`/instanceinfo`|Displays in the chat the current zone, clone, and instance id.|0|
|ping|`/ping (-l)`|Displays in chat your average ping. If the `-l` flag is used, the latest ping is displayed.||
|pvp|`/pvp`|Toggle your PVP flag.|0|
|resurrect|`/resurrect`|Resurrects the player.|0|
|requestmailcount|`/requestmailcount`|Sends notification with number of unread messages in the player's mailbox.|0|
|who|`/who`|Displays in chat all players on the instance.|0|
|togglenameplate|`/togglenameplate`|Turns the nameplate above your head that is visible to other players off and on.|8 unless `allow_nameplate_off` is set to exactly `1` in the settings then admin level requirement is 0|
|toggleskipcinematics|`/toggleskipcinematics`|Skips mission and world load related cinematics.|8 unless `allow_players_to_skip_cinematics` is set to exactly `1` in the settings then admin level requirement is 0|
|die|`/die`|Smashes the player as if they were killed by something|0|
|info|`/info`|Displays server info to the user, including where to find the server's source code|0|
|instanceinfo|`/instanceinfo`|Display LWOZoneID info for the current zone|0|
|ping|`/ping (-l)`|Displays your average ping. If the `-l` flag is used, the latest ping is displayed.|0|
|pvp|`/pvp`|Toggle your PVP flag|0|
|requestmailcount|`/requestmailcount`|Sends notification with number of unread messages in the player's mailbox. Aliases: `/checkmail`.|0|
|who|`/who`|Displays all players on the instance|0|
|togglenameplate|`/togglenameplate`|Turns the nameplate above your head that is visible to other players off and on. This must be enabled by a server admin. Aliases: `/tnp`.|8 or 0 if `allow_nameplate_off` is 1|
|toggleskipcinematics|`/toggleskipcinematics`|Skips mission and world load related cinematics. This must be enabled by a server admin. Aliases: `/tsc`.|8 or 0 if `allow_players_to_skip_cinematics` is 1|
## Client-handled Commands
These commands are registered by the server so they appear in help, but their behavior is handled by the LEGO Universe client.
### User-Client related
|Command|Usage|Description|Admin Level Requirement|
|--- |--- |--- |--- |
|faq|`/faq`|Show the LU FAQ Page. Aliases: `/faqs`.|0|
|camp|`/camp`|Returns you to the character select screen. Aliases: `/logoutcharacter`.|0|
|cancelqueue|`/cancelqueue`|Cancel Your position in the queue if you are in one.|0|
|exit|`/exit`|Exit to desktop. Aliases: `/quit`.|0|
|forums|`/forums`|Show the LU Forums!|0|
|loc|`/loc`|Output your current location on the map to the chat box. Aliases: `/locate`, `/location`.|0|
|logout|`/logout`|Returns you to the login screen. Aliases: `/logoutaccount`.|0|
|minigames|`/minigames`|Show the LEGO minigames page!|0|
|shop|`/shop`|Show the LEGO shop page. Aliases: `/store`.|0|
|perfoptionslow|`/perfoptionslow`|Sets the default low-spec performance options in the cfg file|0|
|perfoptionsmid|`/perfoptionsmid`|Sets the default medium-spec performance options in the cfg file|0|
|perfoptionshigh|`/perfoptionshigh`|Sets the default high-spec performance options in the cfg file|0|
|recommendedperfoptions|`/recommendedperfoptions`|Sets the recommended performance options in the cfg file|0|
### Friend-Team related
|Command|Usage|Description|Admin Level Requirement|
|--- |--- |--- |--- |
|addfriend|`/addfriend <name>`|[name] Add a player to your friends list.|0|
|addignore|`/addignore <name>`|[name] Add a player to your ignore list.|0|
|invite|`/invite <name>`|[name] Invite a player to your team. Aliases: `/inviteteam`, `/teaminvite`, `/tinvite`.|0|
|kickplayer|`/kickplayer <name>`|Kicks a player from your current team. The `/kick` alias is reserved by the moderation command. Aliases: `/teamkickplayer`, `/tkick`, `/tkickplayer`.|0|
|leader|`/leader <name>`|[name] Set the leader for your current team. Aliases: `/setleader`, `/teamsetleader`, `/tleader`, `/tsetleader`.|0|
|leave|`/leave`|Leave your current team. Aliases: `/leaveteam`, `/teamleave`, `/tleave`.|0|
|removefriend|`/removefriend <name>`|[name] Removes a player from your friends list.|0|
|removeIgnore|`/removeIgnore <name>`|[name] Removes a player from your ignore list.|0|
|setloot|`/setloot <rr|ffa>`|[rr\|ffa] Set the loot for your current team (round-robin/free for all). Aliases: `/teamsetloot`, `/tloot`, `/tsetloot`.|0|
|s|`/s <message>`|Say something outloud so that everyone can hear you. Aliases: `/say`.|0|
|team|`/team <message>`|Send a message to your teammates. Aliases: `/t`.|0|
|tell|`/tell <name> <message>`|Send a private message to another player. Aliases: `/w`, `/whisper`.|0|
### Actions
|Command|Usage|Description|Admin Level Requirement|
|--- |--- |--- |--- |
|yes|`/yes`|Aye aye, captain!|0|
|sigh|`/sigh`|Another day, another brick.|0|
|shrug|`/shrug`|I dunno...|0|
|talk|`/talk`|Jibber Jabber|0|
|thumb|`/thumb`|Oh, yeah!. Aliases: `/thumbs`, `/thumbsup`.|0|
|cringe|`/cringe`|I don't even want to talk about it...|0|
|victory!|`/victory!`|Victory!|0|
|backflip|`/backflip`|Do a flip!|0|
|clap|`/clap`|A round of applause!|0|
|thanks|`/thanks`|Express your gratitude for another.|0|
|wave|`/wave`|Wave to other players.|0|
|why|`/why`|Why\|!?!!|0|
|gasp|`/gasp`|Oh my goodness!|0|
|cry|`/cry`|Show everyone your 'Aw' face.|0|
|dance|`/dance`|Dance 'til you can't dance no more.|0|
|giggle|`/giggle`|A good little chuckle|0|
|salute|`/salute`|For those about to build...|0|
## Moderation Commands
|Command|Usage|Description|Admin Level Requirement|
|--- |--- |--- |--- |
|gmlevel|`/gmlevel <level>`|Within the authorized range of levels for the current account, changes the character's game master level to the specified value. This is required to use certain commands. Aliases: `/setgmlevel`, `/makegm`.|Account GM level greater than 0|
|kick|`/kick <username>`|Kicks the player off the server.|2|
|mailitem|`/mailitem <player name> <item id>`|Mails an item to the given player. The mailed item has predetermined content. The sender name is set to "Darkflame Universe." The title of the message is "Lost item." The body of the message is "This is a replacement item for one you lost."|3|
|ban|`/ban <username>`|Bans a user from the server.|4|
|approveproperty|`/approveproperty`|Approves the property the player is currently visiting.|5|
|gmlevel|`/gmlevel <level>`|Within the authorized range of levels for the current account, changes the character's game master level to the specified value. This is required to use certain commands. Aliases: `/makegm`, `/setgmlevel`.|0; account GM level must be greater than 0|
|kick|`/kick <username>`|Kicks the player off the server|2|
|mailitem|`/mailitem <player name> <item id>`|Mails an item to the given player. The mailed item has predetermined content. The sender name is set to "Darkflame Universe". The title of the message is "Lost item". The body of the message is "This is a replacement item for one you lost".|3|
|ban|`/ban <username>`|Bans a user from the server|4|
|approveproperty|`/approveproperty`|Approves the property the player is currently visiting|5|
|mute|`/mute <username> (days) (hours)`|Mute player for the given amount of time. If no time is given, the mute is indefinite.|6|
|fly|`/fly <speed>`|This toggles your flying state with an optional parameter for the speed scale.|6|
|attackimmune|`/attackimmune <value>`|Sets the character's immunity to basic attacks state, where value can be one of "1", to make yourself immune to basic attack damage, or "0" to undo.|8|
|gmimmune|`/gmimmunve <value>`|Sets the character's GMImmune state, where value can be one of "1", to make yourself immune to damage, or "0" to undo.|8|
|gminvis|`/gminvis`|Toggles invisibility for the character, though it's currently a bit buggy. Requires nonzero GM Level for the character, but the account must have a GM level of 8.|8|
|setname|`/setname <name>`|Sets a temporary name for your player. The name resets when you log out.|8|
|title|`/title <title>`|Temporarily appends your player's name with " - &#60;title&#62;". This resets when you log out.|8|
|fly|`/fly <speed>`|Toggles your flying state with an optional parameter for the speed scale.|8|
|attackimmune|`/attackimmune <value>`|Sets the character's immunity to basic attacks state, where value can be one of "1", to make yourself immune to basic attack damage, or "0" to undo|8|
|gmimmune|`/gmimmune <value>`|Sets the character's GMImmune state, where value can be one of "1", to make yourself immune to damage, or "0" to undo|8|
|gminvis|`/gminvis`|Toggles invisibility for the character. Does not save across worlds.|1|
|setname|`/setname <name>`|Sets a temporary name for your player. The name resets when you log out|8|
|title|`/title <title>`|Temporarily appends your player's name with " - &#60;title&#62;". This resets when you log out|8|
|showall|`/showall (displayZoneData) (displayIndividualPlayers)`|Usage: /showall (displayZoneData: Default 1) (displayIndividualPlayers: Default 1)|2|
|findplayer|`/findplayer <player name>`|Find the World Server a player is in if they are online|2|
|spectate|`/spectate (player name)`|Specify a player name to spectate. They must be in the same world as you. Leave blank to stop spectating. Aliases: `/follow`.|2|
## Server Operation Commands
|Command|Usage|Description|Admin Level Requirement|
|--- |--- |--- |--- |
|announce|`/announce`|Sends a announcement. `/setanntitle` and `/setannmsg` must be called first to configure the announcement.|8|
|kill|`/kill <username>`|Smashes the character whom the given user is playing.|8|
|metrics|`/metrics`|Prints some information about the server's performance.|8|
|setannmsg|`/setannmsg <title>`|Sets the message of an announcement.|8|
|setanntitle|`/setanntitle <title>`|Sets the title of an announcement.|8|
|announce|`/announce`|Sends an announcement. `/setanntitle` and `/setannmsg` must be called first to configure the announcement.|8|
|kill|`/kill <username>`|Smashes the character whom the given user is playing|8|
|metrics|`/metrics`|Prints some information about the server's performance|8|
|setannmsg|`/setannmsg <message>`|Sets the message of an announcement. Use with `/setanntitle` and `/announce`|8|
|setanntitle|`/setanntitle <title>`|Sets the title of an announcement. Use with `/setannmsg` and `/announce`|8|
|shutdown|`/shutdown`|Shuts this world down|8|
|shutdownuniverse|`/shutdownuniverse`|Sends a shutdown message to the master server. This will send an announcement to all players that the universe will shut down in 10 minutes.|9|
|uptime|`/uptime`|Displays the time the current world server has been active.|8|
|uptime|`/uptime`|Display the time the current world server has been active|8|
## Development Commands
@@ -53,73 +117,75 @@ These commands are primarily for development and testing. The usage of many of t
|Command|Usage|Description|Admin Level Requirement|
|--- |--- |--- |--- |
|fix-stats|`/fix-stats`|Resets skills, buffs, and destroyables.|0|
|join|`/join <password>`|Joins a private zone with given password.|0|
|leave-zone|`/leave-zone` or <br> `/leavezone`|If you are in an instanced zone, transfers you to the closest main world. For example, if you are in an instance of Avant Gardens Survival or the Spider Queen Battle, you are sent to Avant Gardens. If you are in the Battle of Nimbus Station, you are sent to Nimbus Station.|0|
|fix-stats|`/fix-stats`|Resets skills, buffs, and destroyables|0|
|join|`/join <password>`|Join a private zone with given password|0|
|leave-zone|`/leave-zone`|If you are in an instanced zone, transfers you to the closest main world. For example, if you are in an instance of Avant Gardens Survival or the Spider Queen Battle, you are sent to Avant Gardens. If you are in the Battle of Nimbus Station, you are sent to Nimbus Station. Aliases: `/leavezone`.|0|
|resurrect|`/resurrect`|Resurrects the player.|8|
|setminifig|`/setminifig <body part> <minifig item id>`|Alters your player's minifig. Body part can be one of "Eyebrows", "Eyes", "HairColor", "HairStyle", "Pants", "LeftHand", "Mouth", "RightHand", "Shirt", or "Hands". Changing minifig parts could break the character so this command is limited to GMs.|1|
|testmap|`/testmap <zone> (force) (clone-id)`|Transfers you to the given zone by id and clone id. Add "force" to skip checking if the zone is accessible (this can softlock your character, though, if you e.g. try to teleport to Frostburgh).|1|
|reportproxphys|`/reportproxphys`|Prints to console the position and radius of proximity sensors.|6|
|spawnphysicsverts|`/spawnphysicsverts`|Spawns a 1x1 brick at all vertices of phantom physics objects.|6|
|teleport|`/teleport <x/source player> (y) <z/target player>` or <br> `/tele <x/source player> (y) <z/target player>`|Teleports you. If no Y is given, you are teleported to the height of the terrain or physics object at (x, z). Any of the coordinates can use the syntax of an exact position (10.0), or a relative position (~+10.0). A ~ means use the current value of that axis as the base value. Addition or subtraction is supported (~+10) (~-10). If source player and target player are players that exist in the world, then the source player will be teleported to target player. Alias: `/tele`.|6|
|activatespawner|`/activatespawner <spawner name>`|Activates spawner by name.|8|
|testmap|`/testmap <zone> (force) (clone-id)`|Transfers you to the given zone by id and clone id. Add "force" to skip checking if the zone is accessible (this can softlock your character, though, if you e.g. try to teleport to Frostburgh). Aliases: `/tm`.|1|
|reportproxphys|`/reportproxphys`|Prints to console the position and radius of proximity sensors.|9|
|spawnphysicsverts|`/spawnphysicsverts`|Spawns a 1x1 brick at all vertices of phantom physics objects|8|
|teleport|`/teleport <x/source player> (y) <z/target player>`|Teleports you. If no Y is given, you are teleported to the height of the terrain or physics object at (x, z). Any of the coordinates can use the syntax of an exact position (10.0), or a relative position (~+10.0). A ~ means use the current value of that axis as the base value. Addition or subtraction is supported (~+10) (~-10). If source player and target player are players that exist in the world, then the source player will be teleported to target player. Aliases: `/tele`, `/tp`.|6|
|activatespawner|`/activatespawner <spawner name>`|Activates spawner by name|8|
|addmission|`/addmission <mission id>`|Accepts the mission, adding it to your journal.|8|
|boost|`/boost (time)`|Adds a passive boost action if you are in a vehicle. If time is given it will end after that amount of time|8|
|unboost|`/unboost`|Removes a passive vehicle boost|8|
|buff|`/buff <id> <duration>`|Applies the buff with the given id for the given number of seconds.|8|
|buffme|`/buffme`|Sets health, armor, and imagination to 999.|8|
|buffmed|`/buffmed`|Sets health, armor, and imagination to 9.|8|
|clearflag|`/clearflag <flag id>`|Removes the given health or inventory flag from your player. Equivalent of calling `/setflag off <flag id>`.|8|
|completemission|`/completemission <mission id>`|Completes the mission, removing it from your journal.|8|
|createprivate|`/createprivate <zone id> <clone id> <password>`|Creates a private zone with password.|8|
|debugui|`/debugui`|Toggle Debug UI.|8|
|dismount|`/dismount`|Dismounts you from the vehicle or mount.|8|
|reloadconfig|`/reloadconfig`|Reloads the server with the new config values.|8|
|force-save|`/force-save`|While saving to database usually happens on regular intervals and when you disconnect from the server, this command saves your player's data to the database.|8|
|freecam|`/freecam`|Toggles freecam mode.|8|
|freemoney|`/freemoney <coins>`|Gives coins.|8|
|getnavmeshheight|`/getnavmeshheight`|Displays the navmesh height at your current position.|8|
|giveuscore|`/giveuscore <uscore>`|Gives uscore.|8|
|gmadditem|`/gmadditem <id> (count)`|Adds the given item to your inventory by id.|8|
|inspect|`/inspect <component or ldf variable or player name> (-m <waypoint> \| -a <animation> \| -s \| -p \| -f (faction) \| -t)`|Finds the closest entity with the given component or LDF variable (ignoring players and racing cars), printing its ID, distance from the player, and whether it is sleeping, as well as the the IDs of all components the entity has. See [Detailed `/inspect` Usage](#detailed-inspect-usage) below.|8|
|list-spawns|`/list-spawns`|Lists all the character spawn points in the zone. Additionally, this command will display the current scene that plays when the character lands in the next zone, if there is one.|8|
|locrow|`/locrow`|Prints the your current position and rotation information to the console.|8|
|lookup|`/lookup <query>`|Searches through the Objects table in the client SQLite database for items whose display name, name, or description contains the query. Query can be multiple words delimited by spaces.|8|
|playanimation|`/playanimation <id>`|Plays animation with given ID. Alias: `/playanim`.|8|
|playeffect|`/playeffect <effect id> <effect type> <effect name>`|Plays an effect.|8|
|playlvlfx|`/playlvlfx`|Plays the level up animation on your character.|8|
|playrebuildfx|`/playrebuildfx`|Plays the quickbuild animation on your character.|8|
|pos|`/pos`|Displays your current position in chat and in the console.|8|
|refillstats|`/refillstats`|Refills health, armor, and imagination to their maximum level.|8|
|reforge|`/reforge <base item id> <reforged item id>`|Reforges an item.|8|
|resetmission|`/resetmission <mission id>`|Sets the state of the mission to accepted but not yet started.|8|
|rot|`/rot`|Displays your current rotation in chat and in the console.|8|
|buff|`/buff <id> <duration>`|Applies a buff with the given id for the given number of seconds|8|
|buffme|`/buffme`|Sets health, armor, and imagination to 999|8|
|buffmed|`/buffmed`|Sets health, armor, and imagination to 9|8|
|clearflag|`/clearflag <flag id>`|Removes the given health or inventory flag from your player. Equivalent of calling `/setflag off <flag id>`|8|
|completemission|`/completemission <mission id>`|Completes the mission, removing it from your journal|8|
|createprivate|`/createprivate <zone id> <clone id> <password>`|Creates a private zone with password|8|
|debugui|`/debugui`|Toggle Debug UI|8|
|dismount|`/dismount`|Dismounts you from the vehicle or mount|8|
|reloadconfig|`/reloadconfig`|Reloads the server with the new config values. Aliases: `/reload-config`.|8|
|forcesave|`/forcesave`|While saving to database usually happens on regular intervals and when you disconnect from the server, this command saves your player's data to the database. Aliases: `/force-save`.|8|
|freecam|`/freecam`|Toggles freecam mode|8|
|freemoney|`/freemoney <coins>`|Give yourself coins. Aliases: `/givemoney`, `/money`, `/givecoins`, `/coins`.|8|
|getnavmeshheight|`/getnavmeshheight`|Display the navmesh height at your current position|8|
|giveuscore|`/giveuscore <uscore>`|Gives uscore|8|
|gmadditem|`/gmadditem <id> (count)`|Adds the given item to your inventory by id. Aliases: `/give`.|8|
|inspect|`/inspect <component or ldf variable or player name> (-m <waypoint> | -a <animation> | -s | -p | -f (faction) | -t)`|Finds the closest entity with the given component or LNV variable (ignoring players and racing cars), printing its ID, distance from the player, and whether it is sleeping, as well as the IDs of all components the entity has. See detailed usage in the DLU docs|8|
|list-spawns|`/list-spawns`|Lists all the character spawn points in the zone. Additionally, this command will display the current scene that plays when the character lands in the next zone, if there is one. Aliases: `/listspawns`.|8|
|locrow|`/locrow`|Prints your current position and rotation information to the console|8|
|lookup|`/lookup <query>`|Searches through the Objects table in the client SQLite database for items whose display name, name, or description contains the query. Query can be multiple words delimited by spaces.|8|
|playanimation|`/playanimation <id>`|Play an animation with given ID. Aliases: `/playanim`.|8|
|playeffect|`/playeffect <effect id> <effect type> <effect name>`|Plays an effect|8|
|playlvlfx|`/playlvlfx`|Plays the level up animation on your character|8|
|playrebuildfx|`/playrebuildfx`|Plays the quickbuild animation on your character|8|
|pos|`/pos`|Displays your current position in chat and in the console|8|
|refillstats|`/refillstats`|Refills health, armor, and imagination to their maximum level|8|
|reforge|`/reforge <base item id> <reforged item id>`|Reforges an item|8|
|resetmission|`/resetmission <mission id>`|Sets the state of the mission to accepted but not yet started|8|
|rot|`/rot`|Displays your current rotation in chat and in the console|8|
|runmacro|`/runmacro <macro>`|Runs any command macro found in `./res/macros/`|8|
|setcontrolscheme|`/setcontrolscheme <scheme number>`|Sets the character control scheme to the specified number.|8|
|setcurrency|`/setcurrency <coins>`|Sets your coins.|8|
|setflag|`/setflag (value) <flag id>`|Sets the given inventory or health flag to the given value, where value can be one of "on" or "off". If no value is given, by default this adds the flag to your character (equivalent of calling `/setflag on <flag id>`).|8|
|setinventorysize|`/setinventorysize <size> (inventory)` or <br> `/setinvsize <size> (inventory)`|Sets your inventory size to the given size. If `inventory` is provided, the number or string will be used to set that inventory to the requested size. Alias: `/setinvsize`|8|
|setuistate|`/setuistate <ui state>`|Changes UI state.|8|
|spawn|`/spawn <id>`|Spawns an object at your location by id.|8|
|setcontrolscheme|`/setcontrolscheme <scheme number>`|Sets the character control scheme to the specified number|8|
|setcurrency|`/setcurrency <coins>`|Sets your coins. Aliases: `/setcoins`.|8|
|setflag|`/setflag (value) <flag id>`|Sets the given inventory or health flag to the given value, where value can be one of "on" or "off". If no value is given, by default this adds the flag to your character (equivalent of calling `/setflag on <flag id>`)|8|
|setinventorysize|`/setinventorysize <size> (inventory)`|Sets your inventory size to the given size. If `inventory` is provided, the number or string will be used to set that inventory to the requested size. Aliases: `/setinvsize`, `/setinvensize`.|8|
|setuistate|`/setuistate <ui state>`|Changes UI state|8|
|spawn|`/spawn <id>`|Spawns an object at your location by id|8|
|spawngroup|`/spawngroup <id> <amount> <radius>`|Spawns `<amount>` of object `<id>` within the given `<radius>` from your location|8|
|speedboost|`/speedboost <amount>`|Sets the speed multiplier to the given amount. `/speedboost 1.5` will set the speed multiplier to 1.5x the normal speed.|8|
|startcelebration|`/startcelebration <id>`|Starts a celebration effect on your character.|8|
|stopeffect|`/stopeffect <effect id>`|Stops the given effect.|8|
|toggle|`/toggle <ui state>`|Toggles UI state.|8|
|tpall|`/tpall`|Teleports all characters to your current position.|8|
|triggerspawner|`/triggerspawner <spawner name>`|Triggers spawner by name.|8|
|unlock-emote|`/unlock-emote <emote id>`|Unlocks for your character the emote of the given id.|8|
|Set Level|`/setlevel <requested_level> (username)`|Sets the using entities level to the requested level. Takes an optional parameter of an in-game players username to set the level of.|8|
|setskillslot|`/setskillslot <slot> <skill id>`||8|
|speedboost|`/speedboost <amount>`|Sets the speed multiplier to the given amount. `/speedboost 1.5` will set the speed multiplier to 1.5x the normal speed|8|
|startcelebration|`/startcelebration <id>`|Starts a celebration effect on your character|8|
|stopeffect|`/stopeffect <effect id>`|Stops the given effect|8|
|toggle|`/toggle <ui state>`|Toggles UI state|8|
|tpall|`/tpall`|Teleports all characters to your current position|8|
|triggerspawner|`/triggerspawner <spawner name>`|Triggers spawner by name|8|
|unlock-emote|`/unlock-emote <emote id>`|Unlocks for your character the emote of the given id. Aliases: `/unlockemote`.|8|
|setlevel|`/setlevel <requested_level> (username)`|Sets the using entities level to the requested level. Takes an optional parameter of an in-game players username to set the level of|8|
|setskillslot|`/setskillslot <slot> <skill id>`|Set an action slot to a specific skill|8|
|setfaction|`/setfaction <faction id>`|Clears the users current factions and sets it|8|
|addfaction|`/addfaction <faction id>`|Add the faction to the users list of factions|8|
|getfactions|`/getfactions`|Shows the player's factions|8|
|setrewardcode|`/setrewardcode <code>`|Sets the rewardcode for the account you are logged into if it's a valid rewardcode, See cdclient table `RewardCodes`|8|
|barfight|`/barfight start`|Starts a barfight (turns everyones pvp on)|8|
|despawn|`/despawn <objectID>`|Despawns the entity objectID IF it was spawned in through a slash command.|8|
|execute|`/execute <subcommand> ... run <command>`|Execute commands with modified context (Minecraft-style). Subcommands: `as <playername>` (execute as different player), `at <playername>` (execute from player's position), `positioned <x> <y> <z>` (execute from coordinates - supports absolute coordinates like `100 200 300` or relative coordinates like `~5 ~10 ~` where `~` means current position). Example: `/execute as Player1 run pos`, `/execute positioned ~5 ~ ~-3 run spawn 1234`|8|
|crash|`/crash`|Crashes the server.|9|
|rollloot|`/rollloot <loot matrix index> <item id> <amount>`|Given a `loot matrix index`, look for `item id` in that matrix `amount` times and print to the chat box statistics of rolling that loot matrix.|9|
|castskill|`/castskill <skill id>`|Casts the skill as the player|9|
|barfight|`/barfight`|Starts a barfight (turns everyones pvp on)|8|
|despawn|`/despawn <object id>`|Despawns an object by id|8|
|execute|`/execute <subcommand> ... run <command>`|Execute commands as different entities or from different positions. Usage: /execute <subcommand> ... run <command>. Subcommands: as <entity>, at <entity>, positioned <x> <y> <z>. Aliases: `/exec`.|8|
|crash|`/crash`|Crashes the server. Aliases: `/pumpkin`.|9|
|rollloot|`/rollloot <loot matrix index> <item id> <amount>`|Given a `loot matrix index`, look for `item id` in that matrix `amount` times and print to the chat box statistics of rolling that loot matrix. Aliases: `/roll-loot`.|8|
|castskill|`/castskill <skill id>`|Casts the skill as the player|8|
|deleteinven|`/deleteinven <inventory>`|Delete all items from a specified inventory|8|
## Detailed `/inspect` Usage