Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e98f946367 | |||
| e5c15422c1 | |||
| e511b0a179 | |||
| 847bcf9bac | |||
| 6b584bdfbf | |||
| be79e4303d | |||
| 01281ebed2 | |||
| 74adf15820 | |||
| 19cbd9da15 | |||
| c7db28166f | |||
| 8fa3ed49be | |||
| 33764c3ede | |||
| 017c8708d8 | |||
| d2ec932153 | |||
| 38213e1a50 | |||
| d879a2995f | |||
| c2e37eea5a | |||
| 13e36d5bc3 | |||
| b2cbc7239b | |||
| f203dfcbf5 | |||
| 58540763d2 | |||
| 1b9d2a0b87 | |||
| fa3059c09e | |||
| 7a840ac233 | |||
| 0322221529 | |||
| 9066e31c55 | |||
| d19a10c08b | |||
| a90e60ef32 | |||
| 070fb38709 | |||
| ed1cb0e2a8 | |||
| bedcd0cb50 | |||
| 2987de52ec | |||
| aaf888f182 | |||
| 052da9316c | |||
| 842e229e55 | |||
| b2742428d0 | |||
| 48717eeabd | |||
| 5f14414055 | |||
| a253919575 | |||
| 4626a69185 | |||
| 44268d076d | |||
| c2e460b408 | |||
| c827c81d28 | |||
| 5f9aad80ac | |||
| be9bae93de | |||
| 5295ec664b | |||
| f59b5df887 | |||
| cf3c3790b5 | |||
| 4331a58e50 | |||
| 214ccd10d1 | |||
| c6fb3331c2 | |||
| 391c8bc14e | |||
| 84d63cb84d | |||
| e95c68165a | |||
| 070e31dbec | |||
| c9fc193aa3 | |||
| e7f80d83a6 | |||
| 9d9c10179c | |||
| e2a1b4a598 | |||
| ca7b7e9d1b | |||
| 7e53a63455 | |||
| f2aec71b6e | |||
| c317aa4e37 | |||
| df371568c7 | |||
| 6ed1bf7352 | |||
| 31a179bc45 | |||
| cf3c13c303 | |||
| 476211b220 | |||
| 625e5fd596 | |||
| 7f8633ab09 | |||
| 176b5c2934 | |||
| cf53167cec | |||
| 171bb3f018 | |||
| 6e6470086e | |||
| b171d836ad | |||
| f3315d443f | |||
| c09b0cc69f | |||
| 88a3f10192 | |||
| 952d35535f | |||
| 600123dd8b | |||
| b3d6f59aaf | |||
| 07a84f25d5 | |||
| f3269d0bee | |||
| cdbf8f991c | |||
| 04fb9ba50f | |||
| 2d83ba9dfd | |||
| c0a10c4710 | |||
| 1e8489018d | |||
| ab6c93791f | |||
| acc1377bbb | |||
| 3873388b48 | |||
| 0d4d34634a | |||
| d5b7c52641 | |||
| 9c85fb2f10 | |||
| a2d2cb07d4 | |||
| 403489e43c | |||
| d24ec58185 | |||
| a3f47c5b12 | |||
| d5c33e56e5 | |||
| 266c1470ba | |||
| 6fcf1d1f6f | |||
| 30eb6b96e0 | |||
| ebb7611a92 | |||
| 77c71a501f | |||
| c5988f94b0 | |||
| 1671b775e4 | |||
| 4d8c30f48c | |||
| d1150ed84d | |||
| 5dfb7b79d7 | |||
| 19abd94069 | |||
| c0f96b35de | |||
| dedc16fb73 | |||
| f8d4478d35 | |||
| 738721119e | |||
| b8a5db6d48 | |||
| cc48fe2ffc | |||
| a307a3cd9f | |||
| 9a2a10499d | |||
| 3daa559a67 | |||
| e459538f18 | |||
| 0065093ca3 | |||
| 391f634d65 | |||
| 838a33b4d5 | |||
| 647ab8bda9 | |||
| 8b37e854d8 | |||
| 23ec17460e |
@@ -0,0 +1,34 @@
|
||||
name: Build Docker image and push to release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
if: "!github.event.release.prerelease"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Connect to Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
tags: tag:ci
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver: docker
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ secrets.REGISTRY_URL }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
tags: ${{ secrets.REGISTRY_URL }}/beammp/website:${{ github.REF_NAME }}, ${{ secrets.REGISTRY_URL }}/beammp/website:latest, ${{ secrets.REGISTRY_URL }}/beammp/website:production
|
||||
@@ -0,0 +1,34 @@
|
||||
name: Build Docker image and push to prerelease
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
if: github.event.release.prerelease
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Connect to Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
tags: tag:ci
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver: docker
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ secrets.REGISTRY_URL }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
tags: ${{ secrets.REGISTRY_URL }}/beammp/website:${{ github.REF_NAME }}, ${{ secrets.REGISTRY_URL }}/beammp/website:latest
|
||||
@@ -102,7 +102,6 @@ dist
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
*.exe
|
||||
*.zip
|
||||
|
||||
# Logs
|
||||
@@ -129,3 +128,4 @@ frontend/*.ntvs*
|
||||
frontend/*.njsproj
|
||||
frontend/*.sln
|
||||
frontend/*.sw?
|
||||
.DS_Store
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
node_modules
|
||||
dist
|
||||
*.log
|
||||
.DS_Store
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100,
|
||||
"arrowParens": "always",
|
||||
"endOfLine": "lf",
|
||||
"vueIndentScriptAndStyle": false
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"beammp",
|
||||
"beammpservers",
|
||||
"beamng",
|
||||
"Deutsch",
|
||||
"Español",
|
||||
"Français",
|
||||
"freeroam",
|
||||
"gridlines",
|
||||
"Italiano",
|
||||
"Lucide",
|
||||
"maxplayers",
|
||||
"modlist",
|
||||
"modstotal",
|
||||
"modstotalsize",
|
||||
"Offroad",
|
||||
"playerslist",
|
||||
"reka",
|
||||
"rels",
|
||||
"roleplay",
|
||||
"sdesc",
|
||||
"sname",
|
||||
"vueuse",
|
||||
"Русский"
|
||||
]
|
||||
}
|
||||
@@ -1,25 +1,30 @@
|
||||
FROM node:18.16.0-alpine3.17
|
||||
# Step 1: Build stage
|
||||
FROM node:lts-alpine AS build
|
||||
|
||||
# Create app directory
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
ENV NODE_ENV=production
|
||||
RUN npm run build
|
||||
|
||||
RUN apk --no-cache add curl
|
||||
# Step 2: Serve stage
|
||||
FROM nginx:stable
|
||||
|
||||
# Install app dependencies
|
||||
# A wildcard is used to ensure both package.json AND package-lock.json are copied
|
||||
# where available (npm@5+)
|
||||
COPY package*.json /app
|
||||
# Remove default nginx static assets
|
||||
RUN rm -rf /usr/share/nginx/html/*
|
||||
|
||||
# General Install of Deps
|
||||
# RUN npm install
|
||||
# If you are building your code for production
|
||||
RUN npm ci --only=production
|
||||
# Copy built files from the previous stage
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
|
||||
# Bundle app source
|
||||
COPY . /app
|
||||
# Copy secure nginx configs
|
||||
COPY nginx.main.conf /etc/nginx/nginx.conf
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
EXPOSE 3599
|
||||
# Use non-root user for security
|
||||
USER nginx
|
||||
|
||||
HEALTHCHECK CMD curl --fail http://localhost:3599/ping || exit 1
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
CMD [ "node", "index.js" ]
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
|
||||
@@ -1 +1,112 @@
|
||||
# BeamMP-Website
|
||||
# BeamMP Website
|
||||
|
||||
This repository is home for the BeamMP website. The website features support for translations too now!
|
||||
|
||||
**Tech Stack**
|
||||
- **Framework:** Vue 3 (`vue`, `vue-router`)
|
||||
- **Build:** Vite 7 (`vite`, `@vitejs/plugin-vue`)
|
||||
- **Styling:** Tailwind CSS 4 + `tailwindcss-animate`, `tailwind-merge`
|
||||
- **UI Icons/Utils:** `lucide-vue-next`, `clsx`, `class-variance-authority`
|
||||
- **Radix-style Components:** `reka-ui` through `shadcn-vue`
|
||||
- **Composable utilities:** `@vueuse/core`
|
||||
|
||||
**Theming and Colour Guide**
|
||||
- BeamMP Orange `#F36D24`
|
||||
- BeamMP Blue `#4470B6`
|
||||
- BeamMP Green `#1D9749`
|
||||
- Gray `#333333`
|
||||
- Black `#000000`
|
||||
- White `#FFFFFF`
|
||||
|
||||
## Getting Started
|
||||
|
||||
Prerequisites:
|
||||
- Node.js 22+
|
||||
- pnpm, npm, or yarn (examples use npm)
|
||||
|
||||
Install dependencies and run the dev server:
|
||||
|
||||
```powershell
|
||||
# from this folder (repo root)
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Build for production and preview locally:
|
||||
|
||||
```powershell
|
||||
npm run build
|
||||
npm run preview
|
||||
```
|
||||
|
||||
Vite will print the local dev URL (usually `http://localhost:5173`).
|
||||
|
||||
## Project Scripts
|
||||
- `npm run dev`: Start Vite development server
|
||||
- `npm run build`: Production build
|
||||
- `npm run preview`: Preview the production build locally
|
||||
- `npm run lint`: Lint and auto-fix Vue/JS files with ESLint
|
||||
- `npm run format`: Format all source files with Prettier
|
||||
|
||||
## Directory Overview
|
||||
- `src/` – App source (styles, components, pages, routing)
|
||||
- `src/components/ui/` – UI components (e.g., `button`, `navigation-menu`)
|
||||
- `src/lib/` – Utilities and helpers
|
||||
- `routes/` - vue-router routes
|
||||
- `views/` - Pages of the website
|
||||
- `index.html` – Vite HTML entry
|
||||
- `tailwind.config.js` – Tailwind configuration
|
||||
- `vite.config.js` – Vite configuration
|
||||
- `components.json` – Shadcn-Vue component registry
|
||||
|
||||
## Contributing
|
||||
We welcome contributions! Here’s how to get started.
|
||||
|
||||
### 1) Pick an Issue or Open One
|
||||
- Browse issues or propose an enhancement/bug. Share context and repro steps.
|
||||
|
||||
### 2) Create a Branch
|
||||
- Use a descriptive branch name:
|
||||
- `feature/<short-description>`
|
||||
- `fix/<short-description>`
|
||||
- `docs/<short-description>`
|
||||
|
||||
### 3) Dev Environment
|
||||
- Install deps with `npm install` and run `npm run dev`.
|
||||
- Keep changes scoped and focused; avoid drive-by refactors unless agreed.
|
||||
|
||||
### 4) Code Style & Patterns
|
||||
- **Vue 3 + `<script setup>`** preferred for new components.
|
||||
- **Linting**: Run `npm run lint` before committing to catch errors. ESLint is configured for Vue 3 best practices.
|
||||
- **Formatting**: Run `npm run format` to auto-format code with Prettier (or use an editor extension).
|
||||
- **Type safety**: If/when TypeScript is introduced, prefer explicit props and emits.
|
||||
- **Tailwind**: Use utility classes; extract variants with `class-variance-authority` when patterns repeat.
|
||||
- **Accessibility**: Prefer accessible primitives (e.g., `reka-ui`) and keyboard support.
|
||||
- **File naming**: `PascalCase.vue` for components; avoid one-letter variable names.
|
||||
|
||||
### 5) Testing & Checks
|
||||
- Run the app locally and verify core flows.
|
||||
- Ensure components render on both light/dark themes if relevant.
|
||||
- If you add dependencies, update this README and relevant configs.
|
||||
|
||||
### 6) Commit & PR
|
||||
- Write clear, imperative commit messages, e.g., `feat: add NavigationMenu component`.
|
||||
- Open a PR describing the problem, solution, screenshots if UI changes, and any follow-ups.
|
||||
- Link related issues. Keep PRs small; big changes should be split.
|
||||
|
||||
|
||||
# Translations
|
||||
BeamMP makes an effort to be maintained for multiple languages.
|
||||
The current progress of this sits at:
|
||||
[](https://gitlocalize.com/repo/10617?utm_source=badge)
|
||||
We use [GitLocalize](https://gitlocalize.com/) for managing this. You can contribute if you wish here: https://gitlocalize.com/repo/10617.
|
||||
|
||||
The individual language progress is as follows:
|
||||
|
||||
| Language | Badge |
|
||||
|-----------------------|---------------------------------------------------------------------------------------------------------------------------------|
|
||||
| French | [](https://gitlocalize.com/repo/10617/fr?utm_source=badge) |
|
||||
| German | [](https://gitlocalize.com/repo/10617/de?utm_source=badge) |
|
||||
| Italian | [](https://gitlocalize.com/repo/10617/it?utm_source=badge) |
|
||||
| Russian | [](https://gitlocalize.com/repo/10617/ru?utm_source=badge) |
|
||||
| Spanish | [](https://gitlocalize.com/repo/10617/es?utm_source=badge) |
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://shadcn-vue.com/schema.json",
|
||||
"style": "new-york",
|
||||
"typescript": false,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.js",
|
||||
"css": "src/style.css",
|
||||
"baseColor": "gray",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"iconLibrary": "lucide",
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"composables": "@/composables"
|
||||
},
|
||||
"registries": {}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
services:
|
||||
website:
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
container_name: website
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:3000:80"
|
||||
@@ -0,0 +1,74 @@
|
||||
import pluginVue from 'eslint-plugin-vue'
|
||||
import js from '@eslint/js'
|
||||
import prettier from 'eslint-plugin-prettier'
|
||||
import configPrettier from 'eslint-config-prettier'
|
||||
|
||||
export default [
|
||||
// Ignore patterns (replaces .eslintignore)
|
||||
{
|
||||
ignores: ['node_modules', 'dist', '*.log', '.DS_Store'],
|
||||
},
|
||||
|
||||
// Base JavaScript config
|
||||
js.configs.recommended,
|
||||
|
||||
// Vue 3 recommended config
|
||||
...pluginVue.configs['flat/recommended'],
|
||||
|
||||
// Global configuration
|
||||
{
|
||||
plugins: {
|
||||
prettier,
|
||||
},
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
globals: {
|
||||
// Browser globals
|
||||
window: 'readonly',
|
||||
document: 'readonly',
|
||||
navigator: 'readonly',
|
||||
console: 'readonly',
|
||||
localStorage: 'readonly',
|
||||
fetch: 'readonly',
|
||||
alert: 'readonly',
|
||||
prompt: 'readonly',
|
||||
getComputedStyle: 'readonly',
|
||||
// Node globals
|
||||
process: 'readonly',
|
||||
__dirname: 'readonly',
|
||||
__filename: 'readonly',
|
||||
module: 'readonly',
|
||||
require: 'readonly',
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// Prettier integration
|
||||
...configPrettier.rules,
|
||||
'prettier/prettier': 'error',
|
||||
|
||||
// Vue-specific rules
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/no-v-html': 'warn',
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/require-prop-types': 'warn',
|
||||
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
|
||||
'vue/html-self-closing': [
|
||||
'error',
|
||||
{
|
||||
html: {
|
||||
void: 'always',
|
||||
normal: 'always',
|
||||
component: 'always',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
// General JavaScript rules
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'prefer-const': 'error',
|
||||
'no-var': 'error',
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -1,3 +0,0 @@
|
||||
INSTANCES=3
|
||||
DEBUG=false
|
||||
PORT=3000
|
||||
@@ -1,7 +0,0 @@
|
||||
# Vue 3 + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||
@@ -1,13 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>BeamMP</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"name": "beammp-website-frontend",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/vue": "^1.7.16",
|
||||
"@heroicons/vue": "^2.0.18",
|
||||
"@statnett/vue-plotly": "^0.3.2",
|
||||
"axios": "^1.6.2",
|
||||
"plotly.js": "^2.27.1",
|
||||
"plotly.js-dist": "^2.27.1",
|
||||
"plotly.js-dist-min": "^2.27.1",
|
||||
"uuid": "^9.0.1",
|
||||
"vue": "^3.3.8",
|
||||
"vue-router": "^4.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.5.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"postcss": "^8.4.32",
|
||||
"tailwindcss": "^3.3.6",
|
||||
"vite": "^5.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,10 +0,0 @@
|
||||
<script setup>
|
||||
import Navbar from '@/components/NavBar.vue'
|
||||
import Footer from '@/components/Footer.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Navbar />
|
||||
<router-view />
|
||||
<Footer />
|
||||
</template>
|
||||
|
Before Width: | Height: | Size: 4.0 MiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
@@ -1,121 +0,0 @@
|
||||
<template>
|
||||
<div class="bg-gray-800 text-gray-400">
|
||||
<div class="px-4 pt-16 mx-auto md:max-w-full lg:max-w-screen-xl md:px-24 lg:px-8">
|
||||
<div class="grid gap-16 row-gap-10 mb-8 lg:grid-cols-6">
|
||||
<div class="md:max-w-md lg:col-span-2">
|
||||
<a href="/" aria-label="Go home" title="Company" class="inline-flex items-center">
|
||||
<img class="h-8 w-auto" src="../assets/beammp-logo.png" alt="BeamMP Logo" />
|
||||
<span class="ml-4 text-xl font-bold tracking-wide text-gray-200 uppercase">BeamMP</span>
|
||||
</a>
|
||||
<div class="mt-4 lg:max-w-sm">
|
||||
<p class="text-sm text-gray-300">
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.
|
||||
</p>
|
||||
<p class="mt-4 text-sm text-gray-300">
|
||||
Eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-5 row-gap-8 lg:col-span-4 md:grid-cols-4">
|
||||
<div>
|
||||
<p class="font-semibold tracking-wide text-gray-200">Sites</p>
|
||||
<ul class="mt-2 space-y-2">
|
||||
<li>
|
||||
<a href="https://patreon.com/beammp" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Patreon</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://forum.beammp.com/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Forum</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://keymaster.beammp.com/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Keymaster</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://docs.beammp.com/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Docs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://store.beammp.com/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Store</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-semibold tracking-wide text-gray-200">GitHub</p>
|
||||
<ul class="mt-2 space-y-2">
|
||||
<li>
|
||||
<a href="https://github.com/BeamMP/BeamMP" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Mod</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/BeamMP/BeamMP-Launcher" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Launcher</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/BeamMP/BeamMP-Server" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Server</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-semibold tracking-wide text-gray-200">?</p>
|
||||
<ul class="mt-2 space-y-2">
|
||||
<li>
|
||||
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-semibold tracking-wide text-gray-200">Documents</p>
|
||||
<ul class="mt-2 space-y-2">
|
||||
<li>
|
||||
<a href="/rules" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Rules</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/privacy" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Privacy policy</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/terms" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Terms</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col justify-between pt-5 pb-10 border-t sm:flex-row">
|
||||
<p class="text-sm text-gray-300">
|
||||
© Copyright 2024 BeamMP. All rights reserved.
|
||||
</p>
|
||||
<div class="flex items-center mt-4 space-x-4 sm:mt-0">
|
||||
<a href="/" class="text-gray-400 transition-colors duration-300 hover:text-deep-purple-accent-400">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor" class="h-5">
|
||||
<path
|
||||
d="M24 4.6c-0.9 0.4-1.8 0.7-2.8 0.8c1-0.6 1.8-1.6 2.2-2.7c-1 0.6-2 1-3.1 1.2c-0.9-1-2.2-1.6-3.6-1.6 c-2.7 0-4.9 2.2-4.9 4.9c0 0.4 0 0.8 0.1 1.1C7.7 8.1 4.1 6.1 1.7 3.1C1.2 3.9 1 4.7 1 5.6c0 1.7 0.9 3.2 2.2 4.1 C2.4 9.7 1.6 9.5 1 9.1c0 0 0 0 0 0.1c0 2.4 1.7 4.4 3.9 4.8c-0.4 0.1-0.8 0.2-1.3 0.2c-0.3 0-0.6 0-0.9-0.1c0.6 2 2.4 3.4 4.6 3.4 c-1.7 1.3-3.8 2.1-6.1 2.1c-0.4 0-0.8 0-1.2-0.1c2.2 1.4 4.8 2.2 7.5 2.2c9.1 0 14-7.5 14-14c0-0.2 0-0.4 0-0.6 C22.5 6.4 23.3 5.5 24 4.6z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="/" class="text-gray-400 transition-colors duration-300 hover:text-deep-purple-accent-400">
|
||||
<svg viewBox="0 0 30 30" fill="currentColor" class="h-6">
|
||||
<circle cx="15" cy="15" r="4"></circle>
|
||||
<path
|
||||
d="M19.999 3h-10C6.14 3 3 6.141 3 10.001v10C3 23.86 6.141 27 10.001 27h10C23.86 27 27 23.859 27 19.999v-10 C27 6.14 23.859 3 19.999 3z M15 21c-3.309 0-6-2.691-6-6s2.691-6 6-6s6 2.691 6 6S18.309 21 15 21z M22 9c-0.552 0-1-0.448-1-1 c0-0.552 0.448-1 1-1s1 0.448 1 1C23 8.552 22.552 9 22 9z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="/" class="text-gray-400 transition-colors duration-300 hover:text-deep-purple-accent-400">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor" class="h-5">
|
||||
<path
|
||||
d="M22 0H2C0.895 0 0 0.895 0 2v20c0 1.105 0.895 2 2 2h11v-9h-3v-4h3V8.413c0-3.1 1.893-4.788 4.659-4.788 c1.325 0 2.463 0.099 2.795 0.143v3.24l-1.918 0.001c-1.504 0-1.795 0.715-1.795 1.763V11h4.44l-1 4h-3.44v9H22c1.105 0 2-0.895 2-2 V2C24 0.895 23.105 0 22 0z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,133 +0,0 @@
|
||||
<template>
|
||||
<Disclosure as="nav" class="bg-gray-800" v-slot="{ open }">
|
||||
<div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
|
||||
<div class="relative flex h-16 items-center justify-between">
|
||||
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
|
||||
<!-- Mobile menu button-->
|
||||
<DisclosureButton
|
||||
class="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
|
||||
<span class="absolute -inset-0.5" />
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<Bars3Icon v-if="!open" class="block h-6 w-6" aria-hidden="true" />
|
||||
<XMarkIcon v-else class="block h-6 w-6" aria-hidden="true" />
|
||||
</DisclosureButton>
|
||||
</div>
|
||||
<div class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
|
||||
<div class="flex flex-shrink-0 items-center">
|
||||
<a href="/"><img class="h-8 w-auto" src="../assets/beammp-logo.png" alt="BeamMP Logo" /></a>
|
||||
</div>
|
||||
<div class="hidden sm:ml-6 sm:block">
|
||||
<div class="flex space-x-4">
|
||||
<a v-for="item in navigation" :key="item.name" :href="item.href"
|
||||
:class="[item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white', 'rounded-md px-3 py-2 text-sm font-medium']"
|
||||
:aria-current="item.current ? 'page' : undefined">{{ item.name }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mode Switcher Dropdown -->
|
||||
<div class="flex items-center border-l border-slate-200 ml-6 pl-6 dark:border-slate-800">
|
||||
<label class="sr-only" id="headlessui-listbox-label-:Rpkcr6:" data-headlessui-state="">Theme</label>
|
||||
<button type="button" id="headlessui-listbox-button-:R19kcr6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state="" aria-labelledby="headlessui-listbox-label-:Rpkcr6: headlessui-listbox-button-:R19kcr6:" class="">
|
||||
<span class="dark:hidden">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-6 h-6">
|
||||
<path d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" class="stroke-slate-400 dark:stroke-slate-500"></path>
|
||||
<path
|
||||
d="M12 4v1M17.66 6.344l-.828.828M20.005 12.004h-1M17.66 17.664l-.828-.828M12 20.01V19M6.34 17.664l.835-.836M3.995 12.004h1.01M6 6l.835.836"
|
||||
class="stroke-slate-400 dark:stroke-slate-500"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="hidden dark:inline">
|
||||
<svg viewBox="0 0 24 24" fill="none" class="w-6 h-6">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M17.715 15.15A6.5 6.5 0 0 1 9 6.035C6.106 6.922 4 9.645 4 12.867c0 3.94 3.153 7.136 7.042 7.136 3.101 0 5.734-2.032 6.673-4.853Z"
|
||||
class="fill-transparent"></path>
|
||||
<path
|
||||
d="m17.715 15.15.95.316a1 1 0 0 0-1.445-1.185l.495.869ZM9 6.035l.846.534a1 1 0 0 0-1.14-1.49L9 6.035Zm8.221 8.246a5.47 5.47 0 0 1-2.72.718v2a7.47 7.47 0 0 0 3.71-.98l-.99-1.738Zm-2.72.718A5.5 5.5 0 0 1 9 9.5H7a7.5 7.5 0 0 0 7.5 7.5v-2ZM9 9.5c0-1.079.31-2.082.845-2.93L8.153 5.5A7.47 7.47 0 0 0 7 9.5h2Zm-4 3.368C5 10.089 6.815 7.75 9.292 6.99L8.706 5.08C5.397 6.094 3 9.201 3 12.867h2Zm6.042 6.136C7.718 19.003 5 16.268 5 12.867H3c0 4.48 3.588 8.136 8.042 8.136v-2Zm5.725-4.17c-.81 2.433-3.074 4.17-5.725 4.17v2c3.552 0 6.553-2.327 7.622-5.537l-1.897-.632Z"
|
||||
class="fill-slate-400 dark:fill-slate-500"></path>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M17 3a1 1 0 0 1 1 1 2 2 0 0 0 2 2 1 1 0 1 1 0 2 2 2 0 0 0-2 2 1 1 0 1 1-2 0 2 2 0 0 0-2-2 1 1 0 1 1 0-2 2 2 0 0 0 2-2 1 1 0 0 1 1-1Z"
|
||||
class="fill-slate-400 dark:fill-slate-500"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!--<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
|
||||
<button type="button" class="relative rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
|
||||
<span class="absolute -inset-1.5" />
|
||||
<span class="sr-only">View notifications</span>
|
||||
<BellIcon class="h-6 w-6" aria-hidden="true" />
|
||||
</button>-->
|
||||
|
||||
<!-- Profile dropdown - From the Forum Accounts System -->
|
||||
<!--<Menu as="div" class="relative ml-3">
|
||||
<div>
|
||||
<MenuButton class="relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
|
||||
<span class="absolute -inset-1.5" />
|
||||
<span class="sr-only">Open user menu</span>
|
||||
<img class="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
|
||||
</MenuButton>
|
||||
</div>
|
||||
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
|
||||
<MenuItems class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||
<MenuItem v-slot="{ active }">
|
||||
<a href="#" :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">Your Profile</a>
|
||||
</MenuItem>
|
||||
<MenuItem v-slot="{ active }">
|
||||
<a href="#" :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">Settings</a>
|
||||
</MenuItem>
|
||||
<MenuItem v-slot="{ active }">
|
||||
<a href="#" :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">Sign out</a>
|
||||
</MenuItem>
|
||||
</MenuItems>
|
||||
</transition>
|
||||
</Menu>-->
|
||||
<!--</div>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DisclosurePanel class="sm:hidden">
|
||||
<div class="space-y-1 px-2 pb-3 pt-2">
|
||||
<DisclosureButton v-for="item in navigation" :key="item.name" as="a" :href="item.href"
|
||||
:class="[item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white', 'block rounded-md px-3 py-2 text-base font-medium']"
|
||||
:aria-current="item.current ? 'page' : undefined">{{ item.name }}</DisclosureButton>
|
||||
</div>
|
||||
</DisclosurePanel>
|
||||
</Disclosure>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
setTheme(theme) {
|
||||
if (theme === 'light') {
|
||||
document.documentElement.classList.remove('dark');
|
||||
} else if (theme === 'dark') {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else if (theme === 'system') {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
|
||||
import { Bars3Icon, BellIcon, XMarkIcon } from '@heroicons/vue/24/outline'
|
||||
|
||||
const navigation = [
|
||||
{ name: 'Forum', href: 'https://forum.beammp.com/', current: false },
|
||||
{ name: 'Docs', href: 'https://docs.beammp.com/', current: false },
|
||||
{ name: 'Stats', href: '/stats', current: false },
|
||||
{ name: 'Servers', href: '/servers', current: false },
|
||||
{ name: 'Hosting', href: '/hosting', current: false },
|
||||
{ name: 'Events', href: 'https://forum.beammp.com/c/important/events/25', current: false },
|
||||
{ name: 'Store', href: 'https://store.beammp.com/', current: false },
|
||||
{ name: 'GitHub', href: 'https://github.com/BeamMP', current: false },
|
||||
{ name: 'Patreon', href: 'https://patreon.com/BeamMP', current: false },
|
||||
]
|
||||
|
||||
var isOpen = false
|
||||
</script>
|
||||
@@ -1,14 +0,0 @@
|
||||
<template>
|
||||
<div class="bg-white py-24 sm:py-32">
|
||||
<div class="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<h2 class="text-center text-lg font-semibold leading-8 text-gray-900">Used by some of the largest and most innovative BeamNG communities</h2>
|
||||
<div class="mx-auto mt-10 grid max-w-lg grid-cols-4 items-center gap-x-8 gap-y-10 sm:max-w-xl sm:grid-cols-6 sm:gap-x-10 lg:mx-0 lg:max-w-none lg:grid-cols-5">
|
||||
<a href="https://discord.gg/carp"><img class="col-span-2 max-h-10 w-full object-contain lg:col-span-1" src="@/assets/communities/carp-logo.png" alt="CaRP" width="158" height="48" /></a>
|
||||
<a href="https://discord.2fast.racing/"><img class="col-span-2 max-h-12 w-full object-contain lg:col-span-1" src="@/assets/communities/2fast-logo.png" alt="2FastRacing" width="158" height="48" /></a>
|
||||
<a href="https://discord.beamcruise.com"><img class="col-span-2 max-h-12 w-full object-contain lg:col-span-1" src="@/assets/communities/beamcruise-logo.png" alt="Beam\\Cruise" width="158" height="48" /></a>
|
||||
<a href="https://discord.gg/b9G3fXKqpg"><img class="col-span-2 max-h-12 w-full object-contain lg:col-span-1" src="@/assets/communities/nuclear-logo.png" alt="CnR" width="158" height="48" /></a>
|
||||
<img class="col-span-2 col-start-2 max-h-12 w-full object-contain sm:col-start-auto lg:col-span-1" src="@/assets/beammp-logo.png" alt="Community E" width="158" height="48" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,27 +0,0 @@
|
||||
<template>
|
||||
<div class="bg-white">
|
||||
<div class="mx-auto max-w-7xl py-24 sm:px-6 sm:py-32 lg:px-8">
|
||||
<div class="relative isolate overflow-hidden bg-gray-900 px-6 pt-16 shadow-2xl sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0">
|
||||
<svg viewBox="0 0 1024 1024" class="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-y-1/2 [mask-image:radial-gradient(closest-side,white,transparent)] sm:left-full sm:-ml-80 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2 lg:translate-y-0" aria-hidden="true">
|
||||
<circle cx="512" cy="512" r="512" fill="url(#759c1415-0410-454c-8f7c-9a820de03641)" fill-opacity="0.7" />
|
||||
<defs>
|
||||
<radialGradient id="759c1415-0410-454c-8f7c-9a820de03641">
|
||||
<stop stop-color="#7775D6" />
|
||||
<stop offset="1" stop-color="#E935C1" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
<div class="mx-auto max-w-md text-center lg:mx-0 lg:flex-auto lg:py-32 lg:text-left">
|
||||
<h2 class="text-3xl font-bold tracking-tight text-white sm:text-4xl">Looking to write your own mods, plugins or resources?</h2>
|
||||
<p class="mt-6 text-lg leading-8 text-gray-300">Check out our docs to get you started with developing your own mods and resources.</p>
|
||||
<div class="mt-10 flex items-center justify-center gap-x-6 lg:justify-start">
|
||||
<a href="https://docs.beammp.com" class="rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white">Learn more <span aria-hidden="true">→</span></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative mt-16 h-80 lg:mt-8">
|
||||
<img class="absolute left-0 top-0 w-[57rem] max-w-none rounded-md bg-white/5 ring-1 ring-white/10" src="https://tailwindui.com/img/component-images/dark-project-app-screenshot.png" alt="App screenshot" width="1824" height="1080" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,48 +0,0 @@
|
||||
<template>
|
||||
<div class="overflow-hidden bg-white py-24 sm:py-32">
|
||||
<div class="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<div class="mx-auto grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 sm:gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-2">
|
||||
<div class="lg:pr-8 lg:pt-4">
|
||||
<div class="lg:max-w-lg">
|
||||
<h2 class="text-base font-semibold leading-7 text-indigo-600">Integrated Server list</h2>
|
||||
<p class="mt-2 text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">Choose a server to your liking</p>
|
||||
<p class="mt-6 text-lg leading-8 text-gray-600">BeamMP has a builtin server list allowing you to select the server that appeals to your liking the most.</p>
|
||||
<dl class="mt-10 max-w-xl space-y-8 text-base leading-7 text-gray-600 lg:max-w-none">
|
||||
<div v-for="feature in features" :key="feature.name" class="relative pl-9">
|
||||
<dt class="inline font-semibold text-gray-900">
|
||||
<component :is="feature.icon" class="absolute left-1 top-1 h-5 w-5 text-indigo-600" aria-hidden="true" />
|
||||
{{ feature.name }}
|
||||
</dt>
|
||||
{{ ' ' }}
|
||||
<dd class="inline">{{ feature.description }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<img src="@/assets/beammp-servers.png" alt="Product screenshot" class="w-[48rem] max-w-none rounded-xl shadow-xl ring-1 ring-gray-400/10 sm:w-[57rem] md:-ml-4 lg:-ml-0" width="2432" height="1442" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { CloudArrowUpIcon, LockClosedIcon, ServerIcon } from '@heroicons/vue/20/solid'
|
||||
|
||||
const features = [
|
||||
{
|
||||
name: 'Custom mods',
|
||||
description: 'BeamMP includes resource sharing functionality so that you can share your favorite mods with your friends directly from the same server. This applies with each and every server too!',
|
||||
icon: CloudArrowUpIcon,
|
||||
},
|
||||
{
|
||||
name: 'Public & Private Servers',
|
||||
description: 'You have full control over your server including if you want it public for others to join or not.',
|
||||
icon: LockClosedIcon,
|
||||
},
|
||||
{
|
||||
name: 'Self and Paid Hosting',
|
||||
description: 'You are free to host your own server or check out one of our parters who can have you up and running in minutes.',
|
||||
icon: ServerIcon,
|
||||
},
|
||||
]
|
||||
</script>
|
||||
@@ -1,48 +0,0 @@
|
||||
<template>
|
||||
<div class="overflow-hidden bg-white py-24 sm:py-32">
|
||||
<div class="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<div class="mx-auto grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 sm:gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-2">
|
||||
<div class="lg:pr-8 lg:pt-4">
|
||||
<div class="lg:max-w-lg">
|
||||
<h2 class="text-base font-semibold leading-7 text-indigo-600">Integrated Server list</h2>
|
||||
<p class="mt-2 text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">Choose a server to your liking</p>
|
||||
<p class="mt-6 text-lg leading-8 text-gray-600">BeamMP has a builtin server list allowing you to select the server that appeals to your liking the most.</p>
|
||||
<dl class="mt-10 max-w-xl space-y-8 text-base leading-7 text-gray-600 lg:max-w-none">
|
||||
<div v-for="feature in features" :key="feature.name" class="relative pl-9">
|
||||
<dt class="inline font-semibold text-gray-900">
|
||||
<component :is="feature.icon" class="absolute left-1 top-1 h-5 w-5 text-indigo-600" aria-hidden="true" />
|
||||
{{ feature.name }}
|
||||
</dt>
|
||||
{{ ' ' }}
|
||||
<dd class="inline">{{ feature.description }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<img src="@/assets/beammp-servers.png" alt="Product screenshot" class="w-[48rem] max-w-none rounded-xl shadow-xl ring-1 ring-gray-400/10 sm:w-[57rem] md:-ml-4 lg:-ml-0" width="2432" height="1442" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { CloudArrowUpIcon, LockClosedIcon, ServerIcon } from '@heroicons/vue/20/solid'
|
||||
|
||||
const features = [
|
||||
{
|
||||
name: 'Custom mods',
|
||||
description: 'BeamMP includes resource sharing functionality so that you can share your favorite mods with your friends directly from the same server. This applies with each and every server too!',
|
||||
icon: CloudArrowUpIcon,
|
||||
},
|
||||
{
|
||||
name: 'Public & Private Servers',
|
||||
description: 'You have full control over your server including if you want it public for others to join or not.',
|
||||
icon: LockClosedIcon,
|
||||
},
|
||||
{
|
||||
name: 'Self and Paid Hosting',
|
||||
description: 'You are free to host your own server or check out one of our parters who can have you up and running in minutes.',
|
||||
icon: ServerIcon,
|
||||
},
|
||||
]
|
||||
</script>
|
||||
@@ -1,58 +0,0 @@
|
||||
<template>
|
||||
<header class="main-content" :style="{ 'background-position': 'center center, center 0px' }">
|
||||
<div class="introduction" style="margin-top: 0px;">
|
||||
<div class="container mx-auto">
|
||||
<div class="flex items-center justify-center">
|
||||
<div class="lg:w-8/12 md:w-8/12 sm:w-8/12 xs:w-full">
|
||||
<p class="lead">
|
||||
<b>BeamMP</b> Bringing Multiplayer to BeamNG.drive!<br>
|
||||
With a smooth and enjoyable experience.
|
||||
</p>
|
||||
</div>
|
||||
<div id="button" class="lg:w-4/12 md:w-4/12 sm:w-4/12 xs:w-full hidden-xs buttons-wrapper">
|
||||
<div class="buttons mt-3">
|
||||
<button @click="downloadInstaller" class="download-client js-show-story" href="beamMP.zip" download="">
|
||||
<img class="os-icon" src="https://raw.githubusercontent.com/devicons/devicon/master/icons/windows8/windows8-original.svg" alt="windows-logo">
|
||||
<span class="text">Download Client</span>
|
||||
<span class="description"> BeamMP_Installer.zip</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="buttons mt-3">
|
||||
<form action="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.exe">
|
||||
<button class="download-client js-show-story" style="background: radial-gradient(circle,rgb(255 179 38 / 80%),rgb(255 176 0 / 65%)) center/100%;">
|
||||
<img class="os-icon" src="https://raw.githubusercontent.com/devicons/devicon/master/icons/windows8/windows8-original.svg" alt="windows-logo">
|
||||
<span class="text">Download Server</span>
|
||||
<span class="description"> BeamMP-Server.exe</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="buttons mt-3">
|
||||
<form action="https://github.com/BeamMP/BeamMP-Server/releases/latest">
|
||||
<button class="download-client js-show-story" style="background: radial-gradient(circle,rgb(255 179 38 / 80%),rgb(255 176 0 / 65%)) center/100%;">
|
||||
<img class="os-icon" src="https://raw.githubusercontent.com/devicons/devicon/master/icons/linux/linux-plain.svg" alt="linux-logo">
|
||||
<span class="text">Download Server</span>
|
||||
<span class="description">Linux builds</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
downloadInstaller() {
|
||||
// Implement your download logic here
|
||||
// You can use the window.location.href or any other method
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Add your Tailwind CSS styles here */
|
||||
</style>
|
||||
@@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<div class="bg-white py-24 sm:py-32">
|
||||
<div class="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<h2 class="text-center text-lg font-semibold leading-8 text-gray-900">Proudly partnered with trusted hosting companies</h2>
|
||||
<div v-for="partner in partners" :key="partner.id" class="mx-auto mt-10 grid max-w-lg grid-cols-4 items-center gap-x-8 gap-y-10 sm:max-w-xl sm:grid-cols-6 sm:gap-x-10 lg:mx-0 lg:max-w-none lg:grid-cols-5">
|
||||
<a :href="partner.link"><img class="col-span-2 max-h-12 w-full object-contain lg:col-span-1" :src="partner.logo" :alt="partner.alt" width="158" height="48" /></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const partners = [
|
||||
{ id: 1, logo: 'src/assets/partners/horizon_hosting-logo.png', alt: 'Horizon Hosting', link: 'https://billing.horizonnetworks.uk/store/beammp-server-hosting' },
|
||||
]
|
||||
</script>
|
||||
@@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<div class="bg-white dark:bg-slate-800 py-24 sm:py-32">
|
||||
<div class="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<dl class="grid grid-cols-1 gap-x-8 gap-y-16 text-center lg:grid-cols-4">
|
||||
<div v-for="stat in stats" :key="stat.id" class="mx-auto flex max-w-xs flex-col gap-y-4">
|
||||
<a :href="stat.link"><dt class="text-base leading-7 text-gray-600 dark:text-white">{{ stat.name }}</dt></a>
|
||||
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900 sm:text-5xl dark:text-slate-400">{{ stat.value }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const stats = [
|
||||
{ id: 1, name: 'Players Online', value: '1500', link: '/stats' },
|
||||
{ id: 2, name: 'Public Servers', value: '1200', link: '/stats' },
|
||||
{ id: 3, name: 'Users', value: '+760,000', link: 'https://forum.beammp.com' },
|
||||
{ id: 4, name: 'Discord Members', value: '+190,000', link: 'https://discord.com/servers/beammp-601558901657305098' },
|
||||
]
|
||||
</script>
|
||||
@@ -1,169 +0,0 @@
|
||||
<template>
|
||||
<div class="expanded-row-details">
|
||||
<h1 style="padding-left:10px;display:flex;">
|
||||
<template v-if="rowData.raw.official">
|
||||
<img src="/src/assets/beammp-logo.png" alt="" style="height: 23px; padding-right: 10px;"> [Official Server]
|
||||
</template>
|
||||
<template v-else>
|
||||
<img src="/src/assets/beammp-logo.png" alt="" style="height: 23px; padding-right: 10px;">
|
||||
</template>
|
||||
<span v-for="(value, name) in rowData.name" :style="value.f">{{ value.s }}</span>
|
||||
</h1>
|
||||
<div class="columns-2">
|
||||
<div>
|
||||
<h2 class="text-xl">Information:</h2>
|
||||
<hr/>
|
||||
<table class="description-table">
|
||||
<tr>
|
||||
<td>Owner:</td>
|
||||
<td>{{rowData.raw.owner|| ""}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Map:</td>
|
||||
<td>{{rowData.map || ""}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="text-xl">Description:</h2>
|
||||
<hr/>
|
||||
<p><span v-for="(value, name) in formatDescriptionName(rowData.raw.sdesc)" :style="value.f">{{ value.s }}</span></p>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-xl">Mods ({{modCount(rowData.raw.modlist|| "")}}):</h2>
|
||||
<hr/>
|
||||
<p>{{modList(rowData.raw.modlist|| "")}} ({{formatBytes(rowData.raw.modstotalsize) || "0B"}})</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h1 class="text-xl">Players ({{rowData.players|| "0"}}):</h1>
|
||||
<hr/>
|
||||
<p>{{listPlayers(rowData.raw.playerslist|| "")}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
var descStyleMap = {
|
||||
'^0': 'color:#000000',
|
||||
'^1': 'color:#0000AA',
|
||||
'^2': 'color:#00AA00',
|
||||
'^3': 'color:#00AAAA',
|
||||
'^4': 'color:#AA0000',
|
||||
'^5': 'color:#AA00AA',
|
||||
'^6': 'color:#FFAA00',
|
||||
'^7': 'color:#AAAAAA',
|
||||
'^8': 'color:#555555',
|
||||
'^9': 'color:#5555FF',
|
||||
'^a': 'color:#55FF55',
|
||||
'^b': 'color:#55FFFF',
|
||||
'^c': 'color:#FF5555',
|
||||
'^d': 'color:#FF55FF',
|
||||
'^e': 'color:#FFFF55',
|
||||
'^f': 'color:#FFFFFF',
|
||||
'^l': 'font-weight:bold',
|
||||
'^m': 'text-decoration:line-through',
|
||||
'^n': 'text-decoration:underline',
|
||||
'^o': 'font-style:italic',
|
||||
};
|
||||
export default {
|
||||
props: {
|
||||
rowData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
modCount(s) {
|
||||
if(s.length==0) return 0;
|
||||
return s.split(";").length-1;
|
||||
},
|
||||
modList(s) {
|
||||
var modarray = s.split(';');
|
||||
//console.log(modarray);
|
||||
s = "";
|
||||
|
||||
for (var i=0; i<modarray.length-1; i++){
|
||||
var modName = modarray[i].split('/').pop();
|
||||
modName = modName.replace(".zip","");
|
||||
s += modName;
|
||||
//if (i<modarray.length-2)
|
||||
s += ", ";
|
||||
}
|
||||
//console.log(s);
|
||||
s = s.substring(0, s.length -2);
|
||||
return s
|
||||
},
|
||||
formatBytes(bytes = 0, decimals = 2) {
|
||||
if (bytes == 0 || bytes == undefined) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||
},
|
||||
listPlayers(s) {
|
||||
if (s != undefined || s != "") {
|
||||
var re = new RegExp(";", 'g');
|
||||
s = s.replace(re, ', ');
|
||||
s = s.substring(0, s.length -2);
|
||||
return s
|
||||
} else {
|
||||
return "No players..."
|
||||
}
|
||||
},
|
||||
applyCode(string, codes) {
|
||||
var cssText = ''
|
||||
string = string.replace(/\x00*/g, '');
|
||||
for (var i = 0, len = codes.length; i < len; i++) {
|
||||
cssText += styleMap[codes[i]] + ';';
|
||||
}
|
||||
return {s: string, f:cssText};
|
||||
},
|
||||
formatDescriptionName(string) {
|
||||
var codes = string.match(/\^.{1}/g) || [],
|
||||
indexes = [],
|
||||
apply = [],
|
||||
tmpStr,
|
||||
name = [],
|
||||
i,
|
||||
len;
|
||||
for (i = 0, len = codes.length; i < len; i++) {
|
||||
indexes.push(string.indexOf(codes[i]));
|
||||
string = string.replace(codes[i], '\x00\x00');
|
||||
}
|
||||
if (indexes[0] !== 0) {
|
||||
name.push(this.applyCode(string.substring(0, indexes[0]), []))
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
var indexDelta = indexes[i + 1] - indexes[i];
|
||||
if (indexDelta === 2) {
|
||||
while (indexDelta === 2) {
|
||||
apply.push(codes[i]);
|
||||
i++;
|
||||
indexDelta = indexes[i + 1] - indexes[i];
|
||||
}
|
||||
apply.push(codes[i]);
|
||||
} else {
|
||||
apply.push(codes[i]);
|
||||
}
|
||||
if (apply.lastIndexOf('^r') > -1) {
|
||||
apply = apply.slice(apply.lastIndexOf('^r') + 1);
|
||||
}
|
||||
tmpStr = string.substring(indexes[i], indexes[i + 1]);
|
||||
name.push(this.applyCode(tmpStr, apply))
|
||||
}
|
||||
return name
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>/* Add styles for the expanded row details */
|
||||
.expanded-row-details {
|
||||
padding: 10px;
|
||||
background-color: #f5f5f5;
|
||||
}</style>
|
||||
@@ -1,84 +0,0 @@
|
||||
<template>
|
||||
<div class="table-container">
|
||||
<table class="min-w-full divide-y divide-gray-400">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="column in columns" :key="column.key" class="px-6 py-3 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
||||
{{ column.label }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="item in data" :key="item.id">
|
||||
<tr @click="selectRow(item.id)" class="servers-table-row">
|
||||
<td v-for="column in columns" :key="column.key" class="px-6 py-1 whitespace-no-wrap text-sm leading-5 text-gray-600" :style="item.style" >
|
||||
<template v-if="column.key == 'location'">
|
||||
<span style="display:flex;width: 125px;">
|
||||
<img :src="`/src/assets/flags/${item.cc}.png`" alt="" style="padding-right: 10px;">
|
||||
<span style="position: absolute;left: 105px;">{{ item[column.key] }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<template v-else-if="column.key == 'name'">
|
||||
<span v-for="(value, name) in item[column.key]" :style="value.f">{{ value.s }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item[column.key] }}
|
||||
</template>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="selectedRow == item.id">
|
||||
<td :colspan="columns.length">
|
||||
<ExpandedRowDetails :rowData="getExpandedRowData(item)" />
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ExpandedRowDetails from "@/components/servers/ExpandedRowDetails.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ExpandedRowDetails,
|
||||
},
|
||||
props: {
|
||||
columns: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedRow: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
selectRow(id) {
|
||||
if (this.selectedRow === id) {
|
||||
this.selectedRow = null;
|
||||
} else {
|
||||
this.selectedRow = id;
|
||||
}
|
||||
},
|
||||
getExpandedRowData(item) {
|
||||
return item || {}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.table-container {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.servers-table-row:hover {
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
</style>
|
||||
@@ -1,82 +0,0 @@
|
||||
<!-- https://github.com/VanOord/vue3-plotly/pull/10/files -->
|
||||
<template>
|
||||
<div :id="plotlyId"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let Plotly;
|
||||
import events from "./events.js";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
let timeOutFunctionId;
|
||||
|
||||
export default {
|
||||
name: 'VuePlotly',
|
||||
|
||||
data() {
|
||||
return {
|
||||
plotlyId: `plotly-${uuidv4()}`,
|
||||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
'data' : {
|
||||
type : Array,
|
||||
required:false,
|
||||
},
|
||||
'layout': {
|
||||
type : Object,
|
||||
required:false,
|
||||
},
|
||||
'config':{
|
||||
type : Object,
|
||||
required:false,
|
||||
},
|
||||
'bundle':{
|
||||
type : String,
|
||||
default : "full",
|
||||
required:false
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
data() { this.setGraph(); },
|
||||
layout() { this.setGraph(); },
|
||||
config() { this.setGraph(); },
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
switch(this.bundle){
|
||||
//case "basic" : Plotly = await import("plotly.js-basic-dist-min"); break;
|
||||
//case "cartesian" : Plotly = await import("plotly.js-cartesian-dist-min"); break;
|
||||
//case "geo" : Plotly = await import("plotly.js-geo-dist-min"); break;
|
||||
//case "gl3d" : Plotly = await import("plotly.js-gl3d-dist-min"); break;
|
||||
//case "gl2d" : Plotly = await import("plotly.js-gl2d-dist-min"); break;
|
||||
//case "mapbox" : Plotly = await import("plotly.js-mapbox-dist-min"); break;
|
||||
//case "finance" : Plotly = await import("plotly.js-finance-dist-min"); break;
|
||||
//case "strict" : Plotly = await import("plotly.js-strict-dist-min"); break;
|
||||
default : Plotly = await import("plotly.js-dist");
|
||||
}
|
||||
this.setGraph();
|
||||
events.forEach(evt => {
|
||||
this.$el.on(evt.completeName, evt.handler(this));
|
||||
});
|
||||
this.resizeObserver = new ResizeObserver(() => {
|
||||
clearTimeout(timeOutFunctionId); // debounce the reset
|
||||
timeOutFunctionId = setTimeout(this.setGraph, 100);
|
||||
});
|
||||
this.resizeObserver.observe(document.getElementById(this.plotlyId));
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
events.forEach(event => this.$el.removeAllListeners(event.completeName));
|
||||
this.resizeObserver.disconnect();
|
||||
},
|
||||
|
||||
methods: {
|
||||
setGraph() {
|
||||
Plotly.newPlot(this.plotlyId, this.data, this.layout, this.config);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,40 +0,0 @@
|
||||
const eventsName = [
|
||||
"AfterExport",
|
||||
"AfterPlot",
|
||||
"Animated",
|
||||
"AnimatingFrame",
|
||||
"AnimationInterrupted",
|
||||
"AutoSize",
|
||||
"BeforeExport",
|
||||
"ButtonClicked",
|
||||
"Click",
|
||||
"ClickAnnotation",
|
||||
"Deselect",
|
||||
"DoubleClick",
|
||||
"Framework",
|
||||
"Hover",
|
||||
"LegendClick",
|
||||
"LegendDoubleClick",
|
||||
"Relayout",
|
||||
"Restyle",
|
||||
"Redraw",
|
||||
"Selected",
|
||||
"Selecting",
|
||||
"SliderChange",
|
||||
"SliderEnd",
|
||||
"SliderStart",
|
||||
"Transitioning",
|
||||
"TransitionInterrupted",
|
||||
"Unhover"
|
||||
];
|
||||
|
||||
const events = eventsName
|
||||
.map(evt => evt.toLocaleLowerCase())
|
||||
.map(eventName => ({
|
||||
completeName: "plotly_" + eventName,
|
||||
handler: context => (...args) => {
|
||||
context.$emit.apply(context, [eventName, ...args]);
|
||||
}
|
||||
}));
|
||||
|
||||
export default events;
|
||||
@@ -1,6 +0,0 @@
|
||||
import { createApp } from 'vue'
|
||||
import './style.css'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
createApp(App).use(router).mount('#app')
|
||||
@@ -1,36 +0,0 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import Home from '@/views/Home.vue'
|
||||
|
||||
export default createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
component: Home,
|
||||
},
|
||||
{
|
||||
path: '/stats',
|
||||
component: () => import('@/views/Stats.vue'),
|
||||
},
|
||||
{
|
||||
path: '/servers',
|
||||
component: () => import('@/views/Servers.vue'),
|
||||
},
|
||||
{
|
||||
path: '/hosting',
|
||||
component: () => import('@/views/Hosting.vue'),
|
||||
},
|
||||
{
|
||||
path: '/rules',
|
||||
component: () => import('@/views/Rules.vue'),
|
||||
},
|
||||
{
|
||||
path: '/privacy',
|
||||
component: () => import('@/views/Privacy.vue'),
|
||||
},
|
||||
{
|
||||
path: '/terms',
|
||||
component: () => import('@/views/Terms.vue'),
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -1,118 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
.main-content {
|
||||
display: flex;
|
||||
position: relative;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: calc(100vh - 80px);
|
||||
overflow: hidden;
|
||||
background: linear-gradient(-45deg, rgba(22, 25, 35, 0.35) 0%, rgba(22, 25, 35, 0.95) 100%) center center/100%, url(./assets/beamng-mp-landing.png) center top/cover;
|
||||
color: #fefee1;
|
||||
}
|
||||
|
||||
.main-content .introduction {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
transition: transform .2s ease;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.main-content .lead {
|
||||
font-size: 30px;
|
||||
font-weight: 300;
|
||||
font-family: verdana;
|
||||
}
|
||||
|
||||
.middle-xs {
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.center-xs {
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-content .buttons-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
align-content: flex-end;
|
||||
}
|
||||
|
||||
.main-content .buttons-wrapper .buttons .download-client {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: 15px 25px 15px 25px;
|
||||
cursor: pointer;
|
||||
color: #fefee1;
|
||||
border: none;
|
||||
text-shadow: 0 0 1px rgba(22, 25, 35, 0.5);
|
||||
background: radial-gradient(circle, rgba(150, 204, 0, 0.8), rgba(150, 204, 0, 0.65)) center/100%;
|
||||
transition: box-shadow .2s ease;
|
||||
font-size: 27px;
|
||||
font-weight: 300;
|
||||
line-height: 1;
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
min-width: 297px;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.description {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
font-weight: 200;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
div.buttons {
|
||||
min-width: 297px;
|
||||
}
|
||||
|
||||
div.buttons.mt-3 {
|
||||
min-width: 297px;
|
||||
}
|
||||
|
||||
img.os-icon {
|
||||
width: 32px !important;
|
||||
height: 32px !important;
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
#button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo-link {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<script setup>
|
||||
import Hero from '@/components/home/Hero.vue'
|
||||
import Stats from '@/components/home/Stats.vue'
|
||||
import Communities from '@/components/home/Communities.vue'
|
||||
import Partners from '@/components/home/Partners.vue'
|
||||
import Featured2 from '@/components/home/Featured2.vue'
|
||||
|
||||
import Docs from '@/components/home/Docs.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Hero />
|
||||
<Stats />
|
||||
<Communities />
|
||||
<Featured2 />
|
||||
<Partners />
|
||||
<!-- Coders Portion -->
|
||||
<Docs />
|
||||
</template>
|
||||
@@ -1,3 +0,0 @@
|
||||
<template>
|
||||
<h1>BeamMP Privacy Policy</h1>
|
||||
</template>
|
||||
@@ -1,3 +0,0 @@
|
||||
<template>
|
||||
<h1>BeamMP Privacy Policy</h1>
|
||||
</template>
|
||||
@@ -1,3 +0,0 @@
|
||||
<template>
|
||||
<h1>BeamMP Rules</h1>
|
||||
</template>
|
||||
@@ -1,440 +0,0 @@
|
||||
<script setup>
|
||||
import Table from '@/components/servers/Table.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="app" class="p-8">
|
||||
<Table :columns="columns" :data="tableData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
var styleMap = {
|
||||
'^0': 'color:#000000',
|
||||
'^1': 'color:#0000AA',
|
||||
'^2': 'color:#00AA00',
|
||||
'^3': 'color:#00AAAA',
|
||||
'^4': 'color:#AA0000',
|
||||
'^5': 'color:#AA00AA',
|
||||
'^6': 'color:#FFAA00',
|
||||
'^7': 'color:#AAAAAA',
|
||||
'^8': 'color:#555555',
|
||||
'^9': 'color:#5555FF',
|
||||
'^a': 'color:#55FF55',
|
||||
'^b': 'color:#55FFFF',
|
||||
'^c': 'color:#FF5555',
|
||||
'^d': 'color:#FF55FF',
|
||||
'^e': 'color:#FFFF55',
|
||||
'^f': 'color:#FFFFFF',
|
||||
'^l': 'font-weight:bold',
|
||||
'^m': 'text-decoration:line-through',
|
||||
'^n': 'text-decoration:underline',
|
||||
'^o': 'font-style:italic',
|
||||
};
|
||||
|
||||
const isoCountries = {
|
||||
'AF': 'Afghanistan',
|
||||
'AX': 'Aland Islands',
|
||||
'AL': 'Albania',
|
||||
'DZ': 'Algeria',
|
||||
'AS': 'American Samoa',
|
||||
'AD': 'Andorra',
|
||||
'AO': 'Angola',
|
||||
'AI': 'Anguilla',
|
||||
'AQ': 'Antarctica',
|
||||
'AG': 'Antigua And Barbuda',
|
||||
'AR': 'Argentina',
|
||||
'AM': 'Armenia',
|
||||
'AW': 'Aruba',
|
||||
'AU': 'Australia',
|
||||
'AT': 'Austria',
|
||||
'AZ': 'Azerbaijan',
|
||||
'BS': 'Bahamas',
|
||||
'BH': 'Bahrain',
|
||||
'BD': 'Bangladesh',
|
||||
'BB': 'Barbados',
|
||||
'BY': 'Belarus',
|
||||
'BE': 'Belgium',
|
||||
'BZ': 'Belize',
|
||||
'BJ': 'Benin',
|
||||
'BM': 'Bermuda',
|
||||
'BT': 'Bhutan',
|
||||
'BO': 'Bolivia',
|
||||
'BA': 'Bosnia And Herzegovina',
|
||||
'BW': 'Botswana',
|
||||
'BV': 'Bouvet Island',
|
||||
'BR': 'Brazil',
|
||||
'IO': 'British Indian Ocean Territory',
|
||||
'BN': 'Brunei Darussalam',
|
||||
'BG': 'Bulgaria',
|
||||
'BF': 'Burkina Faso',
|
||||
'BI': 'Burundi',
|
||||
'KH': 'Cambodia',
|
||||
'CM': 'Cameroon',
|
||||
'CA': 'Canada',
|
||||
'CV': 'Cape Verde',
|
||||
'KY': 'Cayman Islands',
|
||||
'CF': 'Central African Republic',
|
||||
'TD': 'Chad',
|
||||
'CL': 'Chile',
|
||||
'CN': 'China',
|
||||
'CX': 'Christmas Island',
|
||||
'CC': 'Cocos (Keeling) Islands',
|
||||
'CO': 'Colombia',
|
||||
'KM': 'Comoros',
|
||||
'CG': 'Congo',
|
||||
'CD': 'Congo, Democratic Republic',
|
||||
'CK': 'Cook Islands',
|
||||
'CR': 'Costa Rica',
|
||||
'CI': 'Cote D\'Ivoire',
|
||||
'HR': 'Croatia',
|
||||
'CU': 'Cuba',
|
||||
'CY': 'Cyprus',
|
||||
'CZ': 'Czech Republic',
|
||||
'DK': 'Denmark',
|
||||
'DJ': 'Djibouti',
|
||||
'DM': 'Dominica',
|
||||
'DO': 'Dominican Republic',
|
||||
'EC': 'Ecuador',
|
||||
'EG': 'Egypt',
|
||||
'SV': 'El Salvador',
|
||||
'GQ': 'Equatorial Guinea',
|
||||
'ER': 'Eritrea',
|
||||
'EE': 'Estonia',
|
||||
'ET': 'Ethiopia',
|
||||
'FK': 'Falkland Islands (Malvinas)',
|
||||
'FO': 'Faroe Islands',
|
||||
'FJ': 'Fiji',
|
||||
'FI': 'Finland',
|
||||
'FR': 'France',
|
||||
'GF': 'French Guiana',
|
||||
'PF': 'French Polynesia',
|
||||
'TF': 'French Southern Territories',
|
||||
'GA': 'Gabon',
|
||||
'GM': 'Gambia',
|
||||
'GE': 'Georgia',
|
||||
'DE': 'Germany',
|
||||
'GH': 'Ghana',
|
||||
'GI': 'Gibraltar',
|
||||
'GR': 'Greece',
|
||||
'GL': 'Greenland',
|
||||
'GD': 'Grenada',
|
||||
'GP': 'Guadeloupe',
|
||||
'GU': 'Guam',
|
||||
'GT': 'Guatemala',
|
||||
'GG': 'Guernsey',
|
||||
'GN': 'Guinea',
|
||||
'GW': 'Guinea-Bissau',
|
||||
'GY': 'Guyana',
|
||||
'HT': 'Haiti',
|
||||
'HM': 'Heard Island & Mcdonald Islands',
|
||||
'VA': 'Holy See (Vatican City State)',
|
||||
'HN': 'Honduras',
|
||||
'HK': 'Hong Kong',
|
||||
'HU': 'Hungary',
|
||||
'IS': 'Iceland',
|
||||
'IN': 'India',
|
||||
'ID': 'Indonesia',
|
||||
'IR': 'Iran, Islamic Republic Of',
|
||||
'IQ': 'Iraq',
|
||||
'IE': 'Ireland',
|
||||
'IM': 'Isle Of Man',
|
||||
'IL': 'Israel',
|
||||
'IT': 'Italy',
|
||||
'JM': 'Jamaica',
|
||||
'JP': 'Japan',
|
||||
'JE': 'Jersey',
|
||||
'JO': 'Jordan',
|
||||
'KZ': 'Kazakhstan',
|
||||
'KE': 'Kenya',
|
||||
'KI': 'Kiribati',
|
||||
'KR': 'Korea',
|
||||
'KW': 'Kuwait',
|
||||
'KG': 'Kyrgyzstan',
|
||||
'LA': 'Lao People\'s Democratic Republic',
|
||||
'LV': 'Latvia',
|
||||
'LB': 'Lebanon',
|
||||
'LS': 'Lesotho',
|
||||
'LR': 'Liberia',
|
||||
'LY': 'Libyan Arab Jamahiriya',
|
||||
'LI': 'Liechtenstein',
|
||||
'LT': 'Lithuania',
|
||||
'LU': 'Luxembourg',
|
||||
'MO': 'Macao',
|
||||
'MK': 'Macedonia',
|
||||
'MG': 'Madagascar',
|
||||
'MW': 'Malawi',
|
||||
'MY': 'Malaysia',
|
||||
'MV': 'Maldives',
|
||||
'ML': 'Mali',
|
||||
'MT': 'Malta',
|
||||
'MH': 'Marshall Islands',
|
||||
'MQ': 'Martinique',
|
||||
'MR': 'Mauritania',
|
||||
'MU': 'Mauritius',
|
||||
'YT': 'Mayotte',
|
||||
'MX': 'Mexico',
|
||||
'FM': 'Micronesia, Federated States Of',
|
||||
'MD': 'Moldova',
|
||||
'MC': 'Monaco',
|
||||
'MN': 'Mongolia',
|
||||
'ME': 'Montenegro',
|
||||
'MS': 'Montserrat',
|
||||
'MA': 'Morocco',
|
||||
'MZ': 'Mozambique',
|
||||
'MM': 'Myanmar',
|
||||
'NA': 'Namibia',
|
||||
'NR': 'Nauru',
|
||||
'NP': 'Nepal',
|
||||
'NL': 'Netherlands',
|
||||
'AN': 'Netherlands Antilles',
|
||||
'NC': 'New Caledonia',
|
||||
'NZ': 'New Zealand',
|
||||
'NI': 'Nicaragua',
|
||||
'NE': 'Niger',
|
||||
'NG': 'Nigeria',
|
||||
'NU': 'Niue',
|
||||
'NF': 'Norfolk Island',
|
||||
'MP': 'Northern Mariana Islands',
|
||||
'NO': 'Norway',
|
||||
'OM': 'Oman',
|
||||
'PK': 'Pakistan',
|
||||
'PW': 'Palau',
|
||||
'PS': 'Palestinian Territory, Occupied',
|
||||
'PA': 'Panama',
|
||||
'PG': 'Papua New Guinea',
|
||||
'PY': 'Paraguay',
|
||||
'PE': 'Peru',
|
||||
'PH': 'Philippines',
|
||||
'PN': 'Pitcairn',
|
||||
'PL': 'Poland',
|
||||
'PT': 'Portugal',
|
||||
'PR': 'Puerto Rico',
|
||||
'QA': 'Qatar',
|
||||
'RE': 'Reunion',
|
||||
'RO': 'Romania',
|
||||
'RU': 'Russian Federation',
|
||||
'RW': 'Rwanda',
|
||||
'BL': 'Saint Barthelemy',
|
||||
'SH': 'Saint Helena',
|
||||
'KN': 'Saint Kitts And Nevis',
|
||||
'LC': 'Saint Lucia',
|
||||
'MF': 'Saint Martin',
|
||||
'PM': 'Saint Pierre And Miquelon',
|
||||
'VC': 'Saint Vincent And Grenadines',
|
||||
'WS': 'Samoa',
|
||||
'SM': 'San Marino',
|
||||
'ST': 'Sao Tome And Principe',
|
||||
'SA': 'Saudi Arabia',
|
||||
'SN': 'Senegal',
|
||||
'RS': 'Serbia',
|
||||
'SC': 'Seychelles',
|
||||
'SL': 'Sierra Leone',
|
||||
'SG': 'Singapore',
|
||||
'SK': 'Slovakia',
|
||||
'SI': 'Slovenia',
|
||||
'SB': 'Solomon Islands',
|
||||
'SO': 'Somalia',
|
||||
'ZA': 'South Africa',
|
||||
'GS': 'South Georgia And Sandwich Isl.',
|
||||
'ES': 'Spain',
|
||||
'LK': 'Sri Lanka',
|
||||
'SD': 'Sudan',
|
||||
'SR': 'Suriname',
|
||||
'SJ': 'Svalbard And Jan Mayen',
|
||||
'SZ': 'Swaziland',
|
||||
'SE': 'Sweden',
|
||||
'CH': 'Switzerland',
|
||||
'SY': 'Syrian Arab Republic',
|
||||
'TW': 'Taiwan',
|
||||
'TJ': 'Tajikistan',
|
||||
'TZ': 'Tanzania',
|
||||
'TH': 'Thailand',
|
||||
'TL': 'Timor-Leste',
|
||||
'TG': 'Togo',
|
||||
'TK': 'Tokelau',
|
||||
'TO': 'Tonga',
|
||||
'TT': 'Trinidad And Tobago',
|
||||
'TN': 'Tunisia',
|
||||
'TR': 'Turkey',
|
||||
'TM': 'Turkmenistan',
|
||||
'TC': 'Turks And Caicos Islands',
|
||||
'TV': 'Tuvalu',
|
||||
'UG': 'Uganda',
|
||||
'UA': 'Ukraine',
|
||||
'AE': 'United Arab Emirates',
|
||||
'GB': 'United Kingdom',
|
||||
'US': 'United States',
|
||||
'UM': 'United States Outlying Islands',
|
||||
'UY': 'Uruguay',
|
||||
'UZ': 'Uzbekistan',
|
||||
'VU': 'Vanuatu',
|
||||
'VE': 'Venezuela',
|
||||
'VN': 'Viet Nam',
|
||||
'VG': 'Virgin Islands, British',
|
||||
'VI': 'Virgin Islands, U.S.',
|
||||
'WF': 'Wallis And Futuna',
|
||||
'EH': 'Western Sahara',
|
||||
'YE': 'Yemen',
|
||||
'ZM': 'Zambia',
|
||||
'ZW': 'Zimbabwe'
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Table,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
columns: [
|
||||
{ key: "location", label: "Location" },
|
||||
{ key: "name", label: "Name" },
|
||||
{ key: "map", label: "Map" },
|
||||
{ key: "players", label: "Players" },
|
||||
],
|
||||
tableData: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
axios
|
||||
.get(`https://backend.beammp.com/servers-info`)
|
||||
.then(res => {
|
||||
var servers = []
|
||||
var data = res.data;
|
||||
var i = 0
|
||||
|
||||
var serversArray = new Array();
|
||||
// Parse the data to a nice looking Array
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var v = data[i]
|
||||
v.strippedName = this.stripCustomFormatting(v.sname);
|
||||
serversArray.push(v);
|
||||
}
|
||||
// Sort the servers to display official servers first
|
||||
serversArray.sort(function(a, b) {
|
||||
if (a.official && b.official) return a.strippedName.localeCompare(b.strippedName)
|
||||
else if (a.official) return -1;
|
||||
else if (b.official) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
serversArray.forEach(s => {
|
||||
servers.push({id: i, cc: s.location, location: this.getCountryName(s.location), name: this.formatServerName(s.sname), map: this.smoothMapName(s.map), players: `${s.players}/${s.maxplayers}`, raw: s, style: this.getRowStyle(s)})
|
||||
i++
|
||||
});
|
||||
|
||||
|
||||
this.tableData = servers//res.data
|
||||
})
|
||||
},
|
||||
getRowStyle(server) {
|
||||
const s = false ? 'rgba(255, 215, 0, 0.35)!important' : server.featured ? 'rgba(0, 128, 0, 0.25)!important' : server.official ? 'rgba(255, 106, 0, 0.25)!important' : server.partner ? 'rgba(0, 123, 195, 0.3)!important' : 'rgba(0, 0, 0, 0)!important';
|
||||
return `background: ${s}`
|
||||
},
|
||||
stripCustomFormatting(name) {
|
||||
var serverStyleArray = [
|
||||
"^0",
|
||||
"^1",
|
||||
"^2",
|
||||
"^3",
|
||||
"^4",
|
||||
"^5",
|
||||
"^6",
|
||||
"^7",
|
||||
"^8",
|
||||
"^9",
|
||||
"^a",
|
||||
"^b",
|
||||
"^c",
|
||||
"^d",
|
||||
"^e",
|
||||
"^f",
|
||||
"^l",
|
||||
"^m",
|
||||
"^n",
|
||||
"^o",
|
||||
"^r",
|
||||
"^p"
|
||||
];
|
||||
|
||||
for (var i = 0; i < serverStyleArray.length; i++){
|
||||
while (name.includes(serverStyleArray[i])){
|
||||
name = name.replace(serverStyleArray[i], "");
|
||||
}
|
||||
}
|
||||
return name;
|
||||
},
|
||||
getCountryName(countryCode) {
|
||||
if (isoCountries.hasOwnProperty(countryCode)) {
|
||||
return isoCountries[countryCode];
|
||||
} else {
|
||||
return countryCode;
|
||||
}
|
||||
},
|
||||
toTitleCase(str) {
|
||||
return str.replace(/\w\S*/g, function (txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||
});
|
||||
},
|
||||
smoothMapName(map) {
|
||||
if (map != "Any Map") {
|
||||
map = map.replace("/info.json", "")
|
||||
map = map.split('/').pop().replace(/\s*/g, '')
|
||||
map = map.replace(/_/g, " ")
|
||||
map = map.replace(/-/g, " ")
|
||||
map = this.toTitleCase(map)
|
||||
}
|
||||
return map
|
||||
},
|
||||
applyCode(string, codes) {
|
||||
var cssText = ''
|
||||
string = string.replace(/\x00*/g, '');
|
||||
for (var i = 0, len = codes.length; i < len; i++) {
|
||||
cssText += styleMap[codes[i]] + ';';
|
||||
}
|
||||
return {s: string, f:cssText};
|
||||
},
|
||||
formatServerName(string) {
|
||||
var codes = string.match(/\^.{1}/g) || [],
|
||||
indexes = [],
|
||||
apply = [],
|
||||
tmpStr,
|
||||
name = [],
|
||||
i,
|
||||
len;
|
||||
for (i = 0, len = codes.length; i < len; i++) {
|
||||
indexes.push(string.indexOf(codes[i]));
|
||||
string = string.replace(codes[i], '\x00\x00');
|
||||
}
|
||||
if (indexes[0] !== 0) {
|
||||
name.push(this.applyCode(string.substring(0, indexes[0]), []))
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
var indexDelta = indexes[i + 1] - indexes[i];
|
||||
if (indexDelta === 2) {
|
||||
while (indexDelta === 2) {
|
||||
apply.push(codes[i]);
|
||||
i++;
|
||||
indexDelta = indexes[i + 1] - indexes[i];
|
||||
}
|
||||
apply.push(codes[i]);
|
||||
} else {
|
||||
apply.push(codes[i]);
|
||||
}
|
||||
if (apply.lastIndexOf('^r') > -1) {
|
||||
apply = apply.slice(apply.lastIndexOf('^r') + 1);
|
||||
}
|
||||
tmpStr = string.substring(indexes[i], indexes[i + 1]);
|
||||
name.push(this.applyCode(tmpStr, apply))
|
||||
}
|
||||
return name
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.getData()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,129 +0,0 @@
|
||||
<template>
|
||||
<div class="container mx-auto mt-8">
|
||||
<h1 class="text-4xl font-bold mb-4">Project Metrics</h1>
|
||||
|
||||
<!-- Timeseries Graph -->
|
||||
<div v-if="dataLoaded">
|
||||
<Plotly :data="graphData" :layout="graphLayout" />
|
||||
</div>
|
||||
|
||||
<!-- Metrics -->
|
||||
<div class="mt-8">
|
||||
<p><strong>Concurrent Players (All Time High):</strong> {{ allTimeHigh }}</p>
|
||||
<p><strong>Players Online Now:</strong> {{ playersOnlineNow }}</p>
|
||||
<p><strong>Servers Online Now:</strong> {{ serversOnlineNow }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Plotly from '@/components/stats/Plotly.vue'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Plotly,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Sample Data
|
||||
graphData: [
|
||||
{
|
||||
x: ['2023-01-01', '2023-01-02', '2023-01-03'],
|
||||
y: [10, 15, 8],
|
||||
type: 'scatter',
|
||||
mode: 'lines+markers',
|
||||
name: 'Concurrent Players',
|
||||
},
|
||||
],
|
||||
graphLayout: {
|
||||
title: 'Concurrent Players Over Time',
|
||||
xaxis: {
|
||||
autorange: true,
|
||||
range: ['2015-02-17', '2017-02-16'],
|
||||
rangeselector: {buttons: [
|
||||
{
|
||||
count: 24,
|
||||
label: '24h',
|
||||
step: 'hour',
|
||||
stepmode: 'backward'
|
||||
},
|
||||
{
|
||||
count: 7,
|
||||
label: '7d',
|
||||
step: 'day',
|
||||
stepmode: 'backward'
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
label: '1m',
|
||||
step: 'month',
|
||||
stepmode: 'backward'
|
||||
},
|
||||
{
|
||||
count: 6,
|
||||
label: '6m',
|
||||
step: 'month',
|
||||
stepmode: 'backward'
|
||||
},
|
||||
{
|
||||
count: 12,
|
||||
label: '1y',
|
||||
step: 'month',
|
||||
stepmode: 'backward'
|
||||
},
|
||||
{step: 'all'}
|
||||
]},
|
||||
rangeslider: {range: ['2015-02-17', '2017-02-16']},
|
||||
type: 'date'
|
||||
},
|
||||
yaxis: {
|
||||
title: 'Concurrent Players',
|
||||
autorange: true,
|
||||
range: [86.8700008333, 138.870004167],
|
||||
type: 'linear'
|
||||
}
|
||||
},
|
||||
allTimeHigh: 20,
|
||||
playersOnlineNow: 12,
|
||||
serversOnlineNow: 3,
|
||||
dataLoaded: false,
|
||||
timePeriod: 'today'
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
setTimeRange(range) {
|
||||
// Update graph data based on the selected time range
|
||||
// You need to implement the logic to fetch data from your backend here
|
||||
console.log(`Updating graph for ${range}`);
|
||||
},
|
||||
getData() {
|
||||
axios
|
||||
.get(`https://backend.beammp.com/stats-info?period=${this.timePeriod}`)
|
||||
.then(res => {
|
||||
const data = [];
|
||||
var Labels = [];
|
||||
var Players = [];
|
||||
if (res.data.v2history) {
|
||||
res.data.v2history.forEach(function(item, index) {
|
||||
Labels.push(item.datetime)
|
||||
Players.push(item.players)
|
||||
})
|
||||
this.graphData[0].x = Labels
|
||||
this.graphData[0].y = Players
|
||||
this.allTimeHigh = res.data.maxp
|
||||
console.log('Data Downloaded & Sorted')
|
||||
this.dataLoaded = true
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.getData();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Add Tailwind CSS styles as needed */
|
||||
</style>
|
||||
@@ -1,3 +0,0 @@
|
||||
<template>
|
||||
<h1>BeamMP Terms & Conditions</h1>
|
||||
</template>
|
||||
@@ -1,12 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{vue,js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
@@ -0,0 +1,736 @@
|
||||
<!doctype html>
|
||||
<html lang="en" style="overflow-x: hidden;">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/ico+xml" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>BeamMP Website</title>
|
||||
<script defer src="https://analytics.beammp.com/script.js" data-website-id="9f9e912d-3470-4048-9f11-5dd360b701e7" data-performance="true"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<noscript>
|
||||
<style>
|
||||
/* NoScript Styling */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.warning-banner {
|
||||
background: linear-gradient(135deg, #f36d24 0%, #e85d1f 100%);
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.warning-banner strong {
|
||||
display: block;
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: white;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
padding: 1rem 0;
|
||||
position: sticky;
|
||||
top: 94px;
|
||||
z-index: 999;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.header-content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 64px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.nav a {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 6px;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.nav a:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.hero {
|
||||
background: linear-gradient(to bottom, rgba(0,0,0,0.5), rgba(0,0,0,0.7)), url('/landing-1.jpg') center/cover;
|
||||
color: white;
|
||||
padding: 5rem 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 1rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 2rem;
|
||||
color: #e5e5e5;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 1rem 2rem;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #f36d24 0%, #dc2626 100%);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(243, 109, 36, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: rgba(255,255,255,0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255,255,255,0.3);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
gap: 2rem;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.stat {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 2.5rem;
|
||||
font-weight: bold;
|
||||
color: #f36d24;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
color: #e5e5e5;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 4rem 1rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 4rem 1rem;
|
||||
}
|
||||
|
||||
.section-alt {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 2.5rem;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.grid-2 {
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
}
|
||||
|
||||
.grid-4 {
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
}
|
||||
|
||||
.card {
|
||||
background: white;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
transition: border-color 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
border-color: #4470b6;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-bottom: 1rem;
|
||||
color: #f36d24;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
color: #666;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background: white;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
padding: 2rem 1rem;
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.social-links a {
|
||||
color: #666;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.social-links a:hover {
|
||||
color: #4470b6;
|
||||
}
|
||||
|
||||
.footer-info {
|
||||
text-align: right;
|
||||
color: #666;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.footer-links a {
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer-links a:hover {
|
||||
color: #4470b6;
|
||||
}
|
||||
|
||||
.two-column {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 3rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.feature-list {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.feature-list li {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.feature-bullet {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: rgba(68, 112, 182, 0.2);
|
||||
flex-shrink: 0;
|
||||
margin-top: 4px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.feature-bullet::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #4470b6;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.screenshot {
|
||||
width: 100%;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #e5e5e5;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, #f36d24 0%, #e85d1f 100%);
|
||||
border-radius: 12px;
|
||||
padding: 3rem;
|
||||
text-align: center;
|
||||
color: white;
|
||||
margin: 3rem 0;
|
||||
}
|
||||
|
||||
.cta-section h3 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.cta-section p {
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 2rem;
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.btn-white {
|
||||
background: white;
|
||||
color: #f36d24;
|
||||
padding: 1rem 2rem;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
display: inline-block;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.btn-white:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.two-column {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer-info {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.nav {
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #f9f9f9;
|
||||
min-width: 155px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
text-align: left;
|
||||
color: black;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdown-content > div {
|
||||
color: black;
|
||||
border-bottom: solid 1px #e5e5e5;
|
||||
}
|
||||
</style>
|
||||
<!-- Warning Banner -->
|
||||
<div class="warning-banner">
|
||||
<strong>⚠️ JavaScript is Disabled</strong>
|
||||
<span>This is a limited version of the BeamMP website. Please enable JavaScript for the full interactive experience.</span>
|
||||
</div>
|
||||
|
||||
<!-- Header -->
|
||||
<header class="header">
|
||||
<div class="header-content">
|
||||
<img src="/src/assets/BeamMP_blk.png" alt="BeamMP Logo" class="logo">
|
||||
<nav class="nav">
|
||||
<a href="https://forum.beammp.com">Forum</a>
|
||||
<a href="https://docs.beammp.com">Docs</a>
|
||||
<a href="https://github.com/BeamMP/BeamMP">GitHub</a>
|
||||
<a href="https://www.patreon.com/BeamMP">Patreon</a>
|
||||
<a href="https://discord.gg/beammp">Discord</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="hero">
|
||||
<div class="hero-content">
|
||||
<h1>Multiplayer Mod for <em>BeamNG.drive</em></h1>
|
||||
<p>Drive together in the ultimate soft-body physics sandbox</p>
|
||||
|
||||
<div class="cta-buttons">
|
||||
<a href="/installer/BeamMP_Installer.zip" class="btn btn-primary" download>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg> Download Now
|
||||
</a>
|
||||
<a href="https://forum.beammp.com/c/server-list/13" class="btn btn-secondary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-server-icon lucide-server"><rect width="20" height="8" x="2" y="2" rx="2" ry="2"/><rect width="20" height="8" x="2" y="14" rx="2" ry="2"/><line x1="6" x2="6.01" y1="6" y2="6"/><line x1="6" x2="6.01" y1="18" y2="18"/></svg> Browse Servers
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="stats">
|
||||
<div class="stat">
|
||||
<div class="stat-value">2,000+</div>
|
||||
<div class="stat-label">Active Players</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-value">500+</div>
|
||||
<div class="stat-label">Public Servers</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-value">2M+</div>
|
||||
<div class="stat-label">All Servers</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Features Section -->
|
||||
<section class="section section-alt">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Why Choose BeamMP?</h2>
|
||||
<div class="grid grid-4">
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-server-icon lucide-server"><rect width="20" height="8" x="2" y="2" rx="2" ry="2"/><rect width="20" height="8" x="2" y="14" rx="2" ry="2"/><line x1="6" x2="6.01" y1="6" y2="6"/><line x1="6" x2="6.01" y1="18" y2="18"/></svg></div>
|
||||
<h3 class="card-title">Stable Servers</h3>
|
||||
<p class="card-text">Rock-solid server performance with minimal lag and maximum uptime for the best multiplayer experience.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-package-icon lucide-package"><path d="M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z"/><path d="M12 22V12"/><polyline points="3.29 7 12 12 20.71 7"/><path d="m7.5 4.27 9 5.15"/></svg></div>
|
||||
<h3 class="card-title">BeamNG.drive Required</h3>
|
||||
<p class="card-text">Built specifically for BeamNG.drive, leveraging its incredible soft-body physics engine.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap-icon lucide-zap"><path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/></svg></div>
|
||||
<h3 class="card-title">Standalone Client</h3>
|
||||
<p class="card-text">Easy-to-use launcher that manages everything for you - just install and play.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe-icon lucide-globe"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg></div>
|
||||
<h3 class="card-title">Real-time Sync</h3>
|
||||
<p class="card-text">Advanced synchronization technology ensures smooth gameplay with players around the world.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Communities Section -->
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Join Vibrant Communities</h2>
|
||||
<p style="text-align: center; color: #666; margin-bottom: 3rem; font-size: 1.1rem;">
|
||||
From casual cruising to competitive racing, find your perfect server
|
||||
</p>
|
||||
<div class="grid grid-4">
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket-icon lucide-rocket"><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/><path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"/><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"/></svg></div>
|
||||
<h3 class="card-title">Racing</h3>
|
||||
<p class="card-text">Compete in high-speed races with custom tracks and competitive leaderboards.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-gamepad2-icon lucide-gamepad-2"><line x1="6" x2="10" y1="11" y2="11"/><line x1="8" x2="8" y1="9" y2="13"/><line x1="15" x2="15.01" y1="12" y2="12"/><line x1="18" x2="18.01" y1="10" y2="10"/><path d="M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z"/></svg></div>
|
||||
<h3 class="card-title">Roleplay</h3>
|
||||
<p class="card-text">Immerse yourself in realistic roleplay scenarios with dedicated communities.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-shield-icon lucide-shield"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/></svg></div>
|
||||
<h3 class="card-title">Crash & Derby</h3>
|
||||
<p class="card-text">Destruction enthusiasts unite! Experience epic demolition derby events.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe-icon lucide-globe"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg></div>
|
||||
<h3 class="card-title">Freeroam</h3>
|
||||
<p class="card-text">Explore vast maps with friends in relaxed freeroam servers.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Server Browser Section -->
|
||||
<section class="section section-alt">
|
||||
<div class="container">
|
||||
<div class="two-column">
|
||||
<div>
|
||||
<h2 style="font-size: 2.5rem; font-weight: bold; margin-bottom: 1.5rem;">Find Your Perfect Server</h2>
|
||||
<p style="font-size: 1.1rem; color: #666; margin-bottom: 2rem;">
|
||||
Browse hundreds of unique servers with different game modes, maps, and communities. There's something for everyone!
|
||||
</p>
|
||||
<ul class="feature-list">
|
||||
<li>
|
||||
<div class="feature-bullet"></div>
|
||||
<div>
|
||||
<div class="feature-title">Custom Game Modes</div>
|
||||
<div class="card-text">From racing leagues to roleplay servers</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="feature-bullet"></div>
|
||||
<div>
|
||||
<div class="feature-title">Active Moderation</div>
|
||||
<div class="card-text">Safe and welcoming communities</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="feature-bullet"></div>
|
||||
<div>
|
||||
<div class="feature-title">Global Network</div>
|
||||
<div class="card-text">Servers worldwide for the best connection</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="https://forum.beammp.com/c/server-list/13" class="btn btn-primary">
|
||||
Browse All Servers →
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<img src="/beammpservers.png" alt="BeamMP Server Browser" class="screenshot">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Developer Section -->
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Built for Developers</h2>
|
||||
<p style="text-align: center; color: #666; margin-bottom: 3rem; font-size: 1.1rem;">
|
||||
Powerful tools and extensive documentation to create your own server experiences
|
||||
</p>
|
||||
<div class="grid grid-4">
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-code-icon lucide-code"><path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/></svg></div>
|
||||
<h3 class="card-title">Lua Scripting</h3>
|
||||
<p class="card-text">Create custom game modes and server-side mods with our powerful Lua API.</p>
|
||||
<a href="https://docs.beammp.com/scripting/mod-reference/" style="color: #4470b6; font-weight: 600; text-decoration: none;">Learn More →</a>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-book-open-icon lucide-book-open"><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg></div>
|
||||
<h3 class="card-title">Comprehensive Docs</h3>
|
||||
<p class="card-text">Detailed guides and API references to help you get started quickly.</p>
|
||||
<a href="https://docs.beammp.com" style="color: #4470b6; font-weight: 600; text-decoration: none;">Learn More →</a>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wrench-icon lucide-wrench"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"/></svg></div>
|
||||
<h3 class="card-title">Open Source</h3>
|
||||
<p class="card-text">Contribute to the project or learn from our codebase on GitHub.</p>
|
||||
<a href="https://github.com/BeamMP" style="color: #4470b6; font-weight: 600; text-decoration: none;">Learn More →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hosting CTA -->
|
||||
<div class="cta-section">
|
||||
<h3>Ready to Host Your Own Server?</h3>
|
||||
<p>Check out our trusted hosting partners or download the server software to host it yourself.</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center pt-4">
|
||||
<a
|
||||
href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.exe"
|
||||
class="btn-white flex items-center justify-center gap-3 bg-neutral-800 hover:bg-neutral-700 dark:bg-neutral-700 dark:hover:bg-neutral-600 text-white border border-neutral-600 dark:border-neutral-600 px-6 py-3 rounded-lg font-semibold transition-all"
|
||||
>
|
||||
Windows
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||
</a>
|
||||
<span
|
||||
class="dropdown btn-white flex items-center justify-center gap-3 bg-neutral-800 hover:bg-neutral-700 dark:bg-neutral-700 dark:hover:bg-neutral-600 text-white border border-neutral-600 dark:border-neutral-600 px-6 py-3 rounded-lg font-semibold transition-all"
|
||||
>
|
||||
Linux Builds
|
||||
<div class="dropdown-content">
|
||||
<div>
|
||||
<span style="color: #666; font-size: 0.85rem; padding: 0.5rem 1rem; display: block; font-weight: 600;">x86_64</span>
|
||||
</div>
|
||||
<div style="padding: 0.5rem 1rem;">
|
||||
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.debian.11.x86_64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
|
||||
Debian 11
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div style="padding: 0.5rem 1rem;">
|
||||
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.debian.12.x86_64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
|
||||
Debian 12
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div style="padding: 0.5rem 1rem;">
|
||||
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.ubuntu.22.04.x86_64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
|
||||
Ubuntu 22.04
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div style="padding: 0.5rem 1rem;">
|
||||
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.ubuntu.24.04.x86_64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
|
||||
Ubuntu 24.04
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<span style="color: #666; font-size: 0.85rem; padding: 0.5rem 1rem; display: block; font-weight: 600;">arm64</span>
|
||||
</div>
|
||||
<div style="padding: 0.5rem 1rem;">
|
||||
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.debian.11.arm64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
|
||||
Debian 11
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div style="padding: 0.5rem 1rem;">
|
||||
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.debian.12.arm64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
|
||||
Debian 12
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div style="padding: 0.5rem 1rem;">
|
||||
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.ubuntu.22.04.arm64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
|
||||
Ubuntu 22.04
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div style="padding: 0.5rem 1rem;">
|
||||
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.ubuntu.24.04.arm64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
|
||||
Ubuntu 24.04
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<span/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="footer-content">
|
||||
<div class="social-links">
|
||||
<a href="https://github.com/BeamMP" aria-label="GitHub">
|
||||
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
||||
</a>
|
||||
<a href="https://discord.gg/beammp" aria-label="Discord">
|
||||
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@beammpofficial" aria-label="YouTube">
|
||||
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
|
||||
</a>
|
||||
<a href="https://x.com/beammpofficial" aria-label="X (Twitter)">
|
||||
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"/></svg>
|
||||
</a>
|
||||
<a href="https://www.reddit.com/r/BeamMP" aria-label="Reddit">
|
||||
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.687-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"/></svg>
|
||||
</a>
|
||||
<span style="color: #ccc;">|</span>
|
||||
<a href="https://www.patreon.com/BeamMP" style="color: #f96854; font-size: 0.85rem; text-decoration: underline;">
|
||||
Support on Patreon
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="footer-info">
|
||||
<p>© 2019 - 2025 | BeamMP Mod Team All Rights Reserved</p>
|
||||
<div class="footer-links">
|
||||
<a href="https://forum.beammp.com/topic/95/privacy-policy-v1-0">Privacy Policy</a>
|
||||
<span>·</span>
|
||||
<a href="https://forum.beammp.com/topic/94/terms-of-use-v1-0">Terms of Use</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,93 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
* oooooooooo. ooo ooooo ooooooooo.
|
||||
* `888' `Y8b `88. .888' `888 `Y88.
|
||||
* 888 888 .ooooo. .oooo. ooo. .oo. .oo. 888b d'888 888 .d88'
|
||||
* 888oooo888' d88' `88b `P )88b `888P"Y88bP"Y88b 8 Y88. .P 888 888ooo88P'
|
||||
* 888 `88b 888ooo888 .oP"888 888 888 888 8 `888' 888 888
|
||||
* 888 .88P 888 .o d8( 888 888 888 888 8 Y 888 888
|
||||
* o888bood8P' `Y8bod8P' `Y888""8o o888o o888o o888o o8o o888o o888o
|
||||
* ========================================================================
|
||||
* Copyright (c) 2019-2023 BeamMP Ltd. All rights reserved.
|
||||
*/
|
||||
|
||||
require('dotenv').config()
|
||||
const pkg = require('./package.json')
|
||||
const chalk = require('chalk');
|
||||
const cluster = require('cluster');
|
||||
|
||||
const error = chalk.bold.keyword('red');
|
||||
const warn = chalk.keyword('orange');
|
||||
const good = chalk.keyword('lime');
|
||||
|
||||
process.on('warning', (warning) => {
|
||||
console.log(warning.stack);
|
||||
});
|
||||
|
||||
if (cluster.isMaster) {
|
||||
|
||||
const env = process.env.NODE_ENV || 'development'
|
||||
|
||||
console.log('oooooooooo. ooo ooooo ooooooooo. ')
|
||||
console.log('`888\' `Y8b `88. .888\' `888 `Y88. ')
|
||||
console.log(' 888 888 .ooooo. .oooo. ooo. .oo. .oo. 888b d\'888 888 .d88\' ')
|
||||
console.log(' 888oooo888\' d88\' `88b `P )88b `888P"Y88bP"Y88b 8 Y88. .P 888 888ooo88P\' ')
|
||||
console.log(' 888 `88b 888ooo888 .oP"888 888 888 888 8 `888\' 888 888 ')
|
||||
console.log(' 888 .88P 888 .o d8( 888 888 888 888 8 Y 888 888 ')
|
||||
console.log('o888bood8P\' `Y8bod8P\' `Y888""8o o888o o888o o888o o8o o888o o888o ')
|
||||
console.log('=================================================================================')
|
||||
console.log('Website v' + pkg.version + ' Copyright (C) 2019-2024 BeamMP Ltd')
|
||||
console.log('')
|
||||
console.log('Running in: ' + env)
|
||||
console.log('Server Time: ' + new Date())
|
||||
|
||||
function start() {
|
||||
process.title = pkg.name + "@" + pkg.version;
|
||||
|
||||
|
||||
if (cluster.isMaster) {
|
||||
console.log(`Master PID: ${process.pid}`)
|
||||
console.log(`Creating ${process.env.INSTANCES} Instances of the Website Backend`)
|
||||
for (let i = 0; i < process.env.INSTANCES; i++) {
|
||||
cluster.fork();
|
||||
}
|
||||
// set console's directory so we can see output from workers
|
||||
console.dir(cluster.workers, { depth: 0 });
|
||||
|
||||
cluster.on('exit', (worker, code) => {
|
||||
// Good exit code is 0 :))
|
||||
// exitedAfterDisconnect ensures that it is not killed by master cluster or manually
|
||||
// if we kill it via .kill or .disconnect it will be set to true
|
||||
// \x1b[XXm represents a color, and [0m represent the end of this
|
||||
//color in the console ( 0m sets it to white again )
|
||||
if (code !== 0 && !worker.exitedAfterDisconnect) {
|
||||
console.error(`\x1b[34mWorker ${worker.process.pid} crashed... Starting a new worker...\x1b[0m`);
|
||||
const nw = cluster.fork();
|
||||
console.error(`\x1b[32mWorker ${nw.process.pid} will replace him \x1b[0m`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error('FATAL: This script can only be run as a master process.')
|
||||
}
|
||||
}
|
||||
|
||||
start()
|
||||
} else {
|
||||
const ws = require('./src/webserver')
|
||||
|
||||
try {
|
||||
ws.init(function (err) {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
return
|
||||
}
|
||||
|
||||
ws.listen(function () {
|
||||
console.info('BeamMP Website Ready')
|
||||
})
|
||||
})
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
server_name _;
|
||||
server_tokens off;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
index index.html;
|
||||
|
||||
# Baseline security hardening for a static SPA.
|
||||
# NOTE: add_header directives are NOT inherited by child location blocks that
|
||||
# define their own add_header. To avoid silently dropping security headers,
|
||||
# use the `expires` directive (not add_header Cache-Control) in location blocks.
|
||||
add_header X-Frame-Options "DENY" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; script-src 'self' https://analytics.beammp.com; style-src 'self' 'unsafe-inline'; font-src 'self' data:; connect-src 'self' https://backend.beammp.com https://analytics.beammp.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;
|
||||
|
||||
# Installer directory: serve files directly; return 404 for anything missing.
|
||||
location ^~ /installer/ {
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# Vite-hashed assets (JS, CSS, fonts, images): serve directly with a long cache.
|
||||
# These files have content hashes in their names so stale cache is never an issue.
|
||||
# Return 404 if a file is genuinely missing rather than silently serving index.html.
|
||||
location ~* \.(js|css|woff2?|ttf|eot|svg|webp|avif|png|jpg|jpeg|gif|ico|map)$ {
|
||||
try_files $uri =404;
|
||||
expires 1y;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Data / download files: serve directly, no client-side cache, 404 if missing.
|
||||
location ~* \.(json|txt|exe|zip)$ {
|
||||
try_files $uri =404;
|
||||
expires -1;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Legacy Keymaster paths moved permanently to the dedicated domain.
|
||||
# Match both localized and non-localized URLs.
|
||||
location ~* "^/([a-z]{2}/)?(keymaster|k/dashboard)/?$" {
|
||||
return 301 https://keymaster.beammp.com/;
|
||||
}
|
||||
|
||||
# SPA fallback: all other paths go to index.html so Vue Router can render the
|
||||
# correct view (including the NotFound page for unknown routes).
|
||||
location / {
|
||||
try_files $uri /index.html;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
worker_processes auto;
|
||||
pid /tmp/nginx.pid;
|
||||
error_log /tmp/error.log warn;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
access_log /tmp/access.log;
|
||||
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
server_tokens off;
|
||||
|
||||
# Redefine temp paths to writable tmpfs locations
|
||||
client_body_temp_path /tmp/client_temp;
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
@@ -1,29 +1,40 @@
|
||||
{
|
||||
"name": "beammp-website",
|
||||
"version": "1.0.1",
|
||||
"description": "BeamMP Website",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
"version": "2.5.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"docker-build": "docker build -t 192.168.100.6:5000/beammp/website:latest -t 192.168.100.6:5000/beammp/website:1.0.1 .",
|
||||
"docker-push": "docker push 192.168.100.6:5000/beammp/website:latest"
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint . --fix",
|
||||
"format": "prettier --write \"src/**/*.{js,vue,css,json}\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/BeamMP/BeamMP-Website.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/BeamMP/BeamMP-Website/issues"
|
||||
},
|
||||
"homepage": "https://github.com/BeamMP/BeamMP-Website#readme",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"chalk": "^3.0.0",
|
||||
"dotenv": "^16.0.3",
|
||||
"ejs": "^3.0.1",
|
||||
"express": "^4.17.1",
|
||||
"helmet": "^6.1.5",
|
||||
"morgan": "^1.10.0"
|
||||
"@tailwindcss/typography": "^0.5.20",
|
||||
"@tailwindcss/vite": "^4.1.17",
|
||||
"@vueuse/core": "^14.1.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-vue-next": "^0.555.0",
|
||||
"marked": "^18.0.5",
|
||||
"reka-ui": "^2.7.0",
|
||||
"tailwind-merge": "^3.4.0",
|
||||
"tailwindcss": "^4.1.17",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"vue": "^3.5.25",
|
||||
"vue-i18n": "^11.2.2",
|
||||
"vue-router": "^4.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.2",
|
||||
"@vue/eslint-config-prettier": "^10.2.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"eslint-plugin-vue": "^10.6.2",
|
||||
"prettier": "^3.7.3",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"vite": "^8.0.16"
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 5.1 MiB |
|
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 2.7 MiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
@@ -0,0 +1,155 @@
|
||||
# Privacy Policy
|
||||
|
||||
**Last updated:** 18th June 2026
|
||||
|
||||
This Privacy Policy describes how BeamMP Ltd. (“we”, “us”, or “our”) collects, uses, and protects information when you use the BeamMP website, accounts, forum, mod, server, launcher, and related online services (collectively, the “**Services**”).
|
||||
|
||||
By accessing or using our Services, you agree to the collection and use of information in accordance with this policy.
|
||||
|
||||
---
|
||||
|
||||
## 1. Information We Collect
|
||||
|
||||
### 1.1 Information You Provide
|
||||
When you register or interact with our Services, we may collect:
|
||||
- Email address
|
||||
- Username and profile information you choose to provide
|
||||
- Content you post (topics, replies, messages, reports)
|
||||
- Communications you send to moderators or administrators
|
||||
- Chat messages and logs
|
||||
|
||||
### 1.2 Automatically Collected Information
|
||||
When you access the Services, we may automatically collect:
|
||||
- IP address
|
||||
- Browser type and version
|
||||
- Operating system
|
||||
- Date and time of access
|
||||
- Pages viewed and actions taken on the Forum
|
||||
- Resources accessed
|
||||
- Hardware & Account identifiers
|
||||
|
||||
This information is collected via server logs, cookies, third party services and similar technologies.
|
||||
|
||||
---
|
||||
|
||||
## 2. How We Use Your Information
|
||||
|
||||
We use collected information to:
|
||||
- Operate and maintain our Services
|
||||
- Authenticate users and manage accounts
|
||||
- Moderate content and enforce rules
|
||||
- Prevent abuse, fraud, and malicious activity
|
||||
- Improve site functionality and performance
|
||||
- Communicate with users regarding moderation actions, updates, or support requests
|
||||
- Maintain community safety, security and standards
|
||||
|
||||
We do **not** sell personal information.
|
||||
|
||||
---
|
||||
|
||||
## 3. Legal Bases for Processing (GDPR / UK GDPR)
|
||||
|
||||
Where applicable, we process personal data under the following legal bases:
|
||||
- **Consent** (e.g., account registration, optional profile information)
|
||||
- **Contractual necessity** (providing Services access and functionality)
|
||||
- **Legitimate interests** (security, moderation, abuse prevention, site improvement & anonymised analytics, Preserving conversational data, FAQ or documentation through the means of data anonymisation)
|
||||
- **Legal obligation** (compliance with applicable laws)
|
||||
|
||||
---
|
||||
|
||||
## 4. Cookies and Tracking Technologies
|
||||
|
||||
Our Services use cookies and similar technologies to:
|
||||
- Maintain login sessions
|
||||
- Remember user preferences
|
||||
- Improve usability and performance
|
||||
|
||||
Cookies may be essential for Service functionality. You can control or disable cookies through your browser settings; however, doing so may limit, restrict or break certain features or functionality.
|
||||
|
||||
Third party providers such as Cloudflare may employ cookies for the providing of their services. Please see their policy for how they process your data.
|
||||
|
||||
Where required by law and appropriate, cookie consent mechanisms are employed.
|
||||
|
||||
---
|
||||
|
||||
## 5. Data Retention
|
||||
|
||||
We retain personal data only as long as necessary for the purposes described in this policy:
|
||||
|
||||
- **Server logs and IP addresses (non-account related):** typically retained for 90 days and a maximum of 180 days
|
||||
- **Account-related IP addresses and logs relevant to moderation purposes:** retained up to 5 years
|
||||
- **Account information, moderation actions and posted content:** retained until the account is deleted or content is removed, unless retention is required for moderation, security, continuity, or legal purposes
|
||||
- **Right to Erasure & Data Deletion Requests:** You may request the deletion of your data through your profile within our Services. Accounts with posted content and/or moderator actions require a specific request to `dpo@beammp.com` for review on a case by case basis. Requests will be processed within 28 days in accordance with legal requirements.
|
||||
|
||||
---
|
||||
|
||||
## 6. Third-Party Services
|
||||
|
||||
We may use trusted third-party service providers to operate our Services, such as:
|
||||
- Hosting providers
|
||||
- Content delivery networks
|
||||
- Email and notification services
|
||||
- Security and anti-abuse services
|
||||
- Payment processing & financial services
|
||||
|
||||
These providers are given access only to the information necessary to perform their services and are required by law to protect it accordingly.
|
||||
|
||||
---
|
||||
|
||||
## 7. Data Sharing
|
||||
|
||||
In order for certain functionality, the sharing of details such as account identifiers may be required. For example in providing a unique identifier to servers that you join. This may also include third party services that you choose to link with your BeamMP account.
|
||||
|
||||
---
|
||||
|
||||
## 8. International Data Transfers
|
||||
|
||||
Data relating to our Services may be stored or processed on servers located outside your country of residence. Where required, appropriate safeguards are used to protect personal data in accordance with applicable laws (e.g., standard contractual clauses).
|
||||
|
||||
---
|
||||
|
||||
## 9. Your Privacy Rights
|
||||
|
||||
Depending on your location, you may have the right to:
|
||||
- Access your personal data
|
||||
- Correct inaccurate information
|
||||
- Request deletion of your data
|
||||
- Object to or restrict certain processing
|
||||
- Request data portability
|
||||
- Withdraw consent where processing is based on consent
|
||||
|
||||
To exercise these rights, please contact us using the information below. We may need to verify your identity before fulfilling a request.
|
||||
|
||||
---
|
||||
|
||||
## 10. Children’s Privacy
|
||||
|
||||
The Services are intended for users aged **13 or older**. We do not knowingly collect personal information from children under 13. If you believe a child has provided personal data, please contact us so it can be removed.
|
||||
|
||||
---
|
||||
|
||||
## 11. Security
|
||||
|
||||
We take extensive technical and operational precautions to protect your data from accidental manipulation, loss, destruction or unauthorised access. Our security practices and mechanisms are reviewed on a regular basis and updated in accordance with best practices and industry standards.
|
||||
|
||||
---
|
||||
|
||||
## 12. Changes to This Policy
|
||||
|
||||
We may update this Privacy Policy from time to time to reflect changes in law, technology, or Service operations. Updates will be posted on this page with a revised “Last updated” date and also communicated via our Forum at least 28 days prior to new changes taking effect.
|
||||
|
||||
Continued use of our Services after changes are posted constitutes acceptance of the updated policy.
|
||||
|
||||
---
|
||||
|
||||
## 13. Right to complain
|
||||
|
||||
If you have concerns about how we handle your personal data, please contact us first so we can try to resolve the issue. You also have the right to lodge a complaint with the Information Commissioner's Office (ICO), the UK supervisory authority for data protection matters.
|
||||
|
||||
You can contact the ICO via the ICO website or by calling their helpline.
|
||||
|
||||
---
|
||||
|
||||
## 14. Contact Us
|
||||
|
||||
If you have questions about this Privacy Policy or wish to exercise your privacy rights, please contact the BeamMP team via email at `dpo@beammp.com`.
|
||||
@@ -0,0 +1,228 @@
|
||||
# Terms of Service (Websites, Forum, Services)
|
||||
**Version 2026.6 – United Kingdom**
|
||||
|
||||
**Effective date:** 18th June 2026
|
||||
|
||||
These Terms of Service (“**Terms**”) govern your access to and use of our websites, community forum, and related online services (collectively, the “**Services**”).
|
||||
This includes our Discord Server and the provided "Official Servers".
|
||||
|
||||
By accessing or using the Services, you agree to these Terms.
|
||||
|
||||
---
|
||||
|
||||
## 1. Who We Are
|
||||
“**We**”, “**us**”, or “**our**” refers to the operator of the Services.
|
||||
|
||||
**Contact:**
|
||||
Legal Name: `BeamMP Ltd.`
|
||||
Email: `contact@beammp.com`
|
||||
Address: `2 Queens Road, Boston, PE21 9AA, United Kingdom`
|
||||
|
||||
---
|
||||
|
||||
## 2. Eligibility and Age Requirements
|
||||
1. **Minimum age: 13.** You must be at least **13 years old** to use the Services.
|
||||
2. Users under 18 confirm they have permission from a parent or legal guardian where required by law.
|
||||
3. We may apply age-appropriate safeguards, restrictions, or verification measures to comply with child-safety obligations under UK or other jurisdictional laws.
|
||||
|
||||
---
|
||||
|
||||
## 3. Changes to These Terms
|
||||
We may update these Terms from time to time. Updated versions will be posted on the Website and, where appropriate, notified to registered users. Continued use of the Services constitutes acceptance of the updated Terms.
|
||||
|
||||
---
|
||||
|
||||
## 4. Accounts and Security
|
||||
1. Some features require an account.
|
||||
2. You must provide accurate, current information and keep it up to date as required by law.
|
||||
3. You are responsible for maintaining the security of your account and all activity under it.
|
||||
4. We may suspend or terminate accounts under Section 11.
|
||||
5. Certain Services may use authentication keys, server keys, or access tokens (“**Auth Keys**”).
|
||||
6. Auth Keys are confidential credentials and must not be shared, sold, transferred, or exposed.
|
||||
7. You are responsible for all activity conducted using your Auth Keys.
|
||||
8. We may revoke or rotate Auth Keys immediately if we reasonably believe they have been misused, compromised, or are being used in violation of these Terms.
|
||||
|
||||
---
|
||||
|
||||
## 5. Licence to Use the Services
|
||||
We grant you a limited, personal, non-exclusive, non-transferable, revocable licence to access and use the Services for lawful, non-commercial purposes, subject to these Terms.
|
||||
|
||||
---
|
||||
|
||||
### 5a. User-Hosted Servers
|
||||
1. The Services may allow users to host their own BeamMP servers using provided software, tools, or authentication mechanisms (“**User-Hosted Servers**”).
|
||||
2. User-Hosted Servers are operated independently by users and are **not owned, controlled, or managed by us**, even where they appear in public listings.
|
||||
3. We do not review, moderate, or guarantee the safety, legality, or integrity of User-Hosted Servers or their content.
|
||||
4. Server operators are solely responsible for:
|
||||
- Content hosted or distributed on their servers
|
||||
- Mods, scripts, maps, files, or data made available
|
||||
- Compliance with applicable laws and regulations
|
||||
- Moderation, security, and user safety
|
||||
5. You agree to indemnify us against any liability arising from your use of user-hosted servers.
|
||||
|
||||
---
|
||||
|
||||
## 6. Acceptable Use
|
||||
You must **not** use the Services to:
|
||||
|
||||
1. Break the law or assist others in doing so.
|
||||
2. Harass, threaten, bully, stalk, or abuse others.
|
||||
3. Post or distribute illegal, hateful, sexual, or exploitative content.
|
||||
4. Share personal or private information about others without consent.
|
||||
5. Upload or share malware, spyware, or malicious code.
|
||||
6. Attempt unauthorised access, bypass security, or disrupt the Services.
|
||||
7. Impersonate others or misrepresent affiliation.
|
||||
8. Evade moderation or bans using alternate accounts. You may not utilize additional or alternative accounts to circumvent moderation action by BeamMP or User-Created servers:
|
||||
- using any existing account to rejoin a server you have been banned from.
|
||||
- using any account, existing or newly created, after receiving a platform-level ban on any of your accounts.
|
||||
|
||||
We reserve the right to remove all accounts associated with a banned user upon discovery of evasion
|
||||
9. Send spam or unsolicited advertising.
|
||||
10. Upload, distribute, or host malicious files, exploits, backdoors, or harmful modifications on User-Hosted Servers in a manner that impacts the Services, other users, or network integrity.
|
||||
|
||||
---
|
||||
|
||||
## 7. Content Standards
|
||||
When submitting content (“**User Content**”), you confirm that:
|
||||
|
||||
1. You have the legal right to submit it.
|
||||
2. It does not infringe copyright, privacy, or other rights.
|
||||
3. It is not unlawful, misleading, defamatory, or deceptive.
|
||||
4. It does not promote violence, self-harm, illegal activity, or otherwise breach any terms outlined.
|
||||
5. It does **not** include sexual content, content harmful to children or other users.
|
||||
|
||||
---
|
||||
|
||||
## 8. Your Content and Our Licence
|
||||
1. You retain ownership of your User Content.
|
||||
2. You grant us a worldwide, non-exclusive, royalty-free licence to host, store, reproduce, modify (for moderation or formatting), display, and distribute your content **solely for operating and improving the Services**.
|
||||
3. Deleted content may persist in backups for a limited time.
|
||||
|
||||
---
|
||||
|
||||
### 8a. Content on User-Hosted Servers
|
||||
1. We do not host, control, or take responsibility for content uploaded to User-Hosted Servers.
|
||||
2. This includes, but is not limited to:
|
||||
- Mods, scripts, plugins, maps, assets, or configuration files
|
||||
- Executable or downloadable files
|
||||
- Third-party or user-created content
|
||||
3. Any content uploaded to or distributed through User-Hosted Servers is done at the server operator’s and user’s own risk.
|
||||
4. We are not responsible for damage, data loss, security incidents, or harm arising from content hosted on User-Hosted Servers.
|
||||
5. We may take action against accounts or servers that use User-Hosted Servers to distribute malware, illegal content, or content that threatens the integrity of the Services or its users.
|
||||
|
||||
---
|
||||
|
||||
## 9. Intellectual Property
|
||||
All intellectual property rights in the Services (including software, branding, and design) belong to us or our licensors. You may not copy, modify, sell, or reverse-engineer any part of the Services except as permitted by law.
|
||||
|
||||
---
|
||||
|
||||
## 10. Copyright and Takedowns
|
||||
If you believe content infringes your copyright or other intellectual property rights, contact us with:
|
||||
|
||||
- Identification of the content or works
|
||||
- Location of the infringing material
|
||||
- Your contact details
|
||||
- A good-faith statement of accuracy
|
||||
- Proof of ownership, rights, authority or authenticity
|
||||
|
||||
We may remove infringing material and take action at our discretion.
|
||||
|
||||
If your content is removed and you believe this was an error, you may submit a counter-notice to contact@beammp.com including the removed content's details, your contact information, and a good-faith explanation.
|
||||
We will review and may reinstate where appropriate.
|
||||
|
||||
---
|
||||
|
||||
## 11. Enforcement and Moderation
|
||||
1. We may remove content, restrict features, suspend, or terminate accounts for violation of our Terms, Rules or Policies.
|
||||
2. We cooperate with law enforcement where legally required, and may share information voluntarily where we reasonably consider it necessary to protect the safety of users or the public, or to prevent or detect crime, in line with our Privacy Policy and applicable data-protection law.
|
||||
3. We make a reasonable effort to proactively monitor content on our Services using a combination of community reports, automated tools and active moderation.
|
||||
|
||||
---
|
||||
|
||||
## 12. Reporting and Complaints
|
||||
We provide mechanisms to report:
|
||||
|
||||
- Illegal or harmful content
|
||||
- Harassment or abuse
|
||||
- Child-safety concerns
|
||||
- Privacy or data-protection issues
|
||||
- Moderation appeals
|
||||
- Breach of Rules or Terms of Service
|
||||
- General concerns or queries
|
||||
|
||||
Reports will be handled proportionately and within reasonable timeframes, on a case by case basis.
|
||||
|
||||
---
|
||||
|
||||
## 13. UK Online Safety Act Compliance
|
||||
Where applicable, the Services are operated in line with the **UK Online Safety Act**, including:
|
||||
|
||||
1. Measures to reduce the risk of illegal content.
|
||||
2. Systems to protect children from harmful material.
|
||||
3. Accessible reporting and appeals processes.
|
||||
4. Proportionate enforcement of these Terms.
|
||||
|
||||
---
|
||||
|
||||
## 14. Privacy and Data Protection
|
||||
1. Personal data is processed in accordance with **GDPR**.
|
||||
2. Our **Privacy Policy** explains what data we collect, how it is used, and your rights.
|
||||
3. Lawful bases for processing may include contract performance, legitimate interests (security and moderation), and legal obligations.
|
||||
4. You may request access, correction, deletion, or restriction of your personal data.
|
||||
5. Certain data may be retained where necessary for security, legal compliance, or enforcement.
|
||||
|
||||
Requests in relation to the above or any other query or concern can be raised via email with `dpo@beammp.com`.
|
||||
|
||||
---
|
||||
|
||||
## 15. Third-Party Services
|
||||
Our Services may link to or integrate with third-party services. We are not responsible for third-party content, services, or policies.
|
||||
Please see their respective policies for further information on how they operate.
|
||||
|
||||
---
|
||||
|
||||
### 15a. Discord and External Platforms
|
||||
1. The Services may include official or community-operated spaces on third-party platforms, including Discord.
|
||||
2. Use of such platforms is subject to their own terms, rules, and policies.
|
||||
3. We are not responsible for outages, moderation actions, or data handling by third-party platforms.
|
||||
4. Violations of our rules on third-party platforms may be considered when enforcing these Terms where relevant to community safety.
|
||||
|
||||
---
|
||||
|
||||
## 16. Disclaimers
|
||||
The Services are provided **“as is”** and **“as available.”** To the maximum extent permitted by law, we disclaim all warranties, including fitness for purpose and non-infringement.
|
||||
|
||||
---
|
||||
|
||||
## 17. Limitation of Liability
|
||||
To the extent permitted by law:
|
||||
|
||||
1. We are not liable for indirect, incidental, or consequential damages.
|
||||
2. Our total liability is limited to the greater of:
|
||||
- The amount you paid us in the past 12 months (if any), or
|
||||
- £100
|
||||
3. Nothing limits liability where it cannot be excluded under UK law.
|
||||
|
||||
---
|
||||
|
||||
## 18. Indemnity
|
||||
You agree to indemnify us against losses arising from your breach of these Terms or unlawful use of the Services.
|
||||
This includes claims arising from content, files, or services operated through User-Hosted Servers.
|
||||
|
||||
---
|
||||
|
||||
## 19. Termination
|
||||
You may stop using the Services at any time. We may suspend or terminate access for violations, legal obligations, or security reasons.
|
||||
|
||||
---
|
||||
|
||||
## 20. Governing Law and Jurisdiction
|
||||
These Terms are governed by the laws of **England and Wales**, and disputes are subject to the exclusive jurisdiction of its courts.
|
||||
|
||||
---
|
||||
|
||||
## 21. Miscellaneous
|
||||
1. If any provision is unenforceable, the remainder remains effective.
|
||||
2. You may not transfer your rights under these Terms without consent.
|
||||
3. These Terms and the Privacy Policy constitute the entire agreement regarding the Services.
|
||||
|
After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 207 B |
|
Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 280 B |
|
Before Width: | Height: | Size: 122 B After Width: | Height: | Size: 122 B |
|
Before Width: | Height: | Size: 339 B After Width: | Height: | Size: 339 B |
|
Before Width: | Height: | Size: 362 B After Width: | Height: | Size: 362 B |
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 217 B After Width: | Height: | Size: 217 B |
|
Before Width: | Height: | Size: 114 B After Width: | Height: | Size: 114 B |
|
Before Width: | Height: | Size: 235 B After Width: | Height: | Size: 235 B |
|
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |
|
Before Width: | Height: | Size: 162 B After Width: | Height: | Size: 162 B |
|
Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 448 B |
|
Before Width: | Height: | Size: 104 B After Width: | Height: | Size: 104 B |
|
Before Width: | Height: | Size: 312 B After Width: | Height: | Size: 312 B |
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 153 B After Width: | Height: | Size: 153 B |
|
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
|
Before Width: | Height: | Size: 235 B After Width: | Height: | Size: 235 B |
|
Before Width: | Height: | Size: 179 B After Width: | Height: | Size: 179 B |
|
Before Width: | Height: | Size: 190 B After Width: | Height: | Size: 190 B |
|
Before Width: | Height: | Size: 114 B After Width: | Height: | Size: 114 B |
|
Before Width: | Height: | Size: 145 B After Width: | Height: | Size: 145 B |
|
Before Width: | Height: | Size: 117 B After Width: | Height: | Size: 117 B |
|
Before Width: | Height: | Size: 125 B After Width: | Height: | Size: 125 B |
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 383 B |
|
Before Width: | Height: | Size: 102 B After Width: | Height: | Size: 102 B |
|
Before Width: | Height: | Size: 627 B After Width: | Height: | Size: 627 B |
|
Before Width: | Height: | Size: 536 B After Width: | Height: | Size: 536 B |
|
Before Width: | Height: | Size: 685 B After Width: | Height: | Size: 685 B |
|
Before Width: | Height: | Size: 117 B After Width: | Height: | Size: 117 B |
|
Before Width: | Height: | Size: 352 B After Width: | Height: | Size: 352 B |
|
Before Width: | Height: | Size: 344 B After Width: | Height: | Size: 344 B |
|
Before Width: | Height: | Size: 211 B After Width: | Height: | Size: 211 B |
|
Before Width: | Height: | Size: 451 B After Width: | Height: | Size: 451 B |
|
Before Width: | Height: | Size: 152 B After Width: | Height: | Size: 152 B |
|
Before Width: | Height: | Size: 113 B After Width: | Height: | Size: 113 B |
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 228 B |