本地化翻译
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
# 打包命令
|
||||
# docker buildx build -t zhushenwudi/lovelive_sif2:1.0.0 --platform=linux/amd64 .
|
||||
# docker buildx build -t zhushenwudi/lovelive-sif2:1.0.1 --platform=linux/amd64 .
|
||||
# 使用适用于 Linux x86 的基础映像
|
||||
# 保存镜像
|
||||
# docker save -o lovelive_sif2.tar zhushenwudi/lovelive_sif2:1.0.0
|
||||
# docker save -o lovelive-sif2.tar zhushenwudi/lovelive-sif2:1.0.1
|
||||
|
||||
FROM docker.io/library/debian:latest AS builder
|
||||
|
||||
@ -31,7 +31,7 @@ RUN npm i && npm run build
|
||||
|
||||
WORKDIR /ew/
|
||||
|
||||
RUN . "$HOME/.cargo/env" && cargo build --release
|
||||
RUN . "$HOME/.cargo/env" && cargo build --release --jobs=16
|
||||
|
||||
## Second - sort stuff idk
|
||||
|
||||
|
@ -1,34 +1,42 @@
|
||||
version: '3'
|
||||
services:
|
||||
lovelive_sif2:
|
||||
image: zhushenwudi/lovelive_sif2:1.0.0
|
||||
image: zhushenwudi/lovelive-sif2:1.0.0
|
||||
container_name: sif2
|
||||
environment:
|
||||
PORT: 8080
|
||||
ASSET_PORT: 8000
|
||||
DIRECTORY: /data/
|
||||
ASSET_DIRECTORY: /assets/
|
||||
# Server URL是否存在SSL/TSL加密协议
|
||||
HTTPS: false
|
||||
# 是否允许内部启动资源服务
|
||||
ENABLE_ASSET_SERVER: false
|
||||
# <数据迁移> SIF1服务器地址
|
||||
#NPPS4_ADDRESS: "http://127.0.0.1:51376"
|
||||
MAXTIME: 1717045200 # A day before global EOS
|
||||
HIDDEN: false # Will disable the webui
|
||||
DISABLE_IMPORTS: false # Will disable account imports
|
||||
DISABLE_EXPORTS: false # Will disable account exports
|
||||
# 服务器默认时间,建议设置到开服时间,最大设置为关服时间
|
||||
MAXTIME: 1736076211
|
||||
# 是否隐藏WebUI
|
||||
HIDDEN: false
|
||||
# 是否禁用账号导入
|
||||
DISABLE_IMPORTS: false
|
||||
# 是否禁用账号导出
|
||||
DISABLE_EXPORTS: false
|
||||
|
||||
# Everything below is for the "Help" page
|
||||
# 以下内容出现在Help界面
|
||||
# 未签名的apk下载地址
|
||||
ANDROID_JAPAN: "http://fir.zhushenwudi.top/n2tvzrhl"
|
||||
#ANDROID_GLOBAL: "link.to/patched/android/global.apk"
|
||||
#ANDROID_JAPAN: "link.to/patched/android/japan.apk"
|
||||
# 脱壳的ipa下载地址
|
||||
#IOS_JAPAN: "link.to/ios/jp.ipa"
|
||||
#IOS_GLOBAL: "link.to/ios/global.ipa"
|
||||
#IOS_JAPAN: "link.to/ios/japan.ipa"
|
||||
#ASSET_URL: "link.to/client/assets/"
|
||||
ports:
|
||||
# 只修改左侧本地端口
|
||||
# Server URL 端口
|
||||
- "8080:8080"
|
||||
# Assets URL 端口
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
# 只修改左侧本地路径
|
||||
# 数据库存放路径(建议添加)
|
||||
- ./data:/data
|
||||
# 资源文件存放路径(搭建asset server需要指定本地资源路径)
|
||||
# 资源文件存放路径(搭建assets server需要指定本地资源路径)
|
||||
- ./assets:/assets
|
||||
restart: unless-stopped
|
||||
|
19
readme.md
19
readme.md
@ -1,31 +1,30 @@
|
||||
# EW
|
||||
(stands for ew why)
|
||||
|
||||
A (mostly functioning) server for Love Live! School idol festival 2 MIRACLE LIVE!
|
||||
一款基本能正常运行的《Love Live! 学园偶像祭2 MIRACLE LIVE!》服务器程序
|
||||
|
||||
## Building
|
||||
## 构建
|
||||
|
||||
### Linux
|
||||
|
||||
#### Requirements
|
||||
- [perl](https://www.perl.org/get.html) (This is normally pre-installed)
|
||||
#### 环境要求
|
||||
- [perl](https://www.perl.org/get.html) (这通常是预装的)
|
||||
- [rust](https://www.rust-lang.org/tools/install)
|
||||
- [npm](https://www.npmjs.com/)
|
||||
- The [libssl-dev](https://packages.debian.org/buster/libssl-dev) package. This will vary across distros.
|
||||
- [libssl-dev](https://packages.debian.org/buster/libssl-dev) (这在不同的发行版中会有所不同)
|
||||
|
||||
`apt install -y npm libssl-dev perl`
|
||||
|
||||
### Windows
|
||||
|
||||
#### Requirements
|
||||
#### 环境要求
|
||||
- [Strawberry Perl](https://strawberryperl.com/)
|
||||
- [rust](https://www.rust-lang.org/tools/install)
|
||||
|
||||
### Packaging/Running
|
||||
### 打包/运行
|
||||
|
||||
**Build npm:**
|
||||
**编译WebUI**
|
||||
`cd webui && npm install && npm run build`
|
||||
|
||||
**Build Rust:**
|
||||
**编译Rust**
|
||||
Debug: `cargo run`
|
||||
Release: `cargo build --release --jobs=16`
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { useState, useParams, useEffect } from 'react'
|
||||
import {useEffect, useState} from 'react'
|
||||
import './Help.css'
|
||||
import Request from '../Request.jsx'
|
||||
let init = false;
|
||||
|
||||
let init = false
|
||||
let defaultDownloadUrl = "您的服务器管理员没有可供下载的预打补丁的应用程序包。请参阅下面的问题。"
|
||||
|
||||
function Help() {
|
||||
const [downloadUrl, setDownloadUrl] = useState(<div>Your server admin has no pre-patched apks to download. See the question below..</div>);
|
||||
const [downloadUrl, setDownloadUrl] = useState(<div>{defaultDownloadUrl}</div>);
|
||||
const [downloadUrliOSGL, setDownloadUrliOSGL] = useState("https://ethanthesleepy.one/public/lovelive/sif2/sif2-gl.ipa");
|
||||
const [downloadUrliOSJP, setDownloadUrliOSJP] = useState("https://ethanthesleepy.one/public/lovelive/sif2/sif2-jp.ipa");
|
||||
|
||||
@ -21,15 +23,16 @@ function Help() {
|
||||
if (!resp.data.links) return;
|
||||
if (resp.data.links.global && resp.data.links.japan) {
|
||||
setDownloadUrl(
|
||||
<div>Your server admin has a link to download! Download <a href={resp.data.links.japan}>Japan</a> or <a href={resp.data.links.global}>Global</a></div>
|
||||
<div>您的服务器管理员有下载链接!下载 <a href={resp.data.links.japan}>日服</a> 或者 <a
|
||||
href={resp.data.links.global}>国际服</a></div>
|
||||
);
|
||||
} else if (resp.data.links.global) {
|
||||
setDownloadUrl(
|
||||
<div>Your server admin has a link to download! Download <a href={resp.data.links.global}>Global</a></div>
|
||||
<div>您的服务器管理员有下载链接!下载 <a href={resp.data.links.global}>国际服</a></div>
|
||||
);
|
||||
} else if (resp.data.links.japan) {
|
||||
setDownloadUrl(
|
||||
<div>Your server admin has a link to download! Download <a href={resp.data.links.japan}>Japan</a></div>
|
||||
<div>您的服务器管理员有下载链接!下载 <a href={resp.data.links.japan}>日服</a></div>
|
||||
);
|
||||
}
|
||||
if (resp.data.links.assets) {
|
||||
@ -47,42 +50,62 @@ function Help() {
|
||||
})();
|
||||
});
|
||||
|
||||
const renderNoAndroidDownloadUrl = () => {
|
||||
return <>
|
||||
<h2>我的服务器管理员没有下载链接,我该如何修补apk(安卓)?</h2>
|
||||
<p>你可以用 <a href="https://sif2patch.zhushenwudi.top">@arasfon's sif2 apk 修补工具</a>。
|
||||
在“服务器URL”中填写"{window.location.origin}",在“资源URL”中填写 "{assetUrl}"(默认已经帮你填入了以上信息)。
|
||||
选择你的游戏版本, 更改头部格式为“Lowercase”, 最后点击开始修补。完成修补后使用 <a
|
||||
href="https://github.com/patrickfav/uber-apk-signer">uber-apk-signer</a> 来签署apk.
|
||||
最后便可以安装到你的手机上了!</p>
|
||||
</>
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="home">
|
||||
<h1>Help/About</h1>
|
||||
<h2>What is "ew"? What is this server for?</h2>
|
||||
<p>"ew" is a private server, written in Rust, for the short lived game "Love Live! School idol festival 2 MIRACLE LIVE!", a Love Live! themed mobile rhythm game.</p>
|
||||
<div id="home">
|
||||
<h1>帮助/关于</h1>
|
||||
<h2>“ew”是什么?这个服务器是用来做什么的?</h2>
|
||||
<p>“ew”是一个用Rust编写的私人服务器,原作者:Ethan O'Brien,原项目:<a
|
||||
href="https://git.ethanthesleepy.one/ethanaobrien/ew">ew仓库地址</a>。
|
||||
本项目为二次开发版本,用于短命的游戏《Love Live! School idol festival 2 MIRACLE LIVE!》,
|
||||
这是一款以Love Live!为主题的移动节奏游戏。</p>
|
||||
|
||||
<h2>I'm just trying to play on this server, how do I install the app? (Android)</h2>
|
||||
<p>{downloadUrl}</p>
|
||||
<h2>我只是想在这个服务器上玩,我该如何安装这个应用程序?(安卓)</h2>
|
||||
<p>{downloadUrl}</p>
|
||||
|
||||
<h2>My server admin has no download URLs, how do I patch the apk? (Android)</h2>
|
||||
<p>You can use <a href="https://arasfon.ru/sif2/patcher/">@arasfon's sif2 apk patcher</a>. Plug and the asset url, which is "{assetUrl}", into the "Assets URL" textbox, and then the server url (Which is likely "{window.location.origin}", though this may not be the case). Select your game version, set "header format" to "Lowercase", and press patch. Once that done, use <a href="https://github.com/patrickfav/uber-apk-signer">uber-apk-signer</a> to sign the apk. Then, get it onto your phone and install!</p>
|
||||
{downloadUrl === defaultDownloadUrl ? renderNoAndroidDownloadUrl() : null}
|
||||
|
||||
<h2>How do I install the app? (iOS)</h2>
|
||||
<p>Running on iOS is much simpler than Android, thanks to triangle on the discord. You first download an ipa file for <a href={downloadUrliOSGL}>global</a> or <a href={downloadUrliOSJP}>Japan</a>, and use <a href="https://sideloadly.io/">Sideloadly</a> (or your preferred application installer) to install the app. Then open settings, navigate to the app you just installed, and input the server url (Which is likely "{window.location.origin}", though this may not be the case), and the asset url, which is "{assetUrl}". If you have any errors opening the app, make sure none of the urls in settings end with a slash (/).</p>
|
||||
<h2>我该如何安装这款应用?(iOS)</h2>
|
||||
<p>在iOS上运行要比Android简单得多,这要归功于Discord上的Triangle。你首先要下载一个用于 <a
|
||||
href={downloadUrliOSGL}>国际服</a> 或者 <a href={downloadUrliOSJP}>日服</a> 的ipa文件,
|
||||
然后使用 <a href="https://sideloadly.io/">Sideloadly</a> (或任何能够实现侧载的应用程序)来安装这个APP。打开手机系统设置,
|
||||
导航到SIF2应用的设置页面, 填入“Server URL”:"{window.location.origin}" 与 “Assets URL”:"{assetUrl}"。
|
||||
如果您在打开应用程序时遇到任何错误,请确保设置中的所有网址都没有以斜杠结尾。</p>
|
||||
|
||||
<h2>Help! I'm trying to open the app and it shows as "unavailable" (iOS)</h2>
|
||||
<p>Do not delete it, Just re-sideload the app. This is an Apple security feature.</p>
|
||||
<h2>求求!我尝试打开SIF2,但它显示为“不可用”(iOS)。</h2>
|
||||
<p>不要删除当前的SIF2,只需重新侧载该应用程序。这是苹果的安全功能。</p>
|
||||
|
||||
<h2>How well does this work?</h2>
|
||||
<p>Works well enough. The server itself takes up not even 20mb of storage, and it's written in rust. I personally think it's pretty well written.</p>
|
||||
<h2>程序的执行效率如何?</h2>
|
||||
<p>运行得相当不错。服务器本身占用的存储空间甚至不到20兆字节,并且是用Rust编写的。我个人认为它写得相当好。</p>
|
||||
|
||||
<h2>Could my computer/laptop run a server?</h2>
|
||||
<p>Very very likely. If the platform is <a href="https://doc.rust-lang.org/nightly/rustc/platform-support.html">supported by rust</a>, then the answer is yes! It is recommended to manually compile the project until I get the time to setup actions. <a href="https://git.ethanthesleepy.one/ethanaobrien/ew">ew repo</a></p>
|
||||
<h2>我的电脑/笔记本电脑能运行服务器吗?</h2>
|
||||
<p>非常有可能。如果平台是支持 <a
|
||||
href="https://doc.rust-lang.org/nightly/rustc/platform-support.html">Rust语言</a> 的,
|
||||
那么答案是肯定的!在我有时间设置自动操作之前,建议手动编译项目。 <a
|
||||
href="https://git.zhushenwudi.top/zhushenwudi/ew">ew仓库地址</a></p>
|
||||
|
||||
<h2>Is the server down right now? I can't connect</h2>
|
||||
<p>Assuming you have just loaded this page on the server you use, then the answer is no, otherwise please contact your server admin.</p>
|
||||
<h2>服务器现在是宕机了吗?我无法连接。</h2>
|
||||
<p>假设你刚刚在你使用的服务器上加载了这个页面,那么答案是否定的,否则请联系你的服务器管理员。</p>
|
||||
|
||||
<h2>Do events work?</h2>
|
||||
<p>Most events do not, though most should not crash the game. Star events are partially implemented. You can get your rank up, and compete with other players in a ranking table, but no rewards are currently implemented.</p>
|
||||
<h2>打歌活动能正常游玩吗?</h2>
|
||||
<p>大多数活动会让游戏崩溃,不过这确实是不应该的。明星活动部分已实现。你可以提升自己的排名,并在排名表中与其他玩家竞争,但目前尚未实现奖励功能。</p>
|
||||
|
||||
<h2>But then, how do I get event URs?</h2>
|
||||
<p>There are serial codes for several things, one of which includes all the event URs. I don't remember what does what but it is recommended to look at the serial code file to get the latest codes.</p>
|
||||
<h2>我该如何获取活动UR呢?</h2>
|
||||
<p>可以通过游戏内兑换码的方式领取活动UR:meow、kode、ganuy</p>
|
||||
|
||||
<h2>Why does the game crash when I do x?</h2>
|
||||
<p>This likely means something on the server is broken. If you're self hosting, please contact me via matrix. Otherwise, contact your server admin and ask them to report the issue.</p>
|
||||
</div>
|
||||
<h2>当我操作窗口关闭时,为什么游戏会崩溃?</h2>
|
||||
<p>这很可能意味着服务器上有某些地方出故障了。如果你是自行托管(服务器),请通过Matrix联系我。否则,联系你的服务器管理员,并让他们报告这个问题。</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -50,28 +50,29 @@ function Bonus() {
|
||||
updatedItems.splice(index, 1);
|
||||
setSubmittedItems(updatedItems);
|
||||
};
|
||||
// <button onClick={() => handleRemoveItem(index)}>X</button>
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Current login bonus list</h2>
|
||||
<h2>当前登录奖励列表</h2>
|
||||
<div id="error"> { error[0] ? <p>Error: { error[0] } </p> : <p></p> } </div>
|
||||
<ul>
|
||||
{submittedItems.map((item, index) => (
|
||||
<li key={index}>
|
||||
{item}
|
||||
</li>
|
||||
<li key={index}>
|
||||
{item}
|
||||
<button onClick={() => handleRemoveItem(index)}>X</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(event) => setInputValue(event.target.value)}
|
||||
placeholder="Enter login bonus ID"
|
||||
placeholder="输入登录奖励ID"
|
||||
/>
|
||||
<button type="submit">Submit</button>
|
||||
<button type="submit">提交</button>
|
||||
</form>
|
||||
<p>You can find a list of available login bonus IDs <a href="https://git.ethanthesleepy.one/ethanaobrien/ew/src/branch/main/src/router/databases/json/login_bonus.json">here</a>. You should input the <code>id</code> field</p>
|
||||
<p>你可以找到可用登录奖励ID的列表。 <a href="https://git.ethanthesleepy.one/ethanaobrien/ew/src/branch/main/src/router/databases/json/login_bonus.json">这里</a>. 你应该输入指定 <code>id</code></p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -158,10 +159,10 @@ function Home() {
|
||||
|
||||
userdata(
|
||||
<div>
|
||||
<p>User id: { user.user.id } </p>
|
||||
<p>Migration id: { getMigrationID(user.user.id) } </p>
|
||||
<p>Rank: { user.user.rank } ({ user.user.exp } exp)</p>
|
||||
<p>Last Login: { (new Date(user.user.last_login_time * 1000)).toString() } </p>
|
||||
<p>SIF2 用户id: { user.user.id } </p>
|
||||
<p>引继码: { getMigrationID(user.user.id) } </p>
|
||||
<p>等级: { user.user.rank } ({ user.user.exp } exp)</p>
|
||||
<p>上次登录时间: { (new Date(user.user.last_login_time * 1000)).toString() } </p>
|
||||
<Bonus />
|
||||
</div>
|
||||
);
|
||||
@ -170,23 +171,23 @@ function Home() {
|
||||
|
||||
return (
|
||||
<div id="home">
|
||||
<button id="logout" onClick={expor}>Export account</button><br/><br/><br/>
|
||||
<button id="logout" onClick={logout}>Logout</button>
|
||||
<h1>Home</h1>
|
||||
<button id="logout" onClick={expor}>导出用户数据</button><br/><br/><br/>
|
||||
<button id="logout" onClick={logout}>登出</button>
|
||||
<h1>用户主页</h1>
|
||||
|
||||
{ user ? <div>
|
||||
{ user }
|
||||
<h2>Server time</h2>
|
||||
<h2>服务器时间</h2>
|
||||
<div id="error"> { error[0] ? <p>Error: { error[0] } </p> : <p></p> } </div>
|
||||
<p>Currently set to { serverTime }. Setting to 0 will set it to now, and -1 will reset it. Time will still progress, based off of when you set this timestamp.</p>
|
||||
<p>当前时间设置的值为 { serverTime }. 将其设置为0将会设置为当前时间,而-1则会重置它。时间的推进仍将基于您设置此时间戳的时间。</p>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(event) => setInputValue(event.target.value)}
|
||||
placeholder="Enter Server Time"
|
||||
placeholder="输入服务器时间"
|
||||
/>
|
||||
<button type="submit">Submit</button>
|
||||
<button type="submit">提交</button>
|
||||
</form></div>
|
||||
: <p>Loading...</p> }
|
||||
</div>
|
||||
|
@ -54,27 +54,27 @@ function Login() {
|
||||
|
||||
return (
|
||||
<div id="login-form">
|
||||
<h1>Transfer</h1>
|
||||
<h1>导入数据</h1>
|
||||
<form>
|
||||
{ <p>{ status[0] } </p> }
|
||||
<label htmlFor="id">User data file (required):</label>
|
||||
<label htmlFor="id">userdata.json(必要):</label>
|
||||
<input type="file" id="id" name="id" onChange={(event) => {file = event.target.files}} accept="application/json"/>
|
||||
|
||||
<label htmlFor="file1">User Home data file (required):</label>
|
||||
<label htmlFor="file1">userhome.json(必要):</label>
|
||||
<input type="file" id="file1" name="file1" onChange={(event) => {file1 = event.target.files}} accept="application/json"/>
|
||||
|
||||
<label htmlFor="file2">User Missions data file (optional):</label>
|
||||
<label htmlFor="file2">missions.json(可选):</label>
|
||||
<input type="file" id="file2" name="file2" onChange={(event) => {file2 = event.target.files}} accept="application/json"/>
|
||||
|
||||
<label htmlFor="file3">Sif cards data file (optional):</label>
|
||||
<label htmlFor="file3">sifcards.json(可选):</label>
|
||||
<input type="file" id="file3" name="file3" onChange={(event) => {file3 = event.target.files}} accept="application/json"/>
|
||||
|
||||
<label htmlFor="password">Transfer passcode (game will not recognize special characters, only use letters and numbers or you will be locked out):</label>
|
||||
<label htmlFor="password">数据迁移密钥 (游戏将无法识别特殊字符,只能使用字母和数字,否则您将被锁定):</label>
|
||||
<input type="password" id="password" name="password" onChange={(event) => {password = event.target.value}} />
|
||||
|
||||
<input type="submit" value="Submit" onClick={handleSubmit}/>
|
||||
<input type="submit" value="提交" onClick={handleSubmit}/>
|
||||
<div id="sub_div">
|
||||
{ error[0] ? <p>Error: { error[0] }. Please reload the page and try again.</p> : <p></p> }
|
||||
{ error[0] ? <p>错误: { error[0] }。请重新加载页面并重试。</p> : <p></p> }
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -48,19 +48,19 @@ function Login() {
|
||||
|
||||
return (
|
||||
<div id="login-form">
|
||||
<h1>Login</h1>
|
||||
<h1>登录</h1>
|
||||
<form>
|
||||
<label htmlFor="id">SIF2 ID:</label>
|
||||
<input type="text" id="id" name="id" onChange={(event) => {uid[1](event.target.value)}} value={uid[0]} />
|
||||
<label htmlFor="password">Transfer passcode:</label>
|
||||
<label htmlFor="password">数据迁移密钥:</label>
|
||||
<input type="password" id="password" name="password" onChange={(event) => {password[1](event.target.value)}} />
|
||||
<input type="submit" value="Submit" onClick={handleSubmit}/>
|
||||
<input type="submit" value="提交" onClick={handleSubmit}/>
|
||||
<div id="sub_div">
|
||||
<button onClick={import_user}>Import User</button><br/><br/>
|
||||
<button onClick={help}>Need help?</button><br/><br/>
|
||||
<button onClick={import_user}>导入用户数据</button><br/><br/>
|
||||
<button onClick={help}>需要帮助?</button><br/><br/>
|
||||
{ error[0] ? <p>Error: { error[0] } </p> : <p></p> }
|
||||
</div>
|
||||
<p>EW Version 1.0.0 - <a href="https://git.ethanthesleepy.one/ethanaobrien/ew">View source</a> - <a href="https://git.ethanthesleepy.one/ethanaobrien/ew/src/branch/main/LICENSE">View license</a></p>
|
||||
<p>EW 版本号 1.0.1 - <a href="https://git.zhushenwudi.top/zhushenwudi/ew">查看源代码</a> - <a href="https://git.zhushenwudi.top/zhushenwudi/ew/src/branch/main/LICENSE">查看许可证</a></p>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
Reference in New Issue
Block a user