Merge branch 'dev' into discourse-sso-updates

This commit is contained in:
mrjvs
2026-08-19 23:31:38 +02:00
514 changed files with 54735 additions and 33747 deletions

View File

@@ -0,0 +1,32 @@
# Taken from: https://spwoodcock.dev/blog/2026-03-03-automate-garage-standalone/
# Modified to add environment variable support
# chroot into the s3 container's filesystem so the garage binary runs
# with its own libs/linker, while the shared network namespace keeps
# 127.0.0.1:3901 pointing at the live Garage server
G="chroot /proc/1/root /garage -c /etc/garage.toml"
# Wait for server
for i in $(seq 1 20); do
if $G node id -q 2>/dev/null; then break; fi
echo "Waiting for Garage RPC... ($i/20)"
sleep 3
done
$G node id -q || { echo "Garage RPC not ready"; exit 1; }
# Init garage nodes
if $G status 2>&1 | grep -q 'NO ROLE ASSIGNED'; then
NODE_ID=$($G node id -q | cut -c1-16)
$G layout assign "$NODE_ID" -z local -c 1G
$G layout apply --version 1
fi
# Create S3 bucket
$G key import --yes -n "$S3_ACCESS_KEY_NAME" \
"$S3_ACCESS_KEY_ID" \
"$S3_ACCESS_KEY_SECRET" || true
$G bucket create "$S3_BUCKET" || true
$G bucket allow "$S3_BUCKET" --key "$S3_ACCESS_KEY_NAME" --read --write --owner || true
$G bucket website --allow "$S3_BUCKET"
echo "Garage initialized."

View File

@@ -0,0 +1,17 @@
metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
replication_factor = 1
db_engine = "sqlite"
rpc_bind_addr = "[::]:3901"
rpc_public_addr = "127.0.0.1:3901"
rpc_secret = "fbb4c8c25cdb7766ef9c2913cee0a6b52a927c03fafea2aa21e8658c68cc14c7"
[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
[s3_web]
bind_addr = "[::]:3902"
root_domain = ".localhost"

View File

@@ -0,0 +1,97 @@
name: "pn-website-dev"
services:
redis:
image: redis:8.2-alpine
restart: unless-stopped
ports:
- "6379:6379" # Redis port
mailpit:
image: axllent/mailpit
restart: unless-stopped
networks:
- net
ports:
- 8025:8025 # Web port
- 1025:1025 # SMTP port
mongo:
image: mongo:8.0
restart: unless-stopped
networks:
- net
command: ["--replSet", "rs0", "--bind_ip_all", "--port", "27017"]
ports:
- 27017:27017 # MongoDB port
# This funky stuff is needed for making a replicaset
healthcheck:
test: echo "try { rs.status() } catch (err) { rs.initiate({_id:'rs0',members:[{_id:0,host:'mongo:27017'}]}) }" | mongosh --port 27017 --quiet
interval: 5s
timeout: 30s
start_period: 0s
start_interval: 1s
retries: 30
volumes:
- "mongo_data:/data/db"
garage:
image: dxflrs/garage:v2.3.0
restart: unless-stopped
networks:
- net
ports:
- "3900:3900" # S3 API port
- "3902:3902" # Web port
healthcheck:
test: ["CMD", "/garage", "status"]
start_period: 5s
interval: 5s
timeout: 5s
retries: 10
volumes:
- ./assets/garage.toml:/etc/garage.toml:ro
- garage_data:/var/lib/garage
garage-init:
image: alpine:3.23
depends_on:
garage:
condition: service_healthy
network_mode: service:garage
pid: service:garage
environment:
GARAGE_ADMIN_TOKEN: garage-admin-token
S3_ACCESS_KEY_NAME: pretendo-key
S3_ACCESS_KEY_ID: GK3515373e4c851ebaad366558
S3_ACCESS_KEY_SECRET: 7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34
S3_BUCKET: pretendo
restart: "on-failure:2"
entrypoint: "/bin/sh -eu /etc/init.sh"
volumes:
- "./assets/garage-init.sh:/etc/init.sh"
account:
image: ghcr.io/pretendonetwork/account:sha-edb4b02
restart: unless-stopped
networks:
- net
ports:
- "8123:8123" # grpc
- "8056:8056" # http
environment:
PN_ACT_CONFIG_HTTP_PORT: 8056
PN_ACT_CONFIG_GRPC_PORT: 8123
PN_ACT_CONFIG_MONGO_CONNECTION_STRING: "mongodb://mongo:27017/account?directConnection=true"
PN_ACT_CONFIG_S3_ENDPOINT: "http://garage:3900"
PN_ACT_CONFIG_S3_REGION: "garage"
PN_ACT_CONFIG_S3_BUCKET: "pretendo"
PN_ACT_CONFIG_S3_ACCESS_KEY: "GK3515373e4c851ebaad366558"
PN_ACT_CONFIG_S3_ACCESS_SECRET: "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"
PN_ACT_CONFIG_S3_FORCE_PATH_STYLE: "true"
PN_ACT_CONFIG_CDN_BASE_URL: "http://pretendo.localhost:3902/"
PN_ACT_CONFIG_AES_KEY: "1234567812345678123456781234567812345678123456781234567812345678"
PN_ACT_CONFIG_GRPC_MASTER_API_KEY_ACCOUNT: "12345678123456781234567812345678"
PN_ACT_CONFIG_GRPC_MASTER_API_KEY_API: "12345678123456781234567812345678"
networks:
net:
volumes:
mongo_data:
garage_data:

View File

@@ -1,5 +1,5 @@
.git
.git/
node_modules/
.env
node_modules
dist
logs
.nuxt
.output

View File

@@ -1,15 +1,9 @@
# http://editorconfig.org
root = true
[*]
[*.{ts,js,vue,json}]
indent_style = tab
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.js]
indent_size = 4
[*.{css,handlebars,json}]
indent_size = 2

View File

@@ -1,2 +0,0 @@
# web javascript causes a lot of eslint warnings
assets/js

View File

@@ -1,42 +0,0 @@
{
"env": {
"browser": true,
"node": true,
"commonjs": true,
"es6": true
},
"globals": {
"document": true
},
"parserOptions": {
"ecmaVersion": 2021
},
"extends": "eslint:recommended",
"rules": {
"no-case-declarations": "off",
"no-empty": "off",
"no-console": "off",
"linebreak-style": "off",
"prefer-const": "error",
"no-var": "error",
"one-var": [
"error",
"never"
],
"indent": [
"error",
"tab",
{
"SwitchCase": 1
}
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}

3
.gitattributes vendored
View File

@@ -1,2 +1 @@
# Auto detect text files and perform LF normalization
* text=auto
* text=auto eol=lf

View File

@@ -8,18 +8,21 @@ on:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
SHOULD_PUSH_IMAGE: ${{ (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev')) || github.event_name == 'workflow_dispatch' }}
permissions:
contents: read
packages: write
jobs:
build-publish:
env:
SHOULD_PUSH_IMAGE: ${{ (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev')) || github.event_name == 'workflow_dispatch' }}
build-publish-amd64:
name: Build and Publish (amd64)
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU for Docker
uses: docker/setup-qemu-action@v3
@@ -48,9 +51,52 @@ jobs:
id: build-and-push
uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm64
platforms: linux/amd64
push: ${{ env.SHOULD_PUSH_IMAGE }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-publish-arm64:
name: Build and Publish (arm64)
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU for Docker
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log into the container registry
if: ${{ env.SHOULD_PUSH_IMAGE == 'true' }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest-arm,enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=edge-arm,enable=${{ github.ref == 'refs/heads/dev' }}
type=sha,suffix=-arm
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v6
with:
platforms: linux/arm64
push: ${{ env.SHOULD_PUSH_IMAGE }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

29
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Lint
on:
pull_request: {}
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "24"
- name: Install dependencies
run: npm ci
- name: Prepare linting
run: npm run prepare
- name: Typecheck
run: npm run typecheck
- name: Lint
run: npm run lint -- --max-warnings=0

77
.gitignore vendored
View File

@@ -1,72 +1,11 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# vscode settings
.vscode
# JetBrains settings
.idea
# dotenv environment variables file
.output
.data
.nuxt
.nitro
.cache
dist
node_modules
.env
# keep config and blog posts out of this
# Old configuration ignored for safety
config.json
static-text.json
.DS_Store
# keep browserified files out
*.bundled.js

View File

@@ -1,10 +0,0 @@
language: node_js
node_js:
- "7"
- "8"
- "9"
sudo: false
script:
- "npm run lint"

7
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"vue.volar"
]
}

6
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
},
"eslint.format.enable": true
}

View File

@@ -4,7 +4,7 @@ ARG app_dir="/home/node/app"
# * Base Node.js image
FROM node:20-alpine AS base
FROM node:24-alpine AS base
ARG app_dir
WORKDIR ${app_dir}
@@ -27,25 +27,23 @@ RUN --mount=type=bind,source=package.json,target=package.json \
npm ci
COPY . .
# TODO: re-enable after TypeScript migration
#RUN npm run build
RUN npm run build
# * Running the final application
FROM base AS final
ARG app_dir
RUN mkdir -p ${app_dir}/logs && chown node:node ${app_dir}/logs
ENV NODE_ENV=production
USER node
ENV NODE_ENV=production
ENV NITRO_HOST=0.0.0.0
ENV NITRO_PORT=8080
EXPOSE 8080
COPY package.json .
COPY --from=dependencies ${app_dir}/node_modules ${app_dir}/node_modules
COPY --from=build ${app_dir} ${app_dir}
COPY --chown=node:node --from=build ${app_dir}/.output ${app_dir}/.output
# TODO: change back after TypeScript migration
#COPY --from=build ${app_dir}/dist ${app_dir}/dist
CMD ["node", "."]
CMD ["node", "--enable-source-maps", ".output/server/index.mjs"]

View File

@@ -1,18 +1,64 @@
# Website
# Pretendo website
This repository contains the source code for [our website](https://pretendo.network). All contributions should go in the [dev branch](https://github.com/PretendoNetwork/website/tree/dev).
This repository contains the source code for [our website](https://pretendo.network).
### Localization
If you'd like to help localize Pretendo Network, you can check out our project on [Weblate](https://hosted.weblate.org/engage/pretendonetwork/).
# Running locally for development
<a href="https://hosted.weblate.org/engage/pretendonetwork/">
<img src="https://hosted.weblate.org/widgets/pretendonetwork/-/website/multi-auto.svg" alt="Translation status" />
</a>
Prerequisites:
- Clone the repository
- Have Docker Desktop installed (or Docker engine)
- Have NodeJS 24 or higher installed
* * *
Then follow these steps:
- Run `docker compose up -d` inside `/.docker`
- Create a file called `.env` in the root, fill it with the contents of `example.env`
- Install dependencies with `npm i`
- Run the app with `npm run dev`
Join our Discord:
# Translation
<a href="https://discord.gg/DThgbba" target="_blank">
<img src="https://discordapp.com/api/guilds/408718485913468928/widget.png?style=banner3">
</a>
If you'd like to help localize Pretendo Network, you can contribute to the translations on our project on [Weblate](https://hosted.weblate.org/engage/pretendonetwork/).
# Configuration
The application can be configured with environment variables. `.env` files are available for development.
There are no fully required configuration variables, the app can runs minimally without any configuration:
| Feature | Variable | Description | Default |
| ---------------------------- | -------------------------------------- | --------------------------------------------- | ---------------------------- |
| Core | `PN_WEBSITE_PUBLIC_BASE_URL` | Base URL of the app | `https://pretendo.network` |
| | `PN_WEBSITE_PUBLIC_CDN_BASE_URL` | Base URL for the CDN | `https://r2-cdn.pretendo.cc` |
| | `PN_WEBSITE_PUBLIC_COOKIE_SECURE` | Should Secure be enabled for auth cookies | `true` |
| | `PN_WEBSITE_TRUST_PROXY` | Should X-Forwarded-* headers be trusted? | `false` |
| | `PN_WEBSITE_REDIS_URL` | Redis URL to use for caching & ratelimits | (No distributed KV) |
| | | | |
| Authentication | `PN_WEBSITE_GRPC_HOST` | Account server GRPC host + port | - |
| | `PN_WEBSITE_GRPC_API_KEY` | Account server GRPC API key | - |
| | `PN_WEBSITE_API_BASE` | Base URL of the account server | `https://api.pretendo.cc` |
| | `PN_WEBSITE_API_BASE_HOST` | Hostname of the account server | `api.pretendo.cc` |
| | | | |
| Progress tracking | `PN_WEBSITE_GITHUB_API_TOKEN` | Github API token | - |
| | | | |
| Discord | `PN_WEBSITE_DISCORD_BOT_TOKEN` | Discord bot token | - |
| | `PN_WEBSITE_DISCORD_CLIENT_ID` | Discord OAuth client ID | - |
| | `PN_WEBSITE_DISCORD_CLIENT_SECRET` | Discord OAuth client secret | - |
| | `PN_WEBSITE_DISCORD_GUILD_ID` | Discord server ID for role linking | - |
| | `PN_WEBSITE_DISCORD_TESTER_ROLE_ID` | Role to give for tester access | (No role) |
| | `PN_WEBSITE_DISCORD_SUPPORTER_ROLE_ID` | Role to give for supporter access | (No role) |
| | | | |
| Payments | `PN_WEBSITE_STRIPE_SECRET_KEY` | Stripe secret key | - |
| (Requires `discord` feature) | `PN_WEBSITE_STRIPE_WEBHOOK_SECRET` | Stripe webhook signing key | - |
| | `PN_WEBSITE_STRIPE_NOTIFICATION_EMAIL` | Email address to send stripe notifications to | (No notifications) |
| | `PN_WEBSITE_MONGO_CONNECTION_STRING` | MongoDB connection string for account server | - |
| | `PN_WEBSITE_SMTP_HOST` | Host for the SMTP server | - |
| | `PN_WEBSITE_SMTP_PORT` | Port for the SMTP server | `587` |
| | `PN_WEBSITE_SMTP_SECURE` | Use a secure SMTP connection | `true` |
| | `PN_WEBSITE_SMTP_USER` | Username for the SMTP server | (No SMTP auth) |
| | `PN_WEBSITE_SMTP_PASSWORD` | Password for the SMTP server | (No SMTP auth) |
| | `PN_WEBSITE_SMTP_FROM_EMAIL` | Email to sent emails from | - |
| | `PN_WEBSITE_SMTP_FROM_NAME` | Display of the FROM email adress | - |
| | | | |
| Captcha | `PN_WEBSITE_HCAPTCHA_SECRET_KEY` | HCaptcha secret key | - |
| | `PN_WEBSITE_PUBLIC_HCAPTCHA_SITE_KEY` | HCaptcha site key | - |
| | | | |
| Discourse SSO | `PN_WEBSITE_DISCOURSE_SSO_SECRET` | Discourse SSO secret | - |

95
content.config.ts Normal file
View File

@@ -0,0 +1,95 @@
import {
defineContentConfig,
defineCollection,
defineCollectionSource,
z
} from '@nuxt/content';
import { getAllErrors, getErrorInfo } from '@pretendonetwork/error-codes';
const errorCodeSource = defineCollectionSource({
getKeys: () => {
return getAllErrors().map((key: string) => `${key}.json`);
},
getItem: (key: string) => {
const errorString = key.split('.')[0];
const sysmodule = errorString.split('-')[0];
const code = errorString.split('-')[1];
const errorInfo = getErrorInfo(sysmodule, code, 'en-US');
if (errorInfo) {
errorInfo.code = errorString;
}
return errorInfo;
}
});
export default defineContentConfig({
collections: {
blog: defineCollection({
type: 'page',
source: 'blog/*.md',
schema: z.object({
author: z.string(),
author_image: z.string(),
date: z.string(),
caption: z.string(),
cover_image: z.string()
})
}),
docs: defineCollection({
type: 'page',
source: 'docs/**/*.md',
schema: z.object({
description: z.string()
})
}),
terms: defineCollection({
type: 'page',
source: 'terms/*.md'
}),
errorcodes: defineCollection({
type: 'data',
source: errorCodeSource,
schema: z.object({
name: z.string(),
message: z.string(),
short_description: z.string(),
long_description: z.string(),
short_solution: z.string(),
long_solution: z.string(),
support_link: z.string(),
module: z.object({
name: z.string(),
description: z.string(),
system: z.string()
}),
code: z.string()
})
}),
team: defineCollection({
type: 'data',
source: 'team.json',
schema: z.object({
people: z.array(z.object({
name: z.string(),
captionKey: z.string(),
picture: z.string().url(),
github: z.string().url()
}))
})
}),
specialThanks: defineCollection({
type: 'data',
source: 'specialthanks.json',
schema: z.object({
people: z.array(z.object({
name: z.string(),
captionKey: z.string(),
picture: z.string().url(),
github: z.string().url(),
isSpecial: z.boolean().default(false)
}))
})
})
}
});

View File

@@ -4,7 +4,7 @@ author: "SuperMarioDaBom"
author_image: "https://www.github.com/SuperMarioDaBom.png"
date: "October 30, 2022"
caption: "Our latest progress, alongside new info!"
cover_image: "/assets/images/blogposts/10-30-22.jpg"
cover_image: "/assets/images/blogposts/10-30-22.webp"
---
### If you want to see more frequent updates, consider supporting us by [**upgrading your account with a subscription!**](https://pretendo.network/account/upgrade)
@@ -14,6 +14,7 @@ Where do I even start?
This past year has been a very busy one. From Juxtaposition updates to general stability improvements to reviving a Wii U title that's been dead for 5 years now, there's something for everyone to enjoy. A lot has happened, so we won't be able to cover everything in detail. We've still got a lot of ground to cover, so let's jump into it right away!
# Posts Galore
> **DUE TO SOME TECHNICAL ISSUES JUXT IS CURRENTLY NOT AVAILABLE FOR THE PUBLIC BETA. THANK YOU FOR UNDERSTANDING.**
Let's start with Juxtaposition (or Juxt for short). If you're not aware, Juxt is Pretendo's reimplementation of Miiverse functionality. For more details on it's history, as well as what it all encompasses, please check out [**this blog post from 2021!**](https://pretendo.network/blog/9-29-21)
@@ -21,57 +22,74 @@ Let's start with Juxtaposition (or Juxt for short). If you're not aware, Juxt is
What's changed since then?
## Messages Have Arrived
You can now send messages to users that you are mutual followers with! Just like Nintendo's implementation, these messages are not secured, so do not treat it like a private conversation platform.
## When Away From Console
Juxt now has a web version! It is still somewhat limited, and you must first use Juxt on-console to get everything set up, but it's there and will be a great way to interact with users even while not using your game console.
## Wara Wara What Now?
![An active Wara Wara Plaza, with a bunch of Miis walking around](https://media.discordapp.net/attachments/882044583238832238/1035956941052194877/unknown.png?width=2200&height=1239)
Wara Wara Plaza is back to its former glory! For those who don't know, Wara Wara Plaza is the plaza of Miis you see on one of the Home Menu screens. Previously, the above could only be seen through manually adding the data to the console. If you have access to Juxt, you should be able to see the plaza back to bustling.
## That's Not All
Plenty more has changed with Juxt, too much to go into detail here. For now, let's move on to the next big addition!
# Who's The BOSS Now?
SpotPass (known internally as BOSS) is a service that allows servers to push new content to consoles without requiring an update. We've demonstrated the ability to push custom Splatfests to Splatoon, but since then we've got a fully functional server to push out content! Do I sense a Splatfest in development?
# Pikachu, I Choose You
Servers for 3DS Pokémon titles are nearly functional! These games require additional effort to get working correctly (including signature patches), so please stay tuned for that.
# A Wild Raccoon Has Appeared!
![Bandwidth Raccoon holding a Wii U Gamepad and a brick](https://pretendo.network/assets/images/bandwidth.svg)
In case you haven't yet met him, this is Bandwidth the Raccoon! He's appeared to welcome everyone alongside some major website updates!
## Progress, Progress, Progress
The Progress page has received an upgrade! Data is now pulled from GitHub repositories, and you can see a better breakdown of the progress for each server in development!
## Have You Checked The Docs?
A Docs section has been added to the website! Here, you can find information on how to get started, as well as error codes in the event you encounter any issues. This section is still a work-in-progress, so it will be updated and added onto as time goes on.
## Goodbye Patreon, Hello Stripe
We are moving away from Patreon due to security concerns, and better integration with our services. Tiers will stay exactly the same - no changes in cost. If you wish to support the project, log into your PNID on the website and check out the info on upgrading. Pretendo is an open source project, therefore payment is not required to use the project when open publicly or self-hosted. See the info of the different tiers for a list of perks.
## It's All About Mii
One of the biggest additions to the website is you now have the ability to create & edit your account Mii! This is great for emulator users who aren't necessarily able to use a Mii Maker app to create their Miis, or for those who wish to create their PNID entirely on the web.
## Accounts, Just The Way You Like It
You can now create your PNID entirely on the web, no console required. Most settings cannot be changed just yet, though you can change your Mii.
# Further Improvements To Overall System Stability And Other Minor Adjustments Have Been Made To Enhance The User Experience
Multiple servers got improvements, including the Account server and the Friends servers. The Account server now has proper access levels, which allows specific users to have access to specific services. Friends servers have increased stability, and on the Wii U side are only missing a few pieces to become fully functional.
# Official Cemu Support Has Arrived!
In the latest version of the Cemu 2.0 experimental builds, support for Pretendo has been added! Check out our [Cemu usage guide](https://pretendo.network/docs/install/cemu) for more info and to get started.
# Finally, After 5 Years... It Lives!
If you haven't yet seen this video by Good Vibes Gaming, go check it out! I won't go anywhere...
[yt-iframe](Xtc9DJ6LYas)
::md-iframe{video-id="Xtc9DJ6LYas"}
::
All done? Welcome back! Yes, you aren't dreaming - Wii U Chat is finally here! The journey leading up to this point has been an adventurous one, so grab your popcorn as we go back to the beginning.
## Where It All Started
![](https://media.discordapp.net/attachments/413884110667251722/679178001065443358/image0.jpg)
Back in February 2020, Jon shared a few photos of Wii U Chat getting into the app. Hardly anything was implemented, just enough to get to the list of friends. Since we did not have a functional Friends server at the time, this was actually performed using a Nintendo Network account. We did not seriously explore the app at that time, since there were other priorities that took precedence. It would be a bit until the app was looked at again.
@@ -89,6 +107,7 @@ Fast forward to October 2021. Shutterbug2000 decided to take a stab at it, and s
Attempting to answer would crash the app, which would become a common theme. Wii U Chat has less than what one would consider to be the bare minimum for error handling. He left the app at that, and moved on.
## It Was Friends All Along
Two months later, in December, shutterbug2000 was looking into notifications regarding the friends list. Certain games allowed users to join their friends in ongoing online matches right from the list, and he wanted to figure out how those worked. To do this, he injected the Friends applet into a normal application. Titles such as Smash Bros. support the feature; Mario Kart 8 may have had this as a planned feature, but seems to ignore it if attempted.
![](https://media.discordapp.net/attachments/881852117550243860/919051163431747614/20211210_202021.jpg)
@@ -100,6 +119,7 @@ While he was here, Shutter decided to try and see if an incoming call could be t
It was from the Friends server all along! Now that the pieces were there, all that was left was to handle call sessions via matchmaking (yes, it uses similar processes to joining game sessions) and NAT traversal (a process allowing consoles to talk directly). Unfortunately, it would be some time before much more progress could be made.
## Putting It All Together
In late August of this year Jon, Shutter & I got to work to get it put together and finally working. On September 7, the first call since 2017 was made.
![](https://media.discordapp.net/attachments/881852117550243860/1017131964429516910/IMG_9043.jpg)
@@ -107,14 +127,16 @@ In late August of this year Jon, Shutter & I got to work to get it put together
After 5 years of this app lying dormant, it is now possible to make calls and draw on your friends' faces! This could not have been done without all of the contributions from devs and non-devs alike, so thank you to all who contributed to this effort!
## What Remains
If you're seeing this within the current public beta, good news: Wii U Chat is open for use! There are a few caveats to keep in mind, due to the early nature of the servers:
* Wii U Chat heavily relies on Miiverse functionality for certain features such as missed calls, which haven't yet been figured out & implemented. As such, the console may freeze or lock up from time to time, especially if you cancel an outgoing call. If you experience a freezing issue, please fully power off your console and try again.
* As mentioned above, missed calls are not implemented yet. Do not expect a log of calls you didn't get to while away.
* Currently, notifications are only sent to the call recipient while in the app; as mentioned above, we know how to trigger them, but this server intercommunication is not yet implemented.
* Expect bugs. Lots of them. We will not be providing much technical support for the app at this time, due to it's early nature and the fact that we know there are issues.
- Wii U Chat heavily relies on Miiverse functionality for certain features such as missed calls, which haven't yet been figured out & implemented. As such, the console may freeze or lock up from time to time, especially if you cancel an outgoing call. If you experience a freezing issue, please fully power off your console and try again.
- As mentioned above, missed calls are not implemented yet. Do not expect a log of calls you didn't get to while away.
- Currently, notifications are only sent to the call recipient while in the app; as mentioned above, we know how to trigger them, but this server intercommunication is not yet implemented.
- Expect bugs. Lots of them. We will not be providing much technical support for the app at this time, due to it's early nature and the fact that we know there are issues.
We hope you enjoy Wii U Chat!
# The End, For Now
That's all we've got to share for now. There's sure to be more updates in the future, so come back again later for more.

89
content/blog/11-1-24.md Normal file
View File

@@ -0,0 +1,89 @@
---
title: "October Progress Update"
author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "November 1, 2024"
caption: "Archiverse, new team members, new server architecture and more!"
cover_image: "/assets/images/blogposts/11-1-24.webp"
---
Welcome back to another progress report. While it may seem like not a lot has been going on lately, we've been hard at work in private working on some exciting new updates to share! This blog post will serve as both an announcement for some upcoming features/additions, as well as a sneak-peak behind the scenes to see what sort of experiments we've been running!
# Archiverse
As many of you know, the original Miiverse service shut down late 2017. However before the service went dark for good, a team of dedicated archivists known as [Archive Team](https://wiki.archiveteam.org) managed to archive 17TB worth of posts, drawings, and images. This data was then published onto the [Internet Archive](https://archive.org).
A group known as Archiverse was later established in 2018, providing the archived data both for modern audiences who may not have experienced Miiverse in its prime, and those feeling nostalgic who want to see themselves and what they were doing all those years ago, formally accessible at [archiverse.guide](https://archiverse.guide). In early 2024 the original maintainer left the project, leaving it in the hands of a new team now accessible at [archiverse.app](https://archiverse.app).
We are happy to announce that we have come together with the new maintainers of Archiverse to merge our services! Archiverse is now an official Pretendo Network service, with the intent to have full (read-only) integrations within the on-console Miiverse apps and in games. This migration will take some time to complete, as we work towards moving many terabytes of data to our systems and finalizing the modifications needed to integrate everything, so stay tuned for a future blog post announcing the migration's completion!
Archiverse can now be visited at [archiverse.pretendo.network](https://archiverse.pretendo.network)!
**_Note: Archiverse data will be read-only, and will not be able to be modified by any account system, PNID or otherwise. Functions like "Yeahs", comments, etc. will be disabled when using Archiverse. The data used by Archiverse was taken from the browser version of Miiverse, meaning it lacks some critical in-game data needed for some games which may be impossible to recover, as it was only accessible via the Miiverse in-game API. Archiverse support in games will vary on a game-by-game basis depending on what data can and cannot be recovered/reconstructed._**
# New Members
With the aforementioned project merge with Archiverse, we'd like to welcome our two newest team members joining us along for the ride! Please welcome [SuperFX](https://kylewade.dev) and [Luna](https://github.com/masopuppy), the lead maintainer and designer of Archiverse respectively. Originally only helping out with the migration, we've now offered them official spots on our development team. Both are incredibly talented web developers/designers, so expect to see some exciting new features and improvements rolling out in the future.
# New Licensing
We encourage others to use our work in other 3rd party projects, such as [GoCentral](https://rb3e.rbenhanced.rocks/), custom "Rock Central" servers for Rock Band 3 on the Wii, PlayStation 3, and Xbox 360. To maintain openness, we typically license our work in ways that prevent privatization. Most of our work has been licensed under [AGPLv3](https://choosealicense.com/licenses/agpl-3.0), as it ensures "network use" (running software on a server) is treated as "distribution", which aligns with our focus on server-based projects.
However, AGPLv3's strict requirements can be too restrictive, as it forces works which use the AGPLv3 licensed work (even as a library, or a non-derivative work) to also adopt AGPLv3 in its entirety, limiting compatibility with other, more permissive, licenses such as [Apache 2.0](https://choosealicense.com/licenses/apache-2.0). While this infectious nature has benefits, we recognize the need for more flexibility in certain cases. Thus, we will be reviewing some repositories when appropriate to see if less restrictive licenses could work better for specific projects.
One project, our [`error-codes`](https://github.com/PretendoNetwork/error-codes) library for Wii U/3DS, [has already been re-licensed](https://github.com/PretendoNetwork/error-codes/pull/15) under [LGPLv3](https://choosealicense.com/licenses/lgpl-3.0), which offers similar protections to AGPLv3 but is less restrictive and avoids the full infection of AGPLv3. We will still use AGPLv3 for most projects however as other licenses lack the "network use is distribution" clause which makes it unsuitable for purely server-side software.
# Enhanced Multiplayer with Relays
We have begun some experiments of a new method of handling multiplayer sessions known as "relays". The networking library Nintendo used for Nintendo Network has support for relays, however they go unused officially and many games have the relay functionality stripped out to varying degrees. We have begun our own attempt at manually recreating the concept in order to boost security and stability in the future.
**_Note: Relays are highly experimental, and not widely tested. We have seen promising results during some initial private tests, however these tests were tiny in scale and nothing suggests these are ready for any sort of public use. The experiment MAY be scrapped if found to be inviable in the future. Relays are not deployed on any game server, beta or otherwise, at this time._**
Some background: All games on Nintendo Network which feature multiplayer are P2P ([peer-to-peer](https://en.wikipedia.org/wiki/Peer-to-peer)). Nintendo uses very little in terms of dedicated servers, opting to only use dedicated servers for features such as object storage and leaderboards. This means that rather than your console talking to a server the entire time, your console instead talks directly to other consoles in a [mesh](https://en.wikipedia.org/wiki/Mesh_networking). Our servers act as the middlemen, managing individual client connections and grouping them together in what's known as a "gathering", also called a "session". Once a gathering is created on the server, users may join it. The server then tells all the relevant clients in the session who each of the other players are (either directly on join or through live notifications after already joining), and then your consoles begin talking to each other after establishing connections following [NAT traversal](<https://en.wikipedia.org/wiki/Hole_punching_(networking)>).
This architecture has several pros, including:
1. Less strain on the servers
2. Potentially lower latency for clients geographically closer to each other
3. P2P networks tend to be very good at self-adjusting to account for dropped/new connections
However it does come with some notable cons, such as:
1. Connection issues due to incompatible networks, resulting in failed NAT traversal (very common cause of `118-XXXX` errors)
2. Potential security concerns over direct visibility of other clients IP addresses
3. Lack of server involvement makes cheating/hacking much easier
4. Potentially _higher_ latency for clients geographically _farther_ from each other or between those with slower home internet speeds
Relays are designed to try and combat some of these cons. Rather than the matchmaking server telling each client the addresses of other players, the server would instead provide the address for a running relay server. Clients then connect to these relay servers as if they were other clients in the mesh. The server then accepts all incoming P2P packets and routes them to the other players also connected to the relay as needed. These relay servers effectively turn P2P games into client->server games.
Routing this session traffic through our own relay servers could fix many of the cons associated with P2P networking, including:
1. Removing the issue of incompatible networks, as now you are only talking to our server and not directly to another user
2. Effectively masking your IP address from other users, as now the only addresses being used would be ours
3. Logging of gameplay events to look for anomalies, and even logging entire sessions for later review in the style of [Hypixel Atlas "Replays"](https://support.hypixel.net/hc/en-us/articles/4411166834834-About-the-Hypixel-Replay-System-and-Atlas) to more easily track and report cheaters
4. More efficient player kicks on a per-session basis
Early tests in Splatoon showed promising results, being able to complete several test matches while running through relays with no direct connections between users. However this system is still in it's infancy and many technical and design quirks have not been ironed out, including managing many relays at scale, increased cost estimations due to increased data usage on our servers, etc. We do not have an ETA for when this system will arrive or in what shape/form it would take.
# New Games and Updated Matchmaking
At the moment we are prioritizing improving our internal tooling, underlying networking libraries, game server protocol implementations, and more rather than prioritizing the total number of games we output. However we may decide to release new games if it relates to those efforts, such as games which use features which have yet to be tested, or simple games used to test large-scale changes just as reworks to common protocols.
As of today we are releasing 2 new games into beta testing:
- Monster Hunter 4 Ultimate
- Super Street Fighter IV
These games had their servers created using some experimental internal tooling we are developing to help streamline to creation of simple game servers. In these cases, the backends for these servers were entirely generated automatically! These servers also serve as a test for the [large-scale matchmaking rework](https://github.com/PretendoNetwork/nex-protocols-common-go/pull/35) that [DaniElectra](https://github.com/DaniElectra) has been working on the past few months!
These matchmaking reworks bring not only better matchmaking logic in general, but also more stable session tracking and creation. These changes give us more control over match management and can be used for more accurate player tracking/moderation, even in cases where players may try to anonymize themselves or mask their user information in local connections.
Pending the results of the matchmaking tests, existing games may soon be getting the same matchmaking rework to try and improve the quality of matchmaking. Similarly, smaller/simple games may be released more often pending the results of our new internal tooling.
Additionally, Minecraft: Wii U Edition has been upgraded with this matchmaking rework, fixing the bug where only 2 players can connect at a time. These changes are available to the public for more widespread testing.
Finally, we have recently documented all the official names for `118-XXXX` error codes. Using this knowledge, we have begun to identify some potential causes for several of these errors. These are now also being looked into, in an effort to improve our matchmaking logic and reduce the number of incompatible clients being put in the same sessions. For details, see the [official feature enhancement request on GitHub](https://github.com/PretendoNetwork/nex-protocols-common-go/issues/43).
# Conclusion
While this month did not see much in the way of new public features, we've been hard at work on many internal affairs. We hope you enjoyed our first more "technical"/"behind the scenes" blog post, and we hope to add more updates like these to future blog posts, mixed in with actual content updates!

View File

@@ -4,41 +4,52 @@ author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "November 14, 2021"
caption: "Progress made in the month of October"
cover_image: "/assets/images/blogposts/11-14-21.jpg"
cover_image: "/assets/images/blogposts/11-14-21.webp"
---
### If you want to see more frequent updates, consider supporting us on [**Patreon**](https://patreon.com/PretendoNetwork)
# Introduction
Welcome to the October monthly recap. While not a lot of updates happened, the ones which did were important!
## RSS
Small update to the website, we now have an RSS feed for blog posts! Use your favorite reader to keep up to date on all our blog posts
## Stability
Both `nex-go` and `nex-protocols-go` recieved several stability, code quality, and feature updates. These include, but are not limited to, RMC Request creation, fixing packet fragment IDs not being used, many new types being supported in our `StreamIn` and `StreamOut` structs, and a server ping timeout to properly close connections when a client leaves. These all make the network work much better and feel much more cohesive
## Where is everyone?
The core of online multiplayer is connecting users together. On the Wii U and 3DS, multiplayer is handled via a p2p (peer-to-peer) connection, where one use is assigned as the "host" allowing other users to directly connect to their game session. The technology behind allowing users to connect to other users using arbitrary ports is called `NAT Traversal`. Until now, `NAT Traversal` was not working correctly and clients needed to open all ports to connect. Thanks to developer [shutterbug](https://github.com/shutterbug2000) `NAT` now properly works!
![Screenshot of shutterbug showing off NAT traversal using mario kart 7](/assets/images/blogposts/screenshot-of-shutterbug-showing-off-nat-traversal-using-mario-kart-7.png)
![Screenshot of shutterbug showing off NAT traversal using mario kart 7](/assets/images/blogposts/screenshot-of-shutterbug-showing-off-nat-traversal-using-mario-kart-7.webp)
## Rev your engines!
Both Mario Kart 7 and Mario Kart 8 have started going online and can play matches. These games are far from complete but this is a great stepping stone. Patrons can access the beta servers for Mario Kart 8 right now, Mario Kart 7 has no servers available however. [CTGP-7](https://ctgp-7.github.io/) is also confirmed working for Mario Kart 7, and [CTGP-Café](https://rambo6glaz.github.io/CTGP-Cafe/) being planned for testing as well with full integration planned for both
![Screenshot of Billy showing off CTGP-7](/assets/images/blogposts/screenshot-of-billy-showing-off-ctgp-7.png)
![Screenshot of Billy showing off CTGP-7](/assets/images/blogposts/screenshot-of-billy-showing-off-ctgp-7.webp)
[yt-iframe](W974FEDIoAA)
::md-iframe{video-id="W974FEDIoAA"}
::
## Hello YouTube!
An unintended side effect of working on Miiverse support in Mario Kart 8 was YouTube uploading being re-enabled! You can now upload race clips from Mario Kart 8 to YouTube again. Patrons who run the Miiverse patch can try this feature out right now
[yt-iframe](d3Bq7auupV0)
::md-iframe{video-id="d3Bq7auupV0"}
::
## Squid Game
Splatoon multiplayer battles now works! As of now only private friend battles have been tested, but they seem to be working without issue
[yt-iframe](d_qFnXrP7a4)
::md-iframe{video-id="d_qFnXrP7a4"}
::
## Friendship is magic
The friends server received some big updates. You can now properly set your privacy settings, add friends, and receive notifications from the server on what your friends are playing
The friends server received some big updates. You can now properly set your privacy settings, add friends, and receive notifications from the server on what your friends are playing

View File

@@ -4,17 +4,19 @@ author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "December 23, 2023"
caption: "Information regarding Nintendo's rollout of the Nintendo Network shutdown"
cover_image: "/assets/images/blogposts/12-23-23.jpg"
cover_image: "/assets/images/blogposts/12-23-23.webp"
---
## EDIT December 27th, 2023: THIS INFORMATION IS NOW OUTDATED. SEE https://pretendo.network/blog/12-27-23. THIS POST WILL REMAIN UP ONLY FOR HISTORICAL REASONS
## Intro
First, we would like to apologize for the lack of blog posts this year. We planned to do more, but other priorities kept getting in the way. We continued to provide updates through our Discord and social medias during this time, but we plan to use this blog more often now.
This blog post will be a bit more serious than previous posts, as the subject matter is rather somber. We apologize for the lack of energy and quips you may have enjoyed in previous posts. This post will have information regarding several aspects of the shutdown, some of which have been covered on other social media posts. Please use the table of contents below to jump to your desired section.
## Table of Contents
1. [The Shutdown](#the-shutdown)
2. [Super Mario Maker](#super-mario-maker)
3. [New Accounts (Prerequisite)](#new-accounts-prerequisite)
@@ -22,13 +24,15 @@ This blog post will be a bit more serious than previous posts, as the subject ma
5. [Conclusion](#conclusion)
## The Shutdown
In October of 2023, Nintendo [announced the shutdown of Nintendo Network](https://en-americas-support.nintendo.com/app/answers/detail/a_id/63227/~/announcement-of-discontinuation-of-online-services-for-nintendo-3ds-and-wii-u) for April of 2024. It was stated that a specific date and time would be announced later, and as of this post that has not happened yet. There have been no public announcements of any services shutting down early, though Nintendo stated they reserve they right to do so if:
> *"an event occurs that would make it difficult to continue online services for Nintendo 3DS and Wii U software"*
> _"an event occurs that would make it difficult to continue online services for Nintendo 3DS and Wii U software"_
However, it appears that Nintendo has begun a slow rollout of shutdowns. Intentional or not.
## Super Mario Maker
This information was also detailed in a [Twitter thread](https://twitter.com/PretendoNetwork/status/1736325668412031255). You may read this there if you wish, or read the repost below.
Some time in early December 2023, Super Mario Maker began throwing error `106-0502` very often when trying to connect. It is unclear when this truly began, but the earliest occurrences we could find were around the 8th of December. Upon inspection, the cause for this error was clear: the server the game was attempting to connect to no longer existed. Our first assumption was that this was the beginning of the shutdown early, that Nintendo may have started turning off games without notice. After some more research, however, we discovered some users able to still connect.
@@ -44,6 +48,7 @@ Every game on Nintendo Network uses the same 2 authentication servers. However e
We believe this is due to Nintendo attempting to scale back how many servers are running for each game, to save on costs as the shutdown date approaches. They most likely made an error in their presumed load balancer to not remove these now dead servers from the pool of available addresses. We believe this was done completely unintentionally, however Nintendo shows no signs of fixing this error.
## New Accounts (Prerequisite)
As briefly touched on in [Super Mario Maker](#super-mario-maker), Nintendo actually uses a series of internal accounts for several services. For games, these are called "NEX accounts". Some background knowledge is required for this section, which will be gone over now.
NEX is the software Nintendo uses for all 3DS and WiiU games (and some Switch games). It is based on a library called Rendez-Vous, made by Canadian software company [Quazal](https://web.archive.org/web/20040610104624/http://www.quazal.com/modules.php?op=modload&name=Sections&file=index&req=viewarticle&artid=101&page=1). Quazal, before being bought out by Ubisoft, would license Rendez-Vous to anyone. Many games, on many platforms, by many developers, all use some variation of Rendez-Vous as it was highly extensible. This is why our server libraries are [theoretically compatible with Ubisoft games](https://twitter.com/PretendoNetwork/status/1727016210435641508).
@@ -51,11 +56,12 @@ NEX is the software Nintendo uses for all 3DS and WiiU games (and some Switch ga
Nintendo licensed Rendez-Vous and modified it quite a bit, stripping out some more complex features and adding in some custom protocols, rebranding it to NEX. The important takeaway here is that Nintendo did not build this system from scratch, and instead modified a system made for generic game server usage.
## New Accounts
Some time in late December 2023, new accounts could no longer go online in any games on both the WiiU and 3DS.
As mentioned in [New Accounts (Prerequisite)](#new-accounts-prerequisite), Nintendo did not make their game server software from scratch. Rendez-Vous comes with its own account system, likely due to it being designed for use in one-off games. At the time of its development, online multiplayer games were still very new and the concept of a unified account system (such as Nintendo Network or Uplay) spanning many different games made by the same company, was not a thing. Therefore, Nintendo needed to cope with this existing account system in some way.
On the 3DS, the console registers a new NEX account on the Friends server once during the console's setup process. Each 3DS, under normal circumstances, will only ever have a single account at a time (though this is not *always* true, but not relevant). This is why a NNID is not required to play most games online on the 3DS, as games use your NEX account to login to all game servers. Because of this, a new NEX account will never be created again unless the old one is removed using CFW or by factory resetting the console.
On the 3DS, the console registers a new NEX account on the Friends server once during the console's setup process. Each 3DS, under normal circumstances, will only ever have a single account at a time (though this is not _always_ true, but not relevant). This is why a NNID is not required to play most games online on the 3DS, as games use your NEX account to login to all game servers. Because of this, a new NEX account will never be created again unless the old one is removed using CFW or by factory resetting the console.
On the WiiU, a new NEX account is created automatically when the NNID is registered, and the NEX account is linked to this NNID. The console then alerts the Friends server of the new NEX account, much like 3DS. Despite using NNIDs, the WiiU also uses these NEX accounts to go online in all games.
@@ -66,6 +72,7 @@ This synchronization process has been stopped. New NEX accounts are no longer be
It is not clear at this time whether this was intentional or not.
## Conclusion
We ask that you do not spam Nintendo's support lines with these issues. Doing so may cause Nintendo to pull the plug entirely early. There are only 3 possible scenarios:
1. Nintendo is aware of these issues already, and spam would annoy them to the point of pulling the plug.

171
content/blog/12-25-25.md Normal file
View File

@@ -0,0 +1,171 @@
---
title: "Christmas Progress Update"
author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "December 25, 2025"
caption: "Internal changes, Juxtaposition, 3rd party servers and more"
cover_image: "/assets/images/blogposts/december-25-2025/banner.png"
---
These last few months saw a large focus on internal changes to our systems, internal gRPC services, and improvements to Juxtaposition, amongst others!
# Animal Crossing: New Leaf
As Im sure you all remember, on July 24th of this year, we made the unfortunate announcement that we were taking our Animal Crossing: New Leaf servers offline, indefinitely. This was in direct response to reports of an RCE exploit being actively used in the game.
To reiterate, this is an exploit *within the game itself*. It was not caused by our servers, and in fact can be exploited when not online at all via local wireless play. Even still, we felt it best to take the servers down to limit the impact while we investigated.
After several months of testing, research, and talking with famous Animal Crossing content creator [Hunter R.](https://www.youtube.com/@Hunter-R.), a working patch for the exploit was made. Animal Crossing: New Leaf is back online for ALL users as of December 8th! We would like to thank everyone for their patience, and thank all of our testers for helping with the process.
For a deeper explanation of what the exploit is, how it worked, and how we are patching it, see [Hunter R.s breakdown video on YouTube](https://youtu.be/pV0xnIsgGXE).
# Technical Updates
## Account Server
When logging into your account, the server issues 2 tokens:
1. A short lived access token
2. A long lived refresh token
The access token is used by the console/games to identify your account with the account server, for reasons such as querying for user data, requesting additional tokens, etc. These tokens are short lived, forcing a client to reauthenticate after they expire. In order to skip the normal login flow, the client may send the refresh token to the server to "refresh" the login session, getting back a new set of access/refresh tokens.
One of the biggest long-standing bugs with our account server is that it issued "useless" refresh tokens, which were unable to actually refresh the session. This was because refresh tokens were expiring at the same time as the access tokens! Refresh tokens now properly expire and are actually usable.
At the same time, we also changed how service tokens are handled. A "service token" is a token issued by the account server for an "independent service". An "independent service" is essentially any server a game needs to operate which is not a game server written using the NEX library. These are most commonly used by 3rd parties to implement their own servers (RPG Maker FES, Colors! 3D, etc.) or to add supplementary servers that assist the main NEX game server (Super Mario Maker's bookmark site, Pokemon legality checking, etc.). These service tokens are requested using the accounts access token and provide developers a way to ensure a user passed the normal authentication checks to obtain the token, as well as a read-only way to interact with user data.
Initially, we treated service token expiration the same way we treated all token expiration. The token has an associated "expiration time" and, when used on the account server, it would validate that time, rejecting any tokens that had expired. However, this was later found to be inconsistent with how we observed some services operating. [Dani](https://github.com/DaniElectra) noticed some time ago that there are references to [local expiration on the 3DS](https://github.com/PretendoNetwork/juxtaposition/pull/114#issuecomment-2863503035). We also noticed that the request to WaraWara Plaza data seems to always use the same token, no matter how much time has passed. These 2 things, when combined, seem to indicate that service tokens, officially, either did not ever expire, or the expiration was ignored when the independent service validated the token with the account server, presumably allowing each independent service to decide how long a token should be "alive" for.
In light of these observations, we have now also changed our service token handling to be more accurate to the behaviour we observed. Rather than tracking an "expire time", service tokens now track an "issued time", allowing each independent service to pick the length of time a token should be valid for. This marks the first step in our larger plans for a total overhaul of how tokens/account data is processed.
## Account Deletion
Until recently, the only ways to delete your account were using a console or by requesting a deletion via our support forums. We have now updated our account server's internal gRPC service to allow for account deletion requests. This uses the same mechanism under the hood as used by the on-console “Delete Account” button, but now allows us to trigger an account deletion from anywhere we choose. This has allowed us to add a “Delete Account” button to both the website, for you to delete your own accounts without needing a console, and to our admin panel, for moderators to take immediate action in extreme cases.
Additionally, deleting your account will also automatically delete personal data from supported services, such as the forums and Juxtaposition.
***NOTE: DELETING YOUR ACCOUNT WILL NOT FREE YOUR USERNAME FOR REUSE. USERNAMES CAN NEVER BE USED AGAIN ONCE ASSIGNED TO AN ACCOUNT***
## BOSS (SpotPass)
BOSS is a system Nintendo provided to allow titles to request/store data (called objects) using background tasks. This is most commonly used for the SpotPass feature, but is also used to deliver data like system notifications, Splatoon rotations, etc. Over the past few months, we have been working on improving our BOSS server both in terms of developer usability and its general operations. The BOSS server received several upgrades to both how we store and process SpotPass files, our internal gRPC service for managing files, as well as improving our data storage and transport systems. All of these combined should provide a much better SpotPass experience for both users and our team, allowing us to more easily ship data like in-game content, console notifications, etc.
## gRPC
As mentioned in [Account Server](#account-server), we have begun making some updates to our internal [gRPC](https://grpc.io/) services. We use gRPC for [interprocess communication (IPC)](https://en.wikipedia.org/wiki/Inter-process_communication) as a way to communicate and request/send data between services as it is fast, lightweight, strongly typed, and allows services to be easily defined via [protocol buffers](https://protobuf.dev/). [Quarky](https://github.com/ashquarky) recently added the ability to [request device information](https://github.com/PretendoNetwork/grpc/pull/3) for devices linked to a user's account, and we have also begun adding a way to [exchange service tokens for account data](https://github.com/PretendoNetwork/grpc/pull/6). Additionally, we have also begun exploring a brand new [NEX gRPC service](https://github.com/PretendoNetwork/grpc/pull/5). This service would live inside game servers and allow us to interact with them more efficiently, for features such as:
- Moderation. Having a link to the game servers will allow us to kick existing clients from games in instances like account/device bans
- Live notifications
- Pulling server statistics like player counts, multiplayer match data, information about UGC, etc.
## Misc
These are some smaller changes compared to the ones above, but still deserve mentioning
- [Will](https://github.com/binaryoverload) upgraded our [BOSS server to Express 5](https://github.com/PretendoNetwork/BOSS/pull/22). While not a huge change by itself, Express 5 brings in many [new features and improvements](https://expressjs.com/en/guide/migrating-5.html) that we can take advantage of
- [Dani](https://github.com/DaniElectra) has updated our documentation wiki both with [the latest upstream changes](https://github.com/PretendoNetwork/nintendo-wiki/pull/43), as well as [new additions to some older NEX protocols](https://github.com/PretendoNetwork/nintendo-wiki/pull/44)
- The account server received some minor bug fixes. Those being a bug with the 6 digit email codes which would incorrectly block registration if a code was in use by another account already, as well as a bug where 3DS devices would not be properly linked to an account when using the NNAS service, and some updates to token validation
- Various research into many games (including those not on the Wii U/3DS) continues to drive our understanding of these games forward, and continues to be documented on our wiki. We now have documentation for [several previously undocumented protocols](https://github.com/PretendoNetwork/nintendo-wiki/pull/52)
- [JVS](https://github.com/mrjvs) made a new [SMTP relay server](https://github.com/PretendoNetwork/smtp-relay) that has been introduced for use on the forums. Our forums are powered by [Discourse](https://discourse.org/), which requires that *all* accounts have a unique email address. NNIDs, and subsequently PNIDs, do NOT require unique email addresses. As a workaround for this, every forum account is assigned a fake email address using each account's unique PID value. This lets us link PNIDs to the forum, but breaks email support. This new SMTP relay runs alongside the forum and maps the fake email address back to the account's real email address, allowing for email notifications to finally work on user accounts
- Splatoon rotations are now fully automated. Previously, we were working with [OatmealDome](https://github.com/OatmealDome), who used his [Rotationator](https://github.com/OatmealDome/Rotationator) tool to generate our Splatoon rotations every few weeks, which we would then manually upload. Utilizing the new updates to the BOSS server, we were able to [fork OatmealDomes tool](https://github.com/PretendoNetwork/Rotationator) and completely automate the process
# Juxtaposition
Juxtaposition has received a large focus over the past few months. Many hands touched these changes, thank you to [Jemma](https://github.com/CaramelKat), [Quarky](https://github.com/ashquarky), [jvs](https://github.com/mrjvs), and everyone else on the team, as well as all of our outside contributors! There are too many individual changes to list here, so only the biggest changes/PRs will be listed. To get a full breakdown of all the changes, please see the official [Juxtaposition GitHub repository](https://github.com/PretendoNetwork/juxtaposition/) and the [`#github` channel on Discord](https://discord.com/channels/408718485913468928/473698995286573066)
Ingest and processing of images has been overhauled, making more compressed and thumbnail versions of uploaded paintings and screenshots. On pages with lots of images, this makes Juxtaposition load dramatically faster and reduces memory load on 3DS systems especially.
![A Juxtapositon post. "my first house!". An image of a Minecraft house is attached.](/assets/images/blogposts/december-25-2025/image8.png)
*Screenshots like these used to be quite a problem for 3DS users. The full-size version of this image, as uploaded by the Wii U, is 88KiB. The new thumbnail version shown on 3DS is 12KiB - an 80% improvement!*
These changes also include aspect ratio tracking for uploaded images, in case.. future changes involve uploading screenshots of other aspect ratios, for some reason. :) Tracking aspect ratio also helps improve content shift on load.
![An animation showing a Juxtaposition post loading in, with the images appearing gradually.](/assets/images/blogposts/december-25-2025/image4.gif)
*The layout used to move around a lot while the images loaded. Now, everything maintains its proper size during loading. (Load times increased for clarity)*
Banners for 3DS communities can now have a small background area behind the community info. Well be steadily updating communities to take advantage of this design.
![An image of Inklings in battle. Below a purple border and on a gold background, the stats for the Juxtaposition community are listed.](/assets/images/blogposts/december-25-2025/image3.png)
*Splatoon is one of the communities featuring the new design.*
On 3DS, Juxtaposition now calls for manual garbage collection after each page load. This helps clean up unused memory and free it up for the new parts of the page. On the Old 3DS, this appears to have nearly completely eliminated the “blue screen” out of memory issues.
![A screenshot of the Homebrew Community on Juxt 3DS, revealing a solid blue background to the right.](/assets/images/blogposts/december-25-2025/image5.png)
*The blue background is always there, you just cant see it. We hope.*
On 3DS, Juxtapositions design assets have been optimised and re-encoded - things like the background pattern, coloured headers, and tab background. Combined with JavaScript delivery improvements, page sizes (excluding images) have dropped by 60%.
![A grid of various icons.](/assets/images/blogposts/december-25-2025/image2.png)
*Juxtaposition on the 3DS uses this spritesheet for the bulk of its design assets to reduce load times. This way, the console only has to load one large image and show different portions of it. Compression makes this more efficient than loading a dozen smaller images.*
Some quick-fire updates:
- The [logic for creating a new post has been updated](https://github.com/PretendoNetwork/juxtaposition/pull/129) to fix several bugs and "smelly" code
- A new [audit log has been implemented](https://github.com/PretendoNetwork/juxtaposition/pull/136) to track actions performed by moderators
- A new [JSX-based rendering system](https://github.com/PretendoNetwork/juxtaposition/pull/132) is being worked on
![A Juxtaposition DM thread on Wii U. Luca messages Jon about a Splatoon battle. Jon does not respond.](/assets/images/blogposts/december-25-2025/image1.png)
*Message threads are one of the pages on the new JSX renderer.*
- Updates to [the new token format](https://github.com/PretendoNetwork/juxtaposition/pull/131) are being worked implemented
- Several parts of our build system have been improved and the UI portions of the applications are slowing being ported to TypeScript
- An [experimental new framework for structuring Wii U/3DS web applications](https://github.com/PretendoNetwork/Yeah/pull/1) is being worked on. This framework is intended to help modernize the development/workflow of Juxtaposition, making it feel more like a modern web application built with frameworks like [Nuxt](http://nuxt.com/)/[Next](https://nextjs.org/). However this should be usable by anyone wanting to make a web application compatible with the Wii U/3DS
## Juxtaposition on Cemu
While not something we completed ourselves, we felt this to be news worthy enough to be included here. Back in 2023, I began looking into getting the Wii U Miiverse app to run in Cemu. Doing so would solve a pretty big pain-point: lack of a full functional web version of Juxtaposition. We do have a read-only website available right now, however it needs some UI updates and lacks the ability to create posts.
With a few tweaks to Cemu, some patched system files, and a couple of server-side patches, I was able to get the [Miiverse app to load without much issue](https://github.com/PretendoNetwork/Martini/issues/13#issuecomment-2544470882). However there were a number of issues with my approach, namely the fact that it required patched system files. Due to these issues, I shelved the idea indefinitely, telling myself I would pick it back up eventually.
Thanks to the dedicated work by developer [Arian Kordi](https://github.com/ariankordi), Cemu now has the ability to [launch the Miiverse app into Juxtaposition](https://github.com/cemu-project/Cemu/pull/1747) without ANY patched system files! This has not yet made it into an official Cemu release, however the changes have been merged and can be used today if compiled manually.
# Game Servers
While the last few months had a lot of focus on internal changes and Juxtaposition, game servers also saw a lot of attention!
- [Dani](https://github.com/DaniElectra) has begun implementing the [`MessageDelivery` and `Messaging` protocols into our "common" module](https://github.com/PretendoNetwork/nex-protocols-common-go/pull/54). Once complete, these protocols should be widely available to all games
- [Dani](https://github.com/DaniElectra) Has begun [implementing the `MatchmakeExtension::GetPlayingSession`](https://github.com/PretendoNetwork/nex-protocols-common-go/pull/55) NEX method for use in multiplayer games
![The Lobby area in Splatoon 1.](/assets/images/blogposts/december-25-2025/image6.png)
*Splatoon, for its part, calls GetPlayingSession every time you enter the multiplayer lobby.*
- [Trace](https://github.com/TraceEntertains) updated [Yo Kai Watch Blasters](https://github.com/PretendoNetwork/yo-kai-watch-blasters/pull/5) to the latest server libraries, including the above mentioned changes by [Dani](https://github.com/DaniElectra). With this update friend rooms and trading are now functional
- A proposal for updating several areas of state tracking in our underlying PRUDP server [has been created](https://github.com/PretendoNetwork/nex-go/issues/87)
- Puyo Puyo Tetris neared completion, with replay upload and club matchmaking - which previously didnt work - now implemented. Theres one issue left where you cant always see other peoples replays.
![The Replay area in Puyo Puyo Tetris (WiiU), showing a single replay of a battle between Imora and skweed.](/assets/images/blogposts/december-25-2025/image9.png)
*There should be more than one replay listed here. Still, one is better than before!*
## Super Smash Bros. 4
Ever since the games launch, Super Smash Bros. 4 has had an issue where only one lobby can be active at a time for a given game mode. This has been often dubbed the “One True Lobby” bug. Trying to fix this bug has been a priority, and we are happy to announce that we now understand why the bug occurs.
When a client wants to join a multiplayer game, it has 2 options to do so:
1. Searching (internally called “browsing”) for active sessions to join manually
2. “Auto matchmaking”, which automatically puts you into a session
In both options, the client sends the server various details about the kind of session it wants (called [“search criteria”](https://nintendo-wiki.pretendo.network/docs/nex/protocols/match-making/types#matchmakesessionsearchcriteria-structure)) and the various settings/capabilities of the game (such as how many players are joining). If no active sessions exist that match what the client wants/needs, the server creates a new one for the client and automatically assigns them as the host/owner.
The key difference between the 2 matchmaking functions is that “browsing” can return a list of candidate sessions the client can pick from manually, whereas the “auto matchmaking” functions will always automatically join and return the 1st session possible, without user input.
The “One True Lobby” bug occurs due to a previous misunderstanding of 2 of the search criteria settings:
- `m_VacantOnly`
- `m_VacantParticipants`
Through past testing prior to the official servers shutdowns, we knew that these 2 settings controlled whether or not sessions should be considered “invalid” for joining based on the number of current participants. The `m_VacantOnly` controlling whether or sessions with full lobbies are valid, and `m_VacantParticipants` controlling the number of empty slots in the session.
Previously, we misunderstood in which contexts these settings are actually used, and when to ignore them. The `m_VacantOnly` setting has always existed (since NEX v1), however the `m_VacantParticipants` setting was added 2 major and 4 minor versions later (in NEX v3.4). Due to this, it seemed like `m_VacantParticipants` *replaced* the original `m_VacantOnly` setting. We also believed that these settings were treated the same in both matchmaking functions.
We now know this to be incorrect. In reality, `m_VacantOnly` and `m_VacantParticipants` are both still used. `m_VacantOnly` is also only used when using the “browsing” matchmaking function, whereas `m_VacantParticipants` is used in all functions. Logically, this also makes sense. Allowing a game client to see full lobbies may be useful in certain contexts, but would not be needed when “auto” matchmaking, whereas checking the number `m_VacantParticipants` *is* required at all times.
This was confirmed through a mix of previous testing/notes, and by decompiling various titles to inspect their implementations. These decompilation efforts also extend past the Wii U/3DS, as NEX is used in various Switch titles as well, and NEX itself is based on an existing library known as Rendez-Vous which is seen in many non-Nintendo titles. This fix for Super Smash Bros. 4 was helped by decompiling Splatoon 2 on the Switch, as it was the only game we could find that still implemented a mix of both `m_VacantOnly` and `m_VacantParticipants` being used at the same time (confirming that one did not replace the other), highlighting how important research is to improving accuracy and why certain updates may take more time than others.
A temporary fix for the bug is already deployed to production, while a [proper implementation is currently in the works](https://github.com/PretendoNetwork/nex-protocols-common-go/pull/59).
![A screenshot with 3 instances of Cemu and an IDE window. Two of the Cemus are in a battle in Smash 4, while the third is in an empty lobby.](/assets/images/blogposts/december-25-2025/image7.png)
*Image demonstrates 2 lobbies active in 1v1 mode, with 3 users!*
# 3rd Party Integrations
Historically, there has always been some confusion as to what the goals/scope of the project actually are. This is not helped by Nintendos often confusing branding of “Nintendo Network” on certain games. Many people, understandably, assume that our goal is to provide servers for *all* games on the Wii U/3DS. This is, in fact, not the case. Our scope has always been limited to supporting games which use Nintendos 1st-party networking library called NEX. At times, we may provide replacement servers for games whose original servers are trivial to implement, but that is not the standard we hold ourselves to. Those are exceptions. If a game did not use NEX, it should always be assumed that we will not provide servers for it.
This confusion often comes from a mixture of word-of-mouth rumors, and due to Nintendos questionable Nintendo Network branding/developer usage, especially in relation to the name we chose for the project. All games which have any online capabilities and/or make use of your system/network account are branded with the Nintendo Network logo, *even if that game uses its own online servers*. This is because all games on the Wii U/3DS first must go through Nintendos own account servers for account/device authentication (this server is called NASC on the 3DS when not using a NNID, and NNAS when using a NNID on either console). These account servers authenticate your device/account and then issue the game tokens that can be used to identify the user. After this initial authentication, the developer is *free to do anything they wish* with the game. However, since the game DID use Nintendos account servers, the game receives the “Nintendo Network” branding.
Games such as WATCH_DOGS are prime examples of this. They authenticate your NNID, get the identity tokens, and then use those tokens to link your NNID to your Uplay (now Ubisoft Connect) account. After that, the game uses servers entirely ran by Ubisoft for games *actual* online features.
These games are *not* within our projects scope, and we have always felt that the best course of action was to leave those games to their own dedicated teams to revive, as they often require expertise specific to said games which we do not have, and do not wish to add onto our ever growing work load.
That being said, it has always been difficult to accomplish this without potential fragmentation in the community. How could someone make their own WATCH_DOGS servers without an accessible NNAS server, and while ours does not support the game? Requiring these 3rd party teams to run portions of the Nintendo Network infrastructure adds unnecessary load onto them and potentially creates fragmentation in the community.
Because of this obvious issue, we are excited to announce that we have begun the process of allowing 3rd parties to register themselves with us, and providing tools for them to use to officially integrate into Pretendo Network *the exact same way Nintendo did*! Right now we are still in the planning stages, but once completed anyone making servers for games that are out of our scope (or even stand-alone applications that wish to integrate with our services), will be able to do so seamlessly.
For details on how 3rd parties operated officially, and for our current plans to support them ourselves, see [this GitHub feature request](https://github.com/PretendoNetwork/account/issues/202).

View File

@@ -4,42 +4,50 @@ author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "December 27, 2023"
caption: "Updates regarding our last blog post"
cover_image: "/assets/images/blogposts/12-23-23.jpg"
cover_image: "/assets/images/blogposts/12-23-23.webp"
---
### *Edit December 27th, 2023 7:35PM UTC: Nintendo has fixed the friends sync issue during maintenance*
### _Edit December 27th, 2023 7:35PM UTC: Nintendo has fixed the friends sync issue during maintenance_
## Intro
This is an update to our [last blog post](https://pretendo.network/blog/12-23-23), where we discussed some issues regarding Nintendo Network and how they could possibly be linked to the upcoming shutdown. This post aims to provide updates on the situation, as things have begun to improve.
This is a developing situation. As such, this blog post may be updated at any time as new information comes in. Edits will be mentioned above this introduction.
## For the media
We deeply appreciate members of the media wanting to cover this situation, and using us as a trusted source for information. We saw a number of outlets covering our last blog post, and we think it's wonderful they are trying to spread the word. With that said, some outlets did a less than stellar job at reporting our last post, not covering some topics fully or accurately. We would like to ask that members of the media who wish to cover anything posted by us please contact us first to verify the accuracy and legitimacy of the information. We have contacts open on most major social media, and would be happy to discuss things.
## Table of Contents
1. [Thanks](#thanks)
2. [New Account Syncing](#new-account-syncing)
2. [New Account Syncing (Friends)](#new-account-syncing-friends)
3. [Super Mario Maker (Dead Servers)](#super-mario-maker-dead-servers)
4. [Super Mario Maker (AWS)](#super-mario-maker)
5. [Conclusion](#conclusion)
3. [New Account Syncing (Friends)](#new-account-syncing-friends)
4. [Super Mario Maker (Dead Servers)](#super-mario-maker-dead-servers)
5. [Super Mario Maker (AWS)](#super-mario-maker)
6. [Conclusion](#conclusion)
## Thanks
Before we begin, I'd like to thank members of both our community and Nintendo for their parts in this situation. In our last blog post we urged users to not spam Nintendo regarding these issues, which many followed. We would like to thank those who followed that advice, as we have been given confirmation that those actions may have led Nintendo to act "in a way that's negative". We were told this by our media contact, who will remain anonymous. This contact was able to reach out to Nintendo directly, and together we were able to privately forward these issues to the correct channels.
We noted in our last blog post that it was unclear whether these issues were intentional or not, and it appears that this was indeed unintentional. While we cannot confirm whether or not Nintendo will take action on all issues presented to them, we would like to thank Nintendo for taking the time to at least acknowledge the issues and look into correcting them. We would also like to specifically thank the engineers and other IT staff at Nintendo working to maintain these legacy servers despite the impending shutdown.
## New Account Syncing
In our last blog post we went into detail about how some parts of Nintendo's server architecture works, and how this led to new users on both platforms not being able to connect to game servers anymore. We are happy to announce that as of December 26th, 2023 at around 5:00PM UTC this seems to have been corrected. We have verified this with several people internally, on both platforms and in several games. New accounts may now go online as normal.
## New Account Syncing (Friends)
Shortly after our last blog post, we discovered that new friends on the 3DS were also not being synced to other servers even for existing users. This meant that games such as Animal Crossing: New Leaf could not be played with 3DS friends made after the recent server changes, as your friends were no longer being synced. This issue has not yet been confirmed to happen on the Wii U, however due to the Wii U and 3DS sharing a Friends server it is likely this happens on both platforms. We did not publicly disclose this at the time as we were still gathering information in order to accurately report on the issue. Following maintenance on December 27th, 2023 this has been fixed.
## Super Mario Maker (Dead Servers)
Previously announced via Twitter, and briefly touched on in our last blog post, Super Mario Maker's authentication server has an error with the list of game servers it gives to the client to connect to. Most of these servers are no longer online, meaning most attempts to connect to the game will fail. As of writing on December 27th, 2023, this has not yet been fixed. The issue has been raised to Nintendo.
## Super Mario Maker (AWS)
For several months we have been aware of a previously undisclosed issue with Super Mario Maker regarding their use of AWS, specifically S3. Super Mario Maker uploads content such as courses and maker profiles to S3 using a NEX protocol called `DataStore`. This protocol gives the client a way to interact with, and upload new, S3 objects. S3 is a service, originally created by Amazon, to manage objects in a secure, scalable, way. For more information on S3 see the official [AWS docs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html).
When a client connects to Super Mario Maker for the first time, it first checks if your account has a "maker" object in S3 using `DataStore`. If not, the server gives the client a URL it can use to upload your "maker" object. Think of this as simply a file with some metadata that will describe you and your stats as you play the game. This object is required for continuing online, and will not function without it.
@@ -53,4 +61,5 @@ The exception to this being Super Mario Maker. Since its release it has always c
As of December 26th, 2023, Super Mario Maker's game server has been updated to now use this Nintendo-owned proxy. The changes made to AWS will no longer affect the game.
## Conclusion
We would again like to thank our community members and Nintendo for their roles in all of this. Sorting these issues out is a complex task, and we thank our community members who have not spam contacted Nintendo's support hotlines regarding these issues. The customer service reps on these hotlines likely have no influence over the day to day operations of these servers. Additionally, the issues mentioned here have already been brought to the proper channels. We will continue to update this blog post as new information comes in.

View File

@@ -4,12 +4,13 @@ author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "April 8, 2024"
caption: "Hackless Wii U connections, farewell to Nintendo Network, and more"
cover_image: "/assets/images/blogposts/4-8-24.png"
cover_image: "/assets/images/blogposts/4-8-24.webp"
---
Today marks the end of Nintendo Network. As sad as this day is for many, it also comes with some positive developments. In this blog post we'll go over some new developments and plans, including official game support and a new way to connect to Pretendo ***without homebrew***!
Today marks the end of Nintendo Network. As sad as this day is for many, it also comes with some positive developments. In this blog post we'll go over some new developments and plans, including official game support and a new way to connect to Pretendo **_without homebrew_**!
# A Somber Farewell
As of today, April 8th, 2024 Nintendo Network, the online servers powering the Wii U and 3DS's multiplayer, has shut down. Launching in 2012, Nintendo Network lasted exactly 12 years, 2 months, and 14 days (longer than the Wii!). This era of Nintendo's history is often looked down upon, made fun of, even by those of us in the scene. But we believe it's important to highlight the good that came from it, sending this generation off with the respect it deserves.
Unlike the competitors at the time, Nintendo opted to continue with offering their online services free of charge. While it may not have had as many features as competitors, including staples like achievements, private messaging, etc. it cannot be denied that the low barrier of entry made it many users' first time playing online. The inclusion of Miiverse gave the games a sense of community still unseen in the current generation, and is something Nintendo fans and non-Nintendo fans alike would like to see again.
@@ -21,16 +22,19 @@ The 3DS pushed hard for player interactions, going so far as to build systems in
We at the Pretendo Network team, as much as we poke and tease, love these consoles and the impact they had on gaming. The Wii U was truly ahead of its time in many ways, plagued with bad marketing killing its chances at success. We thank Nintendo for giving so many of us entertainment in this era, and bringing many of us closer together.
# SSSL
As a parting gift to you all, we are releasing our private SSL exploit for the Wii U: SSSL! Found by our very own [shutterbug](https://twitter.com/shutterbug20002), this exploit allows users to connect to Pretendo Network from a stock Wii U, with no homebrew or custom firmware at all; only a DNS change! We've been holding on to this exploit for this day for quite some time, in case Nintendo decided to issue patches for it. Select services which use their own SSL libraries are unsupported. This includes several 3rd-party titles like WATCH_DOGS and YouTube, as well as titles which run in an embedded browser like TVii, the eShop, and the Miiverse applet. ***Miiverse functionality IN GAMES is still supported through SSSL!***
As a parting gift to you all, we are releasing our private SSL exploit for the Wii U: SSSL! Found by our very own [shutterbug](https://twitter.com/shutterbug20002), this exploit allows users to connect to Pretendo Network from a stock Wii U, with no homebrew or custom firmware at all; only a DNS change! We've been holding on to this exploit for this day for quite some time, in case Nintendo decided to issue patches for it. Select services which use their own SSL libraries are unsupported. This includes several 3rd-party titles like WATCH_DOGS and YouTube, as well as titles which run in an embedded browser like TVii, the eShop, and the Miiverse applet. **_Miiverse functionality IN GAMES is still supported through SSSL!_**
We hope this new method of connecting will be useful for those who have trouble installing homebrew, those who are worried about mods, and for users who may live in areas where local law may make it more difficult to install mods. For more information, see our [updated setup guide](/docs/install/wiiu)!
### *SSSL is only available for Wii U systems running firmware version 5.5.5 or higher. SSSL is not available for 3DS users.*
### _SSSL is only available for Wii U systems running firmware version 5.5.5 or higher. SSSL is not available for 3DS users._
# Archival
Over the past 6 months, we have been hard at work pushing for the archival of as much data as possible. To that end we created the [Archival Tools repository](https://github.com/PretendoNetwork/archival-tools), a selection of tools dedicated to archiving specific content from various games and services. Together with help from the community at large we have been able to archive several terabytes of this data from various services.
All archived data we have collected, including SpotPass data, Super Mario Maker courses, many games leaderboards, etc. will be posted on the [Internet Archive](https://archive.org) at a later date once it has finished being processed. The data will be freely available for anyone to download. Some of this data will also make its way onto our servers at a later time. Specific dates for these events will come in the future.
# Colors! 3D
As of April 7th, the day before the shutdown, Pretendo has collaborated with the developers of [Colors! 3D](https://www.colorslive.com/purchase/3ds), a drawing and art sharing game for the Nintendo 3DS. Together we have *officially* added support for each other, meaning Colors! 3D will continue to operate as normal when using Pretendo Network. Checkout their game, and their [Discord server](https://www.colorslive.com/discord), for more information on the Colors! franchise!
As of April 7th, the day before the shutdown, Pretendo has collaborated with the developers of [Colors! 3D](https://www.colorslive.com/purchase/3ds), a drawing and art sharing game for the Nintendo 3DS. Together we have _officially_ added support for each other, meaning Colors! 3D will continue to operate as normal when using Pretendo Network. Checkout their game, and their [Discord server](https://www.colorslive.com/discord), for more information on the Colors! franchise!

32
content/blog/5-19-24.md Normal file
View File

@@ -0,0 +1,32 @@
---
title: "Exciting updates for the 3DS"
author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "May 19, 2024"
caption: "StreetPass Relay and 3DS notifications"
cover_image: "/assets/images/blogposts/5-19-24.webp"
---
Today we are releasing 2 big features for the 3DS: 3DS system notifications and StreetPass Relay!
**_(Do note that both features are currently in active development, and may not always function properly. A common solution is to remove and reinsert your system's battery, in order to load the latest policylist, however do note this will have side effects in time-based games! It is common for some users to have one, or both, features not function. These issues are being looked in to)_**
# System Notifications
We can now send your 3DS systems notifications using the built-in notifications app! This allows us to deliver news updates right to your console, without needing to be in our Discord server, forum, or even following our social media. You can get all the latest news about the service, right from the console you're using it on!
**_Not all announcements may make it to the system notifications however, namely very long announcements or those which require rich media like links, images, videos, and more._**
![screenshot of the 3DS notifications app showing the release of SPR](/assets/images/blogposts/spr.webp)
# StreetPass Relay
StreetPass Relay was a feature built into the 3DS which allows users to gain "StreetPass'" from other users, even without physically being near them at the time. This worked by using a "StreetPass Relay Point", a wireless access point used by Nintendo Zone to store StreetPass data. When connecting to one of these relays, your console would upload your own StreetPass data as well as download the data of others from that relay.
With our implementation, StreetPass Relay now works **_GLOBALLY_**, removing the need to be at a physical access point! You can now passively gain passes with other Pretendo users simply by being online. There are 2 things note, however:
1. **_You must be using the latest release of Nimbus for StreetPass Relay to function. Previous versions do not have the correct URL patches for StreetPass Relay. You can download the latest release here https://github.com/PretendoNetwork/Nimbus/releases/latest_**
2. **_Due to the [questionable quality](https://twitter.com/MrNbaYoh/status/1783912413068222477) of the StreetPass parsers inside games and the fact that StreetPass Relay happens automatically, you can ONLY gain passes with people who you are friends with on the 3DS friends server. You will NOT be able to gain passes from any other users through StreetPass Relay._**
![screenshot of the 3DS notifications app showing the notification list](/assets/images/blogposts/notification-list.webp)
![screenshot of the 3DS notifications app showing the SPR notification body](/assets/images/blogposts/notification-body.webp)

79
content/blog/6-2-25.md Normal file
View File

@@ -0,0 +1,79 @@
---
title: "May Progress Update"
author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "June 2, 2025"
caption: "Updates covering the first half of the year"
cover_image: "/assets/images/blogposts/6-2-25.jpg"
---
Hey all, Jon here! We know it's been quite a while since our last blog post. We planned to get these out more often, but alas more important issues and updates came first. We apologize for the lack of blog posts, and promise to get them out as often as we can. With that, halfway into the year seems like as good a time as any to summarize what we've been up to!
(Note: This blog post will not cover *all* changes made since the last post, as there are far too many to list. We will be highlighting the more relevant/larger ones here)
# Technical Updates
Many of you voted to have more technical updates in blog posts from now on, and today marks the first time we do!
## Splatoon Database Performance
Around May 26th, 2025 we noticed random instability in Splatoon. The game would work for a while, allowing players to create new, and join existing, matches, before seemingly randomly locking up. This locking up would cause subsequent requests to never get a response from the server, resulting in failed connections. Developers [shutterbug](https://github.com/shutterbug2000) and [quarky](https://github.com/ashquarky) quickly began investigating. We were unsure where the issue was at, but we had a pretty good idea of where to look. The locks could be happening in 2 places:
1. The application layer. A few examples being:
1. A locked [mutex](https://en.wikipedia.org/wiki/Lock_(computer_science)) which never releases. Our servers are written in [Go](https://go.dev/), and make use of [goroutines](https://go.dev/doc/effective_go#goroutines) for concurrency. Primitive Go types such as [slices](https://go.dev/doc/effective_go#slices) and [maps](https://go.dev/doc/effective_go#maps) can only be accessed by one goroutine at a time. To ensure this, a mutex is used to lock access when a goroutine needs the data, and is released when it's done with it. If a goroutine were to lock up and never release the mutex, then future goroutines will never be able to access it, and also be locked up waiting for the mutex to release.
2. A poorly structured SQL query could lock up the database connection at the application layer, causing future requests to no longer be able to access the database.
2. The database layer. A few examples being:
1. Database corruption could lead to queries failing or getting stuck, locking up the connection.
2. Poor indexing causing full table scans on massive tables, locking up the connection.
3. Bad queries causing the table to infinitely loop and lookup in itself, locking up the connection.
Shutter began by checking the code for locked mutexes and the server logs for any abnormalities. Our game server libraries are split into 3 separate modules, one of which we colloquially refer to as ["common"](https://github.com/PretendoNetwork/nex-protocols-common-go). This module holds all the "common" default implementations of features used by many games. Quarky began by investigating the database itself. Together, they were able to narrow down the problem areas to 2 functions. Lockups would happen in the [`MatchmakeExtension::AutoMatchmake_Postpone`](https://github.com/PretendoNetwork/nex-protocols-common-go/blob/50586821d228cdc2bae728797febdae51e67fe5b/matchmake-extension/auto_matchmake_postpone.go) and [`MatchMaking::UnregisterGathering`](https://github.com/PretendoNetwork/nex-protocols-common-go/blob/50586821d228cdc2bae728797febdae51e67fe5b/match-making/unregister_gathering.go) functions. These functions are responsible for creating/joining multiplayer sessions, and for deleting them when the game is over.
There did not appear to be any areas where a mutex would not release, so we switched our attention back to the database itself. We had noticed some wonky behavior from the database earlier as well, later fixed by [Will](https://github.com/binaryoverload), and I had a hunch that this is where the issue would lie as well. Upon investigation, we found several instances of poor database performance, such as a lack of indexes on some "hot spots" resulting in slower queries. Most notably, we found 2 queries that had become locked, running over 7 and 9 hours respectively. These queries are what was causing the database to lock up, and requests to not get responses. But we still didn't quite know WHY they were locking. It was not initially clear if the issue was due to a looping query, poor indexes, or database corruption. The database in question only held ephemeral data about temporary matches, however, so we opted to just rebuild the database and add in the missing indexes at the same time. Doing so would cover both possibilities of database corruption and missing queries causing the locks, and so far things have once again become stable.
During the investigation I also noticed a lack of a proper timeout mechanism in the Go functions that made the database queries. Regardless of the reason for *why* the queries locked up, having a timeout would prevent things from looping *forever*.
This investigation has highlighted some key areas of improvement in regards to our database performance, and we have already begun investigating using even better indexes (currently being tested in Minecraft) and will begin to implement proper query timeouts. So while it is unfortunate that Splatoon was down, in the end this will result in even better performance moving forward.
## `DataStore` Protocol Rework
As mentioned above, many games share a "common" implementation of certain features. This allows us to define this functionality once and simply tell a server to use it. In the past, our philosophy was to be as unopinionated as possible in this regard, only implementing basic boilerplate for the functions and providing developers a series of configurations and hooks to use. The actual *logic* of the functions was still up to the developers to set. This was done so that developers outside of our team could more easily integrate our code into their systems, by just hooking up whatever stack they already use.
We have recognized the limitations of this approach however, and have decided to become more opinionated. This first took place in the matchmaking code, made by [Dani](https://github.com/DaniElectra), making it so that all the logic for matchmaking now lives in our "common" module. This now allows our code to be more "plug-and-play", simply telling servers to use matchmaking and letting our logic do the rest.
Another protocol which used this unopinionated philosophy was our [`DataStore`](https://nintendo-wiki.pretendo.network/docs/nex/protocols/datastore) implementation. `DataStore` is a protocol developed by Nintendo allowing for "object" (file) storage in games, essentially acting as a frontend for [S3](https://en.wikipedia.org/wiki/Amazon_S3). This protocol is what powers games like Super Mario Maker (courses are "objects"), Animal Crossing: New Leaf (dreams are "objects"), Mario vs. Donkey Kong: Tipping Stars (levels are "objects"), and more.
We have now begun the process of moving our `DataStore` implementation into a more opinionated implementation, allowing for the same sort of "plug-and-play" nature as seen in the matchmaking changes. Progress can be seen [here](https://github.com/PretendoNetwork/nex-protocols-common-go/pull/53). Once finished, this will be our first *fully complete* protocol implementation, allowing for MANY games to get their "object" features working without any extra work. This is also why Mario vs. Donkey Kong: Tipping Stars is still offline, it is so old that it needs to be rewritten from the ground up and is mostly just `DataStore`, making it the perfect candidate to test these new changes against.
Eventually we hope to do this with *all* protocols in the future.
# New Games/Updates
Several new games have joined us since our last blog post! Both existing games coming out of beta, and entirely new games!
Also a big thank you to everyone outside of our team as well for helping debug and suggest changes!
## Splatoon
As a belated celebration for Splatoon's 10th anniversary (we deeply apologize that the stability issues mentioned above prevented us from doing anything on time), for the next round of rotations (starting June 7th) our rotations will feature previously banned stages! Allowing banned stages has been a highly requested feature for a long time, so we felt this was a good time to try it out!
## Animal Crossing: New Leaf
Thanks to the work by [shoginyan](https://github.com/shoginyan) and [shutterbug](https://github.com/shutterbug2000), Animal Crossing: New Leaf has officially left beta testing and is available to everyone! Note that Dream Suite is not yet implemented (see [`DataStore` Protocol Rework](#datastore-protocol-rework)), but multiplayer is supported! We've also identified an issue regarding best-friend messages, of which a fix is being actively tested.
## Mario Kart 7 Communities
Mario Kart 7 now has partial support for communities! Leaderboards are not currently implemented, as Mario Kart 7 uses a version of the [`Ranking`](https://nintendo-wiki.pretendo.network/docs/nex/protocols/ranking/legacy) that is very different to the one used by modern games.
## Yo-kai Watch 2 and Yo-kai Watch Blasters
[shoginyan](https://github.com/shoginyan) has also kick-started Yo-kai Watch 2 and Yo-kai Watch Blasters both into development! Yo-kai Watch 2 has left beta and is available to everyone, while Yo-kai Watch Blasters (and variants) is currently in beta testing.
## Monster Hunter 4 Ultimate
Monster Hunter 4 Ultimate has officially left beta testing! We have also removed the region lock, allowing for experimental crossplay between MH4U and MH4G players! You may encounter technical difficulties when playing across regions due to this experimentation, so please report any issues you encounter to [the game's issue tracker](https://github.com/PretendoNetwork/monster-hunter-4-ultimate/issues/new/choose).
## Swapdoodle
Swapdoodle was one of the first titles Dani wanted to work on, prior to him joining our core dev team. After joining, focus was shifted elsewhere and work stopped on Swapdoodle fairly early. However thanks to the work by outside contributors [Silver-Volt4](https://github.com/Silver-Volt4) and [CenTdemeern1](https://github.com/CenTdemeern1), work on Swapdoodle has once again picked up! They took it upon themselves to implement the server entirely, with promising results! For more information, see:
- https://forum.pretendo.network/t/we-implemented-swapdoodle-and-would-like-to-contribute-it/16204
- https://github.com/PretendoNetwork/swapdoodle/pull/1
## Dr. Luigi and Dr. Mario: Miracle Cure
Both Dr. Luigi and Dr. Mario: Miracle Cure have officially left beta testing! Both titles are now available to the public!
## The Legend of Zelda: Tri Force Heroes
After several months of downtime, The Legend of Zelda: Tri Force Heroes is officially back online! This was one of our legacy games requiring upgrades to our latest libraries, and has finally had its issues ironed out. Due to some recent changes to our general matchmaking code, the games multiplayer region lock was unintentionally returned. This is being looked into and should be fixed in due time.

98
content/blog/6-29-24.md Normal file
View File

@@ -0,0 +1,98 @@
---
title: "June Progress Update"
author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "June 29, 2024"
caption: "Updates on 6 games, including beta testing for Smash, Puyo Puyo Tetris, and more!"
cover_image: "/assets/images/blogposts/june-29-2024/preview.webp"
---
_Credits for preview image:_
- Toon Link - https://www.smashbros.com/wiiu-3ds/us/characters/toon_link.html
As June comes to a close we'd like to take this time to welcome some new team members and give some updates on what work we've been doing, including beta testing for some brand new games!
# New Teammates
To kick things off I'd like to welcome 2 of our latest teammates [MatthewL246](https://github.com/MatthewL246) and [wolfendale](https://github.com/wolfendale)! Together they have been doing some fantastic work, some of which is still yet to be seen.
[MatthewL246](https://github.com/MatthewL246) has been hard at work introducing Docker configurations to our servers, as well as working with [SuperMarioDaBom](https://github.com/SuperMarioDaBom) and 2 non-Pretendo developers [Jelle van Snik (mrjvs)](https://mrjvs.com) and [William Oldham (BinaryOverload)](https://williamoldham.co.uk), to prepare our services for their eventual move to our new infrastructure! While much of this work has not been deployed yet, it is vital for Pretendo moving forward as we transition to a containerized deployment on real hardware. These changes will make managing and deploying servers much simpler in the future.
[wolfendale](https://github.com/wolfendale) has been working tirelessly with [DaniElectra](https://github.com/danielectra) and myself on [`nex-go`](https://github.com/PretendoNetwork/nex-go), and some related services. This library is the **_heart_** of our game servers, implementing the lower level transport protocols and tools/features needed to build _all_ of our game servers, and is one of the more difficult areas to work in. The work done on this library is priceless, and will have positive effects on all games across the board.
# General Server Updates
Before talking about the new games joining our beta testing, we'd like to touch on some more general updates which apply to all games. As mentioned, [wolfendale](https://github.com/wolfendale) has been working almost exclusively on [`nex-go`](https://github.com/PretendoNetwork/nex-go) since joining the team. He, along with [DaniElectra](https://github.com/danielectra) and myself, has been doing fantastic work on debugging some long-standing issues, providing bug fixes and optimizations, introducing new unit testing, and implementing some key missing features. This work not only drastically improves stability, but brings our implementation closer to the original with more accurate emulation.
He has also been tackling the task of [optimizing our database queries](https://github.com/PretendoNetwork/friends/pull/22) on the friends server. The friends server is one of the most important services of Nintendo Network. Without a stable connection to the friends server, the console will not attempt to connect to any individual game server, and is the cause of the common [X01-0502](https://forum.pretendo.network/t/error-code-101-0502-no-solution/1426/5?u=pn_jon) error. Optimizations and bug fixes like these to the friends server will ensure connections to game servers also remain stable.
While most of these updates have not yet been deployed yet (a select few have been hot-patched into existing deployments), and some have not yet been merged at all, the changes that have been made recently should show very positive results once deployed (including tackling the common [X01-0502](https://forum.pretendo.network/t/error-code-101-0502-no-solution/1426/5?u=pn_jon) error). We hope to get all of these new updates out relatively soon, so that all games may benefit from the added stability.
![Screenshot of shutter on Discord saying "@ashquarky @Jon @DaniElectra ok so! i can confirm 2 things: 1: Splatoon is now working on nex v2 (i was having @ashquarky [PN_quarky] change the wrong thing lol) 2: Splatoon did not work until I used the master version of nex-go, this means that the new changes to nex-go likely help a lot with stability 🎉"](/assets/images/blogposts/june-29-2024/shutter-nex-go.webp)
[DaniElectra](https://github.com/danielectra) has also been spending quite some time [reworking our matchmaking logic from scratch](https://github.com/PretendoNetwork/nex-protocols-common-go/pull/35). These updates should bring more stability when it comes to matchmaking, as well as better tooling for developers to work on new games.
Similarly to [Dani's](https://github.com/danielectra) matchmaking rework, I have been [reworking our entire type system from scratch](https://github.com/PretendoNetwork/nex-go/pull/56). These changes should provide a much better development experience for us moving forward, streamlining many previously difficult to do tasks such as data storage and storing type data in databases. This should result in faster, and more reliable, server development moving forward.
# New Games and Updates
Now into what most of you came here for; new games and updates in beta testing! This blog post will cover a whopping **_ten_** games. Some games are receiving general updates, while others are joining us for the first time. We will also be aiming to release some smaller, simpler, games on a more frequent basis. Some games share much of their internals with existing games, making it trivial to get the basics up and running. We do not have an official release schedule, but we expect to release more simple games more often.
_Most of the games mentioned here are only available for beta testers at the time of writing._
_All games begin their life in beta testing, only available to testers. Once more features have been added, and pending the evaluation of each game's stability, they will each become available to the general public on a game-by-game basis. Until then, consider [supporting the project](https://pretendo.network/account/upgrade) to gain early beta access_
**_BETA SERVERS ARE NOT CONSIDERED STABLE, AND OFTEN LACK MANY FEATURES. USE AT YOUR OWN RISK_**
## 🥄
Thanks to work done by [wolfendale](https://github.com/wolfendale), [DaniElectra](https://github.com/danielectra) and myself on [`nex-go`](https://github.com/PretendoNetwork/nex-go), as well as work down by [Ash](https://github.com/ashquarky) and [shutterbug](https://github.com/shutterbug2000) on our [Splatoon netcode specifically](https://github.com/PretendoNetwork/splatoon/pull/2), Splatoon has **_officially_** begun its migration to our newest library versions. These changes have, so far, resulted in much more stable and reliable matchmaking across the board. These changes are available **_TODAY_**, for **_everyone_**!
If you experience any issues with Splatoon still, feel free to reach out for support on our [support forum](https://forum.pretendo.network/c/support/6) and file bug reports on the [Splatoon GitHub repository](https://github.com/PretendoNetwork/splatoon).
![Screenshot of a pending Splatoon lobby](/assets/images/blogposts/june-29-2024/splatoon-match.webp)
## A New Title Appears
Thanks to work done by [SuperMarioDaBom](https://github.com/SuperMarioDaBom), **Super Smash Bros. 4 Wii U** is now **_officially_** available for beta testers! The 3DS version is not currently supported, though the controller app should work. Not everything is implemented, however matchmaking is working as expected. Spectating and sharing do not work, nor has Miiverse integration been tested. Attempting to share anything in game may cause the game to stop responding due to unimplemented methods.
![Screenshot of Pikachu and Toon Link fighting in Smash 4 on the Wii U](/assets/images/blogposts/june-29-2024/smash4-wiiu-match.webp)
## Gotta Catch 'em All!
Thanks to work done by [shutterbug](https://github.com/shutterbug2000), **Pokémon Generation 6 (X & Y, Omega Ruby & Alpha Sapphire)** is now **_officially_** available for beta testers! Not all features have been implemented. While still early in development, and missing some recent stability fixes, wonder trades have been fully implemented, and PSS is in active development!
<center>
| | |
| ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| ![Screenshot of Pokemon finding a trade](/assets/images/blogposts/june-29-2024/pokemon-partner-found.webp) | ![Screenshot of Pokemon finishing a trade](/assets/images/blogposts/june-29-2024/pokemon-trade-complete.webp) |
</center>
## Puyo!
Thanks to work done by [Ash](https://github.com/ashquarky), **Puyo Puyo Tetris** is now being worked on. Matchmaking and rankings are both working as expected. This game is not yet available for beta testing, as it relies on unreleased library changes, however it will be released for beta testers soon!
| | |
| ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| ![Screenshot of Puyo Puyo Tetris in a match](/assets/images/blogposts/june-29-2024/puyo-puyo-wiiu-match.webp) | ![Screenshot of Puyo Puyo Tetris rankings](/assets/images/blogposts/june-29-2024/puyo-puyo-wiiu-rankings.webp) |
## An Apple a Day
Thanks to work done by [shutterbug](https://github.com/shutterbug2000), _both_ **Dr. Luigi (Wii U) and Dr. Mario: Miracle Cure (3DS)** are now **_officially_** available for beta testers! Both games feature fully implemented matchmaking and rankings.
| | |
| -------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| <img src="/assets/images/blogposts/june-29-2024/dr-luigi-wiiu-match.webp" alt="Screenshot of Dr. Luigi in a match" width="800"/> | ![Screenshot of Dr. Mario in a match](/assets/images/blogposts/june-29-2024/dr-mario-3ds-match.webp) |
## Minecraft
Minecraft has been available for beta testers for some time now, and is now receiving some new updates! Thanks to work done by [Ash](https://github.com/ashquarky), Minecraft is being updated to the latest version of our libraries which should bring with it more stability and feature support!
![Screenshot of Minecraft in a minigame lobby](/assets/images/blogposts/june-29-2024/minecraft-wiiu-minigame.webp)
# Conclusion
![Screenshot of ACNL saying "Hello there, Mayor Pretendo" teasing ACNL being worked on](/assets/images/blogposts/june-29-2024/mayor-pretendo.webp)

54
content/blog/7-17-26.md Normal file
View File

@@ -0,0 +1,54 @@
---
title: "July 15 security incident"
author: "Dani"
author_image: "https://www.github.com/DaniElectra.png"
date: "July 17, 2026"
caption: "What happened and what we are doing to prevent this from happening again"
cover_image: "/assets/images/blogposts/7-17-26.webp"
---
Hi everyone. We are unfortunate to tell you that we have experienced a security incident. I didn't expect this to be my first blog post, but we want to disclose what happened before, during and after the unplanned maintenance and what we are doing to improve our security and prevent this incident from happening again.
Before starting, we want to assure everyone that **no passwords, console or payment information has been leaked**, and an email will be sent to all potential victims about their account security.
## What happened
On July 15, we received a report about an exploit that a user was using to seemingly reset anybody's account password and get access into it. Given the danger of the exploit if it were true, we decided to take down the servers while we investigated into the claims of the report and the damage they could have done.
The evidence from the report showed an attempt of a ["padding oracle"-style attack](https://en.wikipedia.org/wiki/Padding_oracle_attack) against our tokens to trigger a password reset. I'll explain what that means in layman's terms:
When you login with your username (in our case the PNID) and password, the server gives your web browser or your console a **"token"**, which is a number that identifies that specific session in your device. You don't want to store any sensitive data there for anyone to see, or worse, you don't want to make the token simple, otherwise anyone would be able to *guess* a token and pretend to be you.
To prevent this, our tokens (up until today) only had basic information like the account ID (called **PID**) to identify you, and the purpose of the token. This data would be encrypted to prevent anyone from getting this data or replace it to disguise as another person. However, there is still the possibility of doing a "padding-oracle" attack which allows you to effectively guess and try to replace the PID with a different one, letting the attacker temporary access into the account, which they could protect with a password reset.
## Impact
During the investigation, we saw activity that correlated with someone attempting this attack thousands of times starting on July 9, and according to our records, 1864 password resets were triggered on that timeframe (note that not all of those resets are necessarily compromised accounts, that number includes legitimate resets). This is a small fraction of the userbase (about 0.3% of all PNIDs).
We haven't seen any evidence of data exfiltration from our databases. However, with a compromised account, the attacker *may* have also had access to detailed information of the PNID, though this data is generally already public:
- Access level: whether you have tester access or the account is banned
- Account creation and updated date
- PNID and PID
- Birth date
- Gender: this is usually already public with your Mii
- Country and timezone: these are technically already public if you have played online, since many games show this information to others and on multiplayer your IP address has to be made available to other players
- Email address
- Discord user ID: if you have Discord linked
- Basic tier level data: whether you have Mario or Super Mario perks
**Once again, we want to reiterate that no passwords, console or payment information has been leaked.** The payment information is managed exclusively by Stripe, our payment processor, so we don't have any access into it. And in any case, we store secure password hashes so hackers can't recover the password had those hashes gotten leaked **(which they haven't)**.
## What we're doing
Regarding the compromised accounts, while passwords were not leaked, as a precaution we will be forcing a mandatory password reset to all potentially affected users by changing the passwords to random ones. Alongside that, we will restore the previous emails of the accounts in the cases that it got changed (which was only 7 people). We will notify all possible victims about these measures via email too.
We are also making improvements on the technical side to prevent this from happening anymore. Oracle attacks work by manipulating unauthenticated encrypted data (which was our case, as the Wii U/3DS impose limits on how large certain tokens may be). As we explained we were storing some metadata about the user in the token for consuming services to use (this is also what Nintendo did with their tokens), but even prior to this incident we knew that this system would not work long term and were already planning to phase it out.
The [new system](https://github.com/PretendoNetwork/account/pull/313) which we have migrated to embeds no data inside tokens, and instead uses completely random (opaque) data, and require services to instead always phone back home to get the data that would normally be inside the tokens. The size of the new tokens, along with them cryptographically secure random byte, are functionally impossible to brute force or tamper with, rendering the attack useless.
Some of you may have thought about implementing two-factor authentication (2FA) into our services to improve security. But as promising as that sounds at first, it is much harder to implement within the limitations of the consoles, as the 3DS and Wii U have never supported it. There has been discussion about potential solutions to mitigate this, but it will take time before those ideas come into life.
## Closing
We want to apologise to everyone who has been affected by this incident, whether it be for being a victim of the attack or by our maintenance period. And also give my thanks to the rest of the team who has been working on this maintenance to get our servers out as soon as possible, or handling moderation in our platforms during the incident. I hope our next blog post goes on a more positive note.

111
content/blog/8-2-24.md Normal file
View File

@@ -0,0 +1,111 @@
---
title: "July Progress Update"
author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "August 2, 2024"
caption: "News on AC:NL, general server improvements, Discord bot updates, and more!"
cover_image: "/assets/images/blogposts/august-2-2024/preview.webp"
---
While July didn't see as many new games join our roster, we were all still hard at work. With a focus on enhancing performance and user experience, July brought crucial updates to our services. This blog post will cover many updates to our servers, patches, and go over some future plans we have for popular games like Animal Crossing: New Leaf!
# General Server Updates
As mentioned in [our last blog post](https://pretendo.network/blog/6-29-24), we had many pending server updates yet to be merged/released. While not all of them have been merged/released yet still, several have been! Our core game server library [`nex-go`](https://github.com/PretendoNetwork/nex-go) continued to get love last month, bringing it several new performance boosts.
Together with [wolfendale](https://github.com/wolfendale), we spent much of July reverse engineering several core systems, including the entire packet retransmission system. Before now, this was a very basic, inaccurate, implementation of how [PRUDP](https://developer.pretendo.network/overview/prudp) handles dropped packets. With our implementation now more accurate, both clients and servers should be seeing substantially less dropped packets, resulting in better connection stability.
Additionally some changes were made internally to address issues such as [goroutine](https://go.dev/tour/concurrency/1) overuse, poorly implemented hashing algorithms, and issues regarding the number of allocations each server performs. These issues all lead to degraded server performance and higher system resource usage. Addressing these issues has substantially dropped the libraries overall footprint (taking the average amount of memory used per server from \~300mb at the low end, to just barely \~50mb!) and increased general performance.
For a full breakdown of last month's changes to `nex-go`, [see here](https://github.com/PretendoNetwork/nex-go/commits/master/?since=2024-07-01&until=2024-08-01).
# Better Infrastructure
As mentioned in [our last blog post](https://pretendo.network/blog/6-29-24), we have been working closely with 2 non-Pretendo developers [Jelle van Snik (mrjvs)](https://mrjvs.com) and [William Oldham (BinaryOverload)](https://williamoldham.co.uk). These are personal friends working in these fields professionally, who have graciously helped with restructuring our internal infrastructure. With their help, we have been making even more strides towards full containerization through [Docker](https://docker.com) and a deployment strategy built on top of [Kubernetes](https://kubernetes.io).
Over the past month they have been making great strides towards this goal, completely redesigning our deployment strategy from the ground up. We have also begun releasing pre-built Docker containers for our servers to aid in this, which can be found on our [GitHub organization](https://github.com/orgs/PretendoNetwork/packages?visibility=public).
Once complete, these changes should help dramatically increase our productivity by streamlining many of our more tedious workflows, leading to higher server output in the long run! They also should help increase overall stability through failsafes and rollovers in the event of a server failure!
# New Games and Updates
Last month saw less new games join our roster than June (hard to beat 10 new games!), but that doesn't mean games were not worked on. Last month saw the addition of two new games, as well as several existing games/services receiving new updates/features!
**_All games begin their life in beta testing, only available to testers. Once more features have been added, and pending the evaluation of each game's stability, they will each become available to the general public on a game-by-game basis. Until then, consider [supporting the project](https://pretendo.network/account/upgrade) to gain early beta access._**
**_BETA SERVERS ARE NOT CONSIDERED STABLE, AND OFTEN LACK MANY FEATURES. USE AT YOUR OWN RISK_**
## Smash 3DS
Thanks to work done by [SuperMarioDaBom](https://github.com/SuperMarioDaBom), **Super Smash Bros. 4 3DS** is now **_officially_** available for beta testers! Just like the Wii U version, only matchmaking is implemented. All other features are still being worked on. Unlike the Wii U version, trying to use an unimplemented feature will not hang the game, however it is still not recommended to try anything besides matchmaking.
![Screenshot of the Smash Bros. 3DS multiplayer menu](/assets/images/blogposts/august-2-2024/smash-3ds.webp)
## Game & WARIO
Thanks to work done by [Jemma](https://github.com/CaramelKat) and [Trace](https://github.com/TraceEntertains), **Game & WARIO** is now **_officially_** available on Miiverse for beta testers! Most features have been tested, however as a beta title there may still be issues.
<center>
| | |
| ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| ![Screenshot of the Game & WARIO online menu](/assets/images/blogposts/august-2-2024/game-and-wario-1.webp) | ![Screenshot of Game & WARIO drawing Santa](/assets/images/blogposts/august-2-2024/game-and-wario-2.webp) |
</center>
## Minecraft
Thanks to work done by [Ash](https://github.com/ashquarky), **Minecraft: Wii U Edition** is now **_officially_** available to the public! You can now play this LCE classic with friends again, in private worlds or in minigames.
Due to safety concerns regarding the games lack of official anti-cheat, _public minigames_ are currently disabled. For the time being, use the `Friends` tab on the far right to access games. We are interested in opening the game up fully in the future, so keep an eye out for more future updates!
![Screenshot of the Minecraft: Wii U Edition online menu showing that only private matches are available](/assets/images/blogposts/august-2-2024/minecraft.webp)
## Inkay
Thanks to work done by [Ash](https://github.com/ashquarky), [Inkay](https://github.com/PretendoNetwork/Inkay) has received a massive update last month! While the changes may be small, they have a huge impact; the additional patches provided by [Nimble](https://github.com/PretendoNetwork/Nimble) are being phased out! For those unaware, our Wii U patches come in a set:
- [Inkay](https://github.com/PretendoNetwork/Inkay) - The main Pretendo Network patches connecting your Wii U to our servers. Standard Aroma plugin
- [Nimble](https://github.com/PretendoNetwork/Nimble) - Supplementary patches for patching the BOSS (SpotPass) policylist. Aroma setup module
Historically [Nimble](https://github.com/PretendoNetwork/Nimble) has been required for games which make use of SpotPass features, such as Splatoon. Before the console enables SpotPass, it downloads what is called the "policylist". This tells the console which background tasks to enable and what their priorities are. After the Nintendo Network shutdown, Nintendo has changed the official policylist to disable all SpotPass features. The Wii U downloads this policylist extremely early in the boot process, earlier than standard Aroma plugins have access to. Setup modules _are_ loaded early enough, however, thus [Nimble](https://github.com/PretendoNetwork/Nimble) was born.
With the latest changes made to [Inkay](https://github.com/PretendoNetwork/Inkay), after the plugin is loaded it forces the console to refresh the policylist, which triggers a redownload using our patched URLs. This essentially removes the need for [Nimble](https://github.com/PretendoNetwork/Nimble) entirely, as well as dramatically increases SpotPass reliability in certain games (such as 104-2210 in Splatoon). To download the latest release, see the [Inkay releases page](https://github.com/PretendoNetwork/Inkay/releases/latest)!
Additionally thanks to collaborations with [Maschell](https://github.com/Maschell) (the creator of the Aroma CFW), [Inkay](https://github.com/PretendoNetwork/Inkay) is now also available through https://aroma.foryour.cafe! Updates to [Inkay](https://github.com/PretendoNetwork/Inkay) can now be managed through the Aroma updater on-console!
## Miiverse
Thanks to work done by [Jemma](https://github.com/CaramelKat), Miiverse in general has received bug fixes and performance improvements last month. The biggest change was improved data/asset caching, which has dramatically improved the load times on Juxtaposition! These changes affect both the Wii U and 3DS versions, as well as the browser version.
<video controls>
<source src="/assets/images/blogposts/august-2-2024/miiverse-side-by-side.webp" type="video/mp4">
</video>
Additionally a long standing issue of friends not properly being handled in WaraWara Plaza has also been fixed!
![Screenshot of WaraWara Plaza showing the Miis of friends being positioned correctly](/assets/images/blogposts/august-2-2024/wwp.webp)
## Animal Crossing: New Leaf
As teased in [our last blog post](https://pretendo.network/blog/6-29-24), Animal Crossing: New Leaf has **_officially_** entered development! Features such as Tortimer Island are showing signs of life as this highly requested game starts to go online!
<center>
| | |
| ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| ![Screenshot of user "Pretendo" arriving in town "Rin" in Animal Crossing: New Leaf](/assets/images/blogposts/august-2-2024/acnl-1.webp) | ![Screenshot of two players matched together in Tortimer Island in Animal Crossing: New Leaf](/assets/images/blogposts/august-2-2024/acnl-2.webp) |
</center>
Additionally, we have begun the process of processing the data from our Dream Suite archive. Prior to the Nintendo Network shutdown, our team spent a considerable amount of time archiving data from many games, including all available towns from Dream Suite. We collected over **_200GB_** of data from Dream Suite and a total of **_239,105_** towns!
We plan to eventually publish the raw data on the [Internet Archive](https://archive.org/), as well as on our own website where you can view/download the pre-processed data. Currently the amount of data displayed is limited, and the website is still in development, so it's not yet ready for release. However we plan to look into extracting more data from the towns themselves, and possibly making them available as town backups that can be directly imported into save files!
**_Eventually we will process and release all the data (around 1.6TB) for all games/services we collected data for. Animal Crossing: New Leaf is the first of these to start it's processing._**
![Screenshot of the work in progress Animal Crossing: New Leaf archive website. Website contains a table of towns with information on their data ID, version, name, uploader name, creation and updated dates, the time the last person visited, the total number of visits, and the country of origin](/assets/images/blogposts/august-2-2024/acnl-site.webp)
# Conclusion
Thank you everyone for your continued support of the project! We know this progress update may seem small, but we only go over the largest changes! Most of our work consists of small bug fixes, library development, and lots and lots of research time. We hope you all stay tuned for future updates!

View File

@@ -4,7 +4,7 @@ author: "Jon"
author_image: "https://www.github.com/jonbarrow.png"
date: "September 26, 2021"
caption: "First ever progress recap"
cover_image: "/assets/images/blogposts/9-26-21.png"
cover_image: "/assets/images/blogposts/9-26-21.webp"
---
### If you want to see more frequent updates, consider supporting us on [**Patreon**](https://patreon.com/pretendonetwork)
@@ -16,54 +16,75 @@ cover_image: "/assets/images/blogposts/9-26-21.png"
Welcome to the first-ever Pretendo Network recap blog post! Going forward we will post these whenever major updates happen to give you all the latest news about the project in an easy to digest way
## Funding
Before we begin I'd like to make a bit of serious statement when it comes to the future development of Pretendo. The project has grown larger and larger, and as each day goes by it sometimes seems as if more tasks get added to our to-do list than we are completing. This is because many of the people working on the project are volunteering their free time, are university students or, personally, are working full time jobs. This results in slow development time, slow releases, limited research time, and of course a community which could be happier
The solution to this is making Pretendo a full time job! In order to achieve this goal we have setup a Patreon to help in getting funding for the project. Doing so will allow for more time to dedicate to Pretendo which will result in faster development and a faster, more high quality, release for you all! No one is obligated to donate, but if you would like to help support Pretendo consider checking out our Patreon. And if you cannot financially support, that's okay too! You can always help in other ways like spreading the word, giving suggestions for tier rewards, feature suggestions to help make Pretendo even better, and as always helping keep the community safe and fun for everyone by just being kind! And now, without further ado;
## It's the little things in life
A few smaller updates that don't need their own section before we get into the bigger updates; Our website got a new revamp! The design was completely redone, we added a progress page to show data from our Trello and give you all an idea of whats working and whats planned, and we of course added this blog section. The Discord server got a voice channel, as well as some new bot updates to both Yammamura and Chubby. Yammamura now makes use of Discord's new /commands to assign roles, and Chubby now moderates chat better by using AI to detect NSFW images and removing them as needed
## Back to the basics
The [account server](https://github.com/PretendoNetwork/account) got a complete rewrite from the ground up. This cleaned up all of the old code written as far back as 2017 during initial testing (when Pretendo was still called RiiU!), making the code base much cleaner, easier to navigate, and more performant. Any future updates to the account server will now be much easier to implement
## Homebrew clearance-sale
As of 2019 Pretendo has made great progress on implementing a custom eShop. A lot of research and work has gone into the SOAP servers and how the console requests tickets and other title information. Our custom eShop is able to install homebrew apps packed as WiiU titles. Due to copyright reasons with regards to homebrew applications though, Pretendo with most likely _**not**_ be using any kind of custom eShop implementation in our official servers. If this ever changes, however, we have the foundation to support it
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">Heres a video as proof of it working through the official eShop app on the console <a href="https://t.co/akmOIjopCq">https://t.co/akmOIjopCq</a> <a href="https://t.co/mVTnJQJPwi">pic.twitter.com/mVTnJQJPwi</a></p>&mdash; Pretendo (@PretendoNetwork) <a href="https://twitter.com/PretendoNetwork/status/1203710130853949440?ref_src=twsrc%5Etfw">December 8, 2019</a></blockquote>
## All my friends are online mom!
The Friends server, which is the main game server every console always connects to on boot, can now be connected to! This is a huge milestone for Pretendo, since no other games will work without it. All games require an existing connection to the Friends server to operate, and will attempt to connect to it if not already. At this stage most functionality is stubbed and the data sent back is hard-coded, but it's enough to get other games online
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">The <a href="https://twitter.com/hashtag/WiiU?src=hash&amp;ref_src=twsrc%5Etfw">#WiiU</a> starting to show lines of life on <a href="https://twitter.com/hashtag/Pretendo?src=hash&amp;ref_src=twsrc%5Etfw">#Pretendo</a>! The beginnings of online have started!<a href="https://twitter.com/hashtag/PretendoNetwork?src=hash&amp;ref_src=twsrc%5Etfw">#PretendoNetwork</a> <a href="https://t.co/8ocwVSLvRt">pic.twitter.com/8ocwVSLvRt</a></p>&mdash; Pretendo (@PretendoNetwork) <a href="https://twitter.com/PretendoNetwork/status/1218075017545768960?ref_src=twsrc%5Etfw">January 17, 2020</a></blockquote>
## Who needs Skype
WiiU Chat, a popular WiiU title many years ago, was shut down along side Miiverse most likely due it's heavy ties to the social media platform. As of 2020, Pretendo has gotten WiiU Chat back online enough to boot into the title, display a list of friends to call, and attempt to make a connection! As of now though, a full video call cannot be made. WiiU Chat is very complex under the hood and requires additional research into how the WiiU handles title background tasks
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">We have begun the process of restoring <a href="https://twitter.com/hashtag/WiiU?src=hash&amp;ref_src=twsrc%5Etfw">#WiiU</a> Chat! <a href="https://t.co/qzIfBu8cQZ">pic.twitter.com/qzIfBu8cQZ</a></p>&mdash; Pretendo (@PretendoNetwork) <a href="https://twitter.com/PretendoNetwork/status/1229621686640795648?ref_src=twsrc%5Etfw">February 18, 2020</a></blockquote>
## Where's the remote?!
Some small progress was made in regards to getting TVii booting again on the WiiU. We will not be reviving this title completely, as it relied on streaming TV content we do not have the rights for, but the research did help give us some insight into how the WiiU handles custom webpage functionality
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">With the help of <a href="https://twitter.com/shutterbug20002?ref_src=twsrc%5Etfw">@shutterbug20002</a> we have started researching the TVii app and its functionality <a href="https://t.co/xmmuVYB6ni">pic.twitter.com/xmmuVYB6ni</a></p>&mdash; Pretendo (@PretendoNetwork) <a href="https://twitter.com/PretendoNetwork/status/1262577386912124929?ref_src=twsrc%5Etfw">May 19, 2020</a></blockquote>
## Who's in charge of the Festival?
Another huge milestone for Pretendo was hit in January of this year! The WiiU and 3DS both use a service called BOSS/SpotPass to securely register tasks which send/request certain encrypted title contents. Splatfests used by Splatoon are one of these contents! Pretendo can now fully encrypt and decrypt BOSS/SpotPass contents, meaning we can serve custom Splatfests through our network. We are aware that custom Splatfest projects have existed in the past, however they relied on Homebrew and overwriting the existing Splatfest files on the console. With this update we can now make our own and host them the way they were originally intended to be hosted<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">Sorry for the late night Tweet, but we have a special message from Callie and Marie! <a href="https://t.co/HLZxyRf1EU">pic.twitter.com/HLZxyRf1EU</a></p>&mdash; Pretendo (@PretendoNetwork) <a href="https://twitter.com/PretendoNetwork/status/1355791287077761027?ref_src=twsrc%5Etfw">January 31, 2021</a></blockquote>
## Teamwork makes the dream work
Archive Team, known for their _extensive_ work put into archiving everything on the internet, contacted us to help them archive all of the courses uploaded to Nintendo's official servers! Together we were able to do just that, dump and archive all the course data and associated metadata to be preserved for future generations!
## Lets get Making!
Super Mario Maker makes the stage as the first official Nintendo game to go online and start getting functionality with Pretendo. At this stage nearly all content is either stubbed or hard coded just to get the game online and see how it reacts to our data while researching. Only the course world boots here
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">Super Mario Maker 1 now officially goes online with Pretendo!<a href="https://twitter.com/hashtag/WiiU?src=hash&amp;ref_src=twsrc%5Etfw">#WiiU</a> <a href="https://twitter.com/hashtag/supermariomaker?src=hash&amp;ref_src=twsrc%5Etfw">#supermariomaker</a> <a href="https://twitter.com/hashtag/pretendo?src=hash&amp;ref_src=twsrc%5Etfw">#pretendo</a> <a href="https://t.co/Gn2IxlS47D">pic.twitter.com/Gn2IxlS47D</a></p>&mdash; Pretendo (@PretendoNetwork) <a href="https://twitter.com/PretendoNetwork/status/1428659329637437442?ref_src=twsrc%5Etfw">August 20, 2021</a></blockquote>
## Let's a-go!
Very soon after booting, course uploading was re-implemented in Super Mario Maker. This means new content can continue to be added to the game through Pretendo! Not shown in the tweet is course world also now making use of the newly uploaded courses
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="und" dir="ltr"><a href="https://t.co/iIVW6pJJeS">pic.twitter.com/iIVW6pJJeS</a></p>&mdash; Pretendo (@PretendoNetwork) <a href="https://twitter.com/PretendoNetwork/status/1432112205638610945?ref_src=twsrc%5Etfw">August 29, 2021</a></blockquote>
## Going mobile
A few patches and some account server updates later, Pretendo has gotten the 3DS connecting and online with our custom servers! Just like the WiiU, Friends was the first target as it's required for all other games to boot and just like the WiiU at this stage most of the functionality is stubbed just to get it online for other games. With this, though, a whole new door is opened for Pretendo. PNIDs (the Pretendo version of a NNID) are not supported on the 3DS as of right now. The 3DS uses a different account system which more closely resembles the Wii than the WiiU, and thus is able to go online and play games without a NNID
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">3DS showing signs of life! <a href="https://t.co/cXyi0zbSD1">pic.twitter.com/cXyi0zbSD1</a></p>&mdash; Pretendo (@PretendoNetwork) <a href="https://twitter.com/PretendoNetwork/status/1436822070357278727?ref_src=twsrc%5Etfw">September 11, 2021</a></blockquote>
## Mario on the go
Immediately after getting Friends online, work began on Super Mario Maker for the 3DS. All possible functionality was added, making it the first title to ever get 100% support on Pretendo! Though with how limited the games content is, that's not saying a whole lot
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">We heard yall like the 3DS and Super Mario Maker <a href="https://t.co/w5ll3h1tPx">pic.twitter.com/w5ll3h1tPx</a></p>&mdash; Pretendo (@PretendoNetwork) <a href="https://twitter.com/PretendoNetwork/status/1436916321678200833?ref_src=twsrc%5Etfw">September 12, 2021</a></blockquote>
That's all for now! Keep an eye out for more updates, and happy playing!
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

View File

@@ -4,7 +4,7 @@ author: "Jemma"
author_image: "https://www.github.com/caramelkat.png"
date: "September 29, 2021"
caption: "What's Juxtaposition and where it's headed"
cover_image: "/assets/images/blogposts/9-29-21.png"
cover_image: "/assets/images/blogposts/9-29-21.webp"
---
### If you want to see more frequent updates, consider supporting us on [**Patreon**](https://patreon.com/pretendonetwork)
@@ -12,7 +12,9 @@ cover_image: "/assets/images/blogposts/9-29-21.png"
Oh boy another recap post! This time we're going to talk a little bit about Juxtaposition now and what our plans are going forward.
## First off, what is Juxtaposition?
Juxtaposition (or Juxt for short) is the Pretendo Network Miiverse replacement. This includes but is not limited to:
- Wii U App
- 3DS App
- Game API
@@ -21,26 +23,31 @@ Juxtaposition (or Juxt for short) is the Pretendo Network Miiverse replacement.
Juxt isn't the entirety of the Pretendo Network, it's a small but core piece that makes the entire network work in harmony.
## A brief history
Juxt started out before I actually even joined the Pretendo Network development team. In 2019 I contacted [quarky](https://heyquark.com/) about their [miiverse-api-poc](https://github.com/QuarkTheAwesome/miiverse-api-poc) server that had support for the Splatoon Plaza posts, and that was it. The original intent was to take the software and build off of it to generate files for Wara Wara Plaza.
Juxt started out before I actually even joined the Pretendo Network development team. In 2019 I contacted [quarky](https://heyquark.com/) about their [miiverse-api-poc](https://github.com/QuarkTheAwesome/miiverse-api-poc) server that had support for the Splatoon Plaza posts, and that was it. The original intent was to take the software and build off of it to generate files for Wara Wara Plaza.
![](https://cdn.discordapp.com/attachments/868275684630470697/892881351223676968/unknown.png)
> Hello World! Check out the very first instance of Wara Wara Plaza rendering a custom file. A bit underwhelming looking back huh?
From there we quickly realized that the scope of this project was going to be much larger than we though, and moved on to experimenting with the Miiverse Applet itself
[yt-iframe](d9VAr9sEvCo)
::md-iframe{video-id="d9VAr9sEvCo"}
::
> Check out this ancient video of the first demo website that was running in the Miiverse Applet.
> Check out this ancient video of the first demo website that was running in the Miiverse Applet.
Shortly after this the project was absorbed into the Pretendo Network, and our full focus was put onto getting the Miiverse Applet patched and working.
2020 was a big year for Juxt, going from the simple api server before, to rapidly building out its web interface and features across both the 3DS and Wii u
[yt-iframe](NrfaOx5xcJY)
::md-iframe{video-id="NrfaOx5xcJY"}
::
> First attempt at an interface for the 3DS
[yt-iframe](IXnJOacx_gE)
::md-iframe{video-id="IXnJOacx_gE"}
::
> Community page Demo on the Wii U
@@ -48,91 +55,91 @@ Shortly after this the project was absorbed into the Pretendo Network, and our f
Believe it or not Juxt is actually fairly well featured at the moment! Here's a ~~brief~~ list of whats working for the 3DS and Wii U now.
---
#### Wii U
- Communities
- View All Communities
- Searching for Community
- Following/Unfollowing
- Showing Followers
- Showing Posts
- Sorting Posts by Type
- Creating New Post
- View All Communities
- Searching for Community
- Following/Unfollowing
- Showing Followers
- Showing Posts
- Sorting Posts by Type
- Creating New Post
- Posts
- Yeah!
- Replies
- Spoilers
- Yeah!
- Replies
- Spoilers
- Text
- Drawing
- Screenshots
- New Post
- Emotion
- Text
- Drawing
- Screenshots
- New Post
- Emotion
- Text
- Drawing
- Screenshot
- Spoiler
- Screenshot
- Spoiler
- Users
- Mii Profile Pictures
- Following/Unfollowing
- Display Verified
- Display Followers and Following
- Display Country and Game Experience
- Posts
- Profile Settings
- Toggle Visibility of
- Country
- Birthday
- Experience
- Bio
- Set Profile Comment
- Mii Profile Pictures
- Following/Unfollowing
- Display Verified
- Display Followers and Following
- Display Country and Game Experience
- Posts
- Profile Settings
- Toggle Visibility of
- Country
- Birthday
- Experience
- Bio
- Set Profile Comment
- Activity Feed
- Posts from Followed Users
- Posts from Followed Users
- Notifications
- New Follower
- New Reply to Post
- New Follower
- New Reply to Post
---
#### 3DS
- Communities
- View All Communities
- Following/Unfollowing
- Showing Posts
- Sorting Posts by Type
- Creating New Post
- View All Communities
- Following/Unfollowing
- Showing Posts
- Sorting Posts by Type
- Creating New Post
- Posts
- Yeah!
- Replies
- Spoilers
- Yeah!
- Replies
- Spoilers
- Text
- Drawing
- Screenshots
- New Post
- Emotion
- Text
- Drawing
- Screenshots
- New Post
- Emotion
- Text
- Drawing
- Users
- Mii Profile Pictures
- Display Verified
- Mii Profile Pictures
- Display Verified
- Activity Feed
- Posts from Followed Users
- Posts from Followed Users
- Notifications
- New Follower
- New Reply to Post
- New Follower
- New Reply to Post
---
#### API
- /v1/endpoint
- The endpoint that tells the console where to connect to for what, including bans and server maintenance
- The endpoint that tells the console where to connect to for what, including bans and server maintenance
- /v1/communities/0/posts
- In game posts for games like Splatoon, Animal Crossing Plaza, and Nintendo Land
- In game posts for games like Splatoon, Animal Crossing Plaza, and Nintendo Land
- /v1/topics
- The endpoint used for Wara Wara Plaza on the Wii U System Menu
- The endpoint used for Wara Wara Plaza on the Wii U System Menu
## What's still being worked on?
@@ -153,7 +160,7 @@ Great question! there is still quite a bit that's being worked on for both the 3
- Desktop/Mobile Website
- More Translations
- More API Endpoints
- ***So Many Bug Fixes***
- **_So Many Bug Fixes_**
And more!
@@ -166,58 +173,77 @@ Thank you, guys, so much for your patience and support. We can't wait to get Jux
In the meantime, check out our [Patreon](https://patreon.com/pretendonetwork) to get instant access to the Juxt alpha on the Wii U!
## Wii U Screenshots
![](https://i.imgur.com/KTwlLwh.png)
> Landing Page
![](https://i.imgur.com/QLIFy0h.png)
> All Communities and Search
![](https://i.imgur.com/lJL6TYm.png)
> Community Page
> Community Page
![](https://i.imgur.com/W2EocVH.png)
> New Post/Reply Page
![](https://i.imgur.com/hQUtyoX.png)
> Activity Feed with Spoiler Post
![](https://i.imgur.com/Ys6KUjm.png)
> Drawing Post with Reply
![](https://i.imgur.com/HK1lXp5.png)
> Another User's Page
![](https://cdn.discordapp.com/attachments/868275684630470697/892939794345246720/unknown.png)
> Showing Users Following List
![](https://cdn.discordapp.com/attachments/868275684630470697/892940579149844510/unknown.png)
> User Settings Screen
![](https://cdn.discordapp.com/attachments/868275684630470697/892940868674265098/unknown.png)
> Notifications Screen
## 3DS Screenshots
![](https://cdn.discordapp.com/attachments/868275684630470697/892941422930558986/unknown.png)
> Landing Page
![](https://cdn.discordapp.com/attachments/868275684630470697/892941904088539156/unknown.png)
> All Communities and Search
![](https://cdn.discordapp.com/attachments/868275684630470697/892942081935413268/unknown.png)
> Community Page
> Community Page
![](https://cdn.discordapp.com/attachments/868275684630470697/892942228954161163/unknown.png)
> New Post/Reply Page
![](https://cdn.discordapp.com/attachments/868275684630470697/892942546085511188/unknown.png)
> Activity Feed with Spoiler Post
![](https://cdn.discordapp.com/attachments/868275684630470697/892943312380645386/unknown.png)
> Drawing Post with Reply
![](https://cdn.discordapp.com/attachments/868275684630470697/892943575560638534/unknown.png)
> User Menu Screen
![](https://cdn.discordapp.com/attachments/868275684630470697/892943834521161788/unknown.png)
> Notifications Screen

View File

@@ -1,13 +1,13 @@
---
title: "Test"
author: "pinklimes"
author_image: "https://github.com/pinklimes.png"
author: "limes.pink"
author_image: "https://github.com/limes.pink.png"
date: "January 20, 2038"
caption: "A post to test the styling of the various elements we might use (rename to _test.md before deploying the blog section)"
caption: "A post to test the styling of the various elements we might use"
cover_image: "https://media.discordapp.net/attachments/413884110667251722/886474243662037062/image1.jpg"
---
A post to test the styling of the various elements we might use (rename to _test.md before deploying the blog section)
A post to test the styling of the various elements we might use
**bold**
@@ -35,23 +35,23 @@ _italic_
---
| Element | Description |
| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table | The table HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. |
| tuble | The tuble HTML element represents tubular data — that is, information presented in a totally gnarly and radical way. |
| table | A table is an item of furniture with a flat top and one or more legs, used as a surface for working at, eating from or on which to place things. |
| Element | Description |
| :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table | The table HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. |
| tuble | The tuble HTML element represents tubular data — that is, information presented in a totally gnarly and radical way. |
| table | A table is an item of furniture with a flat top and one or more legs, used as a surface for working at, eating from or on which to place things. |
| Element | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| table | The table HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. |
| tuble | The tuble HTML element represents tubular data — that is, information presented in a totally gnarly and radical way. |
| table | A table is an item of furniture with a flat top and one or more legs, used as a surface for working at, eating from or on which to place things. |
| Element | Description |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| table | The table HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. |
| tuble | The tuble HTML element represents tubular data — that is, information presented in a totally gnarly and radical way. |
| table | A table is an item of furniture with a flat top and one or more legs, used as a surface for working at, eating from or on which to place things. |
| Element | Description |
| -----------: | -----------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| table | The table HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. |
| tuble | The tuble HTML element represents tubular data — that is, information presented in a totally gnarly and radical way. |
| table | A table is an item of furniture with a flat top and one or more legs, used as a surface for working at, eating from or on which to place things. |
| Element | Description |
| ------: | -----------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| table | The table HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. |
| tuble | The tuble HTML element represents tubular data — that is, information presented in a totally gnarly and radical way. |
| table | A table is an item of furniture with a flat top and one or more legs, used as a surface for working at, eating from or on which to place things. |
Yee haw 🤠
@@ -126,14 +126,22 @@ console.log(trueOrFalseJSON);
<cite>Adapted from [blockquote: The Block Quotation element, from MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)</cite>
[yt-iframe](djV11Xbc914)
::md-iframe{video-id="djV11Xbc914"}
::
```[yt-iframe](djV11Xbc914)```
```
::md-iframe{video-id="djV11Xbc914"}
::
```
![test](https://media.discordapp.net/attachments/413884110667251722/886474243662037062/image1.jpg)
![test](https://upload.wikimedia.org/wikipedia/commons/5/57/View_of_the_Turin_Metro_tracks_from_Fermi_terminal.jpg)
<a href="https://commons.wikimedia.org/wiki/File:View_of_the_Turin_Metro_tracks_from_Fermi_terminal.jpg">Wikilimes</a> (that's me!), <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons
***
<video controls>
<source src="https://cdn.discordapp.com/attachments/413884110667251722/878216238940160040/video0.mov">
<source src="https://upload.wikimedia.org/wikipedia/commons/transcoded/5/5f/Steamboat_Willie_%281928%29_by_Walt_Disney.webm/Steamboat_Willie_%281928%29_by_Walt_Disney.webm.720p.vp9.webm">
</video>
Blogposts whose filename starts with a \_ will not show up on the /blogs page, but will still be accessible from the url (keep in mind that the file is still going to be publicly accessible on GitHub).
Blogposts with filename starting with \_ will not show up on the /blogs page, but will still be accessible via the url.

View File

@@ -1,5 +1,14 @@
---
description: "Instructions on how to set up Pretendo on the 3DS/2DS family of consoles."
---
# 3DS/2DS Family
<div class="tip red">
<strong>CAUTION:</strong>
DON'T REMOVE YOUR NNID TO SET UP PRETENDO NETWORK, IT'S NOT NECESSARY AND BY DOING SO YOU WILL LOSE BADGES, REDOWNLOADABLE GAMES, THEMES AND POKÉMON BANK DATA!
</div>
<div class="tip red">
<strong>CAUTION:</strong>
SYSTEM TRANSFERS ARE NOT CURRENTLY SUPPORTED BY OUR SERVERS. ATTEMPTING TO PERFORM A SYSTEM TRANSFER MAY PREVENT YOU FROM BEING ABLE TO GO ONLINE IN THE FUTURE. SUPPORT FOR SYSTEM TRANSFERS IS IN DEVELOPMENT.
@@ -15,6 +24,7 @@
</div>
The following steps are required for you to connect to the Pretendo Network:
1. [Downloading Nimbus](#downloading-nimbus)
2. [Enabling Luma patches](#luma-patches)
3. [Nimbus](#using-nimbus)
@@ -34,19 +44,22 @@ Once inserted, download the latest [Nimbus release](https://github.com/PretendoN
Nimbus is available as both a 3DSX app and an installable CIA. The releases page offers downloads for both. Select the version you would like to use, or select the `combined.[version].zip` archive to use both.
<img src="/assets/images/docs/install/3ds/zip-highlight.png" alt="Screenshot of a GitHub release page with the file combined.[version].zip highlighted" width=100% height=auto/>
<img src="/assets/images/docs/install/3ds/zip-highlight.webp" alt="Screenshot of a GitHub release page with the file combined.[version].zip highlighted" width=100% height=auto/>
Extract the contents of the zip archive to the root of your SD card. If you are asked to merge or overwrite files, accept the changes.
Ensure your SD card has all the following files
- `SD:/luma/titles/000400300000BC02/code.ips` (Miiverse, JPN)
- `SD:/luma/titles/000400300000BD02/code.ips` (Miiverse, USA)
- `SD:/luma/titles/000400300000BE02/code.ips` (Miiverse, EUR)
- `SD:/luma/sysmodules/0004013000002F02.ips` (SSL)
- `SD:/luma/sysmodules/0004013000003202.ips` (FRD/Friends)
- `SD:/luma/sysmodules/0004013000003802.ips` (ACT/NNID)
- `SD:/3ds/juxt-prod.pem` (Juxtaposition certificate)
- `SD:/3ds/nimbus/update/000400300000BC02.ips` (Miiverse, JPN)
- `SD:/3ds/nimbus/update/000400300000BD02.ips` (Miiverse, USA)
- `SD:/3ds/nimbus/update/000400300000BE02.ips` (Miiverse, EUR)
- `SD:/3ds/nimbus/update/0004013000002902.ips` (HTTP)
- `SD:/3ds/nimbus/update/0004013000002E02.ips` (Sockets)
- `SD:/3ds/nimbus/update/0004013000002F02.ips` (SSL)
- `SD:/3ds/nimbus/update/0004013000003202.ips` (FRD/Friends)
- `SD:/3ds/nimbus/update/0004013000003802.ips` (ACT/NNID)
- `SD:/3ds/nimbus/update/juxt-prod.pem` (Juxtaposition certificate)
- `SD:/3ds/nimbus/update/nimbus.3gx` (Nimbus plugin for Luma)
If not installed through Universal-Updater, ensure at least one of the following also exists
@@ -98,16 +111,17 @@ It is recommended to register the PNID on your device at this time, as registeri
<div class="tip red">
<strong>CAUTION:</strong>
A Pretendo Network ID may not use the same username as the account already linked to your 3DS! Ensure that you have a choose a different name for your PNID than the name on your NNID.
A Pretendo Network ID may not use the same username as the account already linked to your 3DS! Ensure that you have chosen a different name for your PNID than the name on your NNID.
</div>
## Other information
### How does Nimbus work?
Nimbus will create a 2nd local account set to the `test` NASC environment. The IPS patches will set the `test` NASC environment URLs to point to Pretendo. You may freely switch between Pretendo and Nintendo. Your selected mode will persist between reboots.
### 2nd local account?
You may have thought to yourself; _"2nd local account? What's that? I thought the 3DS only had one account?"_ And you'd be half right. The 3DS only _normally_ supports one account, and you may only have one account active at a time. However Nintendo implemented support for multiple local accounts on the 3DS/2DS which remains unused on all retail units. On a normal retail unit only one local account is ever made, which is set to the `prod` NASC environment. Local accounts may be set to `prod`, `test` or `dev`. Nimbus makes use of this unused feature to create sandboxed local accounts with different environments
<ul id="footnotes">
@@ -115,6 +129,7 @@ You may have thought to yourself; _"2nd local account? What's that? I thought th
</ul>
### Restoring Nintendo Badge Arcade Badges
1. Insert your SD Card into your PC.
2. Back up your badges at the folder on your SD Card `SD:Nintendo 3DS/ID0/ID1/extdata/00000000/000014d1`.
3. Download [Simple Badge Injector](https://github.com/AntiMach/simple-badge-injector/releases/latest).
@@ -131,6 +146,6 @@ You may have thought to yourself; _"2nd local account? What's that? I thought th
14. Put your SD card back into your 3DS and go back into SBI
15. Inject your modified badge data files.
All badges *placed* on the home menu will be deleted, and you have to re-add them in the order you have had them before.
All badges _placed_ on the home menu will be deleted, and you have to re-add them in the order you have had them before.
If you encounter any errors, restore your backed up badge data through SBI. Injecting badges while using Pretendo Network will make them disappear when swapping back to Nintendo Network, and vice versa.

View File

@@ -0,0 +1,117 @@
---
description: "Instructions on how to set up Pretendo on Azahar, the 3DS/2DS emulator."
---
# Azahar
<div class="tip red">
<strong>CAUTION:</strong>
This guide only supports official builds provided by the Azahar Emulator team. Any unofficial/third-party emulator builds are not supported, and we do not provide technical support for issues caused by using said unofficial builds.
</div>
<div class="tip">
Azahar <b>requires</b> connecting to a real 3DS/2DS system using an app called Artic Setup Tool before you can play online. This guide assumes that you have a <b>Homebrewed System running the latest version of Luma3DS (v13.3.1 or higher)</b>. If you don't, please follow this <a href="https://3ds.hacks.guide/" target="_blank">guide</a> on how to install homebrew to your system first.
</div>
The following steps are required for you to connect to Pretendo Network:
1. [Downloading Artic Setup Tool](#downloading-artic-setup-tool)
2. [Using Artic Setup Tool](#using-artic-setup-tool)
3. [LLE module setup in Azahar](#lle-module-setup-in-azahar)
4. [Downloading Nimbus](#downloading-nimbus)
5. [Using Nimbus](#using-nimbus)
6. [Link a Pretendo Network ID (optional)](#link-a-pretendo-network-id-optional)
## Downloading Artic Setup Tool
### Using Universal Updater
The easiest way to get Artic Setup Tool is by using Universal Updater. Universal Updater is also great for updating all of your other homebrew apps, so installing it is highly recommended. To install Universal Updater, get it from <a href="https://universal-team.net/projects/universal-updater.html" target="_blank">here</a>.
Once you have Universal Updater, simply open it and search for "Artic Setup Tool". Select `AzaharArticSetup.3dsx` if you want to launch the setup tool from the Homebrew Launcher, or select `AzaharArticSetup.cia` if you want to launch it from your HOME Menu.
### Without using Universal Updater
If you'd prefer not to use Universal Updater, Artic Setup Tool can be installed manually using the FBI title manager.
Before starting, power off your console and insert its SD card into your computer.
If you want to launch Artic Setup Tool from your HOME Menu, download `AzaharArticSetup.cia` from the [latest Artic Setup Tool release](https://github.com/azahar-emu/ArticSetupTool/releases/latest) and put it on your SD card. Then, open FBI and install it.
If you want to launch Artic Setup Tool from the Homebrew Launcher, download `AzaharArticSetup.3dsx` from the [latest Artic Setup Tool release](https://github.com/azahar-emu/ArticSetupTool/releases/latest) and put it inside the `3ds` folder on your SD card.
## Using Artic Setup Tool
<div class="tip">
Before opening Artic Setup Tool, ensure that your 3DS/2DS is on the same Wi-Fi network as the computer running Azahar.
</div>
Open Artic Setup Tool on your 3DS/2DS. Once it's open, press A to run the tool. An IP address will be displayed on the top screen.
<img src="/assets/images/docs/install/azahar/artic_setup_tool.png" width=100% height=auto/>
If your system's top screen is broken, hold L + D-Pad Down + SELECT to open the Rosalina menu, then go to `Debugger options...` and enable the debugger, then press B. Your IP address will be displayed in the top-right corner of the bottom screen. Write down this IP address somewhere, then disable the debugger and exit the Rosalina menu.
Open Azahar on your computer. Click `File`, then `Set Up System Files...`. A window will pop up containing some information and a text box. `Old 3DS Setup` will be selected regardless of what system you have. <b>This is normal.</b> Enter your 3DS/2DS IP address into the text box in Azahar and click OK.
<img src="/assets/images/docs/install/azahar/azahar_set_up_enterIP.png" width=100% height=auto/>
<div class="tip yellow">
⚠️ If you see an error that says "Missing OTP backup on SD card", you need to run a program to recreate the backup. Put <a href="https://github.com/MisterSheeple/GodMode9/releases/download/otp_1.0.0/otp_dump.firm" target="_blank">otp_dump.firm</a> inside /luma/payloads/ on your SD card, then hold START + Power on your system with the SD card inserted. If you are not immediately booted into the dumper program, select "otp_dump" on the top screen and press A to load it. The program should tell you that your OTP has been successfully dumped. Press A to power off your system.
</div>
<div class="tip yellow">
⚠️ If you see an error that says "The country configuration does not match the console region", you need to change the country set in Azahar to match the region of your system. To do this, click "Emulation", then "Configure", then click "System". Find the country drop-down box and select your system's country from the list, then click OK to save your configuration settings. <b>Please note that "Country" and "Region" are two separate drop-down boxes in Azahar.</b> "Country" is the one that needs to be changed to fix this issue.
</div>
On Azahar, a screen will appear telling you to "update your system". This is actually a process that downloads some required system files from the 3DS update servers so that Azahar can connect online. This won't modify anything on your 3DS/2DS system. Click OK to allow it to proceed.
<img src="/assets/images/docs/install/azahar/azahar_set_up_sysupdate.png" width=100% height=auto/>
After a few minutes, Azahar will notify you that the update is complete. Click OK to continue. <b>You are not finished with Artic Setup Tool.</b>
In Azahar, click `File` and `Set Up System Files...` again. Enter the IP address again, but this time, click `New 3DS Setup`. <b>This is required and will work regardless of whether or not your system is a New 3DS/2DS.</b> Click OK.
<img src="/assets/images/docs/install/azahar/azahar_set_up_enterIP_N3DS.png" width=100% height=auto/>
Once again, a screen will appear on Azahar telling you to "update your system". Click OK to allow it to proceed.
<img src="/assets/images/docs/install/azahar/azahar_set_up_sysupdate_N3DS.png" width=100% height=auto/>
Another screen will appear telling you some important information about system updates. Review this information and click "I Accept" to proceed to the update.
Once the update is complete, click OK.
On your 3DS/2DS system, press START to exit Artic Setup Tool. Your 3DS/2DS system is no longer needed for the rest of this guide.
## LLE module setup in Azahar
In Azahar, click `Emulation`, then `Configure`.
Select the `System` menu and click `Enable required LLE modules for online features`. Make sure this box is checked, then click OK. Please note that you will not be able to use savestates while this option is enabled, but you will not be able to connect online when it is disabled.
<img src="/assets/images/docs/install/azahar/azahar_emulation_configure_LLE_module.png" width=100% height=auto/>
## Downloading Nimbus
Download the [latest Nimbus release](https://github.com/PretendoNetwork/Nimbus/releases/latest). Be sure to select a zip file labeled either `cia` or `combined`. Once downloaded, extract this zip file.
Open your emulator's SDMC folder. By default, this will be located in the main Azahar folder. To get there, click `File` and `Open Azahar Folder`. A file explorer window will open. Enter the `sdmc` folder and paste the `3ds` folder from the zip file into there. If everything goes correct, inside the `sdmc` folder you should have two folders named `3ds` and `Nintendo 3DS` (with the `Nintendo 3DS` folder already being present).
Close Azahar and re-open it. Click `File` and `Install CIA`. Navigate into the `cias` folder from the zip file and select `nimbus.cia`, then click OK. This will install Nimbus to your emulator.
## Using Nimbus
Open Nimbus within Azahar. Upon opening it, it will notify you that it's been updated. Click `Emulation` and then `Stop` to exit it.
<img src="/assets/images/docs/install/azahar/azahar_nimbus_update.png" width=100% height=auto/>
Reopen Nimbus and click the Pretendo button. Once you have switched to Pretendo, click `Emulation` and then `Stop` to exit Nimbus again.
<img src="/assets/images/docs/install/azahar/azahar_nimbus_pretendo_select.png" width=100% height=auto/>
Once you're connected to Pretendo Network, you may want to open the HOME Menu and check the Friend List to confirm that you've been assigned a friend code. Please note that Artic Setup Tool does not copy your account or save data from your system.
## Link a Pretendo Network ID (optional)
Some games and apps require a Pretendo Network ID (PNID) to be linked before you can use them online. To link a PNID, open the System Settings app in Azahar and click on `Nintendo Network ID Settings`. From here, you can either create a new PNID or link an existing one. Follow the directions on your screen to create or link a PNID. Please note that even though it says "Nintendo Network ID" throughout, you are still creating/linking a Pretendo Network ID.

View File

@@ -1,3 +1,7 @@
---
description: "Instructions on how to set up Pretendo on Cemu, the Wii U emulator."
---
<div class="tip green">This Guide may be missing some info or incomplete.</div>
# Cemu
@@ -7,6 +11,7 @@
</div>
## Download
<div class="tip red">
<strong>Note:</strong>
Only experimental builds of Cemu 2.0 are supported. At this time Cemu does not have a stable release of Cemu 2.0 which supports Pretendo
@@ -15,12 +20,15 @@
Cemu 2.0 has official built-in support for Pretendo as of October 10, 2022. Head to the Cemu GitHub [releases](https://github.com/cemu-project/Cemu/releases) page and download the latest Cemu experimental release (tagged as `Pre-release`). Only `Cemu 2.0-5 (Experimental)` and above is supported at the moment. Additionally you may build Cemu from source using the provided [build instructions](https://github.com/cemu-project/Cemu/blob/main/BUILD.md)
## Dumping your pretendo account
Ensure you have followed [Cemu's guide](https://cemu.cfw.guide/online-play.html) to set up the emulator for online play. When dumping your user account files, ensure you select your PNID.
## Connecting to Pretendo
Once you have Cemu setup for online play navigate to `Options > General settings > Account`. You should now see a section titled `Network Service`. Select your PNID from the `Active account` menu and select the `Pretendo` Network Service option. Cemu should now be connected to Pretendo's servers
<center><img src="/assets/images/docs/install/cemu/network-services-settings.png" alt="Screenshot of Cemu's Account Settings with different Network Service Options."/></center>
<center><img src="/assets/images/docs/install/cemu/network-services-settings.webp" alt="Screenshot of Cemu's Account Settings with different Network Service Options."/></center>
## Miiverse
Cemu has limited to no Miiverse support as of now. Some in game features may work, but this is not guaranteed. The Miiverse applet does not work in official builds.

View File

@@ -0,0 +1,7 @@
---
description: "Citra is not supported. Please use Azahar instead."
---
# Citra
Citra is not supported. Please use <a href="/docs/install/azahar" target="_blank">Azahar</a> instead.

View File

@@ -1,13 +1,13 @@
---
description: "Instructions on how to install Juxtaposition."
---
# Installing Juxtaposition
<div class="tip">
This guide assumes that you have a <b>Homebrewed System</b>, and have already connected to Pretendo. If you have not yet set up your Pretendo Network ID, follow this <a href="/docs/install" target="_blank">guide</a> to get started.
</div>
<div class="tip yellow">
<b>Pretendo Network is currently in a closed beta. Not all features, including game servers and Miiverse, are open to the public</b>.
</div>
Juxtaposition is the Pretendo Network replacement for the now defunct Miiverse service
## Select your console
@@ -24,10 +24,6 @@ Juxtaposition is the Pretendo Network replacement for the now defunct Miiverse s
# 3DS
<div class="tip yellow">
⚠️ Nimbus will overwrite existing patches for services such as Rverse. As such, use with caution
</div>
<div class="tip">
Nimbus already handles all the required patches for the Miiverse applet. If you do not have Nimbus installed, follow this <a href="/docs/install/3ds" target="_blank">guide</a> to get started.
</div>

View File

@@ -1,21 +1,34 @@
---
description: "Instructions on how to set up Pretendo on the Wii U console."
---
# Wii U
<div class="tip red">
<strong>CAUTION:</strong>
DON'T REMOVE YOUR NNID TO SET UP PRETENDO NETWORK, IT'S NOT NECESSARY AND BY DOING SO YOU WILL LOSE ALL YOUR PREVIOUSLY PURCHASED GAMES AND WILL BE UNABLE TO UPDATE THEM!</strong>
</div>
You can connect your Wii U to Pretendo using one of 2 methods. Inkay is recommended unless you have some reason to avoid modding your console (e.g. you live in Japan where is is legally gray).
- [Inkay (homebrew - recommended)](#inkay)
- [SSSL (hackless)](#sssl)
# Inkay
**Pros:**
- All services supported
- Contains additional features and patches
- Works regardless of ISP
- Easy toggle on and off
**Cons:**
- Requires homebrew
## Installation
<div class="tip">
This part of the guide assumes that you have a <b>Homebrewed System</b> using <b>Aroma</b>.
If you don't yet, you can follow this <a href="https://wiiu.hacks.guide/" target="_blank">guide to set up homebrew on your Wii U</a>.
@@ -23,7 +36,7 @@ You can connect your Wii U to Pretendo using one of 2 methods. Inkay is recommen
Locate the `Aroma Updater` icon on your Wii U Menu and open it.
<img src="/assets/images/docs/install/wiiu/aroma/aroma-updater-icon.jpg" alt="Screenshot of Wii U Menu with the Aroma Updater icon highlighted" width="100%">
<img src="/assets/images/docs/install/wiiu/aroma/aroma-updater-icon.webp" alt="Screenshot of Wii U Menu with the Aroma Updater icon highlighted" width="100%">
On the welcome screen, press A to check for updates.
@@ -56,75 +69,79 @@ Wait for the installation to complete, then press A to restart your console.
Once the console restarts, you'll see a notification in the top-left informing you that Pretendo will be used. The notification disappears after a few moments.
<img src="/assets/images/docs/install/wiiu/aroma/pretendo-notification.jpg" alt="The Wii U user selection screen, with 'Using Pretendo Network' overlaid in the top-left" width="100%">
<img src="/assets/images/docs/install/wiiu/aroma/pretendo-notification.webp" alt="The Wii U user selection screen, with 'Using Pretendo Network' overlaid in the top-left" width="100%">
Inkay is now installed and working. You can proceed to [PNID Setup](#pnid-setup) to create an account.
# SSSL
**Pros:**
- Does not require homebrew
- Very easy to setup
**Cons:**
- Only a subset of services are supported
- Lacks additional features and patches
- Does not work on some ISPs
- Hard to switch on or off
SSSL is a (limited) hackless method of accessing most services by exploiting a bug in the Wii U's SSL module. All Nintendo Network games produced by Nintendo are supported by SSSL, as are the ***in-game*** Miiverse features. The main Miiverse app, in-game ***posting*** app, and any game which uses its own SSL stack (YouTube, WATCH_DOGS, etc.), are ***NOT*** supported by this method, as they are unaffected by the SSL exploit.
SSSL is a (limited) hackless method of accessing most services by exploiting a bug in the Wii U's SSL module. All Nintendo Network games produced by Nintendo are supported by SSSL, as are the **_in-game_** Miiverse features. The main Miiverse app, in-game **_posting_** app, and any game which uses its own SSL stack (YouTube, WATCH*DOGS, etc.), are \*\*\_NOT*\*\* supported by this method, as they are unaffected by the SSL exploit.
## Installation
<div class="tip">
System Settings, and therefore SSSL, requires a Wii U GamePad to use on unmodified systems.
</div>
Locate the `System Settings` icon on your Wii U Menu and open it.
<img src="/assets/images/docs/install/wiiu/sssl/system-settings.jpg" alt="The Wii U Menu, with the System Settings icon highlighted" width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/system-settings.webp" alt="The Wii U Menu, with the System Settings icon highlighted" width="100%">
Open the Internet category.
<img src="/assets/images/docs/install/wiiu/sssl/internet-settings.jpg" alt="The System Settings app, with the Internet category highlighted" width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-settings.webp" alt="The System Settings app, with the Internet category highlighted" width="100%">
Select `Connect to the Internet`.
<img src="/assets/images/docs/install/wiiu/sssl/internet-settings-connect.jpg" alt="The System Settings app, with the Connect to the Internet button highlighted" width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-settings-connect.webp" alt="The System Settings app, with the Connect to the Internet button highlighted" width="100%">
Select `Connection List` in the top-right.
<img src="/assets/images/docs/install/wiiu/sssl/internet-settings-scan.jpg" alt="The Internet Connection Setup panel. In the top-right is a Connection List button (X)" width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-settings-scan.webp" alt="The Internet Connection Setup panel. In the top-right is a Connection List button (X)" width="100%">
Locate the connection with a "Wii U" logo. This is the one your system will use by default. Press A to edit it.
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-list.jpg" alt="A list of internet connections. 'Wired Connection' is marked with a Wii U and Wii logo, and is highlighted." width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-list.webp" alt="A list of internet connections. 'Wired Connection' is marked with a Wii U and Wii logo, and is highlighted." width="100%">
Select `Change Settings`.
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-change.jpg" alt="A list of options. 'Change Settings' is highlighted." width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-change.webp" alt="A list of options. 'Change Settings' is highlighted." width="100%">
Navigate to the right and down to the `DNS` button, and press A to edit.
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-button.jpg" alt="The second page of the Wii U connection editor. DNS is highlighted." width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-button.webp" alt="The second page of the Wii U connection editor. DNS is highlighted." width="100%">
Select `Do not auto-obtain`. We will provide our own DNS for SSSL to work.
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-obtain.jpg" alt="Two options for 'Automatically obtain DNS?' 'Do not auto-obtain' is highlighted." width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-obtain.webp" alt="Two options for 'Automatically obtain DNS?' 'Do not auto-obtain' is highlighted." width="100%">
This brings up the DNS input. We will change both the Primary and Secondary DNS settings.
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-editor.jpg" alt="Two input fields for Primary and Secondary DNS." width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-editor.webp" alt="Two input fields for Primary and Secondary DNS." width="100%">
For the Primary DNS, enter `88.198.140.154`. This is the SSSL server.
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-primary.jpg" alt="'Enter the primary DNS' field, with 88.198.140.154 - the SSSL server - input." width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-primary.webp" alt="'Enter the primary DNS' field, with 88.198.140.154 - the SSSL server - input." width="100%">
For the Secondary DNS, enter `9.9.9.9` (or another public DNS of your choice). This will serve as a fallback if Pretendo's SSSL server should go offline, allowing your console to still access the Internet. If Pretendo is offline and the fallback is used, however, the console will access Nintendo Network rather than Pretendo Network. If this is undesirable to you, leave this field blank.
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-secondary.jpg" alt="'Enter the secondary DNS' field, with 9.9.9.9 - a public DNS server - input." width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-secondary.webp" alt="'Enter the secondary DNS' field, with 9.9.9.9 - a public DNS server - input." width="100%">
Review the final settings and ensure you typed them correctly. The Wii U will add leading zeroes to each number - this is okay. If they are correct, press Confirm.
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-done.jpg" width="100%">
<img src="/assets/images/docs/install/wiiu/sssl/internet-connection-dns-done.webp" width="100%">
Press B to save the connection. You may perform a connection test and set the connection as default. Then, press B until System Settings exits.
@@ -133,14 +150,16 @@ SSSL is now installed and working. You can proceed to [PNID Setup](#pnid-setup)
To disconnect from Pretendo Network (e.g. to access the Nintendo eShop) repeat this process, but select `Auto-obtain` for the DNS.
# PNID Setup
After installing Pretendo, you must register a Pretendo Network ID (PNID). There is currently two ways of creating a PNID: Creating an account with the website and linking it, or creating it on your Wii U.
<div class="tip red">
<strong>CAUTION:</strong>
A Pretendo Network ID may not use the same username as an account already linked to your Wii U! If you have any existing Nintendo Network IDs on your Wii U which share the username you wish to use, those accounts MUST be removed from your console first.
A Pretendo Network ID may not use the same username as an account already linked to your Wii U! Ensure that you have chosen a different name for your PNID than the name on your NNID.
</div>
### Website
You will want to register an account from [here](/account) and click `Don't have an account?` to register.
<div class="tip yellow">
@@ -148,16 +167,18 @@ You will want to register an account from [here](/account) and click `Don't have
Account settings cannot be modified at this time. Feature updates to the website have been paused as we migrate the codebase, and the account settings app on the Wii U requires additional patches.
</div>
<img src="/assets/images/docs/install/wiiu/pnid/register-account-web.png" alt="Screenshot of a web form to register an account" width="100%">
<img src="/assets/images/docs/install/wiiu/pnid/register-account-web.webp" alt="Screenshot of a web form to register an account" width="100%">
Once your account is registered, link it to your console as you would a Nintendo Network ID.
Your PNID is now set up and ready to use. You may continue reading to learn about optional extras, like Inkay's features and transferring save data, or you can stop here.
### Wii U
Create the Pretendo Network ID as you would a Nintendo Network ID.
# Using Inkay
If you're using Inkay rather than SSSL, there are some additional features you may find helpful.
<details>
@@ -178,9 +199,10 @@ Press A on `Connect to Pretendo network` to toggle it to `false`.
Press `B` three times to exit the Aroma plugin menu. Your console will restart. Once it does, a notification will appear showing that you are now using Nintendo Network.
<img src="/assets/images/docs/install/wiiu/inkay-tips/nintendo-notification.jpg" alt="The Wii U user selection screen, with 'Using Nintendo Network' overlaid in the top-left" width="100%">
<img src="/assets/images/docs/install/wiiu/inkay-tips/nintendo-notification.webp" alt="The Wii U user selection screen, with 'Using Nintendo Network' overlaid in the top-left" width="100%">
You may now use your NNID to access the eShop or other Nintendo services. To return to Pretendo Network, repeat the process and set `Connect to Pretendo network` to `true`.
</details>
<details>
@@ -204,6 +226,7 @@ The button will change to indicate the console must be restarted.
<img src="/assets/images/docs/install/wiiu/inkay-tips/inkay-wwp-apply.png" alt="Screenshot of Inkay menu with Reset Wara Wara Plaza highlighted. The entry now says 'Restart to apply'" width="100%">
Press `B` three times to exit the Aroma plugin menu. Your console will restart. Once it does, the process is complete.
</details>
# Transferring save data to your Pretendo Network account
@@ -215,23 +238,23 @@ Pretendo Network is not compatible with existing Nintendo Network IDs. This mean
This only works with local save data. Any user data stored on Nintendo's servers cannot be transferred to any other accounts.
</div>
To move your save data, you will need a save data backup homebrew application. This guide will use the WUT port of SaveMii for Aroma. To begin, download the latest [GitHub release](https://github.com/Xpl0itU/savemii/releases) of SaveMii or download it from the [Homebrew App Store](https://hb-app.store).
To move your save data, you will need a save data backup homebrew application. This guide will use the WUT port of SaveMii for Aroma. To begin, download the latest [GitHub release](https://github.com/Xpl0itU/savemii/releases) of SaveMii or download it from the [Homebrew App Store](https://hb-app.store).
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-appstore.jpg" alt="Screenshot of Homebrew App Store page of SaveMii Mod" width="100%">
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-appstore.webp" alt="Screenshot of Homebrew App Store page of SaveMii Mod" width="100%">
Once installed, open the application from the HOME Menu. You should see a menu for Wii U and vWii saves.
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-mainmenu.jpg" alt="SaveMii menu" width="100%">
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-mainmenu.webp" alt="SaveMii menu" width="100%">
Select `Wii U Save Management`. You should now see a list of installed games. Find and select the game you would like to transfer the save data of.
Select `Backup savedata`.
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-backup.jpg" alt="SaveMii backup save data menu" width="100%">
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-backup.webp" alt="SaveMii backup save data menu" width="100%">
Select a new slot to backup the save data to. If you select a non-empty slot, the backup data in that slot will be overwritten.
Select the profile to backup the save data from. This should be your ***Nintendo*** Network ID.
Select the profile to backup the save data from. This should be your **_Nintendo_** Network ID.
Optionally you may select to backup "common" save data. This save data should be shared by all users, and is not required to be backed up. Though you may still do so if you choose.
@@ -246,14 +269,14 @@ Once the backup has completed, press the `B` button to return to the games menu.
Select the backup slot you just backed the save data up to.
Select the profile to restore the save data to. This should be your ***Pretendo*** Network ID.
Select the profile to restore the save data to. This should be your **_Pretendo_** Network ID.
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-transfer.jpg" alt="SaveMii restore save data menu" width="100%">
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-transfer.webp" alt="SaveMii restore save data menu" width="100%">
When ready, press the `A` button to transfer your data. Press `A` again to confirm your actions. If you get a message about backing up your data on your Pretendo profile, ignore. Your screen may briefly flash as the data is copied over.
Once completed, exit SaveMii and ensure the game you transferred works properly on your Pretendo profile.
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-saveworkingonpretendo.jpg" alt="Screenshot of a game that loaded successfully" width="100%">
<img src="/assets/images/docs/install/wiiu/savedatabackup/savemii-saveworkingonpretendo.webp" alt="Screenshot of a game that loaded successfully" width="100%">
Repeat this process for any other save data you'd like to transfer to your Pretendo profile.

View File

@@ -1,3 +1,7 @@
---
description: "Instructions on how to gather network dumps of games."
---
# Network Dumps
One of the best ways to support the project is to help in gathering network dumps of games. These network dumps can be used by developers to help understand how the servers operate in a live environment. This kind of data greatly simplifies development of the servers, as it removes a large amount of guesswork and reverse engineering.

View File

@@ -0,0 +1,83 @@
{
"people": [
{
"name": "superwhiskers",
"captionKey": "forCrunch",
"picture": "https://github.com/superwhiskers.png",
"github": "https://github.com/superwhiskers"
},
{
"name": "Stary",
"captionKey": "forCtrDev",
"picture": "https://github.com/Stary2001.png",
"github": "https://github.com/Stary2001"
},
{
"name": "rverse",
"captionKey": "forMiiverseHelp",
"picture": "https://github.com/rverseTeam.png",
"github": "https://twitter.com/rverseClub"
},
{
"name": "Kinnay",
"isSpecial": true,
"captionKey": "forResearch",
"picture": "https://cdn.discordapp.com/avatars/186572995848830987/b55c0d4e7bfd792edf0689f83a25d8ea.png?size=128",
"github": "https://github.com/Kinnay"
},
{
"name": "NinStar",
"captionKey": "forIcons",
"picture": "https://github.com/ninstar.png",
"github": "https://github.com/ninstar"
},
{
"name": "Rambo6Glaz",
"captionKey": "forServerDev",
"picture": "https://github.com/EpicUsername12.png",
"github": "https://github.com/EpicUsername12"
},
{
"name": "GaryOderNichts",
"captionKey": "forPatches",
"picture": "https://github.com/GaryOderNichts.png",
"github": "https://github.com/GaryOderNichts"
},
{
"name": "zaksabeast",
"captionKey": "forPatches",
"picture": "https://cdn.discordapp.com/avatars/219324395707957248/c62573fbd4d26c8b4724f54413df6960.png?size=128",
"github": "https://github.com/zaksabeast"
},
{
"name": "mrjvs",
"captionKey": "forServers",
"picture": "https://github.com/mrjvs.png",
"github": "https://github.com/mrjvs"
},
{
"name": "binaryoverload",
"captionKey": "forServers",
"picture": "https://github.com/binaryoverload.png",
"github": "https://github.com/binaryoverload"
},
{
"name": "Simonx22",
"captionKey": "forSplatoon",
"picture": "https://github.com/Simonx22.png",
"github": "https://github.com/Simonx22"
},
{
"name": "OatmealDome",
"captionKey": "forSplatoon",
"picture": "https://github.com/OatmealDome.png",
"github": "https://github.com/OatmealDome"
},
{
"name": "GitHub contributors",
"captionKey": "general",
"picture": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
"github": "https://github.com/PretendoNetwork"
}
]
}

76
content/team.json Normal file
View File

@@ -0,0 +1,76 @@
{
"people": [
{
"name": "Jonathan Barrow (jonbarrow)",
"captionKey": "owner",
"picture": "https://github.com/jonbarrow.png",
"github": "https://github.com/jonbarrow"
},
{
"name": "Jemma (CaramelKat)",
"captionKey": "miiverseDev",
"picture": "https://github.com/caramelkat.png",
"github": "https://github.com/CaramelKat"
},
{
"name": "quarky",
"captionKey": "wiiuResearchAndPatchDev",
"picture": "https://github.com/ashquarky.png",
"github": "https://github.com/ashquarky"
},
{
"name": "SuperMarioDaBom",
"captionKey": "researchAndServerArch",
"picture": "https://github.com/supermariodabom.png",
"github": "https://github.com/SuperMarioDaBom"
},
{
"name": "limes.pink",
"captionKey": "webDev",
"picture": "https://github.com/limesdotpink.png",
"github": "https://github.com/limesdotpink"
},
{
"name": "Shutterbug2000",
"captionKey": "researchAndGameDev",
"picture": "https://cdn.discordapp.com/avatars/191370953807233024/0311b61e2009c1576828dd2e9a59d72e.png?size=128",
"github": "https://github.com/shutterbug2000"
},
{
"name": "Billy",
"captionKey": "preserveAndServerArch",
"picture": "https://github.com/InternalLoss.png",
"github": "https://github.com/InternalLoss"
},
{
"name": "DaniElectra",
"captionKey": "researchAndGameDev",
"picture": "https://github.com/danielectra.png",
"github": "https://github.com/DaniElectra"
},
{
"name": "niko",
"captionKey": "webDevAndGameDev",
"picture": "https://github.com/hauntii.png",
"github": "https://github.com/hauntii"
},
{
"name": "MatthewL246",
"captionKey": "devopsAndCommunityWork",
"picture": "https://github.com/MatthewL246.png",
"github": "https://github.com/MatthewL246"
},
{
"name": "wolfendale",
"captionKey": "gameDevAndOptimise",
"picture": "https://github.com/wolfendale.png",
"github": "https://github.com/wolfendale"
},
{
"name": "TraceEntertains",
"captionKey": "ctrResearchAndPatchDev",
"picture": "https://github.com/TraceEntertains.png",
"github": "https://github.com/TraceEntertains"
}
]
}

72
content/terms/cookies.md Normal file
View File

@@ -0,0 +1,72 @@
[//]: <> (Basically this whole document is a mashup of generated/pre-made documents from both https://termly.io/ and https://www.termsfeed.com/)
[//]: <> (and then modified slightly to fit our needs. We did not write most of this, but have done our best to make it reflect our goals/intentions.)
[//]: <> (However there is quite a lot of legalese here, and possibly broad policies which we do not necessarily want/need. In those cases we are more)
[//]: <> (than happy to revise/remove the problematic areas to clarify our goals/intentions.)
# Cookies Policy
## Last updated: March 17th, 2025
This Cookies Policy explains what Cookies are and how We use them. You should read this policy so You can understand what type of cookies We use, or the information We collect using Cookies and how that information is used.
Cookies do not typically contain any information that personally identifies a user, but personal information that We store about You may be linked to the information stored in and obtained from Cookies. For further information on how We use, store and keep your personal data secure, see our [Privacy Policy](/terms/privacy).
We do not store sensitive personal information, such as mailing addresses, account passwords, etc. in the Cookies We use.
## Interpretation and Definitions
### Interpretation
The words of which the initial letter is capitalized have meanings defined under the following conditions. The following definitions shall have the same meaning regardless of whether they appear in singular or in plural.
### Definitions
For the purposes of this Cookies Policy:
- **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Cookies Policy) refers to Yesterware LLC.
- **Cookies** means small files that are placed on Your computer, mobile device or any other device by a website, containing details of your browsing history on that website among its many uses.
- **Website** refers to Pretendo Network, accessible from [https://pretendo.network](https://pretendo.network)
- **You** means the individual accessing or using the Website, or a company, or any legal entity on behalf of which such individual is accessing or using the Website, as applicable.
The use of the Cookies
----------------------
### Type of Cookies We Use
We do not use cookies to track You or Your behavior across the web. All Cookies in use are necessary for the operation of Our services. Not all Cookies are issued by Us. Some Cookies may be issued by [Cloudflare](https://cloudflare.com) as part of Our infrastructure. For detailed information on the Cookies issued by Cloudflare, see the [Cloudflare Cookies](https://developers.cloudflare.com/fundamentals/reference/policies-compliances/cloudflare-cookies) documentation.
Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on your personal computer or mobile device when You go offline, while Session Cookies are deleted as soon as You close your web browser. Refer to the table below for information on what Cookies We make use of.
| Name | Type | Issued By | Use |
| --------------- | ---------- | ------------------------------------ | -------------------------------- |
| access_token | Session | Us | Authentication |
| refresh_token | Session | Us | Refresh expired access tokens |
| token_type | Session | Us | The type of token in use |
| preferredLocale | Persistent | Us | Selected locale for translations |
| _cfuvid | Session | [Cloudflare](https://cloudflare.com) | Rate limiting |
| __cf_bm | Persistent | [Cloudflare](https://cloudflare.com) | Bot detection |
### Your Choices Regarding Cookies
If You prefer to avoid the use of Cookies on the Website, first You must disable the use of Cookies in your browser and then delete the Cookies saved in your browser associated with this website. You may use this option for preventing the use of Cookies at any time.
If You do not accept Our Cookies, You may experience some inconvenience in your use of the Website and some features may not function properly.
If You'd like to delete Cookies or instruct your web browser to delete or refuse Cookies, please visit the help pages of your web browser.
- For the Chrome web browser, please visit this page from Google: [https://support.google.com/accounts/answer/32050](https://support.google.com/accounts/answer/32050)
- For the Internet Explorer web browser, please visit this page from Microsoft: [http://support.microsoft.com/kb/278835](http://support.microsoft.com/kb/278835)
- For the Firefox web browser, please visit this page from Mozilla: [https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored](https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored)
- For the Safari web browser, please visit this page from Apple: [https://support.apple.com/guide/safari/manage-cookies-and-website-data-sfri11471/mac](https://support.apple.com/guide/safari/manage-cookies-and-website-data-sfri11471/mac)
For any other web browser, please visit your web browser's official web pages.
## Modifications to the Policy
We may update this Cookies Policy from time to time. We will notify You of any changes by updating the "Last updated" date at the top of this policy. We may also notify You of any changes via email. You are advised to review this page periodically for any changes. Changes to this Cookies Policy are effective when they are posted on this page.
### Contact Us
If you have any questions about this Cookies Policy, You can contact us:
- By email: `privacy@pretendo.network`

420
content/terms/privacy.md Normal file
View File

@@ -0,0 +1,420 @@
[//]: <> (Basically this whole document is a mashup of generated/pre-made documents from both https://termly.io/ and https://www.termsfeed.com/)
[//]: <> (and then modified slightly to fit our needs. We did not write most of this, but have done our best to make it reflect our goals/intentions.)
[//]: <> (However there is quite a lot of legalese here, and possibly broad policies which we do not necessarily want/need. In those cases we are more)
[//]: <> (than happy to revise/remove the problematic areas to clarify our goals/intentions.)
# Privacy Policy
## Last updated: March 17th, 2025
## Interpretation and Definitions
### Interpretation
The words of which the initial letter is capitalized have meanings defined under the following conditions. The following definitions shall have the same meaning regardless of whether they appear in singular or in plural.
### Definitions
For the purposes of this Privacy Policy:
- **Account** means a unique account created for You to access Our Service or parts of Our Service.
- **Affiliate** means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.
- **Application** refers to Pretendo Network, the software program provided by the Company.
- **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to Yesterware LLC.
- **Country** refers to: Florida, United States
- **Device** means any device that can access the Service such as a computer, a cellphone or digital tablet, or game console.
- **Personal Data** is any information that relates to an identified or identifiable individual.
- **Service** refers to the Application.
- **Service Provider** means any natural or legal person who processes the data on behalf of the Company. It refers to third-party companies or individuals employed by the Company to facilitate the Service, to provide the Service on behalf of the Company, to perform services related to the Service or to assist the Company in analyzing how the Service is used.
- **Usage Data** refers to data collected automatically, either generated by the use of the Service or from the Service infrastructure itself (for example, the duration of a page visit).
- **You/Your** means the individual accessing or using the Service, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable.
This privacy notice describes how and why We might collect, store, use, and/or share ("**process**") Your information when You use Our services ("**Services**"), such as when You:
- Visit Our website at https://pretendo.network, or any website of Ours that links to this privacy notice
- Download and use Our applications/software, or any other application of Ours that links to this privacy notice
- Engage with Us in other related ways, including any sales, marketing, or events
**Questions or concerns?** Reading this privacy notice will help You understand Your privacy rights and choices. If You do not agree with Our policies and practices, please do not use Our Services. If You still have any questions or concerns, please contact Us by using the contact details provided in the section "[Contact Us](#contact-us)" below
### SUMMARY OF KEY POINTS
***We aim to collect as little information as possible about You outside of what is required for Us to operate Our Services. We do not collect excess personal data, and we do not directly share Your information with 3rd parties outside of what is automatically collected as part of Our Services. We do not sell or otherwise profit from Your data.***
***This summary provides key points from Our privacy notice, but You can find out more details about any of these topics by clicking the link following each key point or by using Our*** [***table of contents***](#table-of-contents) ***below to find the section You are looking for.***
**What personal information do We process?** When You visit, use, or navigate Our Services, We may process personal information depending on how You interact with Us and the Services, the choices You make, and the products and features You use. Learn more about [personal information You disclose to Us](#personal-information-you-disclose-to-us).
**Do We process any sensitive personal information?** We do not process sensitive personal information.
**Do We receive any information from third parties?** We do not receive any information from third parties.
**How do We process Your information?** We process Your information to provide, improve, and administer Our Services, communicate with You, for security and fraud prevention, and to comply with law. We may also process Your information for other purposes with Your consent. We process Your information only when We have a valid legal reason to do so. Learn more about [how We process Your information](#2-how-do-we-process-your-information).
**In what situations and with which parties do We share personal information?** We may share information in specific situations and with specific third parties. Learn more about [when and with whom We share Your personal information](#4-when-and-with-whom-do-we-share-your-personal-information).
**How do We keep Your information safe?** We have organizational and technical processes and procedures in place to protect Your personal information. However, no electronic transmission over the internet or information storage technology can be guaranteed to be 100% secure, so We cannot promise or guarantee that hackers, cybercriminals, or other unauthorized third parties will not be able to defeat Our security and improperly collect, access, steal, or modify Your information. Learn more about [how We keep Your information safe](#8-how-do-we-keep-your-information-safe).
**What are Your rights?** Depending on where You are located geographically, the applicable privacy law may mean You have certain rights regarding Your personal information. Learn more about [Your privacy rights](#9-what-are-your-privacy-rights).
**How do You exercise Your rights?** The easiest way to exercise Your rights is by contacting Us. We will consider and act upon any request in accordance with applicable data protection laws.
Want to learn more about what We do with any information We collect? [Review the privacy notice in full](#table-of-contents).
### TABLE OF CONTENTS
1. [What Information Do We Collect?](#1-what-information-do-we-collect)
2. [How Do We Process Your Information?](#2-how-do-we-process-your-information)
3. [What Legal Bases Do We Rely on to Process Your Personal Information?](#3-what-legal-bases-do-we-rely-on-to-process-your-information)
4. [When and With Whom Do We Share Your Personal Information?](#4-when-and-with-whom-do-we-share-your-personal-information)
5. [Do We Use Cookies and Other Tracking Technologies?](#5-do-we-use-cookies-and-other-tracking-technologies)
6. [Is Your Information Transferred Internationally?](#6-is-your-information-transferred-internationally)
7. [How Long Do We Keep Your Information?](#7-how-long-do-we-keep-your-information)
8. [How Do We Keep Your Information Safe?](#8-how-do-we-keep-your-information-safe)
9. [What Are Your Privacy Rights?](#9-what-are-your-privacy-rights)
10. [Controls for Do-not-track Features](#10-controls-for-do-not-track-features)
11. [Do California Residents Have Specific Privacy Rights?](#11-do-california-residents-have-specific-privacy-rights)
12. [Do Virginia Residents Have Specific Privacy Rights?](#12-do-virginia-residents-have-specific-privacy-rights)
13. [Do We Make Updates to This Notice?](#13-do-we-make-updates-to-this-notice)
14. [Contact Us](#contact-us)
### 1. What Information Do We Collect?
#### Personal information You disclose to Us
***In Short:*** *We collect personal information that You provide to Us.*
We collect personal information that You voluntarily provide to Us when You register on the Services, express an interest in obtaining information about Us or Our products and Services, when You participate in activities on the Services, or otherwise when You contact Us.
**Personal Information Provided by You.** The personal information that We collect depends on the context of Your interactions with Us and the Services, the choices You make, and the products and features You use. The personal information We collect may include, but is not limited to, the following:
- User Account Details, such as the username and email You provided upon sign up.
- Profile information, such as Your gender, birthday, country, and language.
- Contact Preferences, such as if You wish to receive a newsletter We may offer.
- Console identifiers, for authenticating You to the services.
- The IP address(es) You use when connecting to Our services.
- Your primary 'Mii' character.
- Details of Your connected accounts, such as Your Discord and Google account identifiers.
**Sensitive Information.** We do not process sensitive information.
**Payment Data.** We may collect data necessary to process Your payment if You make purchases, such as Your payment instrument number, and the security code associated with Your payment instrument. All payment data is stored by Stripe. You may find their privacy notice link(s) here: [https://stripe.com/privacy](https://stripe.com/privacy).
All personal information that You provide to Us must be true, complete, and accurate, and You must notify Us of any changes to such personal information.
#### Information automatically collected
***In Short:*** *Some information — such as Your Internet Protocol (IP) address and/or browser and device characteristics — is collected automatically when You visit Our Services.*
We may automatically collect certain information when You visit, use, or navigate the Services. This information does not reveal Your specific identity (like Your name or contact information) but may include device and usage information, such as Your IP address, browser and device characteristics, operating system, language preferences, referring URLs, device name, country, location, information about how and when You use Our Services, and other technical information. This information is primarily needed to maintain the security and operation of Our Services, and for Our internal analytics and reporting purposes.
The information We collect includes:
- *Log and Usage Data.* Log and usage data is service-related, diagnostic, usage, and performance information Our servers automatically collect when You access or use Our Services and which We record in log files. Depending on how You interact with Us, this log data may include Your IP address, device information, browser type, and settings and information about Your activity in the Services (such as the date/time stamps associated with Your usage, pages and files viewed, searches, and other actions You take such as which features You use), device event information (such as system activity, error reports (sometimes called "crash dumps"), and hardware settings). This information is used to ensure compatibility with devices and locate areas of Our Services which may be having issues.
- *Device Data.* We may collect data about the device You use to access the Services. Depending on the device used, this device data may include information such as Your IP address (or proxy server), device and application identification numbers (console serial numbers), location, browser type, hardware model, and system configuration information. This data is uses for moderation and to ensure valid clients are reaching the expected Services.
- *Location Data.* We do not collect location data, either either precise or imprecise, directly. Games may at times send location based data, for the intent of geolocation and region locking purposes, however this is not stored or processed by Our Services.
Pretendo Network uses various 3rd party services as part of Our infrastructure. These 3rd parties may collect additional information outside of our control, but are required for the operation of Our Services. Please refer to the relevant parties policies:
- [Cloudflare](https://www.cloudflare.com/privacypolicy/)
- [Bunny](https://bunny.net/privacy/)
- [Discourse](https://www.discourse.org/privacy)
- [Stripe](https://stripe.com/privacy)
- [Mastodon](https://mastodon.pretendo.network/privacy-policy)
### 2. How Do We Process Your Information?
***In Short:*** *We process Your information to provide, improve, and administer Our Services, communicate with You, for security and fraud prevention, and to comply with law. We may also process Your information for other purposes with Your consent.*
**We process Your personal information for a variety of reasons, depending on how You interact with Our Services, including:**
- **To facilitate account creation and authentication and otherwise manage user accounts.** We may process Your information so You can create and log in to Your account, as well as keep Your account in working order.
- **To deliver and facilitate delivery of services to the user.** We may process Your information to provide You with the requested service.
- **To respond to user inquiries/offer support to users.** We may process Your information to respond to Your inquiries and solve any potential issues You might have with the requested service.
- **To send administrative information to You.** We may process Your information to send You details about Our products and services, changes to Our terms and policies, and other similar information.
- **To fulfill and manage Your orders.** We may process Your information to fulfill and manage Your orders, payments, returns, and exchanges made through the Services.
- **To enable user-to-user communications.** We may process Your information if You choose to use any of Our offerings that allow for communication with another user.
- **To request feedback.** We may process Your information when necessary to request feedback and to contact You about Your use of Our Services.
- **To protect Our Services.** We may process Your information as part of Our efforts to keep Our Services safe and secure, including fraud monitoring and prevention.
- **To identify usage trends.** We may process information about how You use Our Services to better understand how they are being used so We can improve them.
### 3. What Legal Bases Do We Rely on to Process Your Personal Information?
***In Short:*** *We only process Your personal information when We believe it is necessary and We have a valid legal reason (i.e., legal basis) to do so under applicable law, like with Your consent, to comply with laws, to provide You with services to enter into or fulfill Our contractual obligations, to protect Your rights, or to fulfill Our legitimate business interests.*
***If You are located in the EU or UK, this section applies to You.***
The General Data Protection Regulation (GDPR) and UK GDPR require Us to explain the valid legal bases We rely on in order to process Your personal information. As such, We may rely on the following legal bases to process Your personal information:
- **Consent.** We may process Your information if You have given Us permission (i.e., consent) to use Your personal information for a specific purpose. You can withdraw Your consent at any time. Learn more about [withdrawing Your consent](#9-what-are-your-privacy-rights).
- **Performance of a Contract.** We may process Your personal information when We believe it is necessary to fulfill Our contractual obligations to You, including providing Our Services or at Your request prior to entering into a contract with You.
- **Legitimate Interests.** We may process Your information when We believe it is reasonably necessary to achieve Our legitimate business interests and those interests do not outweigh Your interests and fundamental rights and freedoms. For example, We may process Your personal information for some of the purposes described in order to:
- Analyze how Our Services are used so We can improve them to engage and retain users
- Diagnose problems and/or prevent fraudulent activities
- Understand how Our users use Our products and services so We can improve user experience
- **Legal Obligations.** We may process Your information where We believe it is necessary for compliance with Our legal obligations, such as to cooperate with a law enforcement body or regulatory agency, exercise or defend Our legal rights, or disclose Your information as evidence in litigation in which We are involved.
- **Vital Interests.** We may process Your information where We believe it is necessary to protect Your vital interests or the vital interests of a third party, such as situations involving potential threats to the safety of any person.
***If You are located in Canada, this section applies to You.***
We may process Your information if You have given Us specific permission (i.e., express consent) to use Your personal information for a specific purpose, or in situations where Your permission can be inferred (i.e., implied consent). You can [withdraw Your consent](#9-what-are-your-privacy-rights) at any time.
In some exceptional cases, We may be legally permitted under applicable law to process Your information without Your consent, including, for example:
- If collection is clearly in the interests of an individual and consent cannot be obtained in a timely way
- For investigations and fraud detection and prevention
- For business transactions provided certain conditions are met
- If it is contained in a witness statement and the collection is necessary to assess, process, or settle an insurance claim
- For identifying injured, ill, or deceased persons and communicating with next of kin
- If We have reasonable grounds to believe an individual has been, is, or may be victim of financial abuse
- If it is reasonable to expect collection and use with consent would compromise the availability or the accuracy of the information and the collection is reasonable for purposes related to investigating a breach of an agreement or a contravention of the laws of Canada or a province
- If disclosure is required to comply with a subpoena, warrant, court order, or rules of the court relating to the production of records
- If it was produced by an individual in the course of their employment, business, or profession and the collection is consistent with the purposes for which the information was produced
- If the collection is solely for journalistic, artistic, or literary purposes
- If the information is publicly available and is specified by the regulations
### 4. When and With Whom Do We Share Your Personal Information?
***In Short:*** *We may share information in specific situations described in this section and/or with the following third parties.*
We may need to share Your personal information in the following situations:
- **Other Users.** When You share personal information (for example, by posting comments, contributions, or other content to the Services) or otherwise interact with public areas of the Services, such personal information may be viewed by all users and may be publicly made available outside the Services in perpetuity. Similarly, other users will be able to view descriptions of Your activity, communicate with You within Our Services, and view Your profile.
- **3rd Parties.** When using Our Services, Your data may be automatically collected by the various 3rd party services in use as part of Our infrasture. Pretendo Network does not share or sell Your data to these 3rd parties. The data collected is automatic, through normal usage of Our Services and is required for the operation of Our Services.
### 5. Do We Use Cookies and Other Tracking Technologies?
***In Short:*** *We may use cookies and other tracking technologies to collect and store Your information.*
We may use cookies and similar tracking technologies (like web beacons and pixels) to access or store information. Specific information about how We use such technologies and how You can refuse certain cookies is set out in Our [Cookie Notice](/terms/cookies).
### 6. Is Your Information Transferred Internationally?
***In Short:*** *We may transfer, store, and process Your information in countries other than Your own.*
We operate servers in various countries, including in the United States and Germany. If You are accessing Our Services from outside of the countries where Our Services are operating, please be aware that Your information may be transferred to, stored, and processed by Us in Our facilities and by those third parties with whom We may share Your personal information (see "[When and With Whom Do We Share Your Personal Information?](#4-when-and-with-whom-do-we-share-your-personal-information)" above), in and other countries.
If You are a resident in the European Economic Area (EEA) or United Kingdom (UK), then these countries may not necessarily have data protection laws or other similar laws as comprehensive as those in Your country. However, We will take all necessary measures to protect Your personal information in accordance with this privacy notice and applicable law.
### 7. How Long Do We Keep Your Information?
***In Short:*** *We keep Your information for as long as necessary to fulfill the purposes outlined in this privacy notice unless otherwise required by law.*
We will only keep Your personal information for as long as it is necessary for the purposes set out in this privacy notice, unless a longer retention period is required or permitted by law (such as tax, accounting, or other legal requirements). No purpose in this notice will require Us keeping Your personal information for longer than the period of time in which users have an account with Us.
When We have no ongoing legitimate business need to process Your personal information, We will either delete or anonymize such information, or, if this is not possible (for example, because Your personal information has been stored in backup archives), then We will securely store Your personal information and isolate it from any further processing until deletion is possible.
### 8. How Do We Keep Your Information Safe?
***In Short:*** *We aim to protect Your personal information through a system of organizational and technical security measures.*
We have implemented appropriate and reasonable technical and organizational security measures designed to protect the security of any personal information We process. However, despite Our safeguards and efforts to secure Your information, no electronic transmission over the Internet or information storage technology can be guaranteed to be 100% secure, so We cannot promise or guarantee that hackers, cybercriminals, or other unauthorized third parties will not be able to defeat Our security and improperly collect, access, steal, or modify Your information. Although We will do Our best to protect Your personal information, transmission of personal information to and from Our Services is at Your own risk. You should only access the Services within a secure environment.
### 9. What Are Your Privacy Rights?
***In Short:*** *In some regions, such as the European Economic Area (EEA), United Kingdom (UK), and Canada, You have rights that allow You greater access to and control over Your personal information. You may review, change, or terminate Your account at any time. These rights are extended to all users regardless of region.*
In some regions (like the EEA, UK, and Canada), You have certain rights under applicable data protection laws. These may include the right (i) to request access and obtain a copy of Your personal information, (ii) to request rectification or erasure; (iii) to restrict the processing of Your personal information; and (iv) if applicable, to data portability. In certain circumstances, You may also have the right to object to the processing of Your personal information. You can make such a request by contacting Us by using the contact details provided in the section "[Contact Us](#contact-us)" below.
We will consider and act upon any request in accordance with applicable data protection laws.
If You are located in the EEA or UK and You believe We are unlawfully processing Your personal information, You also have the right to complain to Your [Member State data protection authority](https://ec.europa.eu/justice/data-protection/bodies/authorities/index_en.htm) or [UK data protection authority](https://ico.org.uk/make-a-complaint/data-protection-complaints/data-protection-complaints/).
If You are located in Switzerland, You may contact the [Federal Data Protection and Information Commissioner](https://www.edoeb.admin.ch/edoeb/en/home.html).
**Withdrawing Your consent:** If We are relying on Your consent to process Your personal information, which may be express and/or implied consent depending on the applicable law, You have the right to withdraw Your consent at any time. You can withdraw Your consent at any time by contacting Us by using the contact details provided in the section "[Contact Us](#contact-us)" below.
However, please note that this will not affect the lawfulness of the processing before its withdrawal nor, when applicable law allows, will it affect the processing of Your personal information conducted in reliance on lawful processing grounds other than consent.
#### Account Information
If You would at any time like to review or change the information in Your account or terminate Your account, You can:
- Use the provided methods of managing Your account on Your given game console.
- Contact Us using the contact information provided.
Upon Your request to terminate Your account, We will deactivate or delete Your information from Our active databases. However, We may retain some information in Our files to prevent fraud, troubleshoot problems, assist with any investigations, enforce Our legal terms and/or comply with applicable legal requirements. We may also retain some account information, such as both the account usernames and Your account principal ID, in order to prevent reallocation and for various system requirements.
**Cookies and similar technologies:** Most Web browsers are set to accept cookies by default. If You prefer, You can usually choose to set Your browser to remove cookies and to reject cookies. If You choose to remove cookies or reject cookies, this could affect certain features or services of Our Services.
### 10. Controls for Do-Not-Track Features
Most web browsers and some mobile operating systems and mobile applications include a Do-Not-Track ("DNT") feature or setting You can activate to signal Your privacy preference not to have data about Your online browsing activities monitored and collected. At this stage no uniform technology standard for recognizing and implementing DNT signals has been finalized. As such, We do not currently respond to DNT browser signals or any other mechanism that automatically communicates Your choice not to be tracked online. If a standard for online tracking is adopted that We must follow in the future, We will inform You about that practice in a revised version of this privacy notice.
### 11. Do California Residents Have Specific Privacy Rights?
***In Short:*** *Yes, if You are a resident of California, You are granted specific rights regarding access to Your personal information. These rights are extended to all users regardless of region.*
California Civil Code Section 1798.83, also known as the "Shine The Light" law, permits Our users who are California residents to request and obtain from Us, once a year and free of charge, information about categories of personal information (if any) We disclosed to third parties for direct marketing purposes and the names and addresses of all third parties with which We shared personal information in the immediately preceding calendar year. If You would like to make such a request, please submit Your request in writing to Us using the contact information provided below.
If You are under 18 years of age, reside in California, and have a registered account with Services, You have the right to request removal of unwanted data that You publicly post on the Services. To request removal of such data, please contact Us using the contact information provided below and include the email address associated with Your account and a statement that You reside in California. We will make sure the data is not publicly displayed on the Services, but please be aware that the data may not be completely or comprehensively removed from all Our systems (e.g., backups, etc.).
#### CCPA Privacy Notice
The California Code of Regulations defines a "resident" as:
(1) every individual who is in the State of California for other than a temporary or transitory purpose and
(2) every individual who is domiciled in the State of California who is outside the State of California for a temporary or transitory purpose
All other individuals are defined as "non-residents."
The rights described above are extended to all users regardless of California residency.
**What categories of personal information do We collect?**
We have collected the following categories of personal information in the past twelve (12) months:
| **Category*- | **Examples*- | **Collected** |
| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| A. Identifiers | Contact details, such as real name, alias, postal address, telephone or mobile contact number, unique personal identifier, online identifier, Internet Protocol address, email address, and account name | YES |
| B. Personal information categories listed in the California Customer Records statute | Name, contact information, education, employment, employment history, and financial information | NO |
| C. Protected classification characteristics under California or federal law | Gender and date of birth | YES |
| D. Commercial information | Transaction information, purchase history, financial details, and payment information | YES |
| E. Biometric information | Fingerprints and voiceprints | NO |
| F. Internet or other similar network activity | Browsing history, search history, online behavior, interest data, and interactions with Our and other websites, applications, systems, and advertisements | NO |
| G. Geolocation data | Device location | NO |
| H. Audio, electronic, visual, thermal, olfactory, or similar information | Images and audio, video or call recordings created in connection with Our business activities | NO |
| I. Professional or employment-related information | Business contact details in order to provide You Our Services at a business level or job title, work history, and professional qualifications if You apply for a job with Us | NO |
| J. Education Information | Student records and directory information | NO |
| K. Inferences drawn from other personal information | Inferences drawn from any of the collected personal information listed above to create a profile or summary about, for example, an individual's preferences and characteristics | NO |
| L. Sensitive Personal Information | | NO |
We will use and retain the collected personal information as needed to provide the Services or for:
- Category A - As long as the user has an account with Us
- Category C - As long as the user has an account with Us
- Category D - As long as the user has an account with Us
We may also collect other personal information outside of these categories through instances where You interact with Us in person, online, or by phone or mail in the context of:
- Receiving help through Our customer support channels;
- Participation in customer surveys or contests; and
- Facilitation in the delivery of Our Services and to respond to Your inquiries.
**How do We use and share Your personal information?**
More information about Our data collection and sharing practices can be found in this privacy notice.
You may contact Us or by referring to the contact details at the bottom of this document.
If You are using an authorized agent to exercise Your right to opt out We may deny a request if the authorized agent does not submit proof that they have been validly authorized to act on Your behalf.
**Will Your information be shared with anyone else?**
We will not directly share Your information with any 3rd parties outside of the automatic data collection implemented by the 3rd parties as part of Our infrastructure.
We have not disclosed, sold, or shared any personal information to third parties for a business or commercial purpose in the preceding twelve (12) months. We will not sell or share personal information in the future belonging to Service users, website visitors, users, and other consumers.
**Your rights with respect to Your personal data**
*Right to request deletion of the data — Request to delete*
You can ask for the deletion of Your personal information. If You ask Us to delete Your personal information, We will respect Your request and delete Your personal information, subject to certain exceptions provided by law, such as (but not limited to) the exercise by another consumer of his or her right to free speech, Our compliance requirements resulting from a legal obligation, or any processing that may be required to protect against illegal activities. Additionally, we operate several archives of historical data prior to the shutdown of Nintendo Network. The data held in these archives may be viewed publicly and are exempt from various GDPR and related laws regarding data deletion as they are archived for the interest of the public. See each archives respective policies for how dtaa retention is handled.
*Right to be informed — Request to know*
Depending on the circumstances, You have a right to know:
- whether We collect and use Your personal information;
- the categories of personal information that We collect;
- the purposes for which the collected personal information is used;
- whether We sell or share personal information to third parties;
- the categories of personal information that We sold, shared, or disclosed for a business purpose;
- the categories of third parties to whom the personal information was sold, shared, or disclosed for a business purpose;
- the business or commercial purpose for collecting, selling, or sharing personal information; and
- the specific pieces of personal information We collected about You.
In accordance with applicable law, We are not obligated to provide or delete consumer information that is de-identified in response to a consumer request or to re-identify individual data to verify a consumer request.
*Right to Non-Discrimination for the Exercise of a Consumer's Privacy Rights*
We will not discriminate against You if You exercise Your privacy rights.
*Right to Limit Use and Disclosure of Sensitive Personal Information*
We do not process consumer's sensitive personal information.
*Verification process*
Upon receiving Your request, We will need to verify Your identity to determine You are the same person about whom We have the information in Our system. These verification efforts require Us to ask You to provide information so that We can match it with information You have previously provided Us. For instance, depending on the type of request You submit, We may ask You to provide certain information so that We can match the information You provide with the information We already have on file, or We may contact You through a communication method (e.g., email) that You have previously provided to Us. We may also use other verification methods as the circumstances dictate.
We will only use personal information provided in Your request to verify Your identity or authority to make the request. To the extent possible, We will avoid requesting additional information from You for the purposes of verification. However, if We cannot verify Your identity from the information already maintained by Us, We may request that You provide additional information for the purposes of verifying Your identity and for security or fraud-prevention purposes. We will delete such additionally provided information as soon as We finish verifying You.
*Other privacy rights*
- You may object to the processing of Your personal information.
- You may request correction of Your personal data if it is incorrect or no longer relevant, or ask to restrict the processing of the information.
- You can designate an authorized agent to make a request under the CCPA on Your behalf. We may deny a request from an authorized agent that does not submit proof that they have been validly authorized to act on Your behalf in accordance with the CCPA.
- You may request to opt out from future selling or sharing of Your personal information to third parties. Upon receiving an opt-out request, We will act upon the request as soon as feasibly possible, but no later than fifteen (15) days from the date of the request submission.
To exercise these rights, You can contact Us or by referring to the contact details at the bottom of this document. If You have a complaint about how We handle Your data, We would like to hear from You.
### 12. Do Virginia Residents Have Specific Privacy Rights?
***In Short:** Yes, if You are a resident of Virginia, You may be granted specific rights regarding access to and use of Your personal information. These rights are extended to all users regardless of region.*
**Virginia CDPA Privacy Notice**
Under the Virginia Consumer Data Protection Act (CDPA):
"Consumer" means a natural person who is a resident of the Commonwealth acting only in an individual or household context. It does not include a natural person acting in a commercial or employment context.
"Personal data" means any information that is linked or reasonably linkable to an identified or identifiable natural person. "Personal data" does not include de-identified data or publicly available information.
"Sale of personal data" means the exchange of personal data for monetary consideration.
If this definition "consumer" applies to You, We must adhere to certain rights and obligations regarding Your personal data.
The information We collect, use, and disclose about You will vary depending on how You interact with Us and Our Services. To find out more, please visit the following links:
- [Personal data We collect](#1-what-information-do-we-collect)
- [How We use Your personal data](#2-how-do-we-process-your-information)
- [When and with whom We share Your personal data](#4-when-and-with-whom-do-we-share-your-personal-information)
*Your rights with respect to Your personal data*
- Right to be informed whether or not We are processing Your personal data
- Right to access Your personal data
- Right to correct inaccuracies in Your personal data
- Right to request deletion of Your personal data
- Right to obtain a copy of the personal data You previously shared with Us
- Right to opt out of the processing of Your personal data if it is used for targeted advertising, the sale of personal data, or profiling in furtherance of decisions that produce legal or similarly significant effects ("profiling")
We will not directly share Your information with any 3rd parties outside of the automatic data collection implemented by the 3rd parties as part of Our infrastructure.
We have not sold any personal data to third parties for business or commercial purposes. We will not sell personal data in the future belonging to Service users, website visitors, users, and other consumers.
*Exercise Your rights provided under the Virginia CDPA*
More information about Our data collection and sharing practices can be found in this privacy notice.
You may contact Us by referring to the contact details at the bottom of this document.
If You are using an authorized agent to exercise Your rights, We may deny a request if the authorized agent does not submit proof that they have been validly authorized to act on Your behalf.
*Verification process*
We may request that You provide additional information reasonably necessary to verify You and Your consumer's request. If You submit the request through an authorized agent, We may need to collect additional information to verify Your identity before processing Your request.
Upon receiving Your request, We will respond without undue delay, but in all cases, within forty-five (45) days of receipt. The response period may be extended once by forty-five (45) additional days when reasonably necessary. We will inform You of any such extension within the initial 45-day response period, together with the reason for the extension.
*Right to appeal*
If We decline to take action regarding Your request, We will inform You of Our decision and reasoning behind it. If You wish to appeal Our decision, please email Us at privacy@pretendo.network. Within sixty (60) days of receipt of an appeal, We will inform You in writing of any action taken or not taken in response to the appeal, including a written explanation of the reasons for the decisions. If Your appeal if denied, You may contact the [Attorney General to submit a complaint](https://www.oag.state.va.Us/consumer-protection/index.php/file-a-complaint).
### 13. Do We Make Updates to This Notice?
***In Short:** Yes, We will update this notice as necessary to stay compliant with relevant laws.*
We may update this privacy notice from time to time. The updated version will be indicated by an updated "Revised" date and the updated version will be effective as soon as it is accessible. If We make material changes to this privacy notice, We may notify You either by prominently posting a notice of such changes or by directly sending You a notification. We encourage You to review this privacy notice frequently to be informed of how We are protecting Your information.
## Modifications to the Policy
We may update this Privacy Policy from time to time. We will notify You of any changes by updating the "Last updated" date at the top of this policy. We may also notify You of any changes via email. You are advised to review this page periodically for any changes. Changes to this Privacy Policy are effective when they are posted on this page.
### Contact Us
If You have any questions about this policy, You can contact Us:
- By email: privacy@pretendo.network

View File

@@ -1,5 +0,0 @@
# Citra
At the moment Citra does not support true online play, so it doesn't work with Pretendo. Moreover, it shows no sign of supporting true play in the future.
Mikage, a 3DS emulator for mobile devices, may provide support in the future, though this is far from certain.

45
eslint.config.mjs Normal file
View File

@@ -0,0 +1,45 @@
import pluginVue from 'eslint-plugin-vue';
import eslintConfig from '@pretendonetwork/eslint-config';
import globals from 'globals';
import withNuxt from './.nuxt/eslint.config.mjs';
export default withNuxt([
...eslintConfig,
...pluginVue.configs['flat/recommended'],
{
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
'@eslint-community/eslint-comments/disable-enable-pair': 'off',
'no-restricted-imports': 'off'
}
},
{
files: ['*.vue', '**/*.vue'],
languageOptions: {
parserOptions: {
parser: '@typescript-eslint/parser'
},
globals: {
...globals.browser
}
},
rules: {
'vue/multi-word-component-names': 'off'
}
},
{
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
project: [
'./.nuxt/tsconfig.json'
]
}
}
}
},
{
ignores: ['.output', '.nuxt', '.old']
}
]);

View File

@@ -1,77 +0,0 @@
{
"http": {
"port": 3000,
"base_url": "http://localhost:3000"
},
"github": {
"graphql_token": "ghp_..."
},
"discord": {
"roles": {
"supporter": "role_id",
"tester": "role_id"
},
"guild_id": "guild_id",
"client_id": "client_id",
"client_secret": "client_secret",
"bot_token": "bot_token"
},
"stripe": {
"goal_cents": 300000,
"secret_key": "secret_key",
"webhook_secret": "webhook_secret",
"notification_emails": []
},
"database": {
"account": {
"uri": "mongodb://127.0.0.1:27017",
"database": "database_name",
"connection_string": "mongodb://127.0.0.1:27017",
"options": {
"useNewUrlParser": true,
"useUnifiedTopology": true
}
}
},
"email": {
"ses": {
"region": "AWS SES us-east-1",
"key": "AWS SES access key",
"secret": "AWS SES secret key"
},
"from": "Firstname Lastname <user@domain.com>"
},
"trello": {
"api_key": "api_key",
"api_token": "api_token",
"board_name": "board_name"
},
"api_base": "https://api.domain.com",
"discourse": {
"sso": {
"secret": "Discourse SSO secret"
},
"api": {
"base_url": "https://discourse.example.com",
"username": "system",
"key": "Discourse API key"
},
"groups": {
"access_level": {
"1": "testers",
"2": "juxt-moderators",
"3": "developers"
},
"stripe_tier": {
"1": "supporters-mario",
"2": "supporters-super",
"3": "supporters-mega"
},
"discord_role": {
"1234567890123456789": "developers",
"9876543210987654321": "discord-moderators",
"1234567890987654321": "network-moderators"
}
}
}
}

49
example.env Normal file
View File

@@ -0,0 +1,49 @@
# The defaults in this file are meant for the docker-compose based setup.
# Core
PN_WEBSITE_PUBLIC_BASE_URL=http://localhost:3000
PN_WEBSITE_PUBLIC_CDN_BASE_URL=http://pretendo.localhost:3902
PN_WEBSITE_PUBLIC_COOKIE_SECURE=false
PN_WEBSITE_PUBLIC_REDIRECT_HOSTS=localhost:3000
PN_WEBSITE_TRUST_PROXY=false
PN_WEBSITE_REDIS_URL=redis://localhost:6379
# Optional - Authentication
PN_WEBSITE_GRPC_HOST=localhost:8123
PN_WEBSITE_GRPC_API_KEY=12345678123456781234567812345678
PN_WEBSITE_API_BASE=http://localhost:8056
PN_WEBSITE_API_BASE_HOST=api.pretendo.cc
# --- Partially configured features ---
# You will need to fill in some parts in this section before these features start working
# Optional - Github progress tracking:
PN_WEBSITE_GITHUB_API_TOKEN=
# Optional - Discord:
PN_WEBSITE_DISCORD_BOT_TOKEN=
PN_WEBSITE_DISCORD_CLIENT_ID=
PN_WEBSITE_DISCORD_CLIENT_SECRET=
PN_WEBSITE_DISCORD_GUILD_ID=
PN_WEBSITE_DISCORD_TESTER_ROLE_ID=
PN_WEBSITE_DISCORD_SUPPORTER_ROLE_ID=
# Optional - Donation features + rewards (Requires discord):
PN_WEBSITE_STRIPE_SECRET_KEY=
PN_WEBSITE_STRIPE_WEBHOOK_SECRET=
PN_WEBSITE_STRIPE_NOTIFICATION_EMAIL=notifs@example.com
PN_WEBSITE_MONGO_CONNECTION_STRING=mongodb://localhost:27017/account?directConnection=true
PN_WEBSITE_SMTP_HOST=localhost
PN_WEBSITE_SMTP_USER=localhost
PN_WEBSITE_SMTP_PORT=1025
PN_WEBSITE_SMTP_SECURE=false
PN_WEBSITE_SMTP_FROM_EMAIL=pretendo@example.com
PN_WEBSITE_SMTP_FROM_NAME=Pretendo Network
# Optional - Captchas:
PN_WEBSITE_HCAPTCHA_SECRET_KEY=
PN_WEBSITE_PUBLIC_HCAPTCHA_SITE_KEY=
# Optional - Discourse SSO:
PN_WEBSITE_DISCOURSE_SSO_SECRET=

4
i18n.config.ts Normal file
View File

@@ -0,0 +1,4 @@
export default {
fallbackLocale: 'en-US',
warnHtmlMessage: false
};

View File

@@ -1,451 +0,0 @@
{
"nav": {
"about": "Über uns",
"faq": "FAQ",
"docs": "Docs",
"credits": "Mitwirkende",
"progress": "Fortschritt",
"blog": "Blog",
"account": "Konto",
"accountWidget": {
"settings": "Einstellungen",
"logout": "Abmelden"
},
"donate": "Spenden",
"dropdown": {
"captions": {
"credits": "Lerne das Team kennen",
"about": "Über das Projekt",
"faq": "Häufig gestellte Fragen",
"blog": "Unsere neuesten Updates, zusammengefasst",
"progress": "Überprüfe den Projektfortschritt und die Ziele"
}
}
},
"hero": {
"subtitle": "Spielserver",
"title": "Rekonstruiert",
"text": "Pretendo ist ein kostenloser, Open-Source-Ersatz für Nintendo-Server für den 3DS und die Wii U, der die Onlineverbindung für alle, auch nach der Einstellung der offiziellen Server, ermöglicht",
"buttons": {
"readMore": "Mehr lesen"
}
},
"aboutUs": {
"title": "Über uns",
"paragraphs": [
"Pretendo ist ein Open-Source-Projekt, welches das Nintendo Network für den 3DS und die Wii U durch Clean-Room-Reverse-Engineering rekonstruiert.",
"Da unsere Dienste kostenlos und Open-Source sind, werden diese auch zukünftig weiterhin existieren."
]
},
"progress": {
"title": "Fortschritt",
"githubRepo": "Github-Repository"
},
"faq": {
"title": "Frequently Asked Questions (Häufig gestellte Fragen)",
"text": "Hier sind einige Fragen, die wir häufiger gestellt bekommen, zur schnellen Informationsbeschaffung.",
"QAs": [
{
"question": "Was ist Pretendo?",
"answer": "Pretendo ist ein Open-Source-Ersatz für das Nintendo Network, mit dem eigene Server für die Wii U und der 3DS-Familie erstellt werden sollen. Unser Ziel ist es, die Online-Funktionalität der Konsolen beizubehalten, damit Spieler auch weiterhin ihre Lieblingsspiele für die Wii U und den 3DS vollständig spielen können."
},
{
"question": "Werden meine vorhandenen NNIDs mit Pretendo weiterhin funktionieren?",
"answer": "Leider nicht. Vorhandene NNIDs werden nicht mit Pretendo funktionieren, da nur Nintendo deine Nutzerdaten hat. Auch wenn eine NNID-zu-PNID Migration theoretisch möglich ist, wäre es riskant und würde sensible Nutzerdaten erfordern, die wir nicht speichern möchten."
},
{
"question": "Wie benutze ich Pretendo?",
"answer": "Um Pretendo Network auf der 3DS-Familie, der Wii U oder Emulatoren zu nutzen, sollten sie den Installationsanweisungen folgen: <a href=\"/docs/install\">setup instructions</a>"
},
{
"question": "Weißt du, wann Funktion/Dienst bereit ist?",
"answer": "Nein. Viele der Funktionen und Dienste von Pretendo werden unabhängig voneinander entwickelt (z. B., ein Entwickler arbeitet am Miiverse während ein anderer an Accounts und der Freundesliste arbeitet), deshalb können wir keine genauen Angaben zur jeweiligen Fertigstellung machen."
},
{
"question": "Wann werdet ihr neue Spiele hinzufügen?",
"answer": "Wir arbeiten am Hinzufügen neuer Spiele, sobald unsere Backend-Libraries bereit dazu sind, diese zu unterstützen und sobald unsere Entwickler Zeit haben, diese instand zu halten. Eine Menge unserer Zeit fließt in die Stabilisierung und Abschließen der bereits existierenden Spiele. Wir möchten euch die besten Spielerfahrungen möglich machen, bevor wir uns neuen Spieltiteln widmen. Aufgrund von ständiger neu auftauchender Arbeit können wir keine Angaben machen, wann wir neue Spiele hinzufügen werden."
},
{
"question": "Funktioniert Pretendo auch auf Cemu oder anderen Emulatoren?",
"answer": "Cemu 2.1 ist von Pretendo unterstützt. Dies kann man unter den Netztwerk/Account Einstellungen in Cemu 2.1 einstellen. Für mehr Informationen, wie man Cemu mit Pretendo Network nutzt, schauen sie sich den <a href=\"https://pretendo.network/docs/install/cemu\">Guide</a>an.<br> Manche 3DS Emulatoren oder \"Forks\" unterstützen vielleicht Pretendo, es gibt aber momentan keine offiziellen Empfehlungen oder Setup Guides. Die finalen Builds von Citra werden nicht unterstützt."
},
{
"question": "Wird Pretendo die Wii/Switch unterstützen?",
"answer": "Für die Wii gibt es bereits eigene Server von <a href=\"https://wiimmfi.de/\" target=\"_blank\">Wiimmfi</a>. Aktuell möchten wir die Switch auch nicht als Ziel festlegen, da der Online-Service der Switch kostenpflichtig ist und sich stark vom Nintendo Network unterscheidet."
},
{
"question": "Benötige ich einen Hack um Pretendo zu verwenden?",
"answer": "Ja, du musst deine Konsole hacken, allerdings reicht auf der Wii U den Zugriff zum Homebrew-Launcher (z.B. über Haxchi, CBHC, oder den Browser-Exploit). Informationen, wie der 3DS verbunden wird, werden später noch veröffentlicht."
},
{
"question": "Wenn ich auf dem Nintendo Network gebannt bin, heißt das auch das ich auf Pretendo gebannt bin?"
},
{
"question": "Kann ich Cheats oder Mods online mit Pretendo verwenden?",
"answer": "Nur in privaten Matches sich einen unfairen Vorteil zu verschaffen oder das Online-Erlebnis von Personen zu stören, die nicht zugestimmt haben (wie beispielsweise in öffentlichen Matches), ist ein bannbarer Verstoß. Wir verhängen regelmäßig Konto- und Konsolensperren sowohl für Wii U- als auch für 3DS-Systeme. Pretendo verwendet zusätzliche Sicherheitsmaßnahmen, die traditionelle Entbannungs-Methoden wie das Ändern der Seriennummer unwirksam machen."
}
]
},
"showcase": {
"title": "Was wir machen",
"text": "Unser Projekt hat viele Komponenten, hier sind einige davon.",
"cards": [
{
"title": "Spiel-Server",
"caption": "Bringt dir deine Lieblingsspiele und Inhalte zurück, mithilfe eigener Server."
},
{
"title": "Juxtaposition",
"caption": "Eine Neuinterpretation des Miiverse, als ob es im modernen Zeitalter entwickelt wurde."
},
{
"title": "Cemu-Unterstützung",
"caption": "Spiele deine Lieblings-Wii U-Spiele, sogar ohne eine Konsole!"
}
]
},
"credits": {
"title": "Das Team",
"text": "Lerne das Team hinter dem Projekt kennen",
"people": [
{
"picture": "https://github.com/jonbarrow.png",
"github": "https://github.com/jonbarrow",
"name": "Jonathan Barrow (jonbarrow)",
"caption": "Projektleiter und leitender Entwickler"
},
{
"name": "Jemma (CaramelKat)",
"picture": "https://github.com/caramelkat.png",
"caption": "Miiverse Analyse/Forschung und Entwicklung",
"github": "https://github.com/CaramelKat"
},
{
"name": "quarky",
"picture": "https://github.com/ashquarky.png",
"github": "https://github.com/ashquarky",
"caption": "Wii U Forschung und Patch-Entwicklung"
},
{
"picture": "https://github.com/supermariodabom.png",
"github": "https://github.com/SuperMarioDaBom",
"name": "SuperMarioDaBom",
"caption": "Systemforschung und Serverarchitektur"
},
{
"picture": "https://github.com/gitlimes.png",
"name": "pinklimes",
"github": "https://github.com/gitlimes",
"caption": "Webentwicklung"
},
{
"name": "Shutterbug2000",
"picture": "https://cdn.discordapp.com/avatars/191370953807233024/0311b61e2009c1576828dd2e9a59d72e.png?size=128",
"github": "https://github.com/shutterbug2000",
"caption": "Systemforschung und Server Entwicklung"
},
{
"name": "Billy",
"picture": "https://github.com/InternalLoss.png",
"github": "https://github.com/InternalLoss",
"caption": "Erhaltung und Server-Architektur"
},
{
"name": "DaniElectra",
"picture": "https://github.com/danielectra.png",
"github": "https://github.com/DaniElectra",
"caption": "Systemforschung und Server-Entwicklung"
},
{
"name": "niko",
"picture": "https://github.com/hauntii.png",
"github": "https://github.com/hauntii",
"caption": "Web- und Serverentwicklung"
},
{
"name": "MatthewL246",
"picture": "https://github.com/MatthewL246.png",
"github": "https://github.com/MatthewL246",
"caption": "DevOps und Community-Arbeit"
},
{
"name": "wolfendale",
"picture": "https://github.com/wolfendale.png",
"github": "https://github.com/wolfendale",
"caption": "Server-Entwicklung und Optimierungen"
},
{
"name": "TraceEntertains",
"picture": "https://github.com/TraceEntertains.png",
"caption": "3DS Patch-Entwicklung und Forschung",
"github": "https://github.com/TraceEntertains"
}
]
},
"specialThanks": {
"title": "Besonderer Dank",
"text": "Ohne sie wäre Pretendo nicht, wo es heute ist.",
"people": [
{
"name": "GitHub-Mitwirkende",
"caption": "Übersetzungen und andere Beiträge",
"picture": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
"github": "https://github.com/PretendoNetwork"
},
{
"caption": "Crunch Library Entwicklung",
"picture": "https://github.com/superwhiskers.png",
"github": "https://github.com/superwhiskers",
"name": "superwhiskers"
},
{
"name": "Stary",
"github": "https://github.com/Stary2001",
"picture": "https://github.com/Stary2001.png"
},
{
"caption": "Miiverse-Informationsaustausch",
"github": "https://twitter.com/rverseClub",
"name": "rverse",
"picture": "https://github.com/rverseTeam.png"
},
{
"special": "Besonderer Dank",
"caption": "Forschung zu Nintendo-Datenstrukturen",
"name": "Kinnay",
"picture": "https://cdn.discordapp.com/avatars/186572995848830987/b55c0d4e7bfd792edf0689f83a25d8ea.png?size=128",
"github": "https://github.com/Kinnay"
},
{
"name": "NinStar",
"caption": "Symbole für dem Mii-Editor und Juxt-Reaktionen",
"picture": "https://github.com/ninstar.png",
"github": "https://github.com/ninstar"
},
{
"name": "Rambo6Glaz",
"caption": "Konsolenforschung und Spiele-Server",
"github": "https://github.com/EpicUsername12",
"picture": "https://github.com/EpicUsername12.png"
},
{
"github": "https://github.com/GaryOderNichts",
"name": "GaryOderNichts",
"caption": "Wii U Patch-Entwicklung",
"picture": "https://github.com/GaryOderNichts.png"
},
{
"name": "zaksabeast",
"caption": "3DS Patch-Ersteller",
"picture": "https://cdn.discordapp.com/avatars/219324395707957248/c62573fbd4d26c8b4724f54413df6960.png?size=128",
"github": "https://github.com/zaksabeast"
},
{
"name": "mrjvs",
"caption": "Server-Architektur",
"picture": "https://github.com/mrjvs.png",
"github": "https://github.com/mrjvs"
},
{
"name": "binaryoverload",
"caption": "Server-Architektur",
"picture": "https://github.com/binaryoverload.png",
"github": "https://github.com/binaryoverload"
},
{
"name": "Simonx22",
"caption": "Spatoon-Rotations und Forschung",
"picture": "https://github.com/Simonx22.png",
"github": "https://github.com/Simonx22"
},
{
"name": "OatmealDome",
"caption": "Splatoon-Rotations und Forschung",
"github": "https://github.com/OatmealDome",
"picture": "https://github.com/OatmealDome.png"
},
{
"caption": "Lokalisierung und andere Beiträge",
"picture": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
"name": "GitHub-Beiträger",
"github": "https://github.com/PretendoNetwork"
}
]
},
"discordJoin": {
"title": "Bleib auf dem Laufenden",
"text": "Tritt unserem Discord-Server bei, um die neuesten Updates des Projektes zu erhalten.",
"widget": {
"text": "Erhalte Echtzeitinformationen über unseren Fortschritt",
"button": "Tritt dem Server bei"
}
},
"footer": {
"socials": "Soziale Medien",
"usefulLinks": "Nützliche Links",
"widget": {
"captions": [
"Du möchtest auf dem Laufenden bleiben?",
"Tritt dem Discord-Server bei!"
],
"button": "Tritt noch heute bei!"
},
"bandwidthRaccoonQuotes": [
"Ich bin Bandwidth der Waschbär und ich liebe es, in die Kabel der Server des Pretendo Networks zu beißen. Lecker!",
"Viele Leute fragen uns ob wir für das hier in legale Schwierigkeiten mit Nintendo kommen; voller Freude berichte ich, dass meine Tante bei Nintendo arbeitet, und sagt es ist in Ordnung.",
"Webkit v537 ist die beste Webkit-Version für die Wii U. Nein, wir werden Chrome nicht auf die Wii U bringen.",
"Ich kann es kaum erwarten, dass die Uhrzeit 03:14:08 UTC am 19. Januar 2038 erreicht wird!",
"Die Wii U ist ein unterbewertetes System: die Werbungen waren wirklich schlecht, aber die Konsole ist toll! Hmm, moment mal, ich bin mir nicht sicher, warum sich mein GamePad nicht mit der Wii verbindet.",
"Die Titelmusik von \"Super Mario World 2 - Yoshi's Island\" ist ein absoluter Hit und niemand kann mir das Gegenteil beweisen.",
"Meine Lieblingsveröffentlichungen für die Nintendo Switch sind Nintendo Switch Online + Expansion Pack, Nintendo Switch Online + Rumble Pak, Nintendo Switch Online + Offline Play Pack, Nintendo Switch Online + Noch Ein Port Pack und Nintendo Switch Online + Dr. Kawashimas Gehirnjogging / Brain Age \"Ihr Mochtet Den Nintendo Wii U Virtual Console-Titel Sehr, Also Bringen Wir Ihn Zurück\" Pack. Man merkt, dass es Nintendo am Herzen liegt.",
"So etwas wie \"Du kennst Ash, Gott segne ihr Herz, sie schreibt den ganzen Tag UwU\" ist die südländische Art zu sagen \"Ash schreibt die ganze Zeit UwU und es ist wirklich seltsam und dumm und ich wünschte, sie würde es nicht tun\"",
"Mein erstes Video auf meinem kanal!! Ich wolte schon lange viedeos machen, aber mein leptop wahr zu schwach um Fraps, Skipe und Minekraft gleichzeitieg laufen zu laßen. aber dass ist jetzt vorbei. mit etwas hilfe von meinen informatiklerer läüft mein leptop jetzt fiel besser und ich kan aufnemen. ich hoffe ihr alle mögt dass video und fals ihr das tut bite gebt einen daumen nach oben und aboniert!!!",
"Sieht gut für mich aus"
]
},
"progressPage": {
"title": "Unser Fortschritt",
"description": "Prüfe den Projektfortschritt und die Ziele! (Wird stündlich aktualisiert, reflektiert nicht ALLE Projekte oder Ziele)"
},
"blogPage": {
"title": "Blog",
"description": "Die letzten Updates in Kurzform. Wenn du Updates häufiger einsehen möchtest, kannst du uns gerne <a href=\"/account/upgrade\" target=\"_blank\">unterstützen</a>.",
"published": "Veröffentlicht von",
"publishedOn": "am"
},
"account": {
"accountLevel": [
"Standard",
"Tester*in",
"Moderator*in",
"Entwickler*in"
],
"loginForm": {
"login": "Anmelden",
"detailsPrompt": "Gib deine Kontodaten unten ein",
"register": "Registrieren",
"username": "Benutzername",
"password": "Passwort",
"confirmPassword": "Passwort bestätigen",
"email": "E-Mail",
"miiName": "Mii-Name",
"forgotPassword": "Passwort vergessen?",
"registerPrompt": "Du hast noch kein Konto?",
"loginPrompt": "Du hast schon ein Konto?"
},
"settings": {
"settingCards": {
"profile": "Profil",
"nickname": "Spitzname",
"birthDate": "Geburtsdatum",
"gender": "Geschlecht",
"country": "Land/Region",
"timezone": "Zeitzone",
"production": "Produktion",
"upgradePrompt": "Beta-Server sind exklusiv für Beta-Tester.<br>Um Beta-Tester zu werden, musst du ein Upgrade auf eine höhere Konto-Stufe durchführen.",
"signInSecurity": "Anmeldung und Sicherheit",
"signInHistory": "Anmeldeverlauf",
"fullSignInHistory": "Vollständigen Anmeldeverlauf anzeigen",
"otherSettings": "Andere Einstellungen",
"discord": "Discord",
"connectedToDiscord": "Verbunden mit Discord als",
"linkDiscord": "Discord-Konto verknüpfen",
"newsletter": "Newsletter",
"newsletterPrompt": "Erhalte Projekt-Updates per E-Mail (Du kannst sie jederzeit abbestellen)",
"passwordPrompt": "Gib dein PNID-Passwort ein, um Cemu-Dateien herunterzuladen",
"hasAccessPrompt": "Mit deiner aktuellen Stufe hast du Zugang zu den Beta-Servern. Cool!",
"noDiscordLinked": "Kein Discord-Konto verknüpft.",
"serverEnv": "Server-Umgebung",
"beta": "Beta",
"email": "E-Mail",
"password": "Passwort",
"passwordResetNotice": "Nachdem du dein Passwort geändert hast, wirst du von allen Geräten abgemeldet.",
"removeDiscord": "Discord-Konto entfernen",
"no_signins_notice": "Der Anmeldeverlauf wird momentan nicht gespeichert. Schau später nochmal vorbei!",
"no_edit_from_dashboard": "PNID Einstellungen vom Nutzer Dashboard sind momentan nicht verfügbar. Bitte aktualisiere die Benutzereinstellungen über deine verknüpfte Konsole",
"no_newsletter_notice": "Newsletter ist momentan nicht verfügbar. Schau später nochmal vorbei",
"userSettings": "Nutzer-Einstellungen"
},
"upgrade": "Konto upgraden",
"unavailable": "Nicht verfügbar"
},
"banned": "Gebannt",
"account": "Konto",
"forgotPassword": {
"sub": "Gib deine E-Mail oder deine PNID ein",
"input": "Email-Adresse oder PNID",
"header": "Passwort vergessen",
"submit": "Bestätigen"
},
"resetPassword": {
"header": "Passwort zurücksetzen",
"sub": "Gib das neue Passwort ein",
"password": "Passwort",
"confirmPassword": "Passwort bestätigen",
"submit": "Bestätigen"
}
},
"upgrade": {
"title": "Upgraden",
"description": "Das Erreichen des monatlichen Ziels wird aus Pretendo eine Vollzeitbeschäftigung machen, die qualitativ bessere und schnellere Updates liefert.",
"month": "Monat",
"tierSelectPrompt": "Wähle eine Stufe",
"unsub": "Deabonnieren",
"unsubPrompt": "Bist du dir sicher, dass du <span>tiername</span> deabonnieren möchtest? Du wirst den Zugang zu den Vorteilen verlieren, die mit dieser Stufe verbunden sind.",
"unsubConfirm": "Deabonnieren",
"changeTier": "Stufe ändern",
"changeTierPrompt": "Bist du dir sicher, dass du <span class=\"oldtier\">oldtiername</span> deabonnieren und <span class=\"newtier\">newtiername</span> abonnieren möchtest?",
"back": "Zurück",
"changeTierConfirm": "Stufe ändern"
},
"donation": {
"progress": "<span>$${totd}</span> von <span>$${goald}</span>/Monat, <span>${perc}%</span> des monatlichen Ziels.",
"upgradePush": "Um Abonnent zu werden und Zugang zu coolen Vorteilen zu erhalten, besuche die <a href=\"/account/upgrade\">Upgrade-Seite</a>."
},
"localizationPage": {
"description": "Füge einen Link zu einem öffentlich zugänglichen JSON-Locale ein, um es auf der Website zu testen",
"filePlaceholder": "https://ein.link.zu/der_datei.json",
"button": "Test-Datei",
"title": "Lass uns lokalisieren",
"instructions": "Anweisungen zur Lokalisierung anzeigen",
"fileInput": "Zu testende Datei"
},
"docs": {
"missingInLocale": "Diese Seite ist nicht auf Deutsch verfügbar. Bitte schau dir die englische Version unten an.",
"quickLinks": {
"header": "Schnelle Links",
"links": [
{
"header": "Pretendo installieren",
"caption": "Einrichtungsanweisungen anzeigen"
},
{
"header": "Hast du einen Fehler?",
"caption": "Suche hier nach ihm"
}
]
},
"search": {
"title": "Hast du einen Fehlercode bekommen?",
"caption": "Schreibe unten in die Box, was für ein Problem du hast, um Infos zu erhalten!",
"label": "Fehler-Code",
"no_match": "Keine Ergebnisse gefunden"
},
"sidebar": {
"getting_started": "Erste Schritte",
"welcome": "Herzlich willkommen",
"install_extended": "Pretendo installieren",
"install": "Installieren",
"search": "Suchen",
"juxt_err": "Fehler-Codes - Juxt"
}
},
"modals": {
"cancel": "Abbrechen",
"confirm": "Bestätigen",
"close": "Schließen"
},
"notfound": {
"description": "Woops! Diese Seite konnte nicht gefunden werden."
}
}

View File

@@ -1,11 +0,0 @@
{
"nav": {
"faq": "FAQ",
"about": "À propos",
"account": "Compte",
"blog": "Blogue",
"accountWidget": {
"settings": "Paramètres"
}
}
}

View File

@@ -1 +0,0 @@
{}

View File

@@ -1 +0,0 @@
{}

View File

@@ -1,38 +0,0 @@
{
"nav": {
"about": "Tentang",
"docs": "Dokumentasi",
"credits": "Kredit",
"progress": "Kemajuan",
"account": "Akun",
"accountWidget": {
"settings": "Pengaturan",
"logout": "Keluar"
},
"dropdown": {
"captions": {
"credits": "Berkenalan dengan Tim",
"progress": "Lihat kemajuan dan tujuan proyek"
}
}
},
"hero": {
"title": "Dibuat ulang",
"subtitle": "Server gim",
"text": "Pretendo adalah sebuah pengganti server Nintendo yang gratis dan dengan sumber terbuka untuk 3DS dan Wii U, yang memungkinkan konektivitas online untuk semua, bahkan setelah server aslinya dihentikan",
"buttons": {
"readMore": "Baca lebih lanjut"
}
},
"aboutUs": {
"title": "Tentang kami",
"paragraphs": [
"Pretendo adalah proyek sumber terbuka dengan tujuan untuk membuat ulang Nintendo Network untuk 3DS dan Wii U menggunakan rekaya terbalik ruang bersih.",
"Karena layanan kami bersifat gratis dan sumber terbuka, layanan tersebut akan tetap bertahan lama setelah penutupan Nintendo Network yang pasti akan terjadi."
]
},
"progress": {
"title": "Perkembangan",
"githubRepo": "Repositori Github"
}
}

View File

@@ -1,186 +0,0 @@
{
"nav": {
"about": "Om oss",
"faq": "Ofte stilte spørsmål",
"docs": "Dokumentasjon",
"credits": "Kreditt",
"progress": "Framgang",
"blog": "Blogg",
"account": "Konto",
"dropdown": {
"captions": {
"credits": "Møt laget",
"about": "Om prosjektet",
"faq": "O-S-S"
}
},
"donate": "Doner",
"accountWidget": {
"settings": "Innstillinger",
"logout": "Logg ut"
}
},
"hero": {
"subtitle": "Spilltjenere",
"title": "Omskapt",
"text": "Pretendo er en gratis og fri kildekodeerstatning for Nintendo sine tjenere for både 3DS-en og Wii U-en, som tillater nettbasert tilkobling for alle, til og med etter at de originale tjenerne legges ned",
"buttons": {
"readMore": "Les mer"
}
},
"aboutUs": {
"title": "Om oss",
"paragraphs": [
"Pretendo er et fritt kildekodeprosjekt som prøver å implementere Nintendo Network på nytt for 3DS and Wii U ved å bruke helt egen kildekode.",
"Siden våres tjenester vil være gratis frie, kan de eksistere lenge etter uunngåelig nedstenging av Nintendo Network."
]
},
"progress": {
"title": "Framgang"
},
"faq": {
"title": "Ofte stilte spørsmål",
"text": "Her er noen ting vi ofte blir spurt om.",
"QAs": [
{
"question": "Hva er Pretendo?",
"answer": "Pretendo er en fri kildekodeerstatning for Nintendo Network som prøver å lage sine egne tjenere for Wii U- og 3DS-konsollene. Vårt mål er å bevare muligheten å spille nettbasert på disse konsollene, for å tillate spillere å nyte sine favorittspill i fulle drag."
},
{
"question": "Kommer mine eksisterende NNID-er til å fungere på Pretendo?",
"answer": "Nei. NNID-er som allerede eksisterer fungerer ikke på Pretendo, fordi kun Nintendo har dine brukerdata. Det hadde vært teknisk sett mulig med en NNID-til-PNID, men det hadde vært risikabelt og krevd sensitiv brukerdata vi ikke har lyst til å befatte oss med."
},
{
"question": "Hvordan bruker jeg Pretendo?",
"answer": "Pretendo er ikke klar til offentlig bruk, men når tiden er inne vil du kunne bruke Pretendo ved å kjøre vår hjemmebrent-feilfiks på din konsoll."
},
{
"question": "Vet dere når en funksjon/tjeneste er klar?",
"answer": "Nei. Mange av Pretendo sine funksjoner/tjenester er utvikleruavhengelige (for eksempel, Miiverse kan arbeides på av én utvikler mens «Kontoer og Venner» jobbes på av en annen utvikler) og derfor kan vi ikke gi anslå hvor lang tid dette kommer til å ta."
},
{
"question": "Fungerer Pretendo på CEMU/emulatorer?",
"answer": "Pretendo er laget for Wii U og 3DS maskinvare i det minste, men akkurat nå den eneste emulatorer med støtte for NN for disse konsollene er Cemu. Cemu støtter ikke tilpasset servere offisielt, men det skal fortsatt være mulig å bruke Pretendo med Cemu. <br>Pretendo støtter ikke Cemu akkurat nå."
},
{
"question": "Hvis jeg er utestengt fra Nintendo Network, kommer jeg til å være utestengt fra Pretendo?",
"answer": "Vi kommer ikke til å ha tilgang til Nintendo Network sine utestengelser, og alle brukere kommer ikke til å bli utestengt på vår tjeneste. Vi har fortsatt regler du må følge når du bruker tjenesten, og hvis du ikke følger disse kan du bli utestengt."
},
{
"question": "Kommer Pretendo til å støtte Wii-en/Switch-en?",
"answer": "Wii-en har allerede tilpassede tjenere fra <a href=\"https://wiimmfi.de/\" target=\"_blank\">Wiimmfi</a>. Vi tar ikke sikte på Switch-en fordi det er både betalt og helt annerledes fra Nintendo Network."
},
{
"question": "Kommer jeg til å trenge en hacket konsoll for å koble til Pretendo?",
"answer": "Ja. Du vil måtte hacke din konsoll for å koble til, men på Wii U trenger du bare tilgang til Homebrew Launcher (i.e. Haxchi, Coldboot Haxchi, eller til og med nettleser-utnyttelsen), med info om hvordan 3DS-en kommer til å koble til Pretendo senere."
}
]
},
"showcase": {
"title": "Hva vi lager",
"text": "Vårt projekt har mange deler. Her er noen av dem.",
"cards": [
{
"title": "Spilltjenere",
"caption": "Tar tilbake dine favorittspill og innhold med våre egne tjenere."
},
{
"title": "Juxtaposition",
"caption": "En ny forestilling av Miiverse, som om den hadde vært laget i den moderne æra."
},
{
"title": "Støtte for CEMU",
"caption": "Spill dine favoritt Wii U-titler, til og med uten Wii U-konsoll!"
}
]
},
"credits": {
"title": "Laget",
"text": "Møt laget bak prosjektet"
},
"specialThanks": {
"title": "Spesiell takk",
"text": "Uten dem, hadde ikke Pretendo vært der det er i dag."
},
"discordJoin": {
"title": "Hold deg oppdatert",
"text": "Bli med på vår Discord-tjener for å få de nyeste prosjektoppdateringene.",
"widget": {
"text": "Få sanntidsoppdateringer om fremgang",
"button": "Ta del i tjeneren"
}
},
"footer": {
"socials": "Sosiale media",
"usefulLinks": "Nyttige lenker",
"widget": {
"captions": [
"Vil du holde deg oppdatert?",
"Ta del i vår Discord-tjener."
],
"button": "Bli med nå."
},
"bandwidthRaccoonQuotes": [
"Jeg er båndbreddevaskebjørnen, og jeg elsker å bite over kablene som går til Pretendo-nettverkets tjenere. Nam.",
"Mange spør oss om vi kommer i rettslige problemer med Nintendo om dette. Jeg er glad for å si at min tante jobber på Nintendo og hun sier at det går fint.",
"WebKit v537 er den beste versjonen av WebKit for Wii U. Nei, vi kommer ikke til å portere Chromium til Wii U.",
"Kan ikke vente til klokken når 03:14:08 UTC den 19 Januar 2038.",
"Wii U er faktisk et undervurdert system. Reklamene er dårlige, men konsollen er bra. Vent nå litt, hvorfor kobler ikke spillkontrollen min seg til Wii-en?",
"Super Mario World 2 - Yoshi's Islands hovedtema er en klassiker av en låt, og jeg lar meg ikke overbevise om annet.",
"",
"",
"Min første video på min kanal. jeg har ventet med å lage videoer lenge, men min bærbare kjørte veldig dårlig og jeg kunne ikke kjøre Fraps, Skype og minecraft samtidig. nå er det over! med litt hjelp fra min IT-lærer kjører min bærbare mye bedre og jeg kan ta opp skjermen. Håper dere liker denne videoen. Lik og abonner for flere videoer."
]
},
"progressPage": {
"title": "Vår fremgang",
"description": "Sjekk prosjektets fremgang og målene våre. (Oppdatert hver time eller så, og reflekterer ikke ALLE prosjektmål eller framgang)"
},
"blogPage": {
"title": "Blogg",
"description": "",
"published": "Publisert av"
},
"localizationPage": {
"title": "La oss snakke ditt språk",
"description": "Lim inn en lenke til en offentlig JSON-lokalitet for å teste den på nettsiden",
"instructions": "Vis lokaliseringsinstruksen",
"fileInput": "Fil å teste med",
"filePlaceholder": "https://en.linke.til/filen.json",
"button": "Testfil"
},
"docs": {
"missingInLocale": "Denne siden er utilgjengelig på ditt språk. Sjekk den engelske versjonen nedenfor.",
"quickLinks": {
"header": "Hurtiglenker",
"links": [
{
"header": "Installer Pretendo",
"caption": "Vis instruks om installasjon av Pretendo"
},
{
"header": "Har du et problem?",
"caption": "Søk her"
}
]
}
},
"account": {
"account": "Konto",
"loginForm": {
"miiName": "Mii-navn",
"confirmPassword": "Gjenta passord",
"register": "Registrering",
"email": "E-post",
"login": "Logg inn"
},
"settings": {
"unavailable": "Utilgjengelig",
"upgrade": "Oppgrader konto",
"settingCards": {
"gender": "Kjønn",
"beta": "Beta"
}
}
}
}

View File

@@ -1 +0,0 @@
{}

View File

@@ -1,133 +0,0 @@
{
"nav": {
"about": "關於",
"dropdown": {
"captions": {
"about": "關於專案",
"progress": "檢視專案進度與目標",
"credits": "認識團隊",
"faq": "常見問題",
"blog": "更新摘要"
}
},
"docs": "文件",
"credits": "貢獻者",
"progress": "進度",
"blog": "部落格",
"account": "帳號",
"accountWidget": {
"settings": "設定",
"logout": "登出"
},
"faq": "常見問題",
"donate": "捐款"
},
"hero": {
"buttons": {
"readMore": "閱讀更多"
},
"text": "Pretendo 是為了官方伺服器終止後,還能讓 3DS 和 Wii U 繼續用Nintendo Network的另解免費且開源的專案",
"subtitle": "遊戲伺服器",
"title": "重製"
},
"credits": {
"text": "見見在專案背後努力的團隊",
"title": "開發團隊"
},
"showcase": {
"cards": [
{
"title": "遊戲伺服器",
"caption": "用客製伺服器還原你最愛的遊戲體驗。"
},
{
"title": "Juxtaposition",
"caption": "一個 Miiverse 的重新塑造,會讓你以為在現代製作的。"
},
{
"caption": "即使沒有主機,也能玩你最喜歡的 Wii U 遊戲!",
"title": "Cemu 支援"
}
],
"text": "我們的專案有很多細項,這裡是其中一些。",
"title": "我們正在做什麼"
},
"faq": {
"QAs": [
{
"question": "Pretendo 是什麼?"
},
{
"question": "我現有的 NNID 可以用在 Pretendo 上嗎?",
"answer": "很抱歉,不行。你現有的 NNID 不能用於 Pretendo你的帳號資料都在任天堂手上雖然 NNID 到 PNID 的轉移理論上是能做到的,但是存在風險並且會包含我們不想知道的個人隱私。"
},
{
"question": "如何使用 Pretendo ?",
"answer": "Pretendo 目前還在內測,但是一旦完成,只要在系統上執行自製補丁就能使用 Pretendo。"
},
{
"answer": "不知道。許多 Pretendo 功能都是獨立開發的(例如 : Miiverse 可能由一位人員開發,而 Accounts 和 Friends 正在由另一位人員開發),因此我們無法告訴你確切的完成時間。",
"question": "這些 功能/服務 什麼時候才會完成?"
},
{
"answer": "Pretendo 主要為了實體 Wii U 和 3DS 而開發目前為止支援NintendoNetwork(NN)的只有 Cemu。",
"question": "Pretendo 能用在 Cemu 之類的模擬器上嗎?"
},
{
"question": "如果我在 Nintendo Network 上被ban帳號我在用 Pretendo 時還會是鎖著的嗎?",
"answer": "我們無法知道你在Nintendo Network有沒有被ban我們也不會亂ban人。然而我們之後會制定規則違者將會被ban。"
},
{
"answer": "Wii已經有 <a href=\"https://wiimmfi.de/\" target=\"_blank\">Wiimmfi</a> 提供的客製伺服器. Switch 的部分他既是收費項目運作方式也與Nintendo Network全然不同將不支援。",
"question": "Pretendo 會支援 Wii/Switch 嗎?"
},
{
"answer": "是的你必須破解主機才能連上。然而Wii U 的話只要有 Homebrew Launcher 就能連接 (軟解),之後會提供 3DS 連接的指南。",
"question": "要連接的話,我需要破解主機嗎 ?"
}
],
"title": "常見問題",
"text": "為了讓你快速理解,我們準備了一些常見問題。"
},
"specialThanks": {
"title": "特別感謝",
"text": "沒有他們Pretendo 就不會是今天的樣子。"
},
"footer": {
"widget": {
"captions": [
"想知道最新動態?",
"加入我們的 Discord!"
],
"button": "現在就加入 !"
},
"usefulLinks": "相關連結",
"bandwidthRaccoonQuotes": [
"我是浣熊\"頻寬\" ! 我最愛咬連上 Pretendo Network 的線路,真美味 !",
"很多人問我們是否會因此與任天堂發生法律糾紛;我很高興我的阿姨在任天堂工作,她說是合法的。",
"Webkit v537 是用於 Wii U 的最佳 Webkit 版本。然而,我們並不會移植 Chrome 轉到 Wii U。",
"迫不及待地等待時鐘到達2038年1月19日03:14:08 UTC !",
"Wii U实际上是一个被低估的系统广告好像真的很糟糕但控制台是伟大的。嗯等一下我不知道为什么但我的游戏手柄没有连接到我的Wii上。"
],
"socials": "社群帳號"
},
"aboutUs": {
"title": "關於我們",
"paragraphs": [
"Pretendo 是一個旨在為了還原 3DS 和 Wii U 的 Nintendo Network合法使用逆向工程的開源專案。",
"我們的服務會是免費和開源的。就算Nintendo Network因為特殊原因中止還是能繼續使用。"
]
},
"progress": {
"title": "進度",
"githubRepo": "Github 倉庫"
},
"discordJoin": {
"title": "持續獲得最新資訊",
"text": "加入我们的Discord服务器获取项目的最新进展。",
"widget": {
"text": "獲取我們進度的即時更新",
"button": "加入伺服器"
}
}
}

252
nuxt.config.ts Normal file
View File

@@ -0,0 +1,252 @@
export default defineNuxtConfig({
compatibilityDate: '2026-08-07',
srcDir: './src',
dir: {
public: './src/public'
},
nitro: {
prerender: {
routes: ['/blog/feed.xml']
}
},
vite: {
server: {
allowedHosts: ['pretendo.network']
}
},
modules: [
'@pinia/nuxt',
'@nuxt/eslint',
'@nuxt/fonts',
'@nuxt/icon',
'@nuxt/content',
'@nuxtjs/i18n'
],
eslint: {
config: {
standalone: false
}
},
routeRules: {
'/docs': { redirect: '/docs/welcome' }
},
runtimeConfig: {
nitro: {
envPrefix: 'PN_WEBSITE_'
},
trustProxy: false,
githubApiToken: '',
stripeSecretKey: '',
stripeWebhookSecret: '',
stripeNotificationEmail: '',
hcaptchaSecretKey: '',
grpcHost: '',
grpcApiKey: '',
mongoConnectionString: '',
smtpHost: '',
smtpPort: 587,
smtpUser: '',
smtpPassword: '',
smtpSecure: true,
smtpFromEmail: '',
smtpFromName: '',
discordBotToken: '',
discordClientId: '',
discordClientSecret: '',
discordGuildId: '',
discordTesterRoleId: '',
discordSupporterRoleId: '',
discourseSsoSecret: '',
apiBase: 'https://api.pretendo.cc',
apiBaseHost: 'api.pretendo.cc',
redisUrl: '',
public: {
baseUrl: 'https://pretendo.network',
cdnBaseUrl: 'https://r2-cdn.pretendo.cc',
redirectHosts: 'pretendo.network',
hcaptchaSiteKey: '',
cookieSecure: true
}
},
css: ['~/assets/css/main.css'],
fonts: {
defaults: {
weights: [400, 700],
styles: ['normal', 'italic']
}
},
icon: {
clientBundle: {
scan: true
},
provider: 'none',
serverBundle: 'local'
},
components: [
{
path: '~/components',
pathPrefix: false
}
],
content: {
build: {
markdown: {
highlight: {
theme: 'github-dark'
}
}
}
},
app: {
head: {
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: '/assets/images/icons/favicon.ico'
},
{
rel: 'apple-touch-icon',
sizes: '180x180',
href: '/assets/images/icons/apple-touch-icon.png'
},
{
rel: 'icon',
sizes: '32x32',
type: 'image/png',
href: '/assets/images/icons/favicon-32x32.png'
},
{
rel: 'icon',
sizes: '16x16',
type: 'image/png',
href: '/assets/images/icons/favicon-16x16.png'
},
{
rel: 'mask-icon',
href: '/assets/images/icons/safari-pinned-tab.svg',
color: '#1b1f3b'
},
{ rel: 'manifest', href: '/assets/site.webmanifest' },
{
rel: 'alternate',
type: 'application/rss+xml',
title: 'Pretendo Network Blog',
href: '/blog/feed.xml'
}
],
meta: [
{ name: 'msapplication-config', content: '/assets/browserconfig.xml' },
{ 'http-equiv': 'X-UA-Compatible', 'content': 'ie=edge' },
{ name: 'apple-mobile-web-app-title', content: 'Pretendo Network' },
{ name: 'application-name', content: 'Pretendo Network' },
{ name: 'msapplication-TileColor', content: '#1b1f3b' },
{ name: 'theme-color', content: '#1b1f3b' },
{
property: 'og:description',
content:
'An open source Nintendo Network replacement that aims to build custom servers for the WiiU and 3DS family of consoles'
},
{ property: 'og:type', content: 'website' },
{ property: 'og:url', content: 'https://pretendo.network' },
{
property: 'og:image',
content:
'https://pretendo.network/assets/images/opengraph/opengraph-image.png'
},
{ property: 'og:image:alt', content: '' },
{ property: 'og:site_name', content: 'Pretendo Network' },
{ property: 'twitter:url', content: 'https://pretendo.network/' },
{ property: 'twitter:card', content: 'summary_large_image' },
{ property: 'twitter:site', content: '@PretendoNetwork' },
{
property: 'twitter:description',
content:
'An open source Nintendo Network replacement that aims to build custom servers for the WiiU and 3DS family of consoles'
},
{
property: 'twitter:image',
content:
'https://pretendo.network/assets/images/opengraph/opengraph-image.png'
},
{
name: 'description',
content:
'An open source Nintendo Network replacement that aims to build custom servers for the WiiU and 3DS family of consoles'
},
{ property: 'robots', content: 'index, follow' }
]
}
},
i18n: {
compilation: {
strictMessage: false
},
restructureDir: 'src',
strategy: 'no_prefix',
defaultLocale: 'en-US',
vueI18n: '../i18n.config.ts',
locales: [
{ code: 'ar-AR', name: 'العربية', file: 'ar_AR.json' },
{ code: 'ast', name: 'Asturianu', file: 'ast.json' },
{ code: 'be-BY', name: 'Беларуская', file: 'be_BY.json' },
{ code: 'ca-ES', name: 'Català', file: 'ca_ES.json' },
{ code: 'cs-CZ', name: 'Čeština', file: 'cs_CZ.json' },
{ code: 'cy-GB', name: 'Cymraeg', file: 'cy_GB.json' },
{ code: 'da-DK', name: 'Dansk', file: 'da_DK.json' },
{ code: 'de-DE', name: 'Deutsch', file: 'de_DE.json' },
{ code: 'el-GR', name: 'Ελληνικά', file: 'el_GR.json' },
{ code: 'en-GB', name: 'English (United Kingdom)', file: 'en_GB.json' },
{ code: 'en-US', name: 'English (United States)', file: 'en_US.json' },
{ code: 'en@uwu', name: 'English (lolcat)', file: 'en@uwu.json' },
{ code: 'eo-XX', name: 'Esperanto', file: 'eo_XX.json' },
{ code: 'es-ES', name: 'Español', file: 'es_ES.json' },
{ code: 'fi-FI', name: 'Suomi', file: 'fi_FI.json' },
{ code: 'fr-CA', name: 'Français (Canada)', file: 'fr_CA.json' },
{ code: 'fr-FR', name: 'Français', file: 'fr_FR.json' },
{ code: 'ga-IE', name: 'Gaeilge', file: 'ga_IE.json' },
{ code: 'gd-GB', name: 'Gàidhlig', file: 'gd_GB.json' },
{ code: 'gl-ES', name: 'Galego', file: 'gl_ES.json' },
{ code: 'hr-HR', name: 'Hrvatski', file: 'hr_HR.json' },
{ code: 'hu-HU', name: 'Magyar', file: 'hu_HU.json' },
{ code: 'id-ID', name: 'Bahasa Indonesia', file: 'id_ID.json' },
{ code: 'it-IT', name: 'Italiano', file: 'it_IT.json' },
{ code: 'ja-JP', name: '日本語', file: 'ja_JP.json' },
{ code: 'kk-KZ', name: 'Қазақша', file: 'kk_KZ.json' },
{ code: 'ko-KR', name: '한국어', file: 'ko_KR.json' },
{ code: 'lt-LT', name: 'Lietuvių', file: 'lt_LT.json' },
{ code: 'lv-LV', name: 'Latviešu', file: 'lv_LV.json' },
{ code: 'nb-NO', name: 'Norsk bokmål', file: 'nb_NO.json' },
{ code: 'nl-NL', name: 'Nederlands', file: 'nl_NL.json' },
{ code: 'pl-PL', name: 'Polski', file: 'pl_PL.json' },
{ code: 'pt-BR', name: 'Português (Brasil)', file: 'pt_BR.json' },
{ code: 'pt-PT', name: 'Português (Portugal)', file: 'pt_PT.json' },
{ code: 'ro-RO', name: 'Română', file: 'ro_RO.json' },
{ code: 'ru-RU', name: 'Русский', file: 'ru_RU.json' },
{ code: 'sk-SK', name: 'Slovenčina', file: 'sk_SK.json' },
{ code: 'sr-RS', name: 'Српски', file: 'sr_RS.json' },
{ code: 'sv-SE', name: 'Svenska', file: 'sv_SE.json' },
{ code: 'tr-TR', name: 'Türkçe', file: 'tr_TR.json' },
{ code: 'uk-UA', name: 'Українська', file: 'uk_UA.json' },
{ code: 'tr-TR', name: 'Türkçe', file: 'tr_TR.json' },
{ code: 'uk-UA', name: 'Українська', file: 'uk_UA.json' },
{ code: 'zh-CN', name: '中文 (简体)', file: 'zh_CN.json' },
{ code: 'zh-Hant', name: '中文 (繁體)', file: 'zh_Hant.json' }
]
}
});

31307
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,51 +1,70 @@
{
"name": "website",
"version": "1.0.0",
"description": "",
"main": "src/server.js",
"description": "Website for Pretendo Network",
"license": "AGPL-3.0-only",
"type": "module",
"scripts": {
"start": "node src/server.js",
"build": "npm run browserify",
"browserify": "npm run browserify-miieditor && npm run browserify-reset-password",
"browserify-miieditor": "browserify ./public/assets/js/miieditor.js -o ./public/assets/js/miieditor.bundled.js",
"browserify-reset-password": "browserify ./public/assets/js/reset-password.js -o ./public/assets/js/reset-password.bundled.js"
"start": "node --env-file=.env --enable-source-maps .output/server/index.mjs",
"build": "nuxt build",
"prepare": "nuxt prepare",
"dev": "nuxt dev",
"dev:host": "nuxt dev --host",
"typecheck": "nuxt typecheck",
"lint": "eslint .",
"lint:fix": "eslint . --fix"
},
"repository": {
"type": "git",
"url": "git+https://github.com/PretendoNetwork/website.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/PretendoNetwork/website/issues"
},
"homepage": "https://github.com/PretendoNetwork/website#readme",
"dependencies": {
"@aws-sdk/client-ses": "^3.515.0",
"@discordjs/rest": "^0.5.0",
"@node-saml/node-saml": "^5.0.0",
"@pretendonetwork/error-codes": "^1.0.3",
"browserify": "^17.0.0",
"colors": "^1.4.0",
"cookie-parser": "^1.4.5",
"discord-api-types": "^0.36.1",
"discord-oauth2": "github:ryanblenis/discord-oauth2",
"express": "^4.17.1",
"express-handlebars": "^5.3.1",
"express-locale": "^2.0.0",
"fs-extra": "^9.1.0",
"got": "^11.8.5",
"graphql-request": "^4.3.0",
"gray-matter": "^4.0.3",
"lodash.merge": "^4.6.2",
"marked": "^4.0.10",
"mii-js": "github:PretendoNetwork/mii-js#v1.0.4",
"mongoose": "^6.4.0",
"morgan": "^1.10.0",
"nodemailer": "^6.7.5",
"stripe": "^9.9.0"
"@discordjs/rest": "^2.6.3",
"@hcaptcha/vue3-hcaptcha": "^1.3.0",
"@nuxt/content": "^3.4.0",
"@nuxt/eslint": "^1.3.0",
"@nuxt/fonts": "^0.14.0",
"@nuxt/icon": "^2.5.0",
"@nuxtjs/i18n": "^10.6.0",
"@pinia/nuxt": "^1.0.1",
"@pretendonetwork/error-codes": "^1.2.2",
"@pretendonetwork/grpc": "^2.5.4",
"@pretendonetwork/mii-js": "^1.0.11",
"@vueuse/core": "^14.4.0",
"better-sqlite3": "^12.11.1",
"discord-api-types": "^0.38.53",
"eslint": "^9.39.5",
"feed": "^6.0.0",
"hcaptcha": "^0.2.0",
"ioredis": "^5.11.1",
"mlly": "^1.8.2",
"mongodb": "^7.5.0",
"nice-grpc": "^2.1.17",
"nodemailer": "^9.0.5",
"nuxt": "^4.5.2",
"octokit": "^5.0.5",
"papr": "^17.1.1",
"rate-limiter-flexible": "^11.2.0",
"reka-ui": "^2.10.3",
"stripe": "^22.4.0",
"text-mask-core": "^5.1.2",
"vue": "^3.5.13",
"vue-router": "^5.2.0",
"zod": "^4.4.3"
},
"devDependencies": {
"eslint": "^7.32.0"
"@iconify-json/fa7-brands": "^1.2.4",
"@iconify-json/ph": "^1.2.2",
"@pretendonetwork/eslint-config": "^0.1.4",
"@types/nodemailer": "^8.0.1",
"eslint-plugin-vue": "^10.0.0",
"sass-embedded": "^1.86.3",
"vue-tsc": "^3.3.10"
},
"allowScripts": {
"better-sqlite3@12.11.1": true,
"esbuild@0.28.1": true,
"esbuild@0.25.12": true,
"protobufjs@7.6.5": true,
"unrs-resolver@1.12.2": true,
"@parcel/watcher@2.6.0": true,
"vue-demi@0.14.10": true,
"esbuild@0.27.2": true
}
}

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="https://pretendo.network/assets/images/icons/mstile-150x150.png"/>
<TileColor>#1b1f3b</TileColor>
</tile>
</msapplication>
</browserconfig>

View File

@@ -1,24 +0,0 @@
.status {
text-align: center;
font-size: 8rem;
padding-top: 60px;
color: var(--text-shade-1);
}
.description {
text-align: center;
font-size: 1.7rem;
margin-top: -10px;
color: var(--text-shade-1);
}
.shocked-bandwidth {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 70px;
margin-bottom: -120px;
}
@media screen and (max-width: 900px) {
.shocked-bandwidth {
margin-bottom: -100px;
}
}

View File

@@ -1,346 +0,0 @@
/* Removing until it's done */
.sign-in-history a {
display: none;
}
.account-wrapper {
display: grid;
column-gap: 48px;
margin-top: 80px;
color: var(--text-shade-1);
}
/* Account settings sidebar */
.account-sidebar .user {
margin: 55px auto;
width: fit-content;
display: flex;
flex-flow: column;
align-items: center;
}
.account-sidebar .user .miiname {
font-size: 1.2rem;
color: var(--text-shade-3);
margin: 8px 0 4px;
}
.account-sidebar .user .username {
margin: 0;
}
.account-sidebar .user .tier-name {
margin: 12px 0;
line-height: 1.2em;
border-radius: 1.2em;
border-width: 2px;
border-style: solid;
padding: 4px 16px;
}
.account-sidebar .user .tier-level-0,
.account-sidebar .user .access-level-0 {
background: #2a2f50;
color: var(--text-shade-1);
border-color: #383f6b;
}
.account-sidebar .user .tier-level-1 {
background: rgba(255, 132, 132, 0.2);
color: #FF8484;
border-color: rgba(255, 132, 132, 0.8);
}
.account-sidebar .user .tier-level-2 {
background: rgba(89, 201, 165, 0.3);
color:#59c9a5;
border-color: #59c9a5;
}
.account-sidebar .user .tier-level-3 {
background: rgba(202, 177, 251, 0.3);
color:var(--accent-shade-3);
border-color: var(--accent-shade-3);
}
.account-sidebar .user .access-level-banned {
background: rgba(255, 63, 0, 0.1);
color:#FF3F00;
border-color: rgba(255, 63, 0, 0.8);
}
.account-sidebar .user .access-level-1 {
background: rgba(100, 247, 239, 0.3);
color: #64F7EF;
border-color: #64F7EF;
}
.account-sidebar .user .access-level-2 {
background: rgba(255, 199, 89, 0.3);
color: #FFC759;
border-color: #FFC759;
}
.account-sidebar .user .access-level-3 {
background: rgba(90, 255, 21, 0.3);
color:#5AFF15;
border-color: #5AFF15;
}
.account-sidebar .user a.mii {
position: relative;
display: block;
width: 128px;
height: 128px;
overflow: hidden;
border-radius: 100%;
background: var(--bg-shade-3);
}
.account-sidebar .user a.mii::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: no-repeat center/40% url("/assets/images/edit.svg"), rgba(55, 60, 101, 0.7);
opacity: 0;
transition: opacity 150ms;
}
.account-sidebar .user a.mii:hover::after {
opacity: 1;
}
.account-sidebar .user .mii {
width: 100%;
height: 100%;
}
.account-sidebar .buttons a {
display: flex;
flex-flow: column;
align-items: center;
padding: 20px 24px;
margin: 20px 0 0;
text-decoration: none;
text-align: center;
}
.account-sidebar .buttons a svg {
margin-bottom: 16px;
}
.account-sidebar .buttons a p.caption {
margin: 0;
}
.account-sidebar .buttons p.cemu-warning {
margin: 4px 0 0;
font-size: 0.7rem;
color: var(--text-shade-1);
}
/* Settings */
.settings-wrapper {
display: grid;
grid-column-start: 2;
grid-template-columns: 1fr 1fr;
column-gap: 20px;
}
.settings-wrapper a {
color: var(--accent-shade-1);
text-decoration: none;
font-weight: bold;
}
.settings-wrapper a:hover {
text-decoration: underline;
}
.settings-wrapper h2.section-header {
margin-top: 40px;
grid-column: 1 / 3;
color: var(--text-shade-3);
}
.setting-card {
display: grid;
grid-template-rows: 35px repeat(2, auto);
row-gap: 24px;
position: relative;
border-radius: 10px;
background: var(--bg-shade-2);
padding: 48px 60px;
}
.setting-card * {
margin: 0;
}
.setting-card .edit {
color: var(--text-shade-1);
background: var(--bg-shade-3);
border-radius: 100%;
position: absolute;
top: 42px;
right: 48px;
width: 24px;
height: 24px;
padding: 12px;
}
.setting-card .edit:hover {
background: var(--bg-shade-3);
color: var(--text-shade-3);
}
.setting-card .edit svg {
pointer-events: none;
}
.setting-card .header {
color: var(--text-shade-3);
}
.setting-card .setting-list {
display: grid;
grid-template-columns: repeat(2, auto);
gap: 24px;
list-style: none;
padding: 0;
}
.setting-card .setting-list p.label {
color: var(--text-shade-3);
margin-bottom: 4px;
}
fieldset {
position: relative;
height: min-content;
padding: 0;
border: none;
}
.setting-card .server-selection {
display: flex;
border-radius: 5px;
overflow: hidden;
background: var(--bg-shade-3);
}
.setting-card .server-selection input {
display: none;
}
.server-selection input + label {
display: flex;
flex-flow: column;
align-items: center;
flex: 50%;
color: var(--text-shade-1);
padding: 40px;
justify-content: space-between;
cursor: pointer;
}
.server-selection input + label h2 {
margin-top: 12px;
color: var(--text-shade-1);
}
.server-selection input:checked + label,
.server-selection input:checked + label h2 {
background: var(--accent-shade-0);
color: var(--text-shade-3);
}
.setting-card #link-discord-account {
width: 100%;
padding: 12px 48px;
cursor: pointer;
background: var(--bg-shade-3);
}
.setting-card button {
width: 100%;
height: fit-content;
padding: 12px 48px;
align-self: flex-end;
cursor: pointer;
background: var(--bg-shade-3);
}
.setting-card.span-both-columns {
grid-column: 1 / span 2;
}
@keyframes banner-notice {
0% {
top: -150px;
}
20% {
top: 35px;
}
80% {
top: 35px;
}
100% {
top: -150px;
}
}
.banner-notice {
display: flex;
justify-content: center;
position: fixed;
top: -150px;
width: 100%;
animation: banner-notice 5s;
}
.banner-notice div {
padding: 4px 36px;
border-radius: 5px;
z-index: 3;
}
.banner-notice.success div {
background: var(--green-shade-0);
}
.banner-notice.error div {
background: var(--red-shade-1);
}
footer {
margin-top: 80px;
}
@media screen and (max-width: 1300px) {
.account-wrapper {
margin: 20px 0;
}
.settings-wrapper {
grid-column-start: 1;
}
.account-sidebar {
margin: 0;
}
.account-sidebar .user .mii {
width: 128px;
height: 128px;
}
}
@media screen and (max-width: 1000px) {
.settings-wrapper {
display: block;
width: 100%;
}
.setting-card {
margin-bottom: 24px;
}
}
@media screen and (max-width: 550px) {
.setting-card {
padding: 24px;
width: calc(100vw - 48px);
margin-left: -5vw;
margin-right: -2.5vw;
border-radius: 0;
margin-bottom: 12px;
}
.setting-card .edit {
top: 20px;
right: 20px;
transform: scale(0.85);
}
.setting-card .server-selection {
flex-flow: column;
}
}
@media screen and (max-width: 350px) {
.setting-card .setting-list {
grid-template-columns: auto;
}
}

View File

@@ -1,139 +0,0 @@
.new-font {
font-family: museo-sans, sans-serif;
}
.pretendo {
font-family: Poppins, Arial, Helvetica, sans-serif;
font-weight: 700;
}
.announcement-hero {
position: relative;
text-align: center;
padding: 96px 0;
margin: 36px 0 24px;
}
.announcement-hero p {
font-size: 24px;
margin: 0;
margin-bottom: 24px;
}
.announcement-hero h1 {
font-size: 450%;
margin: 0;
}
.announcement-hero::before {
content: "";
position: absolute;
width: 500vw;
height: 100%;
top: 0;
left: -50vw;
background: var(--accent-shade-0);
z-index: -1;
}
.bro-what.subscribe {
padding-top: 0;
display: flex;
}
.bro-what.subscribe h1 {
margin: 0;
margin-right: 12px;
width: fit-content;
}
.buy-now {
margin-left:auto;
}
.buy-now button {
cursor: pointer;
width: max-content;
height: 100%;
}
.bro-what {
padding: 48px;
}
.bro-what a {
color: inherit;
text-decoration: none;
font-weight: 700;
}
.dotted-bg {
position: relative;
}
.dotted-bg::before {
content: "";
position: absolute;
width: 500vw;
height: 100%;
top: 0;
left: -50vw;
background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='100%25' width='100%25'%3E%3Cdefs%3E%3Cpattern id='doodad' width='6' height='6' viewBox='0 0 40 40' patternUnits='userSpaceOnUse' patternTransform=''%3E%3Crect width='100%25' height='100%25' fill='rgba(27, 31, 59,1)'/%3E%3Ccircle cx='20' cy='20' r='11' fill='rgba(103, 61, 182,0.4)'/%3E%3Cpath d='M9 20aInfinityInfinity 0 0 0InfinityNaNaInfinityInfinity 0 0 0-InfinityNaN' fill='%23ecc94b'/%3E%3C/pattern%3E%3C/defs%3E%3Crect fill='url(%23doodad)' height='200%25' width='200%25'/%3E%3C/svg%3E ");
z-index: -1;
}
.footnotes {
color: var(--text-shade-1);
}
@media screen and (max-width: 946px) {
header nav a:not(.keep-on-mobile) {
display: none;
}
.announcement-hero h1 {
font-size: 350%;
}
}
@media screen and (max-width: 724px) {
header .logo-link svg text {
display: none;
}
header .logo-link svg {
width: 39.876px;
}
header .logo-link {
margin-right: 10px;
}
header nav a {
margin: 0 10px;
}
.announcement-hero h1 {
font-size: 250%;
}
.announcement-hero p {
font-size: 18px;
}
}
@media screen and (max-width: 600px) {
.bro-what.subscribe {
flex-flow: column;
}
.bro-what a,
.buy-now button {
width: 100%;
}
.bro-what a {
margin-top: 24px;
}
.announcement-hero {
padding: 72px 0;
}
}
@media screen and (max-width: 480px) {
.bro-what {
padding: 36px 0;
}
}

View File

@@ -1,119 +0,0 @@
.blog-card {
display: flex;
flex-flow: row nowrap;
padding: 0;
margin: 0 auto;
max-width: 1000px;
margin-bottom: 30px;
text-decoration: none;
position: relative;
border-radius: 10px;
overflow: hidden;
}
.blog-card .post-info {
flex: 50%;
padding: 40px;
display: flex;
flex-flow: column;
color: var(--text-shade-1);
}
.blog-card .post-info .title {
color: var(--text-shade-3);
margin: 0;
}
.blog-card .post-info .caption {
margin: 4px 0 32px 0;
}
.blog-card .pub-info {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: left;
margin-top: auto;
}
.blog-card .pub-info .date {
font-weight: bold;
color: var(--text-shade-3);
}
.blog-card .pub-info > * {
margin-right: 0.5em;
margin-top: 0.2em;
}
.blog-card .profile {
display: inline-grid;
grid-template-columns: 30px auto;
grid-gap: 10px;
font-weight: bold;
color: var(--text-shade-3);
align-items: center;
height: 32px;
margin-right: 0.3em;
}
.blog-card .profile img {
border-radius: 4px;
border: 1px solid var(--border);
max-width: 100%;
}
.blog-card .cover {
flex: 50%;
border: 3px solid var(--bg-shade-0);
border-radius: 0 10px 10px 0;
}
.progress-hero a,
.progress-hero a * {
color: var(--accent-shade-1);
text-decoration: none;
font-weight: bold;
}
.progress-hero a:hover,
.progress-hero a:hover {
text-decoration: underline;
}
.buttons {
margin: 10vh auto;
width: min-content;
}
.buttons button.secondary.icon-btn {
cursor: pointer;
width: 35px;
height: 35px;
padding: 0;
}
footer {
margin-top: 160px;
}
@media screen and (max-width: 900px) {
.blog-card {
flex-flow: column;
}
.blog-card .post-info {
padding: 30px;
}
.blog-card .cover {
order: -1;
min-height: 250px;
border-radius: 10px 10px 0 0;
}
footer {
margin-top: 100px;
}
}
@media screen and (max-width: 450px) {
.blog-card .cover {
min-height: 200px;
}
}

View File

@@ -1,225 +0,0 @@
.wrapper {
display: flex;
flex-direction: column;
width: 95%;
min-height: 100vh;
}
header {
width: 100%;
}
.card-wrap {
width: 100%;
}
.blog-card {
padding: 60px;
max-width: 1100px;
margin: 50px auto;
color: var(--text-shade-1);
}
.blog-card h1,
.blog-card h2,
.blog-card h3,
.blog-card h4,
.blog-card h5,
.blog-card h6 {
margin: 40px 0 10px;
color: var(--text-shade-3);
}
.blog-card strong {
color: var(--text-shade-3);
}
.blog-card a,
.blog-card a * {
color: var(--accent-shade-1);
text-decoration: none;
font-weight: bold;
}
.blog-card a:hover,
.blog-card a:hover {
text-decoration: underline;
}
.blog-card del {
text-decoration: line-through;
}
.blog-card .title {
margin: 0;
margin-bottom: 8px;
}
.blog-card .pub-info {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: left;
margin-top: auto;
margin-bottom: 30px;
}
.blog-card .pub-info .date {
font-weight: bold;
color: var(--text-shade-3);
}
.blog-card .pub-info > * {
margin-right: 0.5em;
margin-top: 0.2em;
}
.blog-card .profile {
display: inline-grid;
grid-template-columns: 30px auto;
grid-gap: 10px;
font-weight: bold;
color: var(--text-shade-3);
align-items: center;
height: 32px;
margin-right: 0.3em;
}
.blog-card .profile img {
margin: 0;
border-radius: 4px;
border: 1px solid var(--border);
max-width: 100%;
}
.blog-card p,
.post-info {
color: var(--text-shade-1);
}
.blog-card img {
max-width: 100%;
max-height: 800px;
margin: 10px auto;
display: block;
border-radius: 4px;
border: 1px solid var(--border);
}
.blog-card img.emoji {
display: inline;
margin: 0;
border: none;
}
.blog-card video {
width: 100%;
border-radius: 4px;
border: 1px solid var(--border);
}
.blog-card iframe {
width: 100%;
aspect-ratio: 16/9;
border-radius: 4px;
border: 1px solid var(--border);
}
/* Fallback for aspect-ratio since it's unsupported by some browsers (looking at you Safari) */
@supports not (aspect-ratio: 16/9) {
.blog-card .aspectratio-fallback {
position: relative;
height: 0;
padding-top: 56.25%;
}
.blog-card iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
}
/* Some twitter iframe specific stuff */
.blog-card .twitter-tweet {
margin: auto;
}
.blog-card .twitter-tweet iframe {
border: none; /* Fixes the double border */
}
.blog-card table {
border-radius: 4px;
border-collapse: collapse;
background: var(--bg-shade-3);
margin-bottom: 30px;
overflow: hidden;
}
.blog-card table th {
padding: 8px 12px;
background: var(--bg-shade-4);
color: var(--text-shade-3);
}
.blog-card table td {
padding: 8px 12px;
vertical-align: top;
border-radius: inherit;
}
.blog-card table tr:nth-child(even) {
background: var(--bg-shade-2);
}
.blog-card pre code {
border-radius: 4px;
margin-bottom: 30px;
}
.blog-card input[type="checkbox"] {
appearance: none;
-webkit-appearance: none;
display: inline-block;
background: var(--bg-shade-3);
padding: 12px;
margin: 4px;
border-radius: 4px;
vertical-align: -60%;
}
.blog-card input[type="checkbox"]:checked {
content: "checkboxtest";
background: no-repeat center/contain url(../images/check.svg),
var(--bg-shade-3);
}
.blog-card hr {
border: 1px solid var(--text-shade-1);
margin: 30px 0;
}
.blog-card blockquote {
border-left: 2px solid var(--text-shade-1);
padding: 8px 24px;
margin: 0;
margin-bottom: 30px;
}
@media screen and (max-width: 800px) {
.blog-card {
padding: 40px;
}
}
@media screen and (max-width: 600px) {
.wrapper {
width: 100%;
}
header {
width: 90%;
margin: 35px auto;
}
.blog-card {
padding: 40px 5vw;
border-radius: 0;
margin-top: 0;
}
footer {
width: 95%;
margin: auto auto 40px;
}
}

View File

@@ -1,190 +0,0 @@
/* BUTTONS */
button,
.button {
appearance: none;
-webkit-appearance: none;
border: 0;
border-radius: 6px;
font-family: Poppins, Arial, Helvetica, sans-serif;
font-size: 1rem;
color: var(--text-shade-3);
padding: 12px 48px;
background: var(--bg-shade-3);
cursor: pointer;
display: block;
text-align: center;
}
button:hover,
.button:hover {
background: var(--bg-shade-4);
}
button.inactive {
pointer-events: none;
}
button.primary,
.button.primary {
background: var(--accent-shade-0);
}
button.primary:hover,
.button.primary:hover {
background: var(--accent-shade-1);
}
button.secondary.icon-btn,
.button.secondary.icon-btn {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
button svg,
.button svg {
width: 30px;
height: 30px;
display: block;
}
/* MODALS */
body.modal-open {
overflow: hidden;
}
div.modal-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.6);
z-index: 10;
}
div.modal-wrapper.hidden {
display: none;
}
div.modal {
background: var(--bg-shade-3);
padding: 48px;
border-radius: 8px;
text-align: left;
width: min(660px, 90%);
box-sizing: border-box;
}
div.modal h1 {
margin-top: 0;
}
p.modal-caption {
color: var(--text-shade-1);
}
p.modal-caption span,
p.switch-tier-modal-caption span {
color: var(--text-shade-3);
}
.modal-button-wrapper {
margin-top: 24px;
display: flex;
justify-content: flex-end;
}
.modal-button-wrapper button {
margin-left: 12px;
width: fit-content;
}
.modal-button-wrapper button.cancel {
background: none;
}
.modal-button-wrapper button {
padding: 12px 24px;
}
@media screen and (max-width: 600px) {
div.modal {
padding: 24px;
}
}
/* MISC FORM COMPONENTS */
input[type="checkbox"] {
appearance: none;
-webkit-appearance: none;
background: var(--bg-shade-3);
padding: 12px;
margin: 4px;
margin-left: 0;
border-radius: 4px;
vertical-align: -65%;
width: fit-content;
cursor: pointer;
}
input[type="checkbox"]:checked {
background: no-repeat center/contain url(../images/check.svg), var(--accent-shade-0);
}
input {
appearance: none;
-webkit-appearance: none;
display: block;
font-family: Poppins, Arial, Helvetica, sans-serif;
font-size: 1rem;
background-color: var(--bg-shade-3);
border: none;
border-radius: 4px;
padding: 12px;
color: var(--text-shade-3);
width: calc(100% - 24px);
}
input:focus {
background-color: var(--bg-shade-4);
outline: none;
transition: 150ms;
}
input[type="range"] {
background: transparent;
cursor: pointer;
width: 100%;
box-sizing: border-box;
}
input[type="range"]::-webkit-slider-runnable-track {
background: var(--bg-shade-3);
height: 1rem;
border-radius: 1rem;
}
input[type="range"]::-moz-range-track {
background: var(--bg-shade-3);
border-radius: 1rem;
height: 1rem;
}
input[type="range"]::-webkit-slider-thumb {
appearance: none;
-webkit-appearance: none;
width: 1.5rem;
height: 3rem;
margin-top: -1rem;
background-color: var(--accent-shade-1);
border-radius: 0.5rem;
}
input[type="range"]::-moz-range-thumb {
width: 1.5rem;
height: 3rem;
border: none;
border-radius: 0.5rem;
background-color: var(--accent-shade-1);
}
input[type="range"]:focus {
outline: none;
}
input[type="range"]:focus::-webkit-slider-thumb {
background-color: var(--accent-shade-3);
}
input[type="range"]:focus::-moz-range-thumb {
background-color: var(--accent-shade-3);
}

View File

@@ -1,428 +0,0 @@
html,
body,
div.main-body {
height: 100%;
background: var(--bg-shade-0);
}
a.logo-link {
margin: auto;
margin-left: 36px;
height: 40px;
text-decoration: none;
}
button#openSidebar {
display: none;
}
.docs-wrapper .content:not(.search) a {
text-decoration: none;
font-weight: bold;
color: var(--accent-shade-1);
}
.docs-wrapper header {
position: relative;
box-sizing: border-box;
margin: 20px;
margin-left: 0;
}
.docs-wrapper header::before {
content: none;
background: none;
pointer-events: none;
}
.docs-wrapper header a.logo-link {
display: none;
}
.docs-wrapper header nav a:first-child {
margin-left: 0;
}
.docs-wrapper {
display: grid;
grid-template-columns: fit-content(100%) auto;
grid-template-rows: fit-content(100%) auto;
height: 100%;
}
.docs-wrapper .sidebar {
display: flex;
flex-flow: column;
align-items: center;
width: clamp(270px, 25vw, 500px);
overflow-y: scroll;
overflow-x: hidden;
min-height: 100%;
}
.docs-wrapper .sidebar .section {
display: flex;
flex-flow: column;
width: 200px;
margin-left: clamp(60px, 10vw, 138px);
margin-bottom: 72px;
}
.docs-wrapper .sidebar .section:first-child {
margin-top: 72px;
}
.docs-wrapper .sidebar .section h5 {
margin: 0;
font-weight: normal;
text-transform: uppercase;
color: var(--text-shade-0);
margin-bottom: 12px;
}
.docs-wrapper .sidebar .section a {
position: relative;
text-decoration: none;
color: var(--text-shade-1);
width: fit-content;
margin-bottom: 12px;
}
.docs-wrapper .sidebar .section a.active,
.docs-wrapper .sidebar .section a:hover {
color: var(--text-shade-3);
}
.docs-wrapper .sidebar .section a.active::before {
/* This filter thing is jank, if anyone knows a better way to do this please fix */
filter: invert(51%) sepia(12%) saturate(2930%) hue-rotate(218deg)
brightness(99%) contrast(92%);
position: absolute;
left: -30px;
content: url(../images/docs/arrow-right.svg);
}
.docs-wrapper .content {
background: var(--bg-shade-1);
padding: 72px;
max-height: 100%;
overflow-y: scroll;
border-top-left-radius: 8px;
}
.docs-wrapper .content-inner {
max-width: 900px;
}
.docs-wrapper .content p {
color: var(--text-shade-1);
}
.docs-wrapper .content h1:first-child {
margin-top: 0;
}
.docs-wrapper .content .quick-links-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 24px;
margin-bottom: 60px;
}
.docs-wrapper .quick-links-grid a {
text-decoration: none;
background: var(--bg-shade-2);
border-radius: 6px;
color: var(--text-shade-1);
display: flex;
align-items: center;
padding: 20px;
}
.docs-wrapper .quick-links-grid svg:first-child {
height: 36px;
margin-right: 24px;
margin-left: 4px;
color: var(--accent-shade-2);
}
.docs-wrapper .quick-links-grid p.header {
font-size: 22px;
font-weight: 600;
color: var(--text-shade-3);
margin: 0;
}
.docs-wrapper .quick-links-grid p {
margin: 0;
}
.docs-wrapper .quick-links-grid svg:last-child {
height: 36px;
margin-left: auto;
}
.docs-wrapper .content-inner div.tip {
position: relative;
width: 100%;
padding: 36px;
background: var(--bg-shade-2);
border-radius: 8px;
overflow: hidden;
border: var(--accent-shade-2);
margin: 24px 0;
box-sizing: border-box;
}
.docs-wrapper .content-inner div.tip::after {
content: "";
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 12px;
background: var(--accent-shade-2);
opacity: 1;
}
.docs-wrapper .content-inner div.tip.yellow::after {
background: var(--yellow-shade-1);
}
.docs-wrapper .content-inner div.tip.red::after {
background: var(--red-shade-1);
}
.docs-wrapper .content-inner div.tip.green::after {
background: var(--green-shade-1);
}
.docs-wrapper .content .missing-in-locale-notice {
background: var(--bg-shade-2);
padding: 24px;
border-radius: 6px;
}
.search .purple-card {
padding: 36px;
}
.search .purple-card h1 {
margin-top: 0;
}
.search .purple-card p {
margin-bottom: 2em;
}
.search .purple-card input::placeholder {
color: var(--text-shade-0);
}
.search .purple-card input:focus {
background-color: var(--bg-shade-4);
color: #fff;
transition: 200ms;
outline: none;
}
.search .input-wrapper {
position: relative;
margin-top: 8px;
}
.search .input-wrapper .matches {
display: flex;
flex-flow: column;
font-size: 1rem;
background-color: var(--bg-shade-2);
border: none;
border-radius: 0 0 4px 4px;
max-height: 204px;
overflow-y: auto;
overflow-x: hidden;
}
.search .input-wrapper .matches * {
padding: 12px;
margin: 0;
text-decoration: none;
color: var(--text-shade-3);
}
.search .input-wrapper .matches a:hover {
background-color: var(--bg-shade-1);
}
.search input.has-matches {
border-radius: 4px 4px 0 0;
}
.platform-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 24px;
margin-top: 36px;
}
.docs-wrapper .platform-grid a {
text-decoration: none;
background: var(--bg-shade-3);
border-radius: 12px;
color: var(--text-shade-4) !important;
display: grid;
grid-template-rows: auto fit-content(100%);
align-items: center;
justify-content: center;
text-align: center;
padding: 36px;
padding-bottom: 24px;
gap: 24px;
}
.platform-grid a img {
width: 180px;
max-width: 100%;
height: auto;
}
.platform-grid a span {
margin-top: auto;
font-size: 1.2rem;
}
@media screen and (max-width: 1296px) {
.docs-wrapper .content {
padding: 48px;
}
}
@media screen and (max-width: 1080px) {
.docs-wrapper .header-wrapper {
position: absolute;
top: 0;
left: 0;
display: flex;
width: 100vw;
}
button#openSidebar {
display: block;
padding: 0;
margin: 0;
margin-left: 20px;
background: none;
}
.docs-wrapper header {
margin-left: 20px;
width: 100%;
left: 0;
}
.docs-wrapper {
margin-top: 80px;
height: calc(100% - 80px);
}
a.logo-link {
display: none;
}
.docs-wrapper header a.logo-link {
display: block;
height: 40px;
margin: 0;
margin-right: 34px;
}
.docs-wrapper .sidebar {
grid-column: 1 / span 1;
grid-row: 2 / span 1;
width: 0;
transition: width 250ms;
}
.docs-wrapper .sidebar.open {
width: min(300px, 100vw);
}
.docs-wrapper .content {
width: 100vw;
box-sizing: border-box;
border-top-left-radius: 0;
grid-column: 2 / span 1;
grid-row: 2 / span 1;
}
.docs-wrapper .content.open-sidebar {
border-top-left-radius: 8px;
}
.docs-wrapper .content-inner {
max-width: none;
}
}
@media screen and (max-width: 900px) {
.docs-wrapper header button.dropdown-button#mobile-button {
display: none;
}
.docs-wrapper header .logo-link svg text {
display: block;
}
.docs-wrapper header .logo-link svg {
width: 120px;
}
}
@media screen and (max-width: 820px) {
.docs-wrapper .content .quick-links-grid,
.platform-grid {
grid-template-columns: 1fr;
grid-auto-rows: 1fr;
}
.docs-wrapper header a.logo-link {
margin-right: 6px;
}
}
@media screen and (max-width: 576px) {
.docs-wrapper header div.dropdown {
left: calc(-39.876px - 6px - 30px - 40px);
}
}
@media screen and (max-width: 492px) {
.docs-wrapper .content {
padding: 36px;
}
header .logo-link svg text {
display: none;
}
header .logo-link svg {
width: 39.876px;
}
.docs-wrapper header a.logo-link {
margin-right: 0;
}
}
@media screen and (max-width: 360px) {
.docs-wrapper .content {
padding: 24px;
}
}
/* Scrollbar styling 'cause it's fancy */
.docs-wrapper .sidebar::-webkit-scrollbar,
.docs-wrapper .content::-webkit-scrollbar,
.docs-wrapper .content pre code::-webkit-scrollbar,
.search .input-wrapper .matches::-webkit-scrollbar {
width: 12px;
height: 12px;
}
.docs-wrapper .sidebar::-webkit-scrollbar-track,
.docs-wrapper .content::-webkit-scrollbar-track,
.docs-wrapper .content pre code::-webkit-scrollbar-track,
.search .input-wrapper .matches::-webkit-scrollbar-track {
background: none;
}
.docs-wrapper .sidebar::-webkit-scrollbar-thumb,
.docs-wrapper .content::-webkit-scrollbar-thumb,
.docs-wrapper .content pre code::-webkit-scrollbar-thumb,
.search .input-wrapper .matches::-webkit-scrollbar-thumb {
background-color: var(--text-shade-0);
border-radius: 24px;
border: 3px solid var(--bg-shade-0);
}
.docs-wrapper .content::-webkit-scrollbar-thumb {
border: 3px solid var(--bg-shade-1);
}
.docs-wrapper .content pre code::-webkit-scrollbar-thumb,
.search .input-wrapper .matches::-webkit-scrollbar-thumb {
border: 3px solid var(--bg-shade-2);
}
.docs-wrapper .sidebar,
.search .input-wrapper .matches {
scrollbar-width: thin;
scrollbar-color: var(--text-shade-0) var(--bg-shade-1);
}
.docs-wrapper .content {
scrollbar-width: thin;
scrollbar-color: var(--text-shade-0) var(--bg-shade-1);
}
.docs-wrapper .content pre code {
scrollbar-width: thin;
scrollbar-color: var(--text-shade-0) var(--bg-shade-0);
}

View File

@@ -1,76 +0,0 @@
.select-box {
display: flex;
flex-direction: column;
position: relative;
user-select: none;
}
.select-box > * {
box-sizing: border-box;
}
.select-box .options-container {
max-height: 0;
width: min(90vw, 240px);
opacity: 0;
transition: all 0.4s;
overflow: hidden;
border-radius: 5px;
background-color: var(--bg-shade-3);
order: 1;
position: absolute;
top: 48px;
right: 0;
}
.select-box .option .item {
color: var(--text-shade-2);
}
.select-box .lang {
width: 1.3rem;
height: 1rem;
margin-right: .2rem;
display: inline-block;
}
.select-box .options-container.active {
max-height: 320px;
opacity: 1;
overflow-y: auto;
}
.select-box .options-container.active + .locale-dropdown-toggle::after {
transform: translateY(-50%) rotateX(180deg);
}
.select-box .options-container::-webkit-scrollbar {
width: 8px;
background: var(--bg-shade-3);
border-radius: 0 5px 5px 0;
}
.select-box .options-container::-webkit-scrollbar-thumb {
background: var(--text-shade-1);
border-radius: 0 5px 5px 0;
}
.select-box .option {
padding: 12px 15px;
cursor: pointer;
border-radius: 5px;
}
.select-box .option:hover {
background: var(--bg-shade-4);
}
.select-box .option:hover .item {
color: white;
}
.select-box label {
cursor: pointer;
}
.select-box .option .radio {
display: none;
}

View File

@@ -1,137 +0,0 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 36px;
border-radius: 10px;
font-family: Poppins, Arial, Helvetica, sans-serif;
}
code.hljs {
padding: 3px 5px;
}
.hljs {
background: var(--bg-shade-0);
color: #d6deeb;
}
.hljs-keyword {
color: var(--accent-shade-2);
font-style: italic;
}
.hljs-built_in {
color: #addb67;
font-style: italic;
}
.hljs-type {
color: #82aaff;
}
.hljs-literal {
color: #ff5874;
}
.hljs-number {
color: #f78c6c;
}
.hljs-regexp {
color: #5ca7e4;
}
.hljs-string {
color: #ecc48d;
}
.hljs-subst {
color: #d3423e;
}
.hljs-symbol {
color: #82aaff;
}
.hljs-class {
color: #ffcb8b;
}
.hljs-function {
color: #82aaff;
}
.hljs-title {
color: #dcdcaa;
font-style: italic;
}
.hljs-params {
color: #7fdbca;
}
.hljs-comment {
color: #637777;
font-style: italic;
}
.hljs-doctag {
color: #7fdbca;
}
.hljs-meta,
.hljs-meta .hljs-keyword {
color: #82aaff;
}
.hljs-meta .hljs-string {
color: #ecc48d;
}
.hljs-section {
color: #82b1ff;
}
.hljs-attr,
.hljs-name,
.hljs-tag {
color: #7fdbca;
}
.hljs-attribute {
color: #80cbc4;
}
.hljs-variable {
color: #addb67;
}
.hljs-bullet {
color: #d9f5dd;
}
.hljs-code {
color: #80cbc4;
}
.hljs-emphasis {
color: #c792ea;
font-style: italic;
}
.hljs-strong {
color: #addb67;
font-weight: 700;
}
.hljs-formula {
color: #c792ea;
}
.hljs-link {
color: #ff869a;
}
.hljs-quote {
color: #697098;
font-style: italic;
}
.hljs-selector-tag {
color: #ff6363;
}
.hljs-selector-id {
color: #fad430;
}
.hljs-selector-class {
color: #addb67;
font-style: italic;
}
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #c792ea;
font-style: italic;
}
.hljs-template-tag {
color: #c792ea;
}
.hljs-template-variable {
color: #addb67;
}
.hljs-addition {
color: #addb67ff;
font-style: italic;
}
.hljs-deletion {
color: #ef535090;
font-style: italic;
}

View File

@@ -1,95 +0,0 @@
.localization-wrapper {
width: 100%;
min-height: calc(100vh - 155px);
margin: 0;
text-align: left;
display: flex;
justify-content: center;
align-items: center;
}
.localization-widget {
max-width: 600px;
width: 100%;
}
.caption {
color: var(--text-shade-1);
max-width: 400px;
margin: 20px 0;
}
.title.dot {
margin: 0;
}
.localization-instr,
.localization-instr:visited {
display: flex;
align-items: center;
color: var(--accent-shade-2);
text-decoration: none;
position: relative;
left: -4px;
width: fit-content;
}
.localization-instr svg {
height: 1.3em;
margin-right: 4px;
}
.localization-form {
padding: 36px;
background-color: var(--bg-shade-0);
border-radius: 12px;
margin-top: 36px;
}
.input-wrapper {
display: flex;
margin-top: 8px;
}
.localization-form input {
appearance: none;
-webkit-appearance: none;
border: 0;
font-family: Poppins, Arial, Helvetica, sans-serif;
font-size: 1rem;
background-color: var(--bg-shade-3);
border: none;
border-radius: 4px 0 0 4px;
padding: 12px 24px;
color: var(--text-shade-1);
width: 20px;
flex: 2 10%;
}
.localization-form input::placeholder {
color: var(--text-shade-0);
}
.localization-form input:focus {
background-color: var(--bg-shade-4);
color: var(--bg-shade-3);
transition: 200ms;
outline: none;
}
.localization-form button {
appearance: none;
-webkit-appearance: none;
border: 0;
border-radius: 0 4px 4px 0;
font-family: Poppins, Arial, Helvetica, sans-serif;
font-size: 1rem;
color: var(--text-shade-3);
padding: 12px 36px;
background: var(--accent-shade-0);
cursor: pointer;
}
footer {
margin-top: auto;
}

View File

@@ -1,132 +0,0 @@
.wrapper {
display: flex;
flex-flow: column;
min-height: 100vh;
}
header {
margin: 35px 0;
}
.account-form-wrapper {
margin: auto;
width: fit-content;
overflow: hidden;
}
form.account {
display: block;
padding: 40px 48px;
background-color: var(--bg-shade-2);
color: var(--text-shade-1);
border-radius: 12px;
width: min(480px, 90vw);
box-sizing: border-box;
}
form.account h2 {
margin: 0;
color: var(--text-shade-3);
}
form.account p {
margin: 12px 0;
}
form.account div {
margin-top: 24px;
}
form.account label {
display: block;
margin-bottom: 6px;
text-transform: uppercase;
font-size: 12px;
}
form.account button {
width: 100%;
background: var(--accent-shade-0);
}
form.account a {
text-decoration: none;
display: block;
color: var(--text-shade-1);
text-align: right;
margin: 6px 0;
width: fit-content;
}
form.account a:hover {
color: var(--text-shade-3);
}
form.account a.pwdreset {
margin-left: auto;
font-size: 14px;
}
form.account a.register {
margin: auto;
margin-top: 18px;
}
@keyframes banner-notice {
0% {
top: -150px;
}
20% {
top: 35px;
}
80% {
top: 35px;
}
100% {
top: -150px;
}
}
.banner-notice {
display: flex;
justify-content: center;
position: fixed;
top: -150px;
width: 100%;
animation: banner-notice 5s;
}
.banner-notice div {
padding: 4px 36px;
border-radius: 5px;
z-index: 3;
}
.banner-notice.error div {
background: var(--red-shade-1);
}
form.account.register {
display: grid;
grid-template-columns: repeat(2, 1fr);
width: min(780px, 90vw);
column-gap: 24px;
margin-bottom: 48px;
}
form.account.register div.h-captcha {
grid-column: 1 / span 2;
display: flex;
justify-content: center;
}
form.account.register p,
form.account.register div.email,
form.account.register div.buttons {
grid-column: 1 / span 2;
}
@media screen and (max-width: 720px) {
form.account.register {
grid-template-columns: 1fr;
}
form.account.register div.h-captcha,
form.account.register p,
form.account.register div.email,
form.account.register div.buttons {
grid-column: unset;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,709 +0,0 @@
html,
body,
div.main-body {
height: 100%;
}
body,
div.main-body,
.miieditor-wrapper {
z-index: -1;
user-select: none;
background: var(--bg-shade-0);
}
svg.logotype {
position: absolute;
width: 120px;
top: 42px;
left: 60px;
}
.miieditor-wrapper {
position: relative;
display: grid;
grid-template-columns: auto auto;
width: 95vw;
max-width: 1920px;
height: 100%;
margin: auto;
gap: 0 120px;
}
.params-wrapper::before {
content: "";
display: block;
position: absolute;
background: var(--bg-shade-1);
border-radius: 100% 0 0 100%;
width: 1300px;
height: 1700px;
top: 50%;
transform: translateY(-50%);
left: -200px;
z-index: -1;
}
.miieditor-wrapper::after {
content: "";
display: block;
position: absolute;
background: radial-gradient(
closest-side,
var(--bg-shade-1) 0%,
rgba(27, 31, 59, 0) 100%
);
width: 200vh;
height: 200vh;
top: -100vh;
left: -100vh;
z-index: -1;
}
.canvas-wrapper {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
canvas#miiCanvas {
width: auto;
height: auto;
transform-origin: center;
transition: transform 200ms, filter 200ms;
}
div.mii-img-wrapper::before {
content: "";
position: absolute;
bottom: -22px;
height: 72px;
width: 100%;
background: radial-gradient(
farthest-side,
var(--bg-shade-2) 0%,
rgba(35, 39, 74, 0) 100%
);
}
div.params-wrapper {
position: relative;
margin: auto;
display: grid;
z-index: 3;
}
div.tabs {
display: grid;
grid-template-columns: repeat(11, 1fr);
width: 100%;
box-sizing: border-box;
background: #0a0c19;
padding: 6px;
gap: 6px;
border-radius: 6px;
margin-bottom: 2rem;
}
div.tabs .tabbtn {
display: flex;
align-items: center;
justify-content: center;
aspect-ratio: 1;
border-radius: 6px;
background: none;
padding: 0;
}
div.tabs .tabbtn::after {
content: "";
display: block;
width: 12px;
height: 12px;
background: url("/assets/images/miieditor.svg");
background-position: calc(var(--assetcol) * -12px) -312px;
transform: scale(2.9);
}
div.tabs .tabbtn:hover,
div.tabs .tabbtn.active {
background: var(--bg-shade-2);
}
div.subtabs {
position: relative;
display: flex;
width: fit-content;
}
div.subtabs .subtabbtn {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 60px;
border-radius: 6px;
background: none;
padding: 0;
color: var(--text-shade-3);
aspect-ratio: 1;
}
div.subtabs .subtabbtn::after {
content: "";
display: block;
width: 12px;
height: 12px;
background: url("/assets/images/miieditor.svg");
background-position: calc(var(--assetcol) * -12px) -324px;
transform: scale(2.9);
}
div.subtabs .subtabbtn.active::before,
div.subtabs .subtabbtn.active:hover::before {
content: "";
position: absolute;
bottom: -2px;
left: 5%;
width: 90%;
height: 5px;
background: var(--accent-shade-1);
border-radius: 6px;
}
.has-sliders {
grid-template-columns: 60px auto;
gap: 12px;
}
.has-sliders label {
position: relative;
display: flex;
width: 60px;
height: 60px;
align-items: center;
justify-content: center;
}
.has-sliders label::after {
content: "";
display: block;
width: 16px;
height: 16px;
background: url("/assets/images/miieditor.svg");
background-position: calc(var(--assetcol) * -16px) -336px;
transform: scale(3);
}
.has-textinput {
grid-template-columns: 1fr 1fr;
grid-template-rows: auto;
grid-auto-rows: auto;
gap: 24px;
}
.has-textinput label {
display: block;
margin-bottom: 6px;
text-transform: uppercase;
font-size: 12px;
}
.has-textinput .icons {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
}
.has-textinput .icons input[type="checkbox"] {
box-sizing: border-box;
margin: 0;
height: 49px;
width: 49px;
}
input[type="checkbox"]#allowCopying:checked {
background: no-repeat center/80% url(../images/copy.svg), var(--accent-shade-0);
}
input[type="checkbox"]#disableSharing:checked {
background: no-repeat center/80% url(../images/share.svg), var(--accent-shade-0);
}
input[type="checkbox"]#favorite:checked {
background: no-repeat center/80% url(../images/star.svg), var(--accent-shade-0);
}
form.params {
grid-template-columns: repeat(2, auto);
height: 618px;
width: 582px;
}
form.params .tab {
display: none;
gap: 4rem 0;
}
form.params .tab.active {
display: grid;
}
fieldset,
fieldset.has-subpages .subpage {
appearance: none;
border: none;
padding: 0;
margin: 0;
display: none;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 1fr);
gap: 18px;
width: 100%;
height: fit-content;
}
fieldset.active {
display: grid;
}
fieldset input[type="radio"] {
display: none;
}
fieldset input[type="radio"] + label {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 18px;
background: var(--bg-shade-3);
width: 100%;
aspect-ratio: 1;
}
fieldset.has-subpages.active {
display: block;
}
fieldset.has-subpages .subpage.active {
display: grid;
}
fieldset:not(.color, #favoriteColor) input[type="radio"] + label::after {
content: "";
display: block;
width: 24px;
height: 24px;
background: url("/assets/images/miieditor.svg");
background-position: calc(
((var(--assetcol) + (var(--subpage, 0) * 12)) * -24px)
)
calc(var(--assetrow) * -24px);
transform: scale(4.5);
}
fieldset input[type="radio"]:checked + label {
background: var(--bg-shade-4);
box-shadow: inset 0 0 0 4px var(--accent-shade-1);
}
fieldset.color input[type="radio"]:checked + label,
fieldset#favoriteColor input[type="radio"]:checked + label {
box-shadow: inset 0 0 0 4px var(--accent-shade-1),
inset 0 0 0 6px var(--bg-shade-1);
}
input[type="range"].invert {
direction: rtl;
}
.pagination {
display: flex;
width: max-content;
height: fit-content;
grid-column: 1 / span 4;
grid-row: 4;
margin-left: auto;
align-items: center;
font-size: 18px;
color: var(--text-shade-1);
}
.pagination .current-page-index {
display: inline-block;
font-weight: bold;
color: var(--text-shade-3);
width: 18px;
margin-right: 0.5ch;
text-align: right;
}
.page-btn {
appearance: none;
border: none;
background: none;
cursor: pointer;
padding: 0;
margin-left: 8px;
}
.page-btn:hover {
background: none;
}
.page-btn:hover svg path {
fill: var(--accent-shade-3);
}
.page-btn svg {
height: 36px;
margin: 6px;
}
.page-btn.disabled {
pointer-events: none;
}
.page-btn.disabled svg path {
fill: var(--bg-shade-3);
}
.tab#saveTab {
gap: 2rem 0;
}
.tab#saveTab p.save-prompt {
margin-bottom: 0;
text-align: center;
}
.mii-comparison-animation-wrapper {
position: relative;
height: fit-content;
}
.mii-comparison {
position: relative;
display: grid;
grid-template-columns: repeat(3, auto);
align-items: center;
width: 100%;
}
.mii-comparison.confirmed {
position: absolute;
height: 100%;
top: 0;
left: 0;
opacity: 0;
overflow: hidden;
}
.mii-comparison img {
display: block;
width: 100%;
aspect-ratio: 1;
background: var(--bg-shade-3);
border-radius: 24px;
}
.mii-comparison .new-mii-wrapper {
position: relative;
transition: right 500ms, transform 500ms;
right: 0;
}
.mii-comparison .new-mii-wrapper::after {
position: absolute;
content: "";
display: block;
box-shadow: inset 0 0 0 8px var(--accent-shade-1);
border-radius: 24px;
margin: 0;
right: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 2;
}
.mii-comparison svg {
width: 72px;
height: 72px;
}
.mii-comparison svg path {
fill: var(--accent-shade-1);
}
.fade-in {
animation: fadeIn 0.25s forwards;
}
.fade-out {
animation: fadeOut 0.5s forwards;
}
.mii-comparison div.new-mii-wrapper.centered-mii-img {
position: absolute;
right: 50%;
transform: translateX(50%);
height: 100%;
aspect-ratio: 1;
width: auto;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
button * {
pointer-events: none;
}
@media screen and (max-width: 1400px) {
form.params {
height: 562px;
width: 512px;
}
fieldset,
fieldset.has-subpages .subpage {
gap: 12px;
}
div.params-wrapper {
margin-right: 24px;
}
.params-wrapper::before {
left: -150px;
}
div.tabs {
padding: 4px;
gap: 2px;
}
}
@media screen and (max-width: 1280px) {
form.params {
height: 492px;
width: 480px;
}
fieldset,
fieldset.has-subpages .subpage {
gap: 8px;
}
div.params-wrapper {
margin-right: 24px;
}
.params-wrapper::before {
left: -150px;
}
fieldset:not(.color, #favoriteColor) input[type="radio"] + label::after {
transform: scale(4);
}
div.subtabs .subtabbtn::after,
div.tabs .tabbtn::after {
transform: scale(2.4);
}
div.subtabs .subtabbtn {
width: 48px;
}
.params-wrapper::before {
left: -100px;
}
div.tabs {
margin-bottom: 1rem;
}
form.params .tab {
gap: 2rem 0;
}
}
@media screen and (max-width: 1120px) {
form.params {
height: 444px;
width: 420px;
}
fieldset,
fieldset.has-subpages .subpage {
gap: 6px;
}
}
@media screen and (max-width: 1080px) {
.canvas-wrapper {
height: calc(100% - 12px);
}
svg.logotype {
left: 0;
}
svg.logotype text#Pretendo {
display: none;
}
.miieditor-wrapper {
grid-template-columns: auto;
grid-template-rows: auto fit-content(100%);
margin: auto;
max-width: 360px;
width: 90vw;
}
div.params-wrapper {
width: 100%;
margin: 0 auto;
display: flex;
flex-flow: column;
}
div.tabs,
div.subtabs {
order: 2;
margin-top: 1rem;
}
fieldset {
order: 1;
}
form.params {
width: 100%;
height: 100%;
order: 1;
}
fieldset input[type="radio"] + label {
width: 100%;
height: auto;
border-radius: 8px;
aspect-ratio: 1;
}
fieldset:not(.color, #favoriteColor) input[type="radio"] + label::after {
transform: scale(3.5);
}
.has-sliders {
overflow-y: auto;
overflow-x: hidden;
height: 100%;
gap: 2px 6px;
scrollbar-width: thin;
scrollbar-color: var(--text-shade-1) var(--bg-shade-3);
}
.has-sliders::-webkit-scrollbar {
width: 12px;
background: var(--bg-shade-3);
border-radius: 9px;
}
.has-sliders::-webkit-scrollbar-thumb {
background: var(--text-shade-1);
border-radius: 9px;
}
.params-wrapper::before {
top: -12px;
left: -100vw;
width: 300vw;
border-radius: 0;
background: var(--bg-shade-2);
transform: none;
}
fieldset,
fieldset.has-subpages .subpage {
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr) 48px;
width: 100%;
gap: 8px;
}
.pagination {
grid-column: 1 / span 4;
grid-row: 4;
}
fieldset:not(.has-sliders, .has-textinput) {
position: relative;
margin-bottom: -60px;
}
div.tabs {
margin-bottom: 1rem;
}
form.params .tab {
gap: 0;
height: 100%;
}
div.subtabs {
z-index: 4;
}
form.params {
grid-template-columns: repeat(2, auto);
}
div.tabs .tabbtn::after,
div.subtabs .subtabbtn::after,
.has-sliders label::after {
transform: scale(2);
}
div.subtabs .subtabbtn {
width: 48px;
height: 48px;
}
}
@media screen and (max-width: 424px) {
fieldset:not(.color, #favoriteColor) input[type="radio"] + label::after {
transform: scale(2.8);
}
}
@media screen and (max-width: 396px) {
div.tabs .tabbtn::after,
div.subtabs .subtabbtn::after,
.has-sliders label::after {
transform: scale(1.5);
}
div.tabs .tabbtn {
width: 24px;
height: 24px;
}
div.subtabs .subtabbtn {
width: 36px;
height: 36px;
}
div.pagination {
transform: scale(0.7);
transform-origin: right;
}
.has-textinput {
grid-template-columns: 1fr;
}
}
@media screen and (max-width: 360px) {
fieldset,
fieldset.has-subpages .subpage {
gap: 4px;
}
fieldset input[type="radio"]:checked + label {
box-shadow: inset 0 0 0 3px var(--accent-shade-1);
}
}
@media screen and (max-width: 344px) {
fieldset:not(.color, #favoriteColor) input[type="radio"] + label::after {
transform: scale(2);
}
}
@media screen and (max-width: 320px) {
div.tabs .tabbtn {
width: 18px;
height: 18px;
}
div.tabs .tabbtn::after {
transform: scale(1.25);
}
}

View File

@@ -1,197 +0,0 @@
footer {
width: 100%;
display: grid;
grid-template-columns: repeat(3, fit-content(100%)) 1fr;
gap: min(48px, 7.7vw);
color: var(--text-shade-1);
margin-top: 120px;
position: relative;
padding: 60px 0;
}
footer::after {
content: "";
width: 400vw;
height: 100%;
position: absolute;
top: 0;
left: -50vw;
background: var(--bg-shade-0);
z-index: -1;
}
footer div {
display: flex;
flex-flow: column;
width: fit-content;
}
footer svg.logotype {
height: 56px;
margin: -10px 0 24px -10px;
}
footer p {
margin: 0;
}
footer h1 {
font-size: 20px;
margin-top: 0;
color: var(--text-shade-3);
}
footer a {
color: var(--text-shade-1);
text-decoration: none;
width: fit-content;
}
footer a:hover {
color: var(--text-shade-3);
text-decoration: underline;
}
footer div.discord-server-card-wrapper {
z-index: 2;
justify-self: end;
position: relative;
}
footer div.discord-server-card {
background: var(--bg-shade-2);
border-radius: 12px;
padding: 30px 90px 30px 36px;
}
footer div.discord-server-card h1 {
font-size: 25px;
margin: 0;
}
footer div.discord-server-card h2 {
color: var(--text-shade-3);
font-size: 22px;
margin: 0;
}
footer div.discord-server-card a {
display: flex;
align-items: center;
color: var(--accent-shade-3);
font-size: 22px;
text-decoration: none;
width: fit-content;
margin-left: -2px;
margin-top: 12px;
}
footer div.discord-server-card a:hover {
text-decoration: underline;
}
footer div.discord-server-card svg {
height: 24px;
stroke-width: 3px;
margin-right: 4px;
}
footer div.discord-server-card-wrapper .bandwidth-raccoon-wrapper {
position: absolute;
top: -120px;
right: 0px;
z-index: -1;
}
footer div.discord-server-card-wrapper img.bandwidth-raccoon {
width: 192px;
height: 192px;
cursor: pointer;
transform: none;
transition: transform 150ms;
}
footer div.bandwidth-raccoon-wrapper.speak img.bandwidth-raccoon {
transform: rotate(12deg) translateY(-12px);
}
footer .bandwidth-raccoon-wrapper .text-bubble {
position: absolute;
right: 0;
margin: 0 auto;
top: -24px;
max-width: min(200%, 90vw);
width: max-content;
background: var(--bg-shade-3);
padding: 18px;
align-self: center;
margin-bottom: 12px;
border-radius: 12px;
box-sizing: border-box;
transform: translateY(-100%);
opacity: 0;
pointer-events: none;
transition: opacity 250ms;
}
footer .bandwidth-raccoon-wrapper.speak .text-bubble {
opacity: 1;
}
footer .bandwidth-raccoon-wrapper .text-bubble:after {
content: "";
position: absolute;
display: block;
width: 0;
z-index: 1;
border-style: solid;
border-color: var(--bg-shade-3) transparent;
border-width: 12px 12px 0;
bottom: -9px;
right: 60px;
margin-left: -10px;
}
@media screen and (max-width: 900px) {
footer {
margin-top: 100px;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, fit-content(100%));
}
footer div {
justify-self: center;
}
footer div.discord-server-card-wrapper {
grid-column: 1 / span 4;
width: 100%;
justify-self: normal;
}
footer div.discord-server-card-wrapper::before {
content: "";
width: 100%;
height: 60px;
position: absolute;
bottom: -60px;
left: 0;
background: var(--bg-shade-0);
z-index: 2;
}
footer div.discord-server-card-wrapper .bandwidth-raccoon-wrapper {
bottom: -72px;
top: unset;
z-index: 0;
}
footer div.discord-server-card {
box-sizing: border-box;
width: 100%;
overflow: hidden;
}
}
@media screen and (max-width: 580px) {
footer {
grid-template-columns: 1fr;
grid-template-rows: repeat(4, fit-content(100%));
}
footer div {
justify-self: start;
}
footer div.discord-server-card-wrapper {
grid-column: 1 / span 1;
}
footer div.discord-server-card {
padding: 30px;
overflow: visible;
}
footer div.discord-server-card-wrapper .bandwidth-raccoon-wrapper {
bottom: unset;
top: -120px;
z-index: -1;
}
}
@media screen and (max-width: 320px) {
footer div.discord-server-card-wrapper .bandwidth-raccoon-wrapper {
display: none;
}
}

View File

@@ -1,470 +0,0 @@
header {
position: fixed;
top: 0;
left: 2.5%;
display: flex;
align-items: center;
width: 95%;
margin-top: 35px;
z-index: 60;
transition: box-shadow 180ms, background 180ms;
}
header * {
z-index: 1;
}
header::before {
content: "";
position: absolute;
top: -35px;
left: -10vw;
width: 120vw;
height: calc(100% + 35px + 35px);
background: rgba(27, 31, 59, 0.98);
transition: background 180ms;
}
header.transparent,
header.transparent::before {
background: rgba(27, 31, 59, 0);
}
header.dropdown-active {
background: rgba(27, 31, 59, 0.98);
box-shadow: 0 0 0 600vw rgba(27, 31, 59, 0.8);
}
header .dropdown-arrow {
opacity: 0;
position: absolute;
width: 0;
border-style: solid;
border-color: var(--bg-shade-3) transparent;
border-width: 0 14px 14px;
bottom: -26px;
margin-left: -10px;
margin-bottom: -10px;
transition: left 180ms, margin-bottom 180ms, opacity 180ms;
pointer-events: none;
}
header.dropdown-active .dropdown-arrow {
opacity: 1;
display: block;
margin-bottom: 0;
}
header a {
text-decoration: none;
}
header .logo-link,
header .logo-link svg {
display: block;
}
header div.left-section {
display: flex;
flex-flow: row nowrap;
}
header nav {
position: relative;
display: flex;
flex-flow: row nowrap;
align-items: center;
margin-left: 40px;
}
header button.dropdown-button#mobile-button {
display: none;
background: none;
padding: 0;
margin-right: 12px;
transition: transform 200ms;
}
header button.dropdown-button#mobile-button.active {
transform: rotate(90deg);
}
header div.dropdown-button-wrapper {
position: relative;
display: flex;
flex-flow: row nowrap;
}
/* these are safezones where the dropdown will not close */
header div.dropdown-button-wrapper::before {
content: "";
position: absolute;
top: -16px;
bottom: 100%;
left: 0;
right: -12px;
}
header div.dropdown-button-wrapper::after {
content: "";
position: absolute;
top: 100%;
bottom: -32px;
left: 0;
right: -12px;
}
header nav button {
background: none;
color: var(--text-shade-1);
margin: 0 17px;
padding: 0;
}
header nav button:hover,
header nav button.active {
background: none;
color: var(--text-shade-3);
}
header nav a.donate button {
display: grid;
grid-auto-flow: column;
align-items: center;
gap: 4px;
font-weight: bold;
background: #332b61;
color: var(--accent-shade-3);
padding: 2px 12px;
border-radius: 24px;
}
header nav a.donate button svg {
height: 1rem;
width: 1rem;
}
header nav a.donate button:hover {
background: var(--accent-shade-0);
color: #fff;
}
header nav a.donate button.dropdown-button::after {
content: "";
display: inline-block;
align-items: center;
width: 16px;
height: 8px;
bottom: 0;
margin-left: 0.3rem;
background: no-repeat center url("/assets/images/down-arrow.svg");
filter: brightness(0) invert(78%) sepia(2%) saturate(5488%) hue-rotate(197deg)
brightness(88%) contrast(93%);
transition: transform 100ms;
}
header nav button.dropdown-button.active::after {
transform: scaleY(-1);
filter: none;
}
header div.dropdown {
position: absolute;
top: 100%;
margin-top: 24px;
left: 0;
display: block;
background: var(--bg-shade-3);
border-radius: 8px;
width: 420px;
height: 0;
overflow-y: hidden;
transition: height 180ms;
}
header div.dropdown * {
box-sizing: border-box;
}
header div.dropdown-content {
position: absolute;
top: 0;
width: 100%;
opacity: 0;
pointer-events: none;
transition: opacity 180ms;
}
header div.dropdown-content.show {
opacity: 1;
pointer-events: auto;
}
header div.dropdown .top {
padding: 32px 18px;
}
header div.dropdown .top a {
position: relative;
display: grid;
grid-auto-flow: column;
gap: 16px;
justify-content: start;
align-items: center;
color: var(--text-shade-1);
padding: 16px;
border-radius: 8px;
}
header div.dropdown .top a .icon {
background: var(--bg-shade-2);
color: var(--accent-shade-3);
height: 56px;
width: 56px;
border-radius: 8px;
}
header div.dropdown .top a:hover .icon {
background: #151b44;
color: var(--accent-shade-1);
}
header div.dropdown .top a .icon svg {
width: 32px;
height: 32px;
margin: 12px;
}
header div.dropdown .top a .title {
margin: 0;
font-weight: bold;
color: var(--text-shade-3);
}
header div.dropdown .top a .caption {
margin: 0;
}
header div.dropdown .top a:hover {
background: var(--bg-shade-2-5);
}
header div.dropdown .top a:hover::after {
content: "";
position: absolute;
top: 0;
right: 24px;
width: 24px;
height: 100%;
background: no-repeat center url("/assets/images/arrow-right.svg");
/* garbage to make it look the same color */
filter: brightness(0) invert(60%) sepia(70%) saturate(453%) hue-rotate(208deg)
brightness(113%) contrast(97%);
}
header div.dropdown .top a:hover .title {
color: var(--accent-shade-3);
}
header div.dropdown .bottom {
display: grid;
grid-auto-flow: column;
justify-content: center;
gap: 24px;
background: var(--bg-shade-3-5);
padding: 22px;
width: 100%;
box-sizing: border-box;
}
header div.dropdown .bottom a {
width: 48px;
height: 48px;
background: var(--bg-shade-3);
color: var(--text-shade-3);
border-radius: 100%;
display: flex;
justify-content: center;
align-items: center;
}
header div.dropdown .bottom a:hover {
background: var(--bg-shade-2);
}
header div.dropdown .bottom a svg {
width: 24px;
height: auto;
}
header div.dropdown .top a.show-on-mobile {
display: none;
}
header .right-section {
display: grid;
grid-auto-flow: column;
gap: 24px;
margin-left: auto;
z-index: 2;
color: var(--text-shade-1);
}
header .locale-dropdown-toggle {
width: fit-content;
height: 24px;
padding: 0;
margin: auto;
transition: color 150ms;
cursor: pointer;
}
header .locale-dropdown-toggle:hover,
header .locale-dropdown-toggle.active {
color: var(--text-shade-3);
}
header .user-widget-wrapper {
height: auto;
}
header .user-widget-wrapper a.login-link {
color: var(--text-shade-1);
text-decoration: none;
display: block;
height: 32px;
transition: color 150ms;
}
header .user-widget-wrapper a.login-link:hover {
color: var(--text-shade-3);
}
header .user-widget-wrapper.logged-in {
position: relative;
width: 32px;
height: 32px;
}
header .user-widget-wrapper.logged-in .user-widget-toggle {
width: 32px;
height: 32px;
background: var(--text-shade-0);
border-radius: 50%;
overflow: hidden;
cursor: pointer;
}
header .user-widget-wrapper .user-widget-toggle img,
header .user-widget .user-avatar img {
width: 100%;
height: 100%;
}
header .user-widget {
max-height: 0;
overflow: hidden;
box-sizing: border-box;
transition: max-height 300ms, padding 200ms, opacity 150ms;
position: absolute;
right: 0;
top: 48px;
padding: 0;
background: var(--bg-shade-2);
border-radius: 8px;
text-align: center;
opacity: 0;
box-shadow: 0 0 10px -2px var(--bg-shade-0);
}
header .user-widget.active {
max-height: 100vh;
padding: 36px;
opacity: 1;
}
header .user-widget .user-avatar {
width: 128px;
height: 128px;
margin: auto;
background: var(--text-shade-0);
border-radius: 50%;
overflow: hidden;
}
header .user-widget .user-info {
margin-top: 12px;
}
header .user-widget .user-info .mii-name {
color: var(--text-shade-3);
}
header .user-widget .buttons {
margin-top: 12px;
}
header .user-widget .button {
margin-top: 12px;
width: 100%;
padding: 8px 60px;
cursor: pointer;
word-break: keep-all;
}
header .user-widget .button.logout {
background: var(--bg-shade-3);
color: var(--text-shade-3);
}
@media screen and (max-width: 900px) {
header {
position: relative;
justify-content: flex-end;
width: 90%;
left: 5%;
}
header .hide-on-mobile {
display: none !important;
}
header button.dropdown-button#mobile-button {
display: block;
}
header .left-section {
margin-right: auto;
}
header .right-section {
margin-left: 24px;
}
header nav a.donate button {
margin: 0;
}
header div.dropdown {
left: unset;
right: -104px;
width: 90vw;
}
header div.dropdown .top {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
@media screen and (max-width: 600px) {
header div.dropdown .top {
grid-template-columns: 1fr;
}
header div.dropdown .top {
padding: 16px 9px;
}
}
@media screen and (max-width: 500px) {
header nav a.donate button span {
display: none;
}
header nav a.donate button {
padding: 6px;
}
}
@media screen and (max-width: 420px) {
header nav a.donate button {
display: none;
}
header .right-section {
margin-left: 0;
}
header div.dropdown {
right: -80px;
}
header div.dropdown .top a {
padding: 8px;
}
header div.dropdown .top a .icon {
height: 40px;
width: 40px;
}
header div.dropdown .top a .icon svg {
width: 24px;
height: 24px;
margin: 8px;
}
}
@media screen and (max-width: 330px) {
header .logo-link svg text {
display: none;
}
header .logo-link svg {
width: 39.876px;
}
header .logo-link {
margin-right: 6px;
}
}

View File

@@ -1,13 +0,0 @@
/*
MOVE PROGRESS CSS HERE
*/
#quick-nav a {
color: var(--text-shade-1);
text-decoration: none;
width: fit-content;
}
#quick-nav a:hover {
color: var(--text-shade-3);
text-decoration: underline;
}

View File

@@ -1,132 +0,0 @@
.wrapper {
display: flex;
flex-flow: column;
min-height: 100vh;
}
header {
margin: 35px 0;
}
.account-form-wrapper {
margin: auto;
width: fit-content;
overflow: hidden;
}
form.account {
display: block;
padding: 40px 48px;
background-color: var(--bg-shade-2);
color: var(--text-shade-1);
border-radius: 12px;
width: min(480px, 90vw);
box-sizing: border-box;
}
form.account h2 {
margin: 0;
color: var(--text-shade-3);
}
form.account p {
margin: 12px 0;
}
form.account div {
margin-top: 24px;
}
form.account label {
display: block;
margin-bottom: 6px;
text-transform: uppercase;
font-size: 12px;
}
form.account button {
width: 100%;
background: var(--accent-shade-0);
}
form.account a {
text-decoration: none;
display: block;
color: var(--text-shade-1);
text-align: right;
margin: 6px 0;
width: fit-content;
}
form.account a:hover {
color: var(--text-shade-3);
}
form.account a.pwdreset {
margin-left: auto;
font-size: 14px;
}
form.account a.register {
margin: auto;
margin-top: 18px;
}
@keyframes banner-notice {
0% {
top: -150px;
}
20% {
top: 35px;
}
80% {
top: 35px;
}
100% {
top: -150px;
}
}
.banner-notice {
display: flex;
justify-content: center;
position: fixed;
top: -150px;
width: 100%;
animation: banner-notice 5s;
}
.banner-notice div {
padding: 4px 36px;
border-radius: 5px;
z-index: 3;
}
.banner-notice.success div {
background: var(--green-shade-0);
}
form.account.register {
display: grid;
grid-template-columns: repeat(2, 1fr);
width: min(780px, 90vw);
column-gap: 24px;
margin-bottom: 48px;
}
form.account.register div.h-captcha {
grid-column: 1 / span 2;
display: flex;
justify-content: center;
}
form.account.register p,
form.account.register div.email,
form.account.register div.buttons {
grid-column: 1 / span 2;
}
@media screen and (max-width: 720px) {
form.account.register {
grid-template-columns: 1fr;
}
form.account.register div.h-captcha,
form.account.register p,
form.account.register div.email,
form.account.register div.buttons {
grid-column: unset;
}
}

View File

@@ -1,310 +0,0 @@
.wrapper {
display: flex;
justify-content: center;
text-align: center;
min-height: 100vh;
}
.wrapper::before {
position: absolute;
top: -800px;
content: "";
background: var(--bg-shade-0);
border-radius: 100%;
width: 1600px;
height: 1400px;
}
.back-arrow {
position: absolute;
display: flex;
justify-content: center;
top: 36px;
left: max(calc((100vw - 1590px) / 2), 2.5vw);
padding: 6px 10px;
background: var(--bg-shade-3);
border-radius: 24px;
transition: filter 150ms;
text-decoration: none;
color: var(--text-shade-3);
z-index: 5;
}
.back-arrow:hover {
filter: brightness(1.5)
}
.back-arrow svg {
width: 24px;
height: 24px;
}
.back-arrow span {
margin: 0 4px;
}
.account-form-wrapper {
display: flex;
flex-flow: column;
width: min(1200px, 100%);
color: var(--text-shade-1);
margin: 0 auto 48px;
z-index: 1;
}
.account-form-wrapper .logotype {
margin: 36px auto 0;
width: fit-content;
}
h1.title {
color: var(--text-shade-3);
}
p.caption {
width: min(100%, 500px);
margin: 0 auto 36px;
}
.account-form-wrapper .progress-bar-wrapper {
justify-content: center;
width: min(100%, 500px);
margin: 0 auto 72px;
padding: 24px;
border-radius: 6px;
background: var(--bg-shade-2);
box-sizing: border-box;
}
.account-form-wrapper .progress-bar-wrapper p {
text-align: left;
margin-bottom: 0;
}
.account-form-wrapper .progress-bar-wrapper p span {
color: var(--text-shade-3);
font-weight: 600;
}
.account-form-wrapper .progress-bar {
height: 8px;
border-radius: 4px;
margin-top: 0;
}
form {
box-sizing: border-box;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.3rem;
}
form .tier-radio {
display: none;
}
form .tier-radio:checked + label::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
box-shadow: inset 0 0 0 4px var(--accent-shade-1);
border-radius: 10px;
}
form .tier-radio:checked + label::after {
content: url(/assets/images/check.svg);
display: flex;
justify-content: center;
background: var(--accent-shade-1);
width: 24px;
height: 24px;
border-radius: 100%;
position: absolute;
top: -16px;
right: -16px;
padding: 6px;
}
label.tier {
display: flex;
flex-flow: column;
position: relative;
border-radius: 10px;
align-items: center;
padding-top: calc(50px + 1rem);
background: var(--bg-shade-3);
cursor: pointer;
transition: all 150ms;
margin-top: 50px;
text-align: center;
}
label.tier p {
margin: 0;
margin-bottom: 0.5rem;
}
label.tier .tier-thumbnail {
height: 100px;
width: 100px;
display: flex;
align-items: center;
overflow: hidden;
border-radius: 8px;
position: absolute;
top: -50px;
z-index: 2;
background: var(--bg-shade-4);
padding: 8px;
box-sizing: border-box;
}
form .tier-radio:checked + label .tier-thumbnail::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
box-shadow: inset 0 0 0 4px var(--accent-shade-1);
border-radius: 8px;
}
label.tier .tier-text {
display: flex;
flex-flow: column;
margin-bottom: auto;
}
label.tier .tier-name {
color: var(--text-shade-3);
font-weight: bold;
font-size: 1.2rem;
}
label.tier .tier-perks {
text-align: left;
width: 70%;
margin: 24px auto 48px;
}
label.tier .tier-perks div {
display: grid;
grid-template-columns: 16px auto;
gap: 8px;
}
label.tier .tier-perks svg {
stroke-width: 5px;
stroke: var(--green-shade-1);
stroke-linecap: square;
width: 16px;
height: 16px;
vertical-align: top;
margin-top: 0.5ex;
}
label.tier p.price {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
background: var(--bg-shade-4);
margin: 0;
padding: 1.5rem 1rem;
box-sizing: border-box;
border-radius: 0 0 10px 10px;
}
label.tier p.price span {
font-size: 2rem;
color: var(--text-shade-3);
font-weight: bold;
margin-right: 0.5ch;
}
form .button-wrapper {
grid-column: 2 / span 1;
position: relative;
margin-top: 24px;
}
button {
appearance: none;
-webkit-appearance: none;
display: block;
font-family: Poppins, Arial, Helvetica, sans-serif;
font-size: 1rem;
height: fit-content;
background: var(--accent-shade-0);
border: none;
border-radius: 4px;
padding: 12px;
color: var(--text-shade-3);
width: 100%;
transition: filter 300ms;
pointer-events: all;
cursor: pointer;
filter: none;
}
form button.disabled {
pointer-events: none;
filter: brightness(0.75) saturate(0.75); /* not using opacity here 'cause in the mobile layout you would see the cards under it */
cursor: default;
}
form button.unsubscribe {
position: relative;
background: none;
color: var(--text-shade-1);
margin-top: 12px;
padding: 0;
}
form button.unsubscribe.hidden {
position: absolute;
top: 0;
pointer-events: none;
z-index: -1;
}
form button.unsubscribe:hover {
color: var(--text-shade-3);
}
@media screen and (max-width: 900px) {
.account-form-wrapper {
width: min(500px, 100%);
margin-bottom: 172px;
}
form {
grid-template-columns: 1fr;
gap: 2.4rem;
}
form button {
position: relative;
width: 100%;
}
form .button-wrapper {
grid-column: 1 / span 1;
position: fixed;
bottom: 24px;
width: min(500px, 90%);
z-index: 5;
}
form .button-wrapper::before {
content: "";
position: absolute;
top: -24px;
left: -100vw;
width: 200vw;
height: 300%;
background: var(--bg-shade-0);
}
}
@media screen and (max-width: 380px) {
label.tier .tier-perks {
width: 80%;
}
.back-arrow {
padding: 6px;
}
.back-arrow span {
display: none;
}
}

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>

Before

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="#fff" d="M5 19h1.4l8.625-8.625l-1.4-1.4L5 17.6ZM19.3 8.925l-4.25-4.2l1.4-1.4q.575-.575 1.413-.575q.837 0 1.412.575l1.4 1.4q.575.575.6 1.388q.025.812-.55 1.387ZM4 21q-.425 0-.712-.288Q3 20.425 3 20v-2.825q0-.2.075-.387q.075-.188.225-.338l10.3-10.3l4.25 4.25l-10.3 10.3q-.15.15-.337.225q-.188.075-.388.075ZM14.325 9.675l-.7-.7l1.4 1.4Z"/></svg>

Before

Width:  |  Height:  |  Size: 438 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 571 KiB

View File

@@ -1,55 +0,0 @@
const updateServerEnvironmentForm = document.querySelector('form.server-selection');
const serverSelectionSaveButton = document.querySelector('#save-server-selection');
const editSettingsModal = document.querySelector('.modal-wrapper#edit-settings');
const editSettingsModalButtonClose = document.getElementById('editSettingsCloseButton');
editSettingsModalButtonClose?.addEventListener('click', () => {
editSettingsModal.classList.add('hidden');
});
document.addEventListener('click', event => {
if (event.target.classList.contains('edit')) {
event.preventDefault();
editSettingsModal.classList.remove('hidden');
}
});
serverSelectionSaveButton.addEventListener('click', event => {
event.preventDefault();
const checkedInput = updateServerEnvironmentForm.querySelector('input:checked');
try {
const tokenType = document.cookie.split('; ').find(row => row.startsWith('token_type=')).split('=')[1];
const accessToken = document.cookie.split('; ').find(row => row.startsWith('access_token=')).split('=')[1];
fetch('https://api.pretendo.cc/v1/user', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `${tokenType} ${decodeURIComponent(accessToken)}`
},
body: JSON.stringify({
environment: checkedInput.value
})
})
.then(response => response.json())
.then(json => {
if (!json.error) {
// TODO - Make this prettier
alert('Saved server environment');
} else {
console.log(json.error);
alert('Failed to server environment');
}
})
.catch(error => {
console.log(error);
// TODO - Make this prettier
alert('Failed to server environment');
});
} catch (error) {
alert(error);
}
});

View File

@@ -1,7 +0,0 @@
const openSidebarBtn = document.querySelector('#openSidebar');
const content = document.querySelector('div.content');
openSidebarBtn.addEventListener('click', function() {
const sidebar = document.querySelector('.sidebar');
sidebar.classList.toggle('open');
content.classList.toggle('open-sidebar');
});

View File

@@ -1,198 +0,0 @@
/* eslint-disable no-undef, no-unused-vars */
const header = document.querySelector('header');
const dropdownButtonWrapper = document.querySelector('.dropdown-button-wrapper');
const dropdown = document.querySelector('header div.dropdown');
const allDropdownButtons = document.querySelectorAll('button.dropdown-button');
const desktopDropdownBtns = document.querySelectorAll('header .dropdown-button-wrapper button.dropdown-button');
const mobileDropdownBtn = document.querySelector('.dropdown-button#mobile-button');
let dropdownContent;
function isDropdownOpen() {
return header.classList.contains('dropdown-active');
}
function closeDropdown() {
dropdown.style.height = '0';
header.classList.remove('dropdown-active');
// deselect all buttons
allDropdownButtons.forEach((button) => {
button.classList.remove('active');
});
}
window.addEventListener('resize', () => {
if (isDropdownOpen() && dropdownContent) {
// set the dropdown height to the height of the content
dropdown.style.height = `${dropdownContent.offsetHeight}px`;
}
});
function navbarDropdownHandler(buttonID) {
const allDropdownContents = dropdown.querySelectorAll('div.dropdown-content');
dropdownContent = document.querySelector(`.dropdown-content#${buttonID}-dropdown-content`);
const dropdownButton = document.querySelector(`button.dropdown-button#${buttonID}-button`);
const dropdownArrow = document.querySelector('.dropdown-arrow#navbar-dropdown-arrow');
// if on mobile, reclicking the button should close the dropdown
if (buttonID === 'mobile' && dropdownButton.classList.contains('active')) {
closeDropdown();
return;
}
// hide all contents
allDropdownContents.forEach((content) => {
content.classList.remove('show');
});
// deselect all buttons
allDropdownButtons.forEach((button) => {
button.classList.remove('active');
});
// show the content of the clicked button
dropdownContent.classList.add('show');
// select the clicked button
dropdownButton.classList.add('active');
// set the dropdown height to the height of the content
dropdown.style.height = `${dropdownContent.offsetHeight}px`;
// move the arrow to the selected button
dropdownArrow.style.left = `${dropdownButton.offsetLeft + dropdownButton.offsetWidth / 2 - 5}px`;
// dim the rest of the page
header.classList.add('dropdown-active');
}
const dropdownAnchors = document.querySelectorAll('.dropdown-content a');
dropdownAnchors.forEach((a) => {
a.addEventListener('click', () => {
closeDropdown();
});
});
// make the header background transparent if near the top of the page
function makeHeaderBackgroundTransparent() {
if(window.pageYOffset < 100) {
header.classList.add('transparent');
} else {
header.classList.remove('transparent');
}
}
makeHeaderBackgroundTransparent();
window.addEventListener('scroll', () => {
makeHeaderBackgroundTransparent();
});
desktopDropdownBtns.forEach((btn) => {
[ 'click', 'mouseover' ].forEach((event) => {
btn.addEventListener(event, () => {
const id = btn.id.replace('-button', '');
navbarDropdownHandler(id);
});
});
});
mobileDropdownBtn.addEventListener('click', () => {
const id = 'mobile';
navbarDropdownHandler(id, true);
});
/* if on desktop: we check if the element the mouse moves to is part of the ignored element (keep the dropdown open) or not (close the dropdown)
* if on mobile: do nothing
*/
function dropdownOnMouseLeave(e, ignoredElement) {
if (window.innerWidth > 900) {
const targetElement = e.relatedTarget || e.toElement;
if (targetElement !== ignoredElement && !ignoredElement.contains(targetElement)) {
closeDropdown();
}
}
}
dropdownButtonWrapper.addEventListener('mouseleave', (e) => {
dropdownOnMouseLeave(e, dropdown);
});
dropdown.addEventListener('mouseleave', (e) => {
dropdownOnMouseLeave(e, dropdownButtonWrapper);
});
// Account widget handler
const userWidgetToggle = document.querySelector('.user-widget-toggle') ;
const userWidget = document.querySelector('.user-widget');
// Open widget on click, close locale dropdown
userWidgetToggle?.addEventListener('click', () => {
userWidget.classList.toggle('active');
localeOptionsContainer.classList.toggle('active');
localeDropdownToggle.classList.toggle('active');
});
// Locale dropdown handler
function localeDropdownHandler(selectedLocale) {
document.cookie = `preferredLocale=${selectedLocale};max-age=31536000`;
window.location.reload();
}
const localeDropdown = document.querySelector(
'.locale-dropdown[data-dropdown]'
);
const localeDropdownOptions = document.querySelectorAll(
'.locale-dropdown[data-dropdown] .options-container'
);
const localeDropdownToggle = document.querySelector('.locale-dropdown-toggle');
const localeOptionsContainer = localeDropdown.querySelector('.options-container');
const localeOptionsList = localeDropdown.querySelectorAll('.option');
// click dropdown element will open dropdown
localeDropdownToggle.addEventListener('click', () => {
localeOptionsContainer.classList.toggle('active');
localeDropdownToggle.classList.toggle('active');
});
// clicking on any option will close dropdown and change value
localeOptionsList.forEach((option) => {
option.addEventListener('click', () => {
localeDropdownToggle.classList.remove('active');
localeOptionsContainer.classList.remove('active');
const selectedLocale = option.querySelector('label').getAttribute('for');
localeDropdownHandler(selectedLocale);
});
});
// close all dropdowns on scroll
document.addEventListener('scroll', () => {
localeDropdownOptions.forEach((el) => el.classList.remove('active'));
localeDropdownToggle.classList.remove('active');
userWidget?.classList.remove('active');
});
// click outside of dropdown will close all dropdowns
document.addEventListener('click', (e) => {
const targetElement = e.target;
let found = false;
if (
localeDropdown == targetElement ||
localeDropdown?.contains(targetElement)
) {
found = true;
userWidget?.classList.remove('active');
}
if (
userWidget == targetElement ||
userWidget?.contains(targetElement) ||
userWidgetToggle == targetElement ||
userWidgetToggle?.contains(targetElement)
) {
found = true;
localeDropdownToggle.classList.remove('active');
localeOptionsContainer.classList.remove('active');
}
if (found) return;
// click outside of dropdowns
userWidget?.classList.remove('active');
localeDropdownToggle.classList.remove('active');
localeOptionsContainer.classList.remove('active');
});

Some files were not shown because too many files have changed in this diff Show More