mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
Merge branch 'aperx' into main
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,8 @@
|
||||
dist/
|
||||
node_modules/
|
||||
.vscode
|
||||
exp_util/node-compile-cache/
|
||||
exp_commands/node-compile-cache/
|
||||
exp_groups/node-compile-cache/
|
||||
exp_legacy/node-compile-cache/
|
||||
exp_scenario/node-compile-cache/
|
||||
|
||||
@@ -28,6 +28,7 @@ force=Invalid Force Name.
|
||||
surface=Invalid Surface Name.
|
||||
planet=Invalid Planet Name.
|
||||
color=Invalid Color Name.
|
||||
role=Invalid Role Name.
|
||||
|
||||
[exp-commands-authorities]
|
||||
character-only=This command can not be used in remote view.
|
||||
|
||||
@@ -28,6 +28,7 @@ force=勢力名稱錯誤。
|
||||
surface=地表名稱錯誤。
|
||||
planet=星球名稱錯誤。
|
||||
color=顏色名稱錯誤。
|
||||
role=權限組名稱錯誤。
|
||||
|
||||
[exp-commands-authorities]
|
||||
character-only=該命令不能在遠端視圖中使用。
|
||||
|
||||
@@ -28,6 +28,7 @@ force=勢力名稱錯誤。
|
||||
surface=地表名稱錯誤。
|
||||
planet=星球名稱錯誤。
|
||||
color=顏色名稱錯誤。
|
||||
role=權限組名稱錯誤。
|
||||
|
||||
[exp-commands-authorities]
|
||||
character-only=該命令不能在遠端視圖中使用。
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
import * as lib from "@clusterio/lib";
|
||||
import { BaseControllerPlugin, InstanceInfo } from "@clusterio/controller";
|
||||
|
||||
import {
|
||||
PermissionStrings, PermissionStringsUpdate,
|
||||
PermissionGroup, PermissionGroupUpdate,
|
||||
InstancePermissionGroups,
|
||||
PermissionInstanceId,
|
||||
PermissionGroupEditEvent,
|
||||
} from "./messages";
|
||||
|
||||
import path from "path";
|
||||
import fs from "fs-extra";
|
||||
|
||||
export class ControllerPlugin extends BaseControllerPlugin {
|
||||
static permissionGroupsPath = "exp_groups.json";
|
||||
static userGroupsPath = "exp_user_groups.json";
|
||||
|
||||
userToGroup: Map<lib.User["id"], PermissionGroup> = new Map(); // TODO this needs to be per instance
|
||||
permissionStrings!: Map<PermissionStrings["id"], PermissionStrings>;
|
||||
permissionGroups!: Map<InstancePermissionGroups["id"], InstancePermissionGroups>;
|
||||
|
||||
async init() {
|
||||
this.controller.handle(PermissionStringsUpdate, this.handlePermissionStringsUpdate.bind(this));
|
||||
this.controller.handle(PermissionGroupUpdate, this.handlePermissionGroupUpdate.bind(this));
|
||||
this.controller.handle(PermissionGroupEditEvent, this.handlePermissionGroupEditEvent.bind(this));
|
||||
this.controller.subscriptions.handle(PermissionStringsUpdate, this.handlePermissionStringsSubscription.bind(this));
|
||||
this.controller.subscriptions.handle(PermissionGroupUpdate, this.handlePermissionGroupSubscription.bind(this));
|
||||
this.controller.subscriptions.handle(PermissionGroupEditEvent);
|
||||
this.permissionStrings = new Map([["Global", new PermissionStrings("Global", new Set())]]);
|
||||
this.permissionGroups = new Map([["Global", new InstancePermissionGroups("Global")]]);
|
||||
await this.loadData();
|
||||
|
||||
// Add the default group if missing and add any missing cluster roles
|
||||
const clusterRoles = [...this.controller.userManager.roles.values()]
|
||||
for (const instanceGroups of this.permissionGroups.values()) {
|
||||
const groups = instanceGroups.groups;
|
||||
const instanceRoles = [...groups.values()].flatMap(group => [...group.roleIds.values()]);
|
||||
const missingRoles = clusterRoles.filter(role => instanceRoles.includes(role.id));
|
||||
const defaultGroup = groups.get("Default");
|
||||
if (defaultGroup) {
|
||||
for (const role of missingRoles) {
|
||||
defaultGroup.roleIds.add(role.id)
|
||||
}
|
||||
} else {
|
||||
groups.set("Default", new PermissionGroup(
|
||||
instanceGroups.instanceId,
|
||||
"Default",
|
||||
groups.size,
|
||||
new Set(missingRoles.map(role => role.id))
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async onControllerConfigFieldChanged(field: string, curr: unknown, prev: unknown) {
|
||||
if (field === "exp_groups.allow_role_inconsistency") {
|
||||
// Do something with this.userToGroup
|
||||
}
|
||||
}
|
||||
|
||||
async onInstanceConfigFieldChanged(instance: InstanceInfo, field: string, curr: unknown, prev: unknown) {
|
||||
this.logger.info(`controller::onInstanceConfigFieldChanged ${instance.id} ${field}`);
|
||||
if (field === "exp_groups.sync_permission_groups") {
|
||||
const updates = []
|
||||
const now = Date.now();
|
||||
if (curr) {
|
||||
// Global sync enabled, we dont need the instance config
|
||||
const instanceGroups = this.permissionGroups.get(instance.id);
|
||||
if (instanceGroups) {
|
||||
this.permissionGroups.delete(instance.id);
|
||||
for (const group of instanceGroups.groups.values()) {
|
||||
group.updatedAtMs = now;
|
||||
group.isDeleted = true;
|
||||
updates.push(group);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Global sync disabled, make a copy of the global config as a base
|
||||
const global = this.permissionGroups.get("Global")!;
|
||||
const oldInstanceGroups = this.permissionGroups.get(instance.id);
|
||||
const instanceGroups = new InstancePermissionGroups(
|
||||
instance.id, new Map([...global.groups.values()].map(group => [group.name, group.copy(instance.id)]))
|
||||
)
|
||||
this.permissionGroups.set(instance.id, instanceGroups);
|
||||
for (const group of instanceGroups.groups.values()) {
|
||||
group.updatedAtMs = now;
|
||||
updates.push(group);
|
||||
}
|
||||
// If it has an old config (unexpected) then deal with it
|
||||
if (oldInstanceGroups) {
|
||||
for (const group of oldInstanceGroups.groups.values()) {
|
||||
if (!instanceGroups.groups.has(group.name)) {
|
||||
group.updatedAtMs = now;
|
||||
group.isDeleted = true;
|
||||
updates.push(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Send the updates to all instances and controls
|
||||
if (updates.length) {
|
||||
this.controller.subscriptions.broadcast(new PermissionGroupUpdate(updates));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async loadPermissionGroups() {
|
||||
const file = path.resolve(this.controller.config.get("controller.database_directory"), ControllerPlugin.permissionGroupsPath);
|
||||
this.logger.verbose(`Loading ${file}`);
|
||||
try {
|
||||
const content = await fs.readFile(file, { encoding: "utf8" });
|
||||
for (const groupRaw of JSON.parse(content)) {
|
||||
const group = PermissionGroup.fromJSON(groupRaw);
|
||||
const instanceGroups = this.permissionGroups.get(group.instanceId);
|
||||
if (instanceGroups) {
|
||||
instanceGroups.groups.set(group.name, group);
|
||||
} else {
|
||||
this.permissionGroups.set(group.instanceId,
|
||||
new InstancePermissionGroups(group.instanceId, new Map([[group.name, group]]))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
} catch (err: any) {
|
||||
if (err.code === "ENOENT") {
|
||||
this.logger.verbose("Creating new permission group database");
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async savePermissionGroups() {
|
||||
const file = path.resolve(this.controller.config.get("controller.database_directory"), ControllerPlugin.permissionGroupsPath);
|
||||
this.logger.verbose(`Writing ${file}`);
|
||||
await lib.safeOutputFile(file, JSON.stringify(
|
||||
[...this.permissionGroups.values()].flatMap(instanceGroups => [...instanceGroups.groups.values()])
|
||||
));
|
||||
}
|
||||
|
||||
async loadUserGroups() {
|
||||
if (!this.controller.config.get("exp_groups.allow_role_inconsistency")) return;
|
||||
const file = path.resolve(this.controller.config.get("controller.database_directory"), ControllerPlugin.userGroupsPath);
|
||||
this.logger.verbose(`Loading ${file}`);
|
||||
try {
|
||||
const content = await fs.readFile(file, { encoding: "utf8" });
|
||||
this.userToGroup = new Map(JSON.parse(content));
|
||||
|
||||
} catch (err: any) {
|
||||
if (err.code === "ENOENT") {
|
||||
this.logger.verbose("Creating new user group database");
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async saveUserGroups() {
|
||||
if (!this.controller.config.get("exp_groups.allow_role_inconsistency")) return;
|
||||
const file = path.resolve(this.controller.config.get("controller.database_directory"), ControllerPlugin.userGroupsPath);
|
||||
this.logger.verbose(`Writing ${file}`);
|
||||
await lib.safeOutputFile(file, JSON.stringify([...this.permissionGroups.entries()]));
|
||||
}
|
||||
|
||||
async loadData() {
|
||||
await Promise.all([
|
||||
this.loadPermissionGroups(),
|
||||
this.loadUserGroups(),
|
||||
])
|
||||
}
|
||||
|
||||
async onSaveData() {
|
||||
await Promise.all([
|
||||
this.savePermissionGroups(),
|
||||
this.saveUserGroups(),
|
||||
])
|
||||
}
|
||||
|
||||
addPermisisonGroup(instanceId: PermissionInstanceId, name: string, permissions = new Set<string>(), silent = false) {
|
||||
const instanceGroups = this.permissionGroups.get(instanceId);
|
||||
if (!instanceGroups) {
|
||||
throw new Error("Instance ID does not exist");
|
||||
}
|
||||
if (instanceGroups.groups.has(name)) {
|
||||
return instanceGroups.groups.get(name)!;
|
||||
}
|
||||
for (const group of instanceGroups.groups.values()) {
|
||||
group.order += 1;
|
||||
}
|
||||
const group = new PermissionGroup(instanceId, name, 0, new Set(), permissions, Date.now(), false);
|
||||
instanceGroups.groups.set(group.id, group);
|
||||
if (!silent) {
|
||||
this.controller.subscriptions.broadcast(new PermissionGroupUpdate([group]));
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
removePermissionGroup(instanceId: PermissionInstanceId, name: string, silent = false) {
|
||||
const instanceGroups = this.permissionGroups.get(instanceId);
|
||||
if (!instanceGroups) {
|
||||
throw new Error("Instance ID does not exist");
|
||||
}
|
||||
const group = instanceGroups.groups.get(name)
|
||||
if (!group) {
|
||||
return null;
|
||||
}
|
||||
for (const nextGroup of instanceGroups.groups.values()) {
|
||||
if (nextGroup.order > group.order) {
|
||||
nextGroup.order -= 1;
|
||||
}
|
||||
}
|
||||
instanceGroups.groups.delete(group.id);
|
||||
group.updatedAtMs = Date.now();
|
||||
group.isDeleted = true;
|
||||
if (!silent) {
|
||||
this.controller.subscriptions.broadcast(new PermissionGroupUpdate([group]));
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
async handlePermissionGroupEditEvent(event: PermissionGroupEditEvent) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
async handlePermissionStringsUpdate(event: PermissionStringsUpdate) {
|
||||
for (const update of event.updates) {
|
||||
const global = this.permissionStrings.get("Global")!
|
||||
this.permissionStrings.set(update.instanceId as number, update)
|
||||
global.updatedAtMs = Math.max(global.updatedAtMs, update.updatedAtMs)
|
||||
for (const permission of update.permissions) {
|
||||
global.permissions.add(permission)
|
||||
}
|
||||
// TODO maybe check if changes have happened rather than always pushing updates
|
||||
this.controller.subscriptions.broadcast(new PermissionStringsUpdate([global, update]))
|
||||
}
|
||||
}
|
||||
|
||||
async handlePermissionGroupUpdate(event: PermissionGroupUpdate) {
|
||||
const updates = [];
|
||||
for (const group of event.updates) {
|
||||
const groups = this.permissionGroups.get(group.instanceId);
|
||||
if (!groups) continue;
|
||||
const existingGroup = groups.groups.get(group.id);
|
||||
let update
|
||||
if (!existingGroup) {
|
||||
update = this.addPermisisonGroup(group.instanceId, group.name, group.permissions, true);
|
||||
} else if (group.isDeleted) {
|
||||
update = this.removePermissionGroup(group.instanceId, group.name, true);
|
||||
} else {
|
||||
existingGroup.permissions = group.permissions;
|
||||
existingGroup.updatedAtMs = Date.now();
|
||||
update = existingGroup;
|
||||
}
|
||||
if (update) updates.push(update);
|
||||
}
|
||||
this.controller.subscriptions.broadcast(new PermissionGroupUpdate(updates));
|
||||
}
|
||||
|
||||
async handlePermissionStringsSubscription(request: lib.SubscriptionRequest, src: lib.Address) {
|
||||
const updates = [ ...this.permissionStrings.values() ]
|
||||
.filter(
|
||||
value => value.updatedAtMs > request.lastRequestTimeMs,
|
||||
)
|
||||
return updates.length ? new PermissionStringsUpdate(updates) : null;
|
||||
}
|
||||
|
||||
async handlePermissionGroupSubscription(request: lib.SubscriptionRequest, src: lib.Address) {
|
||||
const updates = [ ...this.permissionGroups.values() ]
|
||||
.flatMap(instanceGroups => [...instanceGroups.groups.values()])
|
||||
.filter(
|
||||
value => value.updatedAtMs > request.lastRequestTimeMs,
|
||||
)
|
||||
if (src.type === lib.Address.instance) {
|
||||
const instanceUpdates = updates.filter(group => group.instanceId === src.id || group.instanceId === "Global");
|
||||
this.logger.info(JSON.stringify(updates))
|
||||
this.logger.info(JSON.stringify(instanceUpdates))
|
||||
return instanceUpdates.length ? new PermissionGroupUpdate(instanceUpdates) : null;
|
||||
}
|
||||
return updates.length ? new PermissionGroupUpdate(updates) : null;
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
import * as lib from "@clusterio/lib";
|
||||
import * as Messages from "./messages";
|
||||
|
||||
lib.definePermission({
|
||||
name: "exp_groups.create_delete_groups",
|
||||
title: "Create and delete permission groups",
|
||||
description: "Create and delete permission groups.",
|
||||
});
|
||||
|
||||
lib.definePermission({
|
||||
name: "exp_groups.reorder_groups",
|
||||
title: "Reorder permission groups",
|
||||
description: "Reorder groups and link them to user roles.",
|
||||
});
|
||||
|
||||
lib.definePermission({
|
||||
name: "exp_groups.modify_permissions",
|
||||
title: "Modify permission groups",
|
||||
description: "Modify game permissions for groups.",
|
||||
});
|
||||
|
||||
lib.definePermission({
|
||||
name: "exp_groups.assign_players",
|
||||
title: "Change player group",
|
||||
description: "Change the permission group of a player",
|
||||
});
|
||||
|
||||
lib.definePermission({
|
||||
name: "exp_groups.list",
|
||||
title: "View permission groups",
|
||||
description: "View permission groups.",
|
||||
});
|
||||
|
||||
lib.definePermission({
|
||||
name: "exp_groups.list.subscribe",
|
||||
title: "Subscribe to permission group updates",
|
||||
description: "Subscribe to permission group updates.",
|
||||
});
|
||||
|
||||
declare module "@clusterio/lib" {
|
||||
export interface ControllerConfigFields {
|
||||
"exp_groups.allow_role_inconsistency": boolean;
|
||||
}
|
||||
export interface InstanceConfigFields {
|
||||
"exp_groups.sync_permission_groups": boolean;
|
||||
}
|
||||
}
|
||||
|
||||
export const plugin: lib.PluginDeclaration = {
|
||||
name: "exp_groups",
|
||||
title: "exp_groups",
|
||||
description: "Create, modify, and link factorio permission groups to clusterio user roles.",
|
||||
|
||||
controllerEntrypoint: "./dist/node/controller",
|
||||
controllerConfigFields: {
|
||||
"exp_groups.allow_role_inconsistency": {
|
||||
title: "Allow User Role Inconsistency",
|
||||
description: "When true, users can be assgined to any group regardless of their roles",
|
||||
type: "boolean",
|
||||
initialValue: false,
|
||||
},
|
||||
},
|
||||
|
||||
instanceEntrypoint: "./dist/node/instance",
|
||||
instanceConfigFields: {
|
||||
"exp_groups.sync_permission_groups": {
|
||||
title: "Sync Permission Groups",
|
||||
description: "When true, the instance cannot deviate from the global group settings and will be hidden from the sellection dropdown.",
|
||||
type: "boolean",
|
||||
initialValue: true,
|
||||
},
|
||||
},
|
||||
|
||||
messages: [
|
||||
Messages.PermissionGroupEditEvent,
|
||||
Messages.PermissionStringsUpdate,
|
||||
Messages.PermissionGroupUpdate,
|
||||
],
|
||||
|
||||
webEntrypoint: "./web",
|
||||
routes: [
|
||||
"/exp_groups",
|
||||
],
|
||||
};
|
||||
@@ -1,129 +0,0 @@
|
||||
import * as lib from "@clusterio/lib";
|
||||
import { BaseInstancePlugin } from "@clusterio/host";
|
||||
import {
|
||||
PermissionGroup, PermissionGroupEditEvent, PermissionGroupEditType,
|
||||
PermissionGroupUpdate, PermissionInstanceId, PermissionStrings, PermissionStringsUpdate
|
||||
} from "./messages";
|
||||
|
||||
const rconBase = "/sc local Groups = package.loaded['modules/exp_groups/module_exports'];"
|
||||
|
||||
type EditIPC = {
|
||||
type: PermissionGroupEditType,
|
||||
changes: string[],
|
||||
group: string,
|
||||
};
|
||||
|
||||
type CreateIPC = {
|
||||
group: string,
|
||||
defiantion: [boolean, string[] | {}]
|
||||
}
|
||||
|
||||
type DeleteIPC = {
|
||||
group: string,
|
||||
}
|
||||
|
||||
export class InstancePlugin extends BaseInstancePlugin {
|
||||
permissions: Set<string> = new Set();
|
||||
permissionGroups = new lib.EventSubscriber(PermissionGroupUpdate, this.instance);
|
||||
permissionGroupUpdates = new lib.EventSubscriber(PermissionGroupEditEvent, this.instance);
|
||||
syncId: PermissionInstanceId = this.instance.config.get("exp_groups.sync_permission_groups") ? "Global" : this.instance.id;
|
||||
|
||||
async init() {
|
||||
this.instance.server.handle("exp_groups-permission_group_edit", this.handleEditIPC.bind(this));
|
||||
this.instance.server.handle("exp_groups-permission_group_create", this.handleCreateIPC.bind(this));
|
||||
this.instance.server.handle("exp_groups-permission_group_delete", this.handleDeleteIPC.bind(this));
|
||||
}
|
||||
|
||||
async onStart() {
|
||||
// Send the most recent version of the permission string
|
||||
const permissionsString = await this.sendRcon(rconBase + "rcon.print(Groups.get_actions_json())");
|
||||
this.permissions = new Set(JSON.parse(permissionsString));
|
||||
this.instance.sendTo("controller", new PermissionStringsUpdate([
|
||||
new PermissionStrings(this.instance.id, this.permissions, Date.now())
|
||||
]));
|
||||
|
||||
// Subscribe to get updates for permission groups
|
||||
this.permissionGroups.subscribe(this.onPermissionGroupsUpdate.bind(this));
|
||||
this.permissionGroupUpdates.subscribe(this.onPermissionGroupUpdate.bind(this));
|
||||
}
|
||||
|
||||
async onControllerConnectionEvent(event: any) {
|
||||
this.permissionGroups.handleConnectionEvent(event);
|
||||
}
|
||||
|
||||
async onInstanceConfigFieldChanged(field: string, curr: unknown, prev: unknown) {
|
||||
if (field === "exp_groups.sync_permission_groups") {
|
||||
this.syncId = curr ? "Global" : this.instance.id;
|
||||
const [snapshot, synced] = this.permissionGroups.getSnapshot();
|
||||
if (synced && this.instance.status !== "running") await this.syncPermissionGroups(snapshot.values());
|
||||
}
|
||||
}
|
||||
|
||||
async onPermissionGroupsUpdate(event: PermissionGroupUpdate | null, synced: boolean) {
|
||||
if (!synced || this.instance.status !== "running" || !event?.updates.length) return;
|
||||
await this.syncPermissionGroups(event.updates);
|
||||
}
|
||||
|
||||
async syncPermissionGroups(groups: Iterable<PermissionGroup>) {
|
||||
const updateCommands = [rconBase];
|
||||
for (const group of groups) {
|
||||
if (group.instanceId === this.syncId && group.updatedAtMs > (this.permissionGroups.values.get(group.id)?.updatedAtMs ?? 0)) {
|
||||
if (group.isDeleted) {
|
||||
updateCommands.push(`Groups.destroy_group('${group.name}')`);
|
||||
} else if (group.permissions.size < this.permissions.size / 2) {
|
||||
updateCommands.push(`Groups.get_or_create('${group.name}'):from_json('${JSON.stringify([false, [...this.permissions.values()]])}')`);
|
||||
} else {
|
||||
const inverted = [...this.permissions.values()].filter(permission => !group.permissions.has(permission));
|
||||
updateCommands.push(`Groups.get_or_create('${group.name}'):from_json('${JSON.stringify([true, inverted])}')`);
|
||||
}
|
||||
}
|
||||
}
|
||||
await this.sendRcon(updateCommands.join(";"), true);
|
||||
}
|
||||
|
||||
async onPermissionGroupUpdate(event: PermissionGroupEditEvent | null, synced: boolean) {
|
||||
if (!synced || this.instance.status !== "running" || !event) return;
|
||||
if (event.src.equals(lib.Address.fromShorthand({ instanceId: this.instance.id }))) return;
|
||||
const getCmd = `Groups.get_or_create('${event.group}')`;
|
||||
if (event.type === "add_permissions") {
|
||||
await this.sendRcon(rconBase + getCmd + `:allow_actions(Groups.json_to_actions('${JSON.stringify(event.changes)}'))`);
|
||||
} else if (event.type === "remove_permissions") {
|
||||
await this.sendRcon(rconBase + getCmd + `:disallow_actions(Groups.json_to_actions('${JSON.stringify(event.changes)}'))`);
|
||||
} else if (event.type === "assign_players") {
|
||||
await this.sendRcon(rconBase + getCmd + `:add_players(game.json_to_table('${JSON.stringify(event.changes)}'))`);
|
||||
}
|
||||
}
|
||||
|
||||
async handleEditIPC(event: EditIPC) {
|
||||
this.logger.info(JSON.stringify(event))
|
||||
this.instance.sendTo("controller", new PermissionGroupEditEvent(
|
||||
lib.Address.fromShorthand({ instanceId: this.instance.id }),
|
||||
event.type, event.group, event.changes
|
||||
))
|
||||
}
|
||||
|
||||
async handleCreateIPC(event: CreateIPC) {
|
||||
this.logger.info(JSON.stringify(event))
|
||||
if (!this.permissionGroups.synced) return;
|
||||
let [defaultAllow, permissionsRaw] = event.defiantion;
|
||||
if (!Array.isArray(permissionsRaw)) {
|
||||
permissionsRaw = [] // lua outputs {} for empty arrays
|
||||
}
|
||||
const permissions = [...this.permissions.values()]
|
||||
.filter(permission => defaultAllow !== (permissionsRaw as String[]).includes(permission));
|
||||
this.instance.sendTo("controller", new PermissionGroupUpdate([ new PermissionGroup(
|
||||
this.syncId, event.group, 0, new Set(), new Set(permissions)
|
||||
) ]));
|
||||
}
|
||||
|
||||
async handleDeleteIPC(event: DeleteIPC) {
|
||||
if (!this.permissionGroups.synced) return;
|
||||
const group = [...this.permissionGroups.values.values()]
|
||||
.find(group => group.instanceId === this.syncId && group.name === event.group);
|
||||
if (group) {
|
||||
group.updatedAtMs = Date.now();
|
||||
group.isDeleted = true;
|
||||
this.instance.sendTo("controller", new PermissionGroupUpdate([ group ]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
import { User, InstanceDetails, IControllerUser, Link, MessageRequest, StringEnum, PermissionError, Address } from "@clusterio/lib";
|
||||
import { Type, Static } from "@sinclair/typebox";
|
||||
|
||||
export const PermissionInstanceIdSchema = Type.Union([InstanceDetails.jsonSchema.properties.id, Type.Literal("Global")])
|
||||
export type PermissionInstanceId = InstanceDetails["id"] | "Global"
|
||||
export type GamePermission = string; // todo: maybe enum this?
|
||||
|
||||
/**
|
||||
* Data class for permission groups
|
||||
*/
|
||||
export class PermissionGroup {
|
||||
constructor(
|
||||
public instanceId: PermissionInstanceId,
|
||||
public name: string,
|
||||
/** A lower order assumes a lower permission group */
|
||||
public order: number = 0,
|
||||
/** A role will use the highest order group it is apart of */
|
||||
public roleIds: User["roleIds"] = new Set(),
|
||||
public permissions: Set<GamePermission> = new Set(),
|
||||
public updatedAtMs: number = 0,
|
||||
public isDeleted: boolean = false,
|
||||
) {
|
||||
}
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
instanceId: PermissionInstanceIdSchema,
|
||||
name: Type.String(),
|
||||
order: Type.Number(),
|
||||
roleIds: Type.Array(Type.Number()),
|
||||
permissions: Type.Array(Type.String()),
|
||||
updatedAtMs: Type.Optional(Type.Number()),
|
||||
isDeleted: Type.Optional(Type.Boolean()),
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof this.jsonSchema>) {
|
||||
return new this(
|
||||
json.instanceId,
|
||||
json.name,
|
||||
json.order,
|
||||
new Set(json.roleIds),
|
||||
new Set(json.permissions),
|
||||
json.updatedAtMs,
|
||||
json.isDeleted
|
||||
);
|
||||
}
|
||||
|
||||
toJSON(): Static<typeof PermissionGroup.jsonSchema> {
|
||||
return {
|
||||
instanceId: this.instanceId,
|
||||
name: this.name,
|
||||
order: this.order,
|
||||
roleIds: [...this.roleIds.values()],
|
||||
permissions: [...this.permissions.values()],
|
||||
updatedAtMs: this.updatedAtMs > 0 ? this.updatedAtMs : undefined,
|
||||
isDeleted: this.isDeleted ? this.isDeleted : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
get id() {
|
||||
return `${this.instanceId}:${this.name}`;
|
||||
}
|
||||
|
||||
copy(newInstanceId: PermissionInstanceId) {
|
||||
return new PermissionGroup(
|
||||
newInstanceId,
|
||||
this.name,
|
||||
this.order,
|
||||
new Set(this.roleIds),
|
||||
new Set(this.permissions),
|
||||
Date.now(),
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export class InstancePermissionGroups {
|
||||
constructor(
|
||||
public instanceId: PermissionInstanceId,
|
||||
public groups: Map<PermissionGroup["name"], PermissionGroup> = new Map(),
|
||||
) {
|
||||
}
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
instanceId: PermissionInstanceIdSchema,
|
||||
permissionsGroups: Type.Array(PermissionGroup.jsonSchema),
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof InstancePermissionGroups.jsonSchema>) {
|
||||
return new InstancePermissionGroups(
|
||||
json.instanceId,
|
||||
new Map(json.permissionsGroups.map(group => [group.name, PermissionGroup.fromJSON(group)])),
|
||||
);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
instanceId: this.instanceId,
|
||||
permissionsGroups: [...this.groups.values()],
|
||||
}
|
||||
}
|
||||
|
||||
getUserGroup(user: User) {
|
||||
const groups = [...user.roleIds.values()].map(roleId =>
|
||||
// There will always be one and only one group for each role
|
||||
[...this.groups.values()].find(group => group.roleIds.has(roleId))!
|
||||
);
|
||||
return groups.reduce((highest, group) => highest.order > group.order ? highest : group);
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this.instanceId;
|
||||
}
|
||||
}
|
||||
|
||||
export class PermissionGroupUpdate {
|
||||
declare ["constructor"]: typeof PermissionGroupUpdate;
|
||||
static type = "event" as const;
|
||||
static src = ["controller", "instance"] as const;
|
||||
static dst = ["control", "instance", "controller"] as const;
|
||||
static plugin = "exp_groups" as const;
|
||||
static permission = "exp_groups.list.subscribe";
|
||||
|
||||
constructor(
|
||||
public updates: PermissionGroup[],
|
||||
) { }
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
"updates": Type.Array(PermissionGroup.jsonSchema),
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof this.jsonSchema>) {
|
||||
return new this(
|
||||
json.updates.map(update => PermissionGroup.fromJSON(update))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export type PermissionGroupEditType = "assign_players" | "add_permissions" | "remove_permissions";
|
||||
|
||||
export class PermissionGroupEditEvent {
|
||||
declare ["constructor"]: typeof PermissionGroupEditEvent;
|
||||
static type = "event" as const;
|
||||
static src = ["instance", "controller"] as const;
|
||||
static dst = ["control", "instance", "controller"] as const;
|
||||
static plugin = "exp_groups" as const;
|
||||
|
||||
static permission(user: IControllerUser, message: MessageRequest) {
|
||||
if (typeof message.data === "object" && message.data !== null) {
|
||||
const data = message.data as Static<typeof PermissionGroupEditEvent.jsonSchema>;
|
||||
if (data.type === "add_permissions" || data.type === "remove_permissions") {
|
||||
user.checkPermission("exp_groups.modify_permissions")
|
||||
} else if (data.type === "assign_players") {
|
||||
user.checkPermission("exp_groups.assign_players")
|
||||
} else {
|
||||
throw new PermissionError("Permission denied");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
constructor(
|
||||
public src: Address,
|
||||
public type: PermissionGroupEditType,
|
||||
public group: string,
|
||||
public changes: String[],
|
||||
) { }
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
"src": Address.jsonSchema,
|
||||
"type": StringEnum(["assign_players", "add_permissions", "remove_permissions"]),
|
||||
"group": Type.String(),
|
||||
"changes": Type.Array(Type.String()),
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof this.jsonSchema>) {
|
||||
return new this(Address.fromJSON(json.src), json.type, json.group, json.changes);
|
||||
}
|
||||
}
|
||||
|
||||
export class PermissionStrings {
|
||||
constructor(
|
||||
public instanceId: PermissionInstanceId,
|
||||
public permissions: Set<GamePermission>,
|
||||
public updatedAtMs: number = 0,
|
||||
public isDeleted: boolean = false,
|
||||
) {
|
||||
}
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
instanceId: PermissionInstanceIdSchema,
|
||||
permissions: Type.Array(Type.String()),
|
||||
updatedAtMs: Type.Optional(Type.Number()),
|
||||
isDeleted: Type.Optional(Type.Boolean()),
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof PermissionStrings.jsonSchema>) {
|
||||
return new PermissionStrings(
|
||||
json.instanceId,
|
||||
new Set(json.permissions),
|
||||
json.updatedAtMs,
|
||||
json.isDeleted
|
||||
);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
instanceId: this.instanceId,
|
||||
permissions: [...this.permissions.values()],
|
||||
updatedAtMs: this.updatedAtMs > 0 ? this.updatedAtMs : undefined,
|
||||
isDeleted: this.isDeleted ? this.isDeleted : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this.instanceId
|
||||
}
|
||||
}
|
||||
|
||||
export class PermissionStringsUpdate {
|
||||
declare ["constructor"]: typeof PermissionStringsUpdate;
|
||||
static type = "event" as const;
|
||||
static src = ["instance", "controller"] as const;
|
||||
static dst = ["controller", "control"] as const;
|
||||
static plugin = "exp_groups" as const;
|
||||
static permission = "exp_groups.list.subscribe";
|
||||
|
||||
constructor(
|
||||
public updates: PermissionStrings[],
|
||||
) { }
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
"updates": Type.Array(PermissionStrings.jsonSchema),
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof this.jsonSchema>) {
|
||||
return new this(
|
||||
json.updates.map(update => PermissionStrings.fromJSON(update))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
local clusterio_api = require("modules/clusterio/api")
|
||||
local Global = require("modules/exp_util/global")
|
||||
local Groups = require("modules/exp_groups")
|
||||
|
||||
local pending_updates = {}
|
||||
Global.register(pending_updates, function(tbl)
|
||||
pending_updates = tbl
|
||||
end)
|
||||
|
||||
local function on_permission_group_added(event)
|
||||
if not event.player_index then return end
|
||||
pending_updates[event.group.name] = {
|
||||
created = true,
|
||||
sync_all = true,
|
||||
tick = event.tick,
|
||||
permissions = {},
|
||||
players = {},
|
||||
}
|
||||
end
|
||||
|
||||
local function on_permission_group_deleted(event)
|
||||
if not event.player_index then return end
|
||||
local existing = pending_updates[event.group_name]
|
||||
pending_updates[event.group_name] = nil
|
||||
if not existing or not existing.created then
|
||||
clusterio_api.send_json("exp_groups-permission_group_delete", {
|
||||
group = event.group_name,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local function on_permission_group_edited(event)
|
||||
if not event.player_index then return end
|
||||
local pending = pending_updates[event.group.name]
|
||||
if not pending then
|
||||
pending = {
|
||||
tick = event.tick,
|
||||
permissions = {},
|
||||
players = {},
|
||||
}
|
||||
pending_updates[event.group.name] = pending
|
||||
end
|
||||
pending.tick = event.tick
|
||||
|
||||
if event.type == "add-permission" then
|
||||
if not pending.sync_all then
|
||||
pending.permissions[event.action] = true
|
||||
end
|
||||
elseif event.type == "remove-permission" then
|
||||
if not pending.sync_all then
|
||||
pending.permissions[event.action] = false
|
||||
end
|
||||
elseif event.type == "enable-all" then
|
||||
pending.sync_all = true
|
||||
elseif event.type == "disable-all" then
|
||||
pending.sync_all = true
|
||||
elseif event.type == "add-player" then
|
||||
local player = game.get_player(event.other_player_index) --- @cast player -nil
|
||||
pending.players[player.name] = true
|
||||
elseif event.type == "remove-player" then
|
||||
local player = game.get_player(event.other_player_index) --- @cast player -nil
|
||||
pending.players[player.name] = nil
|
||||
elseif event.type == "rename" then
|
||||
pending.created = true
|
||||
pending.sync_all = true
|
||||
local old = pending_updates[event.old_name]
|
||||
if old then pending.players = old.players end
|
||||
on_permission_group_deleted{
|
||||
tick = event.tick, player_index = event.player_index, group_name = event.old_name,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function send_updates()
|
||||
local tick = game.tick - 600 -- 10 Seconds
|
||||
local done = {}
|
||||
for group_name, pending in pairs(pending_updates) do
|
||||
if pending.tick < tick then
|
||||
done[group_name] = true
|
||||
if pending.sync_all then
|
||||
clusterio_api.send_json("exp_groups-permission_group_create", {
|
||||
group = group_name, defiantion = Groups.get_group(group_name):to_json(true),
|
||||
})
|
||||
else
|
||||
if next(pending.players) then
|
||||
clusterio_api.send_json("exp_groups-permission_group_edit", {
|
||||
type = "assign_players", group = group_name, changes = table.get_keys(pending.players),
|
||||
})
|
||||
end
|
||||
local add, remove = {}, {}
|
||||
for permission, state in pairs(pending.permissions) do
|
||||
if state then
|
||||
add[#add + 1] = permission
|
||||
else
|
||||
remove[#remove + 1] = permission
|
||||
end
|
||||
end
|
||||
|
||||
if next(add) then
|
||||
clusterio_api.send_json("exp_groups-permission_group_edit", {
|
||||
type = "add_permissions", group = group_name, changes = Groups.actions_to_names(add),
|
||||
})
|
||||
end
|
||||
if next(remove) then
|
||||
clusterio_api.send_json("exp_groups-permission_group_edit", {
|
||||
type = "remove_permissions", group = group_name, changes = Groups.actions_to_names(remove),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for group_name in pairs(done) do
|
||||
pending_updates[group_name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
events = {
|
||||
[defines.events.on_permission_group_added] = on_permission_group_added,
|
||||
[defines.events.on_permission_group_deleted] = on_permission_group_deleted,
|
||||
[defines.events.on_permission_group_edited] = on_permission_group_edited,
|
||||
},
|
||||
on_nth_tick = {
|
||||
[300] = send_updates,
|
||||
},
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "exp_groups",
|
||||
"load": [
|
||||
"control.lua"
|
||||
],
|
||||
"require": [
|
||||
],
|
||||
"dependencies": {
|
||||
"clusterio": "*",
|
||||
"exp_util": "*"
|
||||
}
|
||||
}
|
||||
@@ -1,306 +0,0 @@
|
||||
local Async = require("modules/exp_util/async")
|
||||
|
||||
local table_to_json = helpers.table_to_json
|
||||
local json_to_table = helpers.json_to_table
|
||||
|
||||
--- Top level module table, contains event handlers and public methods
|
||||
local Groups = {}
|
||||
|
||||
--- @class ExpGroup : LuaPermissionGroup
|
||||
--- @field group LuaPermissionGroup The permission group for this group proxy
|
||||
Groups._prototype = {}
|
||||
|
||||
Groups._metatable = {
|
||||
__index = setmetatable(Groups._prototype, {
|
||||
--- @type any Annotation required because otherwise it is typed as 'table'
|
||||
__index = function(self, key)
|
||||
return self.group[key]
|
||||
end,
|
||||
}),
|
||||
__class = "ExpGroup",
|
||||
}
|
||||
|
||||
local action_to_name = {}
|
||||
for name, action in pairs(defines.input_action) do
|
||||
action_to_name[action] = name
|
||||
end
|
||||
|
||||
--- Async Functions
|
||||
-- These are required to allow bypassing edit_permission_group
|
||||
|
||||
--- Add a player to a permission group, requires edit_permission_group
|
||||
--- @param player LuaPlayer Player to add to the group
|
||||
--- @param group LuaPermissionGroup Group to add the player to
|
||||
--- @return boolean # True if successful
|
||||
local function add_player_to_group(player, group)
|
||||
return group.add_player(player)
|
||||
end
|
||||
|
||||
--- Add a players to a permission group, requires edit_permission_group
|
||||
--- @param players LuaPlayer[] Players to add to the group
|
||||
--- @param group LuaPermissionGroup Group to add the players to
|
||||
--- @return boolean # True if successful
|
||||
local function add_players_to_group(players, group)
|
||||
local add_player = group.add_player
|
||||
if not add_player(players[1]) then
|
||||
return false
|
||||
end
|
||||
for i = 2, #players do
|
||||
add_player(players[i])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Async will bypass edit_permission_group but takes at least one tick
|
||||
local add_player_to_group_async = Async.register(add_player_to_group)
|
||||
local add_players_to_group_async = Async.register(add_players_to_group)
|
||||
|
||||
--- Static methods for gettings, creating and removing permission groups
|
||||
|
||||
--- Gets the permission group proxy with the given name or group ID.
|
||||
--- @param group_name string|uint32 The name or id of the permission group
|
||||
--- @return ExpGroup?
|
||||
function Groups.get_group(group_name)
|
||||
local group = game.permissions.get_group(group_name)
|
||||
if group == nil then return nil end
|
||||
return setmetatable({
|
||||
group = group,
|
||||
}, Groups._metatable)
|
||||
end
|
||||
|
||||
--- Gets the permission group proxy for a players group
|
||||
--- @param player LuaPlayer The player to get the group of
|
||||
--- @return ExpGroup?
|
||||
function Groups.get_player_group(player)
|
||||
local group = player.permission_group
|
||||
if group == nil then return nil end
|
||||
return setmetatable({
|
||||
group = group,
|
||||
}, Groups._metatable)
|
||||
end
|
||||
|
||||
--- Creates a new permission group, requires add_permission_group
|
||||
--- @param group_name string Name of the group to create
|
||||
--- @return ExpGroup
|
||||
function Groups.new_group(group_name)
|
||||
local group = game.permissions.get_group(group_name)
|
||||
assert(group == nil, "Group already exists with name: " .. group_name)
|
||||
group = game.permissions.create_group(group_name)
|
||||
assert(group ~= nil, "Requires permission add_permission_group")
|
||||
return setmetatable({
|
||||
group = group,
|
||||
}, Groups._metatable)
|
||||
end
|
||||
|
||||
--- Get or create a permisison group, must use the group name not the group id
|
||||
--- @param group_name string Name of the group to create
|
||||
--- @return ExpGroup
|
||||
function Groups.get_or_create(group_name)
|
||||
local group = game.permissions.get_group(group_name)
|
||||
if group then
|
||||
return setmetatable({
|
||||
group = group,
|
||||
}, Groups._metatable)
|
||||
else
|
||||
group = game.permissions.create_group(group_name)
|
||||
assert(group ~= nil, "Requires permission add_permission_group")
|
||||
return setmetatable({
|
||||
group = group,
|
||||
}, Groups._metatable)
|
||||
end
|
||||
end
|
||||
|
||||
--- Destory a permission group, moves all players to default group
|
||||
--- @param group_name string|uint32 The name or id of the permission group to destroy
|
||||
--- @param move_to_name string|uint32? The name or id of the permission group to move players to
|
||||
function Groups.destroy_group(group_name, move_to_name)
|
||||
local group = game.permissions.get_group(group_name)
|
||||
if group == nil then return end
|
||||
|
||||
local players = group.players
|
||||
if #players > 0 then
|
||||
local move_to = game.permissions.get_group(move_to_name or "Default")
|
||||
for _, player in ipairs(players) do
|
||||
player.permission_group = move_to
|
||||
end
|
||||
end
|
||||
|
||||
local success = group.destroy()
|
||||
assert(success, "Requires permission delete_permission_group")
|
||||
end
|
||||
|
||||
--- Prototype methods for modifying and working with permission groups
|
||||
|
||||
--- Add a player to the permission group
|
||||
--- @param player LuaPlayer The player to add to the group
|
||||
function Groups._prototype:add_player(player)
|
||||
if not add_player_to_group(player, self.group) then
|
||||
add_player_to_group_async(player, self.group)
|
||||
end
|
||||
end
|
||||
|
||||
--- Add players to the permission group
|
||||
--- @param players LuaPlayer[] The player to add to the group
|
||||
function Groups._prototype:add_players(players)
|
||||
if not add_players_to_group(players, self.group) then
|
||||
add_players_to_group_async(players, self.group)
|
||||
end
|
||||
end
|
||||
|
||||
--- Move all players to another group
|
||||
--- @param other_group ExpGroup The group to move players to, default is the Default group
|
||||
function Groups._prototype:move_players(other_group)
|
||||
if not add_players_to_group(self.group.players, other_group.group) then
|
||||
add_players_to_group_async(self.group.players, other_group.group)
|
||||
end
|
||||
end
|
||||
|
||||
--- Allow a set of actions for this group
|
||||
--- @param actions defines.input_action[] Actions to allow
|
||||
--- @return ExpGroup
|
||||
function Groups._prototype:allow_actions(actions)
|
||||
local set_allow = self.group.set_allows_action
|
||||
for _, action in ipairs(actions) do
|
||||
set_allow(action, true)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Disallow a set of actions for this group
|
||||
--- @param actions defines.input_action[] Actions to disallow
|
||||
--- @return ExpGroup
|
||||
function Groups._prototype:disallow_actions(actions)
|
||||
local set_allow = self.group.set_allows_action
|
||||
for _, action in ipairs(actions) do
|
||||
set_allow(action, false)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Reset the allowed state of all actions
|
||||
--- @param allowed boolean? default true for allow all actions, false to disallow all actions
|
||||
--- @return ExpGroup
|
||||
function Groups._prototype:reset(allowed)
|
||||
local set_allow = self.group.set_allows_action
|
||||
if allowed == nil then allowed = true end
|
||||
for _, action in pairs(defines.input_action) do
|
||||
set_allow(action, allowed)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns if the group is allowed a given action
|
||||
--- @param action string|defines.input_action Actions to test
|
||||
--- @return boolean # True if successful
|
||||
function Groups._prototype:allows(action)
|
||||
if type(action) == "string" then
|
||||
return self.group.allows_action(defines.input_action[action])
|
||||
end
|
||||
return self.group.allows_action(action)
|
||||
end
|
||||
|
||||
--- Print a message to all players in the group
|
||||
function Groups._prototype:print(...)
|
||||
for _, player in ipairs(self.group.players) do
|
||||
player.print(...)
|
||||
end
|
||||
end
|
||||
|
||||
--- Static and Prototype methods for use with IPC
|
||||
|
||||
--- Convert an array of strings into an array of action names
|
||||
--- @param actions_names string[] An array of action names
|
||||
--- @return defines.input_action[]
|
||||
local function names_to_actions(actions_names)
|
||||
--- @type defines.input_action[], number[], number
|
||||
local actions, invalid, invalid_i = {}, {}, 1
|
||||
for i, action_name in ipairs(actions_names) do
|
||||
local action = defines.input_action[action_name] --[[ @as defines.input_action? ]]
|
||||
if action then
|
||||
actions[i] = action
|
||||
else
|
||||
invalid[invalid_i] = i
|
||||
invalid_i = invalid_i + 1
|
||||
end
|
||||
end
|
||||
|
||||
local last = #actions
|
||||
for _, i in ipairs(invalid) do
|
||||
actions[i] = actions[last]
|
||||
last = last - 1
|
||||
end
|
||||
|
||||
return actions
|
||||
end
|
||||
|
||||
--- Get the action names from the action numbers
|
||||
function Groups.actions_to_names(actions)
|
||||
local names = {}
|
||||
for i, action in ipairs(actions) do
|
||||
names[i] = action_to_name[action]
|
||||
end
|
||||
|
||||
return names
|
||||
end
|
||||
|
||||
--- Get all input actions that are defined
|
||||
function Groups.get_actions_json()
|
||||
local rtn, rtn_i = {}, 1
|
||||
for name in pairs(defines.input_action) do
|
||||
rtn[rtn_i] = name
|
||||
rtn_i = rtn_i + 1
|
||||
end
|
||||
|
||||
return table_to_json(rtn)
|
||||
end
|
||||
|
||||
--- Convert a json string array into an array of input actions
|
||||
--- @param json string A json string representing a string array of actions
|
||||
--- @return defines.input_action[]
|
||||
function Groups.json_to_actions(json)
|
||||
local tbl = json_to_table(json)
|
||||
assert(tbl, "Invalid Json String")
|
||||
--- @cast tbl string[]
|
||||
return names_to_actions(tbl)
|
||||
end
|
||||
|
||||
--- Returns the shortest defination of the allowed actions
|
||||
-- The first value of the return can be passed to :reset
|
||||
function Groups._prototype:to_json(raw)
|
||||
local allow, disallow = {}, {}
|
||||
local allow_i, disallow_i = 1, 1
|
||||
local allows = self.group.allows_action
|
||||
for name, action in pairs(defines.input_action) do
|
||||
if allows(action) then
|
||||
allow[allow_i] = name
|
||||
allow_i = allow_i + 1
|
||||
else
|
||||
disallow[disallow_i] = name
|
||||
disallow_i = disallow_i + 1
|
||||
end
|
||||
end
|
||||
|
||||
if allow_i >= disallow_i then
|
||||
return raw and { true, disallow } or table_to_json{ true, disallow }
|
||||
end
|
||||
return raw and { false, allow } or table_to_json{ false, allow }
|
||||
end
|
||||
|
||||
--- Restores this group to the state given in a json string
|
||||
--- @param json string The json string to restore from
|
||||
function Groups._prototype:from_json(json)
|
||||
local tbl = json_to_table(json)
|
||||
assert(tbl and type(tbl[1]) == "boolean" and type(tbl[2]) == "table", "Invalid Json String")
|
||||
|
||||
if tbl[1] then
|
||||
self:reset(true):disallow_actions(names_to_actions(tbl[2]))
|
||||
return
|
||||
end
|
||||
self:reset(false):allow_actions(names_to_actions(tbl[2]))
|
||||
end
|
||||
|
||||
return Groups
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.browser.json",
|
||||
"include": [ "web/**/*.tsx", "web/**/*.ts", "messages.ts", "package.json" ],
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.browser.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.node.json",
|
||||
"include": ["./**/*.ts"],
|
||||
"exclude": ["test/*", "./dist/*"],
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Tree } from 'antd';
|
||||
import type { TreeDataNode, TreeProps } from 'antd';
|
||||
|
||||
const defaultData: TreeDataNode[] = [
|
||||
{
|
||||
title: "Group 1",
|
||||
key: "G-1",
|
||||
icon: false,
|
||||
children: [
|
||||
{
|
||||
title: "Role 1",
|
||||
key: "R-1"
|
||||
},
|
||||
{
|
||||
title: "Role 2",
|
||||
key: "R-2"
|
||||
},
|
||||
{
|
||||
title: "Role 3",
|
||||
key: "R-3"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Group 2",
|
||||
key: "G-2",
|
||||
icon: false,
|
||||
children: [
|
||||
{
|
||||
title: "Role 4",
|
||||
key: "R-4"
|
||||
},
|
||||
{
|
||||
title: "Role 5",
|
||||
key: "R-5"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Default",
|
||||
key: "G-3",
|
||||
icon: false,
|
||||
children: [
|
||||
{
|
||||
title: "Role 6",
|
||||
key: "R-6"
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export function GroupTree() {
|
||||
const [gData, setGData] = useState(defaultData);
|
||||
|
||||
const onDrop: TreeProps['onDrop'] = (info) => {
|
||||
const dropKey = info.node.key;
|
||||
const dragKey = info.dragNode.key;
|
||||
const dropPos = info.node.pos.split('-');
|
||||
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]); // the drop position relative to the drop node, inside 0, top -1, bottom 1
|
||||
|
||||
const findKey = (
|
||||
data: TreeDataNode[],
|
||||
key: React.Key,
|
||||
callback: (node: TreeDataNode, i: number, data: TreeDataNode[]) => void,
|
||||
) => {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].key === key) {
|
||||
return callback(data[i], i, data);
|
||||
}
|
||||
if (data[i].children) {
|
||||
findKey(data[i].children!, key, callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const data = [...gData]
|
||||
|
||||
// Find dragObject
|
||||
let dragObj: TreeDataNode;
|
||||
findKey(data, dragKey, (item, index, arr) => {
|
||||
arr.splice(index, 1);
|
||||
dragObj = item;
|
||||
});
|
||||
|
||||
if (!info.dropToGap) {
|
||||
// Drop on the content
|
||||
findKey(data, dropKey, (item) => {
|
||||
item.children = item.children || [];
|
||||
// where to insert. New item was inserted to the start of the array in this example, but can be anywhere
|
||||
item.children.unshift(dragObj);
|
||||
});
|
||||
} else {
|
||||
let ar: TreeDataNode[] = [];
|
||||
let i: number;
|
||||
findKey(data, dropKey, (_item, index, arr) => {
|
||||
ar = arr;
|
||||
i = index;
|
||||
});
|
||||
if (dropPosition === -1) {
|
||||
// Drop on the top of the drop node
|
||||
ar.splice(i!, 0, dragObj!);
|
||||
} else {
|
||||
// Drop on the bottom of the drop node
|
||||
ar.splice(i! + 1, 0, dragObj!);
|
||||
}
|
||||
}
|
||||
|
||||
setGData(data)
|
||||
};
|
||||
|
||||
const allowDrop: TreeProps['allowDrop'] = ({dragNode, dropNode, dropPosition}) => {
|
||||
const dragType = (dragNode.key as string).charAt(0);
|
||||
const dropType = (dropNode.key as string).charAt(0);
|
||||
return dropType === dragType && dropPosition != 0 || dragType === "R" && dropType === "G" && dropPosition == 0
|
||||
}
|
||||
|
||||
return (
|
||||
<Tree
|
||||
className="draggable-tree"
|
||||
defaultExpandAll={true}
|
||||
draggable
|
||||
blockNode
|
||||
onDrop={onDrop}
|
||||
allowDrop={allowDrop}
|
||||
treeData={gData}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
import React, {
|
||||
useContext, useEffect, useState,
|
||||
useCallback, useSyncExternalStore,
|
||||
} from "react";
|
||||
|
||||
// import {
|
||||
//
|
||||
// } from "antd";
|
||||
|
||||
import {
|
||||
BaseWebPlugin, PageLayout, PageHeader, Control, ControlContext, notifyErrorHandler,
|
||||
useInstances,
|
||||
} from "@clusterio/web_ui";
|
||||
|
||||
import { PermissionGroupUpdate, PermissionInstanceId, PermissionStringsUpdate } from "../messages";
|
||||
|
||||
import * as lib from "@clusterio/lib";
|
||||
|
||||
import { GroupTree } from "./components/groupTree";
|
||||
|
||||
function MyTemplatePage() {
|
||||
const control = useContext(ControlContext);
|
||||
const plugin = control.plugins.get("exp_groups") as WebPlugin;
|
||||
const [permissionStrings, permissionStringsSynced] = plugin.usePermissionStrings();
|
||||
const [permissionGroups, permissionGroupsSynced] = plugin.usePermissionGroups();
|
||||
const [instances, instancesSync] = useInstances();
|
||||
|
||||
let [roles, setRoles] = useState<lib.Role[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
control.send(new lib.RoleListRequest()).then(newRoles => {
|
||||
setRoles(newRoles);
|
||||
}).catch(notifyErrorHandler("Error fetching role list"));
|
||||
}, []);
|
||||
|
||||
return <PageLayout nav={[{ name: "exp_groups" }]}>
|
||||
<PageHeader title="exp_groups" />
|
||||
Permission Strings: {String(permissionStringsSynced)} {JSON.stringify([...permissionStrings.values()])} <br/>
|
||||
Permission Groups: {String(permissionGroupsSynced)} {JSON.stringify([...permissionGroups.values()])} <br/>
|
||||
Instances: {String(instancesSync)} {JSON.stringify([...instances.values()].map(instance => [instance.id, instance.name]))} <br/>
|
||||
Roles: {JSON.stringify([...roles.values()].map(role => [role.id, role.name]))} <br/>
|
||||
<GroupTree/>
|
||||
</PageLayout>;
|
||||
}
|
||||
|
||||
export class WebPlugin extends BaseWebPlugin {
|
||||
permissionStrings = new lib.EventSubscriber(PermissionStringsUpdate, this.control);
|
||||
permissionGroups = new lib.EventSubscriber(PermissionGroupUpdate, this.control);
|
||||
|
||||
async init() {
|
||||
this.pages = [
|
||||
{
|
||||
path: "/exp_groups",
|
||||
sidebarName: "exp_groups",
|
||||
permission: "exp_groups.list",
|
||||
content: <MyTemplatePage/>,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
useInstancePermissionStrings(instanceId?: PermissionInstanceId) {
|
||||
const [permissionStrings, synced] = this.usePermissionStrings();
|
||||
return [instanceId !== undefined ? permissionStrings.get(instanceId) : undefined, synced] as const;
|
||||
}
|
||||
|
||||
usePermissionStrings() {
|
||||
const control = useContext(ControlContext);
|
||||
const subscribe = useCallback((callback: () => void) => this.permissionStrings.subscribe(callback), [control]);
|
||||
return useSyncExternalStore(subscribe, () => this.permissionStrings.getSnapshot());
|
||||
}
|
||||
|
||||
useInstancePermissionGroups(instanceId?: PermissionInstanceId) {
|
||||
const [permissionGroups, synced] = this.usePermissionGroups();
|
||||
return [instanceId !== undefined ? [...permissionGroups.values()].filter(group => group.instanceId === instanceId) : undefined, synced] as const;
|
||||
}
|
||||
|
||||
usePermissionGroups() {
|
||||
const control = useContext(ControlContext);
|
||||
const subscribe = useCallback((callback: () => void) => this.permissionGroups.subscribe(callback), [control]);
|
||||
return useSyncExternalStore(subscribe, () => this.permissionGroups.getSnapshot());
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
"use strict";
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const { merge } = require("webpack-merge");
|
||||
|
||||
const common = require("@clusterio/web_ui/webpack.common");
|
||||
|
||||
module.exports = (env = {}) => merge(common(env), {
|
||||
context: __dirname,
|
||||
entry: "./web/index.tsx",
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist", "web"),
|
||||
},
|
||||
plugins: [
|
||||
new webpack.container.ModuleFederationPlugin({
|
||||
name: "exp_groups",
|
||||
library: { type: "window", name: "plugin_exp_groups" },
|
||||
exposes: {
|
||||
"./": "./index.ts",
|
||||
"./package.json": "./package.json",
|
||||
"./web": "./web/index.tsx",
|
||||
},
|
||||
shared: {
|
||||
"@clusterio/lib": { import: false },
|
||||
"@clusterio/web_ui": { import: false },
|
||||
"antd": { import: false },
|
||||
"react": { import: false },
|
||||
"react-dom": { import: false },
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
[exp-gui]
|
||||
clear-left-flow=Hide all open windows.
|
||||
close-toolbar=__CONTROL_LEFT_CLICK__: Toggle Settings\n__CONTROL_RIGHT_CLICK__: Close Toolbar
|
||||
|
||||
@@ -23,13 +23,13 @@ return {
|
||||
|
||||
--- GUI
|
||||
"modules.gui.readme",
|
||||
"modules.gui.rocket-info",
|
||||
"modules.gui.task-list",
|
||||
"modules.gui.warp-list",
|
||||
"modules.gui.player-list",
|
||||
"modules.gui.vlayer",
|
||||
"modules.gui._role_updates",
|
||||
|
||||
"modules.graftorio.require", -- graftorio
|
||||
-- "modules.graftorio.require", -- graftorio
|
||||
--- Config Files
|
||||
"config.expcore.permission_groups", -- loads some predefined permission groups
|
||||
"config.expcore.roles", -- loads some predefined roles
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
--- These are called factories because they return another function
|
||||
-- use these as a simple methods of adding new items
|
||||
-- they will do most of the work for you
|
||||
-- ['item-name'] = factory(params)
|
||||
-- ["item-name"] = factory(params)
|
||||
-- luacheck:ignore 212/amount_made 212/items_made 212/player
|
||||
|
||||
-- Use these to adjust for ticks ie game.tick < 5*minutes
|
||||
@@ -12,7 +12,7 @@
|
||||
local seconds, minutes, hours = 60, 3600, 216000
|
||||
|
||||
--- Use to make a split point for the number of items given based on time
|
||||
-- ['stone-furnace']=cutoff_time(5*minutes, 4,0) -- before 5 minutes give four items after 5 minutes give none
|
||||
-- ["stone-furnace"]=cutoff_time(5*minutes, 4,0) -- before 5 minutes give four items after 5 minutes give none
|
||||
local function cutoff_time(time, before, after)
|
||||
return function(amount_made, items_made, player)
|
||||
if game.tick < time then
|
||||
@@ -24,7 +24,8 @@ local function cutoff_time(time, before, after)
|
||||
end
|
||||
|
||||
--- Use to make a split point for the number of items given based on amount made
|
||||
-- ['firearm-magazine']=cutoff_amount_made(100, 10, 0) -- give 10 items until 100 items have been made
|
||||
-- ["firearm-magazine"]=cutoff_amount_made(100, 10, 0) -- give 10 items until 100 items have been made
|
||||
--[[
|
||||
local function cutoff_amount_made(amount, before, after)
|
||||
return function(amount_made, items_made, player)
|
||||
if amount_made < amount then
|
||||
@@ -34,9 +35,11 @@ local function cutoff_amount_made(amount, before, after)
|
||||
end
|
||||
end
|
||||
end
|
||||
]]
|
||||
|
||||
--- Same as above but will not give any items if x amount has been made of another item, useful for tiers
|
||||
-- ['light-armor']=cutoff_amount_made_unless(5, 0,1,'heavy-armor',5) -- give light armor once 5 have been made unless 5 heavy armor has been made
|
||||
-- ["light-armor"]=cutoff_amount_made_unless(5, 0,1,"heavy-armor",5) -- give light armor once 5 have been made unless 5 heavy armor has been made
|
||||
--[[
|
||||
local function cutoff_amount_made_unless(amount, before, after, second_item, second_amount)
|
||||
return function(amount_made, items_made, player)
|
||||
if items_made(second_item) < second_amount then
|
||||
@@ -50,9 +53,11 @@ local function cutoff_amount_made_unless(amount, before, after, second_item, sec
|
||||
end
|
||||
end
|
||||
end
|
||||
]]
|
||||
|
||||
-- Use for mass production items where you want the amount to change based on the amount already made
|
||||
-- ['iron-plate']=scale_amount_made(5*minutes, 10, 10) -- for first 5 minutes give 10 items then after apply a factor of 10
|
||||
-- ["iron-plate"]=scale_amount_made(5*minutes, 10, 10) -- for first 5 minutes give 10 items then after apply a factor of 10
|
||||
--[[
|
||||
local function scale_amount_made(amount, before, scalar)
|
||||
return function(amount_made, items_made, player)
|
||||
if amount_made < amount then
|
||||
@@ -62,12 +67,13 @@ local function scale_amount_made(amount, before, scalar)
|
||||
end
|
||||
end
|
||||
end
|
||||
]]
|
||||
|
||||
--[[
|
||||
Common values
|
||||
game.tick is the amount of time the game has been on for
|
||||
amount_made is the amount of that item which has been made
|
||||
items_made('item-name') will return the amount of any item made
|
||||
items_made("item-name") will return the amount of any item made
|
||||
player is the player who just spawned
|
||||
hours, minutes, seconds are the number of ticks in each unit of time
|
||||
]]
|
||||
@@ -78,35 +84,30 @@ return {
|
||||
friendly_fire = false, --- @setting friendly_fire weather players will be able to attack each other on the same force
|
||||
disable_crashsite = true, --- @setting disable_crashsite weather to disable creation of the crashsite
|
||||
enemy_expansion = false, --- @setting enemy_expansion a catch all for in case the map settings file fails to load
|
||||
chart_radius = 10 * 32, --- @setting chart_radius the number of tiles that will be charted when the map starts
|
||||
chart_radius = 16 * 32, --- @setting chart_radius the number of tiles that will be charted when the map starts
|
||||
items = { --- @setting items items and there condition for being given
|
||||
-- ['item-name'] = function(amount_made, production_stats, player) return <Number> end -- 0 means no items given
|
||||
-- Plates
|
||||
["iron-plate"] = scale_amount_made(100, 10, 10),
|
||||
["copper-plate"] = scale_amount_made(100, 0, 8),
|
||||
["steel-plate"] = scale_amount_made(100, 0, 4),
|
||||
-- Secondary Items
|
||||
["electronic-circuit"] = scale_amount_made(1000, 0, 6),
|
||||
["iron-gear-wheel"] = scale_amount_made(1000, 0, 6),
|
||||
-- Starting Items
|
||||
["burner-mining-drill"] = cutoff_time(10 * minutes, 4, 0),
|
||||
["stone-furnace"] = cutoff_time(10 * minutes, 4, 0),
|
||||
-- Armor
|
||||
["light-armor"] = cutoff_amount_made_unless(5, 0, 1, "heavy-armor", 5),
|
||||
["heavy-armor"] = cutoff_amount_made(5, 0, 1),
|
||||
-- Weapon
|
||||
["pistol"] = cutoff_amount_made_unless(0, 1, 1, "submachine-gun", 5),
|
||||
["submachine-gun"] = cutoff_amount_made(5, 0, 1),
|
||||
-- Ammo
|
||||
["firearm-magazine"] = cutoff_amount_made_unless(100, 10, 0, "piercing-rounds-magazine", 100),
|
||||
["piercing-rounds-magazine"] = cutoff_amount_made(100, 0, 10),
|
||||
["iron-ore"] = cutoff_time(20 * minutes, 80, 0),
|
||||
["stone"] = cutoff_time(20 * minutes, 20, 0),
|
||||
["coal"] = cutoff_time(20 * minutes, 20, 0),
|
||||
-- ["burner-mining-drill"]=cutoff_time(20 * minutes, 8, 0),
|
||||
-- ["stone-furnace"]=cutoff_time(20 * minutes, 8, 0),
|
||||
["submachine-gun"] = 1,
|
||||
["piercing-rounds-magazine"] = 20,
|
||||
["construction-robot"] = 10,
|
||||
["modular-armor"] = 1,
|
||||
["solar-panel-equipment"] = 16,
|
||||
["belt-immunity-equipment"] = 1,
|
||||
["battery-equipment"] = 2,
|
||||
["personal-roboport-equipment"] = 1
|
||||
--[[
|
||||
['construction-robot'] = 10,
|
||||
['modular-armor'] = 1,
|
||||
['solar-panel-equipment'] = 16,
|
||||
['belt-immunity-equipment'] = 1,
|
||||
['battery-equipment'] = 2,
|
||||
['personal-roboport-equipment'] = 1
|
||||
["construction-robot"] = 50,
|
||||
["spidertron"] = 1,
|
||||
["spidertron-remote"] = 1,
|
||||
["modular-armor"] = 1,
|
||||
["solar-panel-equipment"] = 60,
|
||||
["belt-immunity-equipment"] = 1,
|
||||
["battery-equipment"] = 6,
|
||||
["personal-roboport-equipment"] = 5
|
||||
]]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,9 @@ local afk_time_units = {
|
||||
return {
|
||||
messages = { --- @setting messages will trigger when ever the word is said
|
||||
["discord"] = { "info.discord" },
|
||||
["expgaming"] = { "info.website" },
|
||||
["aperx"] = { "info.website" },
|
||||
["website"] = { "info.website" },
|
||||
["status"] = { "info.status" },
|
||||
["github"] = { "info.github" },
|
||||
["patreon"] = { "info.patreon" },
|
||||
["donate"] = { "info.patreon" },
|
||||
["command"] = { "info.custom-commands" },
|
||||
["commands"] = { "info.custom-commands" },
|
||||
["softmod"] = { "info.softmod" },
|
||||
|
||||
@@ -11,15 +11,16 @@ return {
|
||||
player_kicks = true,
|
||||
player_promotes = false,
|
||||
player_jail = true,
|
||||
["config"] = true,
|
||||
["purge"] = true,
|
||||
["c"] = true,
|
||||
["command"] = true,
|
||||
["silent-command"] = true,
|
||||
["measured-command"] = true,
|
||||
["banlist"] = true,
|
||||
["permissions"] = true,
|
||||
["editor"] = true,
|
||||
["cheat"] = true,
|
||||
["open"] = false,
|
||||
['config']=false,
|
||||
['purge']=false,
|
||||
['c']=false,
|
||||
['sc']=false,
|
||||
['command']=false,
|
||||
['silent-command']=false,
|
||||
['measured-command']=false,
|
||||
['banlist']=false,
|
||||
['permissions']=false,
|
||||
['editor']=false,
|
||||
['cheat']=false,
|
||||
['open']=false
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--- Use this file to add new permission groups to the game;
|
||||
-- start with Permission_Groups.new_group('name');
|
||||
-- start with Permission_Groups.new_group("name");
|
||||
-- then use either :allow_all() or :disallow_all() to set the default for non specified actions;
|
||||
-- then use :allow{} and :disallow{} to specify certain actions to allow/disallow
|
||||
-- @config Permission-Groups
|
||||
@@ -9,6 +9,9 @@ local Groups = require("modules.exp_legacy.expcore.permission_groups") --- @dep
|
||||
|
||||
Groups.new_group("Admin")
|
||||
:allow_all()
|
||||
|
||||
Groups.new_group("Mod")
|
||||
:allow_all()
|
||||
:disallow{
|
||||
"add_permission_group", -- admin
|
||||
"delete_permission_group",
|
||||
@@ -17,11 +20,6 @@ Groups.new_group("Admin")
|
||||
"map_editor_action",
|
||||
"toggle_map_editor",
|
||||
"change_multiplayer_config",
|
||||
"set_heat_interface_mode",
|
||||
"set_heat_interface_temperature",
|
||||
"set_infinity_container_filter_item",
|
||||
"set_infinity_container_remove_unfiltered_items",
|
||||
"set_infinity_pipe_filter",
|
||||
}
|
||||
|
||||
Groups.new_group("Trusted")
|
||||
@@ -34,12 +32,12 @@ Groups.new_group("Trusted")
|
||||
"map_editor_action",
|
||||
"toggle_map_editor",
|
||||
"change_multiplayer_config",
|
||||
"set_heat_interface_mode",
|
||||
"set_heat_interface_mode", -- trusted
|
||||
"set_heat_interface_temperature",
|
||||
"set_infinity_container_filter_item",
|
||||
"set_infinity_container_remove_unfiltered_items",
|
||||
"set_infinity_pipe_filter",
|
||||
"admin_action", -- trusted
|
||||
"admin_action",
|
||||
}
|
||||
|
||||
Groups.new_group("Standard")
|
||||
@@ -58,10 +56,8 @@ Groups.new_group("Standard")
|
||||
"set_infinity_container_remove_unfiltered_items",
|
||||
"set_infinity_pipe_filter",
|
||||
"admin_action", -- trusted
|
||||
"delete_space_platform",
|
||||
"change_programmable_speaker_alert_parameters", -- standard
|
||||
"drop_item",
|
||||
"open_new_platform_button_from_rocket_silo",
|
||||
"set_rocket_silo_send_to_orbit_automated_mode",
|
||||
}
|
||||
|
||||
Groups.new_group("Guest")
|
||||
@@ -80,21 +76,24 @@ Groups.new_group("Guest")
|
||||
"set_infinity_container_remove_unfiltered_items",
|
||||
"set_infinity_pipe_filter",
|
||||
"admin_action", -- trusted
|
||||
"delete_space_platform",
|
||||
"change_programmable_speaker_alert_parameters", -- standard
|
||||
"change_programmable_speaker_circuit_parameters", -- guest
|
||||
"change_programmable_speaker_parameters",
|
||||
"drop_item",
|
||||
"open_new_platform_button_from_rocket_silo",
|
||||
"set_rocket_silo_send_to_orbit_automated_mode",
|
||||
"change_programmable_speaker_parameters", -- guest
|
||||
"open_new_platform_button_from_rocket_silo",
|
||||
"instantly_create_space_platform",
|
||||
"cancel_delete_space_platform",
|
||||
"rename_space_platform",
|
||||
-- "launch_rocket",
|
||||
"change_train_stop_station",
|
||||
-- 'deconstruct',
|
||||
-- "deconstruct",
|
||||
"remove_cables",
|
||||
"remove_train_station",
|
||||
"reset_assembling_machine",
|
||||
"rotate_entity",
|
||||
-- 'use_artillery_remote', -- not in 2.0
|
||||
"launch_rocket",
|
||||
"cancel_research",
|
||||
-- 'activate_cut', -- not in 2.0
|
||||
"flush_opened_entity_fluid",
|
||||
"flush_opened_entity_specific_fluid",
|
||||
}
|
||||
@@ -108,15 +107,15 @@ Groups.new_group("Restricted")
|
||||
local trusted_time = 60*60*60*10 -- 10 hour
|
||||
local standard_time = 60*60*60*3 -- 3 hour
|
||||
local function assign_group(player)
|
||||
local current_group_name = player.permission_group and player.permission_group.name or 'None'
|
||||
local current_group_name = player.permission_group and player.permission_group.name or "None"
|
||||
if player.admin then
|
||||
Permission_Groups.set_player_group(player,'Admin')
|
||||
elseif player.online_time > trusted_time or current_group_name == 'Trusted' then
|
||||
Permission_Groups.set_player_group(player,'Trusted')
|
||||
elseif player.online_time > standard_time or current_group_name == 'Standard' then
|
||||
Permission_Groups.set_player_group(player,'Standard')
|
||||
Permission_Groups.set_player_group(player,"Admin")
|
||||
elseif player.online_time > trusted_time or current_group_name == "Trusted" then
|
||||
Permission_Groups.set_player_group(player,"Trusted")
|
||||
elseif player.online_time > standard_time or current_group_name == "Standard" then
|
||||
Permission_Groups.set_player_group(player,"Standard")
|
||||
else
|
||||
Permission_Groups.set_player_group(player,'Guest')
|
||||
Permission_Groups.set_player_group(player,"Guest")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ Roles.new_role("System", "SYS")
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("report-immune")
|
||||
:set_flag("instant-respawn")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_allow_all()
|
||||
|
||||
Roles.new_role("Senior Administrator", "SAdmin")
|
||||
@@ -36,13 +37,9 @@ Roles.new_role("Senior Administrator", "SAdmin")
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("report-immune")
|
||||
:set_flag("instant-respawn")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Administrator")
|
||||
:allow{
|
||||
"command/_rcon",
|
||||
"command/debug",
|
||||
"command/set-cheat-mode",
|
||||
"command/research-all",
|
||||
}
|
||||
:set_allow_all()
|
||||
|
||||
Roles.new_role("Administrator", "Admin")
|
||||
:set_permission_group("Admin")
|
||||
@@ -51,63 +48,57 @@ Roles.new_role("Administrator", "Admin")
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("report-immune")
|
||||
:set_flag("instant-respawn")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Senior Moderator")
|
||||
:allow{
|
||||
"command/_rcon",
|
||||
"command/debug",
|
||||
"command/set-cheat-mode",
|
||||
"command/research-all"
|
||||
}
|
||||
|
||||
Roles.new_role("Senior Moderator", "SMod")
|
||||
:set_permission_group("Mod")
|
||||
:set_custom_color{ r = 0, g = 170, b = 0 }
|
||||
:set_flag("is_admin")
|
||||
:set_flag("is_system")
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("report-immune")
|
||||
:set_flag("instant-respawn")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Moderator")
|
||||
:allow{
|
||||
"gui/warp-list/bypass-proximity",
|
||||
"gui/warp-list/bypass-cooldown",
|
||||
"command/connect-all",
|
||||
"command/connect-all"
|
||||
}
|
||||
|
||||
Roles.new_role("Moderator", "Mod")
|
||||
:set_permission_group("Admin")
|
||||
:set_permission_group("Mod")
|
||||
:set_custom_color{ r = 0, g = 170, b = 0 }
|
||||
:set_flag("is_admin")
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("report-immune")
|
||||
:set_flag("instant-respawn")
|
||||
:set_parent("Trainee")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Trainee Moderator")
|
||||
:allow{
|
||||
"command/assign-role",
|
||||
"command/unassign-role",
|
||||
"command/repair",
|
||||
"command/kill/always",
|
||||
"command/clear-tag/always",
|
||||
"command/spawn/always",
|
||||
"command/clear-reports",
|
||||
"command/clear-warnings",
|
||||
"command/clear-script-warnings",
|
||||
"command/clear-last-warnings",
|
||||
"command/clear-inventory",
|
||||
"command/kill-enemies",
|
||||
"command/remove-enemies",
|
||||
--'command/bonus',
|
||||
"command/home",
|
||||
"command/set-home",
|
||||
"command/get-home",
|
||||
"command/return",
|
||||
"command/connect-player",
|
||||
"command/set-bot-queue",
|
||||
"command/set-game-speed",
|
||||
"command/set-friendly-fire",
|
||||
"command/set-always-day",
|
||||
"command/set-pollution-enabled",
|
||||
"command/clear-pollution",
|
||||
"gui/rocket-info/toggle-active",
|
||||
"gui/rocket-info/remote_launch",
|
||||
"gui/bonus",
|
||||
"fast-tree-decon",
|
||||
}
|
||||
|
||||
Roles.new_role("Trainee", "TrMod")
|
||||
:set_permission_group("Admin")
|
||||
Roles.new_role("Trainee Moderator", "Trainee")
|
||||
:set_permission_group("Mod")
|
||||
:set_custom_color{ r = 0, g = 170, b = 0 }
|
||||
:set_flag("is_admin")
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("report-immune")
|
||||
:set_parent("Veteran")
|
||||
:set_flag("instant-respawn")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Board Member")
|
||||
:allow{
|
||||
"command/assign-role",
|
||||
"command/unassign-role",
|
||||
"command/admin-chat",
|
||||
"command/goto",
|
||||
"command/protect-tag",
|
||||
"command/teleport",
|
||||
"command/bring",
|
||||
"command/create-warning",
|
||||
@@ -115,19 +106,30 @@ Roles.new_role("Trainee", "TrMod")
|
||||
"command/get-reports",
|
||||
"command/protect-entity",
|
||||
"command/protect-area",
|
||||
"command/protect-tag",
|
||||
"command/jail",
|
||||
"command/unjail",
|
||||
"command/kick",
|
||||
"command/ban",
|
||||
"command/spectate",
|
||||
"command/follow",
|
||||
"command/search",
|
||||
"command/search-online",
|
||||
"command/search-amount",
|
||||
"command/search-recent",
|
||||
"command/clear-blueprints",
|
||||
"gui/playerdata",
|
||||
"command/clear-pollution",
|
||||
"command/set-pollution-enabled",
|
||||
"command/set-bot-queue",
|
||||
"command/set-game-speed",
|
||||
"command/kill-enemies",
|
||||
"command/remove-enemies",
|
||||
"command/set-friendly-fire",
|
||||
"command/set-always-day",
|
||||
"command/clear-reports",
|
||||
"command/clear-warnings",
|
||||
"command/clear-script-warnings",
|
||||
"command/clear-last-warnings",
|
||||
"command/clear-inventory",
|
||||
"command/connect-player",
|
||||
"command/kill/always",
|
||||
-- "command/clear-tag/always",
|
||||
"command/spawn/always",
|
||||
"gui/playerdata"
|
||||
}
|
||||
|
||||
--- Trusted Roles
|
||||
@@ -137,81 +139,95 @@ Roles.new_role("Board Member", "Board")
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("report-immune")
|
||||
:set_flag("instant-respawn")
|
||||
:set_parent("Sponsor")
|
||||
:allow{
|
||||
"command/goto",
|
||||
"command/repair",
|
||||
"command/spectate",
|
||||
"command/follow",
|
||||
"gui/playerdata",
|
||||
}
|
||||
|
||||
Roles.new_role("Senior Backer", "Backer")
|
||||
:set_permission_group("Trusted")
|
||||
:set_custom_color{ r = 238, g = 172, b = 44 }
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("report-immune")
|
||||
:set_flag("instant-respawn")
|
||||
:set_parent("Sponsor")
|
||||
:allow{
|
||||
}
|
||||
|
||||
Roles.new_role("Sponsor", "Spon")
|
||||
:set_permission_group("Trusted")
|
||||
:set_custom_color{ r = 238, g = 172, b = 44 }
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("report-immune")
|
||||
:set_flag("instant-respawn")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Supporter")
|
||||
:allow{
|
||||
"gui/rocket-info/toggle-active",
|
||||
"gui/rocket-info/remote_launch",
|
||||
"gui/bonus",
|
||||
--"command/bonus",
|
||||
"command/home",
|
||||
"command/set-home",
|
||||
"command/get-home",
|
||||
"command/return",
|
||||
"fast-tree-decon",
|
||||
}
|
||||
|
||||
Roles.new_role("Supporter", "Sup")
|
||||
:set_permission_group("Trusted")
|
||||
:set_custom_color{ r = 230, g = 99, b = 34 }
|
||||
:set_flag("is_spectator")
|
||||
:set_parent("Veteran")
|
||||
:set_flag("instant-respawn")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Partner")
|
||||
:allow{
|
||||
"command/tag-color",
|
||||
"command/jail",
|
||||
"command/unjail",
|
||||
"command/set-join-message",
|
||||
"command/remove-join-message",
|
||||
}
|
||||
|
||||
Roles.new_role("Partner", "Part")
|
||||
:set_permission_group("Trusted")
|
||||
:set_custom_color{ r = 140, g = 120, b = 200 }
|
||||
:set_custom_color{ r = 24, g = 172, b = 188 }
|
||||
:set_flag("is_spectator")
|
||||
:set_parent("Veteran")
|
||||
:set_flag("instant-respawn")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Senior Member")
|
||||
:allow{
|
||||
"command/jail",
|
||||
"command/unjail",
|
||||
}
|
||||
|
||||
local hours10, hours250 = 10 * 216000, 250 * 60
|
||||
Roles.new_role("Senior Member", "SMem")
|
||||
:set_permission_group("Trusted")
|
||||
:set_custom_color{ r = 24, g = 172, b = 188 }
|
||||
:set_flag("is_spectator")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_flag("instant-respawn")
|
||||
:set_parent("Member")
|
||||
:allow{
|
||||
}
|
||||
|
||||
--- Standard User Roles
|
||||
Roles.new_role("Member", "Mem")
|
||||
:set_permission_group("Trusted")
|
||||
:set_custom_color{ r = 24, g = 172, b = 188 }
|
||||
:set_flag("instant-respawn")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Veteran")
|
||||
:allow{
|
||||
"command/set-join-message",
|
||||
"command/remove-join-message",
|
||||
"gui/vlayer-edit",
|
||||
"gui/rocket-info/toggle-active",
|
||||
"gui/rocket-info/remote_launch",
|
||||
"gui/tool",
|
||||
-- "command/tag-color",
|
||||
"command/clear-blueprints",
|
||||
--"command/bonus",
|
||||
"gui/bonus",
|
||||
"command/personal-logistic",
|
||||
"command/home",
|
||||
"command/set-home",
|
||||
"command/get-home",
|
||||
"command/return",
|
||||
"command/goto",
|
||||
"command/jail",
|
||||
"command/unjail",
|
||||
"command/spectate",
|
||||
"command/follow",
|
||||
"command/repair",
|
||||
"fast-tree-decon"
|
||||
}
|
||||
|
||||
local hours6, hours250 = 6 * 216000, 250 * 60
|
||||
Roles.new_role("Veteran", "Vet")
|
||||
:set_permission_group("Trusted")
|
||||
:set_custom_color{ r = 140, g = 120, b = 200 }
|
||||
:set_parent("Member")
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Regular")
|
||||
:allow{
|
||||
"gui/surveillance",
|
||||
"gui/warp-list/add",
|
||||
"gui/warp-list/edit",
|
||||
"command/chat-bot",
|
||||
"command/chat-commands",
|
||||
"command/clear-ground-items",
|
||||
"command/clear-blueprints-radius",
|
||||
"command/set-trains-to-automatic",
|
||||
"command/set-auto-research",
|
||||
"command/lawnmower",
|
||||
"command/waterfill",
|
||||
"command/artillery"
|
||||
}
|
||||
:set_auto_assign_condition(function(player)
|
||||
if player.online_time >= hours10 then
|
||||
if player.online_time >= hours6 then
|
||||
return true
|
||||
else
|
||||
local stats = Statistics:get(player, {})
|
||||
@@ -220,44 +236,25 @@ Roles.new_role("Veteran", "Vet")
|
||||
end
|
||||
end)
|
||||
|
||||
--- Standard User Roles
|
||||
Roles.new_role("Member", "Mem")
|
||||
:set_permission_group("Standard")
|
||||
:set_custom_color{ r = 24, g = 172, b = 188 }
|
||||
:set_flag("deconlog-bypass")
|
||||
:set_parent("Regular")
|
||||
:allow{
|
||||
"gui/task-list/add",
|
||||
"gui/task-list/edit",
|
||||
"gui/warp-list/add",
|
||||
"gui/warp-list/edit",
|
||||
"gui/surveillance",
|
||||
"gui/vlayer-edit",
|
||||
"gui/tool",
|
||||
"command/save-quickbar",
|
||||
"command/vlayer-info",
|
||||
"command/personal-logistic",
|
||||
"command/lawnmower",
|
||||
"command/waterfill",
|
||||
"command/artillery",
|
||||
}
|
||||
|
||||
local hours3, hours15 = 3 * 216000, 15 * 60
|
||||
local hours1, hours15 = 1 * 216000, 15 * 60
|
||||
Roles.new_role("Regular", "Reg")
|
||||
:set_permission_group("Standard")
|
||||
:set_custom_color{ r = 79, g = 155, b = 163 }
|
||||
:set_parent("Guest")
|
||||
:allow{
|
||||
"gui/task-list/add",
|
||||
"gui/task-list/edit",
|
||||
"command/kill",
|
||||
"command/rainbow",
|
||||
"command/spawn",
|
||||
"command/me",
|
||||
"command/vlayer-info",
|
||||
"standard-decon",
|
||||
"bypass-entity-protection",
|
||||
"bypass-nukeprotect",
|
||||
"bypass-nukeprotect"
|
||||
}
|
||||
:set_auto_assign_condition(function(player)
|
||||
if player.online_time >= hours3 then
|
||||
if player.online_time >= hours1 then
|
||||
return true
|
||||
else
|
||||
local stats = Statistics:get(player, {})
|
||||
@@ -271,8 +268,8 @@ local default = Roles.new_role("Guest", "")
|
||||
:set_permission_group("Guest")
|
||||
:set_custom_color{ r = 185, g = 187, b = 160 }
|
||||
:allow{
|
||||
"command/tag",
|
||||
"command/tag-clear",
|
||||
-- "command/tag",
|
||||
-- "command/tag-clear",
|
||||
"command/commands",
|
||||
"command/get-roles",
|
||||
"command/locate",
|
||||
@@ -280,6 +277,7 @@ local default = Roles.new_role("Guest", "")
|
||||
"command/ratio",
|
||||
"command/server-ups",
|
||||
"command/save-data",
|
||||
"command/save-quickbar",
|
||||
"command/data-preference",
|
||||
"command/connect",
|
||||
"gui/player-list",
|
||||
@@ -292,7 +290,6 @@ local default = Roles.new_role("Guest", "")
|
||||
"gui/research",
|
||||
"gui/autofill",
|
||||
"gui/module",
|
||||
"gui/landfill",
|
||||
"gui/production",
|
||||
}
|
||||
|
||||
@@ -312,57 +309,69 @@ Roles.define_role_order{
|
||||
"System", -- Best to keep root at top
|
||||
"Senior Administrator",
|
||||
"Administrator",
|
||||
"Senior Moderator",
|
||||
"Moderator",
|
||||
"Trainee",
|
||||
"Trainee Moderator",
|
||||
"Board Member",
|
||||
"Senior Backer",
|
||||
"Sponsor",
|
||||
"Supporter",
|
||||
"Partner",
|
||||
"Veteran",
|
||||
"Senior Member",
|
||||
"Member",
|
||||
"Veteran",
|
||||
"Regular",
|
||||
"Jail",
|
||||
"Guest", -- Default must be last if you want to apply restrictions to other roles
|
||||
"Guest" -- Default must be last if you want to apply restrictions to other roles
|
||||
}
|
||||
|
||||
Roles.override_player_roles{
|
||||
["PHIDIAS0303"] = { "Moderator", "Board Member", "Member" },
|
||||
["aldldl"] = { "Administrator", "Moderator", "Member" },
|
||||
["arty714"] = { "Senior Administrator", "Moderator", "Member" },
|
||||
["Cooldude2606"] = { "Senior Administrator", "Moderator", "Member" },
|
||||
["Drahc_pro"] = { "Administrator", "Moderator", "Member" },
|
||||
["mark9064"] = { "Administrator", "Moderator", "Member" },
|
||||
["7h3w1z4rd"] = { "Moderator", "Member" },
|
||||
["FlipHalfling90"] = { "Moderator", "Member" },
|
||||
["hamsterbryan"] = { "Moderator", "Member" },
|
||||
["HunterOfGames"] = { "Moderator", "Member" },
|
||||
["NextIdea"] = { "Moderator", "Member" },
|
||||
["TheKernel32"] = { "Moderator", "Member" },
|
||||
["TheKernel64"] = { "Moderator", "Member" },
|
||||
["tovernaar123"] = { "Moderator", "Member" },
|
||||
["UUBlueFire"] = { "Moderator", "Member" },
|
||||
["AssemblyStorm"] = { "Moderator", "Member" },
|
||||
["banakeg"] = { "Moderator", "Member" },
|
||||
["connormkii"] = { "Moderator", "Member" },
|
||||
["cydes"] = { "Moderator", "Member" },
|
||||
["darklich14"] = { "Moderator", "Member" },
|
||||
["facere"] = { "Moderator", "Member" },
|
||||
["freek18"] = { "Moderator", "Member" },
|
||||
["Gizan"] = { "Moderator", "Member" },
|
||||
["LoicB"] = { "Moderator", "Member" },
|
||||
["M74132"] = { "Moderator", "Member" },
|
||||
["mafisch3"] = { "Moderator", "Member" },
|
||||
["maplesyrup01"] = { "Moderator", "Member" },
|
||||
["ookl"] = { "Moderator", "Member" },
|
||||
["Phoenix27833"] = { "Moderator", "Member" },
|
||||
["porelos"] = { "Moderator", "Member" },
|
||||
["Ruuyji"] = { "Moderator", "Member" },
|
||||
["samy115"] = { "Moderator", "Member" },
|
||||
["SilentLog"] = { "Moderator", "Member" },
|
||||
["Tcheko"] = { "Moderator", "Member" },
|
||||
["thadius856"] = { "Moderator", "Member" },
|
||||
["whoami32"] = { "Moderator", "Member" },
|
||||
["Windbomb"] = { "Moderator", "Member" },
|
||||
["XenoCyber"] = { "Moderator", "Member" },
|
||||
["PHIDIAS0303"] = { "Senior Administrator" },
|
||||
["7h3w1z4rd"] = { "Moderator" },
|
||||
["aldldl"] = { "Moderator" },
|
||||
["arty714"] = { "Moderator" },
|
||||
["AssemblyStorm"] = { "Moderator" },
|
||||
["banakeg"] = { "Moderator" },
|
||||
["connormkii"] = { "Moderator" },
|
||||
["cydes"] = { "Moderator" },
|
||||
["Cooldude2606"] = { "Moderator" },
|
||||
["darklich14"] = { "Moderator" },
|
||||
["Drahc_pro"] = { "Moderator" },
|
||||
["facere"] = { "Moderator" },
|
||||
["freek18"] = { "Moderator" },
|
||||
["FlipHalfling90"] = { "Moderator" },
|
||||
["Gizan"] = { "Moderator" },
|
||||
["hamsterbryan"] = { "Moderator" },
|
||||
["hidden_relic"] = { "Moderator" },
|
||||
["Hova"] = { "Moderator" },
|
||||
["HunterOfGames"] = { "Moderator" },
|
||||
["LoicB"] = { "Moderator" },
|
||||
["M74132"] = { "Moderator" },
|
||||
["MadKatz"] = { "Moderator" },
|
||||
["mafisch3"] = { "Moderator" },
|
||||
["maplesyrup01"] = { "Moderator" },
|
||||
["mark9064"] = { "Moderator" },
|
||||
["nallaj"] = { "Moderator" },
|
||||
["NextIdea"] = { "Moderator" },
|
||||
["oof2win2"] = { "Moderator" },
|
||||
["ookl"] = { "Moderator" },
|
||||
["Phoenix27833"] = { "Moderator" },
|
||||
["porelos"] = { "Moderator" },
|
||||
["Ruuyji"] = { "Moderator" },
|
||||
["samy115"] = { "Moderator" },
|
||||
["SilentLog"] = { "Moderator" },
|
||||
["Tcheko"] = { "Moderator" },
|
||||
["thadius856"] = { "Moderator" },
|
||||
["TheKernel32"] = { "Moderator" },
|
||||
["TheKernel64"] = { "Moderator" },
|
||||
["tovernaar123"] = { "Moderator" },
|
||||
["UUBlueFire"] = { "Moderator" },
|
||||
["whoami32"] = { "Moderator" },
|
||||
["Windbomb"] = { "Moderator" },
|
||||
["Windsinger"] = { "Moderator" },
|
||||
["XenoCyber"] = { "Moderator" },
|
||||
["Athenaa"] = { "Trainee Moderator" },
|
||||
["hihicome3"] = { "Trainee Moderator" },
|
||||
["JamesJung"] = { "Trainee Moderator" },
|
||||
["konohaScarlet_"] = { "Trainee Moderator" },
|
||||
["majoro"] = { "Trainee Moderator" },
|
||||
["rongli"] = { "Trainee Moderator" },
|
||||
}
|
||||
|
||||
@@ -1,8 +1,2 @@
|
||||
return {
|
||||
Cooldude2606 = "Lua lets you set metatables on numbers, did you know that? Cooldude2606 knows this.",
|
||||
samy115 = "Tremble in fear as the banhammer is now here, its owner: samy115",
|
||||
XenoCyber = '"Fire Fire Fire" oops wrong game, have no fear XenoCyber is here',
|
||||
HunterOfGames = "Unable to support HunterOfGames. You must construct additional miners.",
|
||||
ookl = 'ookl says: "Pineapples are amazing, hello everyone!"',
|
||||
arty714 = "Arty\'s Potato made it!",
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
return {
|
||||
spawn_area = { --- @setting spawn_area Settings relating to the whole spawn area
|
||||
-- Enable predefined patches: 128, else: 32
|
||||
deconstruction_radius = 20, -- @setting deconstruction_radius All entities within this radius will be removed
|
||||
tile_radius = 20,
|
||||
deconstruction_tile = "concrete", --- @setting deconstruction_tile Tile to be placed in the deconstruction radius, use nil for map gen
|
||||
landfill_radius = 50, --- @setting pattern_radius All water within this radius will be land filled
|
||||
deconstruction_radius = 12, -- @setting deconstruction_radius All entities within this radius will be removed
|
||||
deconstruction_tile = "refined-concrete", --- @setting deconstruction_tile Tile to be placed in the deconstruction radius, use nil for map gen
|
||||
tile_radius = 14,
|
||||
landfill_radius = 16, --- @setting pattern_radius All water within this radius will be land filled
|
||||
},
|
||||
turrets = { --- @setting turrets Settings relating to adding turrets to spawn
|
||||
enabled = true, --- @setting enabled Whether turrets will be added to spawn
|
||||
@@ -15,10 +15,10 @@ return {
|
||||
refill_time = 60 * 60 * 5, --- @setting refill_time The time in ticks between each refill of the turrets, only change if having lag issues
|
||||
offset = { x = 0, y = 0 }, --- @setting offset The position offset to apply to turrets
|
||||
locations = { --- @setting locations The locations of all turrets, this list can change during runtime
|
||||
{ -3, -3 },
|
||||
{ 3, -3 },
|
||||
{ -3, 3 },
|
||||
{ 3, 3 },
|
||||
{ -2, -2 },
|
||||
{ 2, -2 },
|
||||
{ -2, 2 },
|
||||
{ 2, 2 },
|
||||
},
|
||||
},
|
||||
afk_belts = { --- @setting afk_belts Settings relating to adding afk belts to spawn
|
||||
@@ -27,9 +27,11 @@ return {
|
||||
protected = true, --- @setting protected Whether belts will be protected from player interaction
|
||||
offset = { x = 0, y = 0 }, --- @setting offset The position offset to apply to afk belts
|
||||
locations = { --- @setting locations The locations to spawn afk belts at, given as the top left position
|
||||
{ -5, -5 }, { 5, -5 },
|
||||
{ -5, 5 }, { 5, 5 },
|
||||
},
|
||||
{ 4, 4 },
|
||||
{ 4, -4 },
|
||||
{ -4, 4 },
|
||||
{ -4, -4 }
|
||||
}
|
||||
},
|
||||
water = { --- @setting water Settings relating to adding water to spawn
|
||||
enabled = true, --- @setting enabled Whether water tiles will be added to spawn
|
||||
@@ -37,147 +39,45 @@ return {
|
||||
offset = { x = 0, y = 0 }, --- @setting offset The position offset to apply to water tiles
|
||||
locations = { --- @setting locations The location of the water tiles {x,y}
|
||||
-- Each is a 3x3 with the closest tile to 0,0 removed
|
||||
{ 7, 8 }, { 7, 9 }, { 8, 7 }, { 8, 8 }, { 8, 9 }, { 9, 7 }, { 9, 8 }, { 9, 9 }, -- Bottom Right
|
||||
{ 7, -9 }, { 7, -10 }, { 8, -8 }, { 8, -9 }, { 8, -10 }, { 9, -8 }, { 9, -9 }, { 9, -10 }, -- Top Right
|
||||
{ -8, -9 }, { -8, -10 }, { -9, -8 }, { -9, -9 }, { -9, -10 }, { -10, -8 }, { -10, -9 }, { -10, -10 }, -- Top Left
|
||||
{ -8, 8 }, { -8, 9 }, { -9, 7 }, { -9, 8 }, { -9, 9 }, { -10, 7 }, { -10, 8 }, { -10, 9 }, -- Bottom Left
|
||||
},
|
||||
{ 5, 6 }, { 5, 7 }, { 6, 5 }, { 6, 6 }, { 6, 7 }, { 7, 5 }, { 7, 6 }, { 7, 7 },
|
||||
{ 5, -7 }, { 5, -8 }, { 6, -6 }, { 6, -7 }, { 6, -8 }, { 7, -6 }, { 7, -7 }, { 7, -8 },
|
||||
{ -6, 6 }, { -6, 7 }, { -7, 5 }, { -7, 6 }, { -7, 7 }, { -8, 5 }, { -8, 6 }, { -8, 7 },
|
||||
{ -6, -7 }, { -6, -8 }, { -7, -6 }, { -7, -7 }, { -7, -8 }, { -8, -6 }, { -8, -7 }, { -8, -8 },
|
||||
}
|
||||
},
|
||||
entities = { --- @setting entities Settings relating to adding entities to spawn
|
||||
enabled = true, --- @setting enabled Whether entities will be added to spawn
|
||||
protected = true, --- @setting protected Whether entities will be protected from player interaction
|
||||
operable = true, --- @setting operable Whether entities can be opened by players, must be true if chests are used
|
||||
offset = { x = 0, y = -2 }, --- @setting offset The position offset to apply to entities
|
||||
offset = { x = 0, y = 0 }, --- @setting offset The position offset to apply to entities
|
||||
locations = { --- @setting locations The location and names of entities {name,x,y}
|
||||
{ "stone-wall", -10, -5 }, { "stone-wall", -10, -4 }, { "stone-wall", -10, -3 }, { "stone-wall", -10, -2 }, { "stone-wall", -10, -1 }, { "stone-wall", -10, 0 }, { "stone-wall", -10, 3 }, { "stone-wall", -10, 4 }, { "stone-wall", -10, 5 },
|
||||
{ "stone-wall", -10, 6 }, { "stone-wall", -10, 7 }, { "stone-wall", -10, 8 }, { "small-lamp", -8, -4 }, { "small-lamp", -8, -1 }, { "iron-chest", -8, 0 }, { "iron-chest", -8, 3 }, { "small-lamp", -8, 4 },
|
||||
{ "small-lamp", -8, 7 }, { "stone-wall", -7, -8 }, { "small-electric-pole", -7, -2 }, { "iron-chest", -7, 0 }, { "iron-chest", -7, 3 }, { "small-electric-pole", -7, 5 }, { "stone-wall", -7, 11 }, { "stone-wall", -6, -8 }, { "small-lamp", -6, -6 },
|
||||
{ "iron-chest", -6, 0 }, { "iron-chest", -6, 3 }, { "small-lamp", -6, 9 }, { "stone-wall", -6, 11 }, { "stone-wall", -5, -8 }, { "small-lamp", -5, -1 }, { "iron-chest", -5, 0 }, { "iron-chest", -5, 3 }, { "small-lamp", -5, 4 }, { "stone-wall", -5, 11 },
|
||||
{ "stone-wall", -4, -8 }, { "small-electric-pole", -4, -5 }, { "iron-chest", -4, 0 }, { "iron-chest", -4, 3 }, { "small-electric-pole", -4, 8 }, { "stone-wall", -4, 11 }, { "stone-wall", -3, -8 }, { "small-lamp", -3, -6 }, { "small-lamp", -3, -3 }, { "small-lamp", -3, 6 },
|
||||
{ "small-lamp", -3, 9 }, { "stone-wall", -3, 11 }, { "stone-wall", -2, -8 }, { "iron-chest", -2, -6 }, { "iron-chest", -2, -5 }, { "iron-chest", -2, -4 }, { "iron-chest", -2, -3 }, { "iron-chest", -2, -2 }, { "iron-chest", -2, 5 }, { "iron-chest", -2, 6 },
|
||||
{ "iron-chest", -2, 7 }, { "iron-chest", -2, 8 }, { "iron-chest", -2, 9 }, { "stone-wall", -2, 11 }, { "stone-wall", 1, -8 }, { "iron-chest", 1, -6 },
|
||||
{ "iron-chest", 1, -5 }, { "iron-chest", 1, -4 }, { "iron-chest", 1, -3 }, { "iron-chest", 1, -2 }, { "iron-chest", 1, 5 }, { "iron-chest", 1, 6 }, { "iron-chest", 1, 7 }, { "iron-chest", 1, 8 }, { "iron-chest", 1, 9 }, { "stone-wall", 1, 11 },
|
||||
{ "stone-wall", 2, -8 }, { "small-lamp", 2, -6 }, { "small-lamp", 2, -3 }, { "small-lamp", 2, 6 }, { "small-lamp", 2, 9 }, { "stone-wall", 2, 11 }, { "stone-wall", 3, -8 }, { "small-electric-pole", 3, -5 }, { "iron-chest", 3, 0 }, { "iron-chest", 3, 3 },
|
||||
{ "small-electric-pole", 3, 8 }, { "stone-wall", 3, 11 }, { "stone-wall", 4, -8 }, { "small-lamp", 4, -1 }, { "iron-chest", 4, 0 }, { "iron-chest", 4, 3 }, { "small-lamp", 4, 4 }, { "stone-wall", 4, 11 }, { "stone-wall", 5, -8 }, { "small-lamp", 5, -6 },
|
||||
{ "iron-chest", 5, 0 }, { "iron-chest", 5, 3 }, { "small-lamp", 5, 9 }, { "stone-wall", 5, 11 }, { "stone-wall", 6, -8 }, { "small-electric-pole", 6, -2 }, { "iron-chest", 6, 0 }, { "iron-chest", 6, 3 }, { "small-electric-pole", 6, 5 }, { "stone-wall", 6, 11 },
|
||||
{ "small-lamp", 7, -4 }, { "small-lamp", 7, -1 }, { "iron-chest", 7, 0 }, { "iron-chest", 7, 3 }, { "small-lamp", 7, 4 }, { "small-lamp", 7, 7 }, { "stone-wall", 9, -5 },
|
||||
{ "stone-wall", 9, -4 }, { "stone-wall", 9, -3 }, { "stone-wall", 9, -2 }, { "stone-wall", 9, -1 }, { "stone-wall", 9, 0 }, { "stone-wall", 9, 3 }, { "stone-wall", 9, 4 }, { "stone-wall", 9, 5 }, { "stone-wall", 9, 6 }, { "stone-wall", 9, 7 },
|
||||
{ "stone-wall", 9, 8 },
|
||||
},
|
||||
{ "steel-chest", 1, 3 }, { "steel-chest", 1, 4 }, { "steel-chest", 1, 5 },
|
||||
{ "steel-chest", 3, 1 }, { "steel-chest", 4, 1 }, { "steel-chest", 5, 1 },
|
||||
{ "steel-chest", 1, -4 }, { "steel-chest", 1, -5 }, { "steel-chest", 1, -6 },
|
||||
{ "steel-chest", 3, -2 }, { "steel-chest", 4, -2 }, { "steel-chest", 5, -2 },
|
||||
{ "steel-chest", -2, 3 }, { "steel-chest", -2, 4 }, { "steel-chest", -2, 5 },
|
||||
{ "steel-chest", -4, 1 }, { "steel-chest", -5, 1 }, { "steel-chest", -6, 1 },
|
||||
{ "steel-chest", -2, -4 }, { "steel-chest", -2, -5 }, { "steel-chest", -2, -6 },
|
||||
{ "steel-chest", -4, -2 }, { "steel-chest", -5, -2 }, { "steel-chest", -6, -2 },
|
||||
{ "medium-electric-pole", 2, 3 }, { "medium-electric-pole", 2, -4 }, { "medium-electric-pole", -3, 3 }, { "medium-electric-pole", -3, -4 },
|
||||
{ "small-lamp", 2, 4 }, { "small-lamp", 2, -5 }, { "small-lamp", -3, 4 }, { "small-lamp", -3, -5 },
|
||||
{ "small-lamp", 4, 2 }, { "small-lamp", 4, -3 }, { "small-lamp", -5, 2 }, { "small-lamp", -5, -3 },
|
||||
{ "stone-wall", 1, 7 }, { "stone-wall", 2, 7 }, { "stone-wall", 3, 7 }, { "stone-wall", 4, 7 },
|
||||
{ "stone-wall", 7, 1 }, { "stone-wall", 7, 2 }, { "stone-wall", 7, 3 }, { "stone-wall", 7, 4 },
|
||||
{ "stone-wall", 1, -8 }, { "stone-wall", 2, -8 }, { "stone-wall", 3, -8 }, { "stone-wall", 4, -8 },
|
||||
{ "stone-wall", 7, -2 }, { "stone-wall", 7, -3 }, { "stone-wall", 7, -4 }, { "stone-wall", 7, -5 },
|
||||
{ "stone-wall", -2, 7 }, { "stone-wall", -3, 7 }, { "stone-wall", -4, 7 }, { "stone-wall", -5, 7 },
|
||||
{ "stone-wall", -8, 1 }, { "stone-wall", -8, 2 }, { "stone-wall", -8, 3 }, { "stone-wall", -8, 4 },
|
||||
{ "stone-wall", -2, -8 }, { "stone-wall", -3, -8 }, { "stone-wall", -4, -8 }, { "stone-wall", -5, -8 },
|
||||
{ "stone-wall", -8, -2 }, { "stone-wall", -8, -3 }, { "stone-wall", -8, -4 }, { "stone-wall", -8, -5 },
|
||||
}
|
||||
},
|
||||
pattern = {
|
||||
enabled = true, --- @setting enabled Whether pattern tiles will be added to spawn
|
||||
pattern_tile = "stone-path", --- @setting pattern_tile The tile to be used for the pattern
|
||||
offset = { x = 0, y = -2 }, --- @setting offset The position offset to apply to pattern tiles
|
||||
enabled = false, --- @setting enabled Whether pattern tiles will be added to spawn
|
||||
pattern_tile = "refined-concrete", --- @setting pattern_tile The tile to be used for the pattern
|
||||
offset = { x = 0, y = 0 }, --- @setting offset The position offset to apply to pattern tiles
|
||||
locations = { --- @setting locations The location of the pattern tiles {x,y}
|
||||
{ -49, -3 }, { -49, -2 }, { -49, 1 }, { -49, 2 }, { -49, 5 }, { -49, 6 }, { -48, -4 }, { -48, -3 }, { -48, -2 }, { -48, 1 }, { -48, 2 }, { -48, 5 }, { -48, 6 }, { -48, 7 }, { -47, -7 }, { -47, -6 }, { -47, -5 }, { -47, -4 }, { -47, -3 }, { -47, -2 }, { -47, 5 }, { -47, 6 }, { -47, 7 }, { -47, 8 }, { -47, 9 }, { -47, 10 }, { -46, -8 }, { -46, -7 }, { -46, -6 }, { -46, -5 },
|
||||
{ -46, -4 }, { -46, -3 }, { -46, -2 }, { -46, -1 }, { -46, 4 }, { -46, 5 }, { -46, 6 }, { -46, 7 }, { -46, 8 }, { -46, 9 }, { -46, 10 }, { -46, 11 }, { -45, -17 }, { -45, -16 }, { -45, -15 }, { -45, -14 }, { -45, -13 }, { -45, -12 }, { -45, -9 }, { -45, -8 }, { -45, -7 }, { -45, -2 }, { -45, -1 }, { -45, 0 }, { -45, 1 }, { -45, 2 }, { -45, 3 }, { -45, 4 }, { -45, 5 }, { -45, 10 },
|
||||
{ -45, 11 }, { -45, 12 }, { -45, 15 }, { -45, 16 }, { -45, 17 }, { -45, 18 }, { -45, 19 }, { -45, 20 }, { -44, -18 }, { -44, -17 }, { -44, -16 }, { -44, -15 }, { -44, -14 }, { -44, -13 }, { -44, -12 }, { -44, -9 }, { -44, -8 }, { -44, -1 }, { -44, 0 }, { -44, 1 }, { -44, 2 }, { -44, 3 }, { -44, 4 }, { -44, 11 }, { -44, 12 }, { -44, 15 }, { -44, 16 }, { -44, 17 }, { -44, 18 }, { -44, 19 },
|
||||
{ -44, 20 }, { -44, 21 }, { -43, -19 }, { -43, -18 }, { -43, -17 }, { -43, -1 }, { -43, 0 }, { -43, 1 }, { -43, 2 }, { -43, 3 }, { -43, 4 }, { -43, 20 }, { -43, 21 }, { -43, 22 }, { -42, -19 }, { -42, -18 }, { -42, -1 }, { -42, 0 }, { -42, 1 }, { -42, 2 }, { -42, 3 }, { -42, 4 }, { -42, 21 }, { -42, 22 }, { -41, -25 }, { -41, -24 }, { -41, -19 }, { -41, -18 }, { -41, -13 }, { -41, -12 },
|
||||
{ -41, -11 }, { -41, -10 }, { -41, -5 }, { -41, -4 }, { -41, 7 }, { -41, 8 }, { -41, 13 }, { -41, 14 }, { -41, 15 }, { -41, 16 }, { -41, 21 }, { -41, 22 }, { -41, 27 }, { -41, 28 }, { -40, -26 }, { -40, -25 }, { -40, -24 }, { -40, -20 }, { -40, -19 }, { -40, -18 }, { -40, -13 }, { -40, -12 }, { -40, -11 }, { -40, -10 }, { -40, -5 }, { -40, -4 }, { -40, 7 }, { -40, 8 }, { -40, 13 }, { -40, 14 },
|
||||
{ -40, 15 }, { -40, 16 }, { -40, 21 }, { -40, 22 }, { -40, 23 }, { -40, 27 }, { -40, 28 }, { -40, 29 }, { -39, -27 }, { -39, -26 }, { -39, -25 }, { -39, -24 }, { -39, -21 }, { -39, -20 }, { -39, -19 }, { -39, -13 }, { -39, -12 }, { -39, -5 }, { -39, -4 }, { -39, -3 }, { -39, -2 }, { -39, -1 }, { -39, 0 }, { -39, 1 }, { -39, 2 }, { -39, 3 }, { -39, 4 }, { -39, 5 }, { -39, 6 }, { -39, 7 },
|
||||
{ -39, 8 }, { -39, 15 }, { -39, 16 }, { -39, 22 }, { -39, 23 }, { -39, 24 }, { -39, 27 }, { -39, 28 }, { -39, 29 }, { -39, 30 }, { -38, -27 }, { -38, -26 }, { -38, -25 }, { -38, -24 }, { -38, -21 }, { -38, -20 }, { -38, -13 }, { -38, -12 }, { -38, -5 }, { -38, -4 }, { -38, -3 }, { -38, -2 }, { -38, -1 }, { -38, 0 }, { -38, 1 }, { -38, 2 }, { -38, 3 }, { -38, 4 }, { -38, 5 }, { -38, 6 },
|
||||
{ -38, 7 }, { -38, 8 }, { -38, 15 }, { -38, 16 }, { -38, 23 }, { -38, 24 }, { -38, 27 }, { -38, 28 }, { -38, 29 }, { -38, 30 }, { -37, -17 }, { -37, -16 }, { -37, -13 }, { -37, -12 }, { -37, -11 }, { -37, -10 }, { -37, -4 }, { -37, -3 }, { -37, -2 }, { -37, -1 }, { -37, 0 }, { -37, 3 }, { -37, 4 }, { -37, 5 }, { -37, 6 }, { -37, 7 }, { -37, 13 }, { -37, 14 }, { -37, 15 }, { -37, 16 },
|
||||
{ -37, 19 }, { -37, 20 }, { -36, -17 }, { -36, -16 }, { -36, -13 }, { -36, -12 }, { -36, -11 }, { -36, -10 }, { -36, -9 }, { -36, -3 }, { -36, -2 }, { -36, -1 }, { -36, 0 }, { -36, 3 }, { -36, 4 }, { -36, 5 }, { -36, 6 }, { -36, 12 }, { -36, 13 }, { -36, 14 }, { -36, 15 }, { -36, 16 }, { -36, 19 }, { -36, 20 }, { -35, -29 }, { -35, -28 }, { -35, -23 }, { -35, -22 }, { -35, -17 }, { -35, -16 },
|
||||
{ -35, -12 }, { -35, -11 }, { -35, -10 }, { -35, -9 }, { -35, -8 }, { -35, 11 }, { -35, 12 }, { -35, 13 }, { -35, 14 }, { -35, 15 }, { -35, 19 }, { -35, 20 }, { -35, 25 }, { -35, 26 }, { -35, 31 }, { -35, 32 }, { -34, -30 }, { -34, -29 }, { -34, -28 }, { -34, -23 }, { -34, -22 }, { -34, -17 }, { -34, -16 }, { -34, -15 }, { -34, -11 }, { -34, -10 }, { -34, -9 }, { -34, -8 }, { -34, 11 }, { -34, 12 },
|
||||
{ -34, 13 }, { -34, 14 }, { -34, 18 }, { -34, 19 }, { -34, 20 }, { -34, 25 }, { -34, 26 }, { -34, 31 }, { -34, 32 }, { -34, 33 }, { -33, -31 }, { -33, -30 }, { -33, -29 }, { -33, -28 }, { -33, -23 }, { -33, -22 }, { -33, -16 }, { -33, -15 }, { -33, -14 }, { -33, -5 }, { -33, -4 }, { -33, -1 }, { -33, 0 }, { -33, 3 }, { -33, 4 }, { -33, 7 }, { -33, 8 }, { -33, 17 }, { -33, 18 }, { -33, 19 },
|
||||
{ -33, 25 }, { -33, 26 }, { -33, 31 }, { -33, 32 }, { -33, 33 }, { -33, 34 }, { -32, -32 }, { -32, -31 }, { -32, -30 }, { -32, -29 }, { -32, -28 }, { -32, -27 }, { -32, -23 }, { -32, -22 }, { -32, -21 }, { -32, -15 }, { -32, -14 }, { -32, -6 }, { -32, -5 }, { -32, -4 }, { -32, -1 }, { -32, 0 }, { -32, 3 }, { -32, 4 }, { -32, 7 }, { -32, 8 }, { -32, 9 }, { -32, 17 }, { -32, 18 }, { -32, 24 },
|
||||
{ -32, 25 }, { -32, 26 }, { -32, 30 }, { -32, 31 }, { -32, 32 }, { -32, 33 }, { -32, 34 }, { -32, 35 }, { -31, -33 }, { -31, -32 }, { -31, -31 }, { -31, -30 }, { -31, -29 }, { -31, -28 }, { -31, -27 }, { -31, -26 }, { -31, -22 }, { -31, -21 }, { -31, -20 }, { -31, -19 }, { -31, -18 }, { -31, -11 }, { -31, -10 }, { -31, -9 }, { -31, -8 }, { -31, -7 }, { -31, -6 }, { -31, -5 }, { -31, -1 }, { -31, 0 },
|
||||
{ -31, 1 }, { -31, 2 }, { -31, 3 }, { -31, 4 }, { -31, 8 }, { -31, 9 }, { -31, 10 }, { -31, 11 }, { -31, 12 }, { -31, 13 }, { -31, 14 }, { -31, 21 }, { -31, 22 }, { -31, 23 }, { -31, 24 }, { -31, 25 }, { -31, 29 }, { -31, 30 }, { -31, 31 }, { -31, 32 }, { -31, 33 }, { -31, 34 }, { -31, 35 }, { -31, 36 }, { -30, -33 }, { -30, -32 }, { -30, -31 }, { -30, -30 }, { -30, -29 }, { -30, -28 },
|
||||
{ -30, -27 }, { -30, -26 }, { -30, -21 }, { -30, -20 }, { -30, -19 }, { -30, -18 }, { -30, -11 }, { -30, -10 }, { -30, -9 }, { -30, -8 }, { -30, -7 }, { -30, -6 }, { -30, -1 }, { -30, 0 }, { -30, 1 }, { -30, 2 }, { -30, 3 }, { -30, 4 }, { -30, 9 }, { -30, 10 }, { -30, 11 }, { -30, 12 }, { -30, 13 }, { -30, 14 }, { -30, 21 }, { -30, 22 }, { -30, 23 }, { -30, 24 }, { -30, 29 }, { -30, 30 },
|
||||
{ -30, 31 }, { -30, 32 }, { -30, 33 }, { -30, 34 }, { -30, 35 }, { -30, 36 }, { -29, -37 }, { -29, -36 }, { -29, -30 }, { -29, -29 }, { -29, -28 }, { -29, -27 }, { -29, -26 }, { -29, -15 }, { -29, -14 }, { -29, -10 }, { -29, -9 }, { -29, -8 }, { -29, -7 }, { -29, 10 }, { -29, 11 }, { -29, 12 }, { -29, 13 }, { -29, 17 }, { -29, 18 }, { -29, 29 }, { -29, 30 }, { -29, 31 }, { -29, 32 }, { -29, 33 },
|
||||
{ -29, 39 }, { -29, 40 }, { -28, -38 }, { -28, -37 }, { -28, -36 }, { -28, -29 }, { -28, -28 }, { -28, -27 }, { -28, -26 }, { -28, -16 }, { -28, -15 }, { -28, -14 }, { -28, -9 }, { -28, -8 }, { -28, 11 }, { -28, 12 }, { -28, 17 }, { -28, 18 }, { -28, 19 }, { -28, 29 }, { -28, 30 }, { -28, 31 }, { -28, 32 }, { -28, 39 }, { -28, 40 }, { -28, 41 }, { -27, -39 }, { -27, -38 }, { -27, -37 }, { -27, -36 },
|
||||
{ -27, -23 }, { -27, -22 }, { -27, -19 }, { -27, -18 }, { -27, -17 }, { -27, -16 }, { -27, -15 }, { -27, -5 }, { -27, -4 }, { -27, -1 }, { -27, 0 }, { -27, 1 }, { -27, 2 }, { -27, 3 }, { -27, 4 }, { -27, 7 }, { -27, 8 }, { -27, 18 }, { -27, 19 }, { -27, 20 }, { -27, 21 }, { -27, 22 }, { -27, 25 }, { -27, 26 }, { -27, 39 }, { -27, 40 }, { -27, 41 }, { -27, 42 }, { -26, -39 }, { -26, -38 },
|
||||
{ -26, -37 }, { -26, -36 }, { -26, -24 }, { -26, -23 }, { -26, -22 }, { -26, -19 }, { -26, -18 }, { -26, -17 }, { -26, -16 }, { -26, -6 }, { -26, -5 }, { -26, -4 }, { -26, -1 }, { -26, 0 }, { -26, 1 }, { -26, 2 }, { -26, 3 }, { -26, 4 }, { -26, 7 }, { -26, 8 }, { -26, 9 }, { -26, 19 }, { -26, 20 }, { -26, 21 }, { -26, 22 }, { -26, 25 }, { -26, 26 }, { -26, 27 }, { -26, 39 }, { -26, 40 },
|
||||
{ -26, 41 }, { -26, 42 }, { -25, -33 }, { -25, -32 }, { -25, -31 }, { -25, -30 }, { -25, -25 }, { -25, -24 }, { -25, -23 }, { -25, -22 }, { -25, -19 }, { -25, -18 }, { -25, -17 }, { -25, -9 }, { -25, -8 }, { -25, -7 }, { -25, -6 }, { -25, -5 }, { -25, -4 }, { -25, -1 }, { -25, 0 }, { -25, 1 }, { -25, 2 }, { -25, 3 }, { -25, 4 }, { -25, 7 }, { -25, 8 }, { -25, 9 }, { -25, 10 }, { -25, 11 },
|
||||
{ -25, 12 }, { -25, 20 }, { -25, 21 }, { -25, 22 }, { -25, 25 }, { -25, 26 }, { -25, 27 }, { -25, 28 }, { -25, 33 }, { -25, 34 }, { -25, 35 }, { -25, 36 }, { -24, -33 }, { -24, -32 }, { -24, -31 }, { -24, -30 }, { -24, -29 }, { -24, -25 }, { -24, -24 }, { -24, -23 }, { -24, -22 }, { -24, -19 }, { -24, -18 }, { -24, -9 }, { -24, -8 }, { -24, -7 }, { -24, -6 }, { -24, -5 }, { -24, -4 }, { -24, -1 },
|
||||
{ -24, 0 }, { -24, 1 }, { -24, 2 }, { -24, 3 }, { -24, 4 }, { -24, 7 }, { -24, 8 }, { -24, 9 }, { -24, 10 }, { -24, 11 }, { -24, 12 }, { -24, 21 }, { -24, 22 }, { -24, 25 }, { -24, 26 }, { -24, 27 }, { -24, 28 }, { -24, 32 }, { -24, 33 }, { -24, 34 }, { -24, 35 }, { -24, 36 }, { -23, -37 }, { -23, -36 }, { -23, -30 }, { -23, -29 }, { -23, -28 }, { -23, -19 }, { -23, -18 }, { -23, -15 },
|
||||
{ -23, -14 }, { -23, -9 }, { -23, -8 }, { -23, -7 }, { -23, -6 }, { -23, -5 }, { -23, 0 }, { -23, 1 }, { -23, 2 }, { -23, 3 }, { -23, 8 }, { -23, 9 }, { -23, 10 }, { -23, 11 }, { -23, 12 }, { -23, 17 }, { -23, 18 }, { -23, 21 }, { -23, 22 }, { -23, 31 }, { -23, 32 }, { -23, 33 }, { -23, 39 }, { -23, 40 }, { -22, -38 }, { -22, -37 }, { -22, -36 }, { -22, -29 }, { -22, -28 }, { -22, -19 },
|
||||
{ -22, -18 }, { -22, -15 }, { -22, -14 }, { -22, -13 }, { -22, -9 }, { -22, -8 }, { -22, -7 }, { -22, -6 }, { -22, 1 }, { -22, 2 }, { -22, 9 }, { -22, 10 }, { -22, 11 }, { -22, 12 }, { -22, 16 }, { -22, 17 }, { -22, 18 }, { -22, 21 }, { -22, 22 }, { -22, 31 }, { -22, 32 }, { -22, 39 }, { -22, 40 }, { -22, 41 }, { -21, -41 }, { -21, -40 }, { -21, -39 }, { -21, -38 }, { -21, -37 }, { -21, -29 },
|
||||
{ -21, -28 }, { -21, -25 }, { -21, -24 }, { -21, -23 }, { -21, -22 }, { -21, -21 }, { -21, -20 }, { -21, -19 }, { -21, -18 }, { -21, -15 }, { -21, -14 }, { -21, -13 }, { -21, -12 }, { -21, -3 }, { -21, -2 }, { -21, 5 }, { -21, 6 }, { -21, 15 }, { -21, 16 }, { -21, 17 }, { -21, 18 }, { -21, 21 }, { -21, 22 }, { -21, 23 }, { -21, 24 }, { -21, 25 }, { -21, 26 }, { -21, 27 }, { -21, 28 }, { -21, 31 },
|
||||
{ -21, 32 }, { -21, 40 }, { -21, 41 }, { -21, 42 }, { -21, 43 }, { -21, 44 }, { -20, -42 }, { -20, -41 }, { -20, -40 }, { -20, -39 }, { -20, -38 }, { -20, -29 }, { -20, -28 }, { -20, -25 }, { -20, -24 }, { -20, -23 }, { -20, -22 }, { -20, -21 }, { -20, -20 }, { -20, -19 }, { -20, -18 }, { -20, -15 }, { -20, -14 }, { -20, -13 }, { -20, -12 }, { -20, -3 }, { -20, -2 }, { -20, -1 }, { -20, 4 }, { -20, 5 },
|
||||
{ -20, 6 }, { -20, 15 }, { -20, 16 }, { -20, 17 }, { -20, 18 }, { -20, 21 }, { -20, 22 }, { -20, 23 }, { -20, 24 }, { -20, 25 }, { -20, 26 }, { -20, 27 }, { -20, 28 }, { -20, 31 }, { -20, 32 }, { -20, 41 }, { -20, 42 }, { -20, 43 }, { -20, 44 }, { -20, 45 }, { -19, -43 }, { -19, -42 }, { -19, -41 }, { -19, -35 }, { -19, -34 }, { -19, -33 }, { -19, -32 }, { -19, -25 }, { -19, -24 }, { -19, -23 },
|
||||
{ -19, -15 }, { -19, -14 }, { -19, -13 }, { -19, -9 }, { -19, -8 }, { -19, -7 }, { -19, -6 }, { -19, -2 }, { -19, -1 }, { -19, 0 }, { -19, 1 }, { -19, 2 }, { -19, 3 }, { -19, 4 }, { -19, 5 }, { -19, 9 }, { -19, 10 }, { -19, 11 }, { -19, 12 }, { -19, 16 }, { -19, 17 }, { -19, 18 }, { -19, 26 }, { -19, 27 }, { -19, 28 }, { -19, 35 }, { -19, 36 }, { -19, 37 }, { -19, 38 }, { -19, 44 },
|
||||
{ -19, 45 }, { -19, 46 }, { -18, -43 }, { -18, -42 }, { -18, -35 }, { -18, -34 }, { -18, -33 }, { -18, -32 }, { -18, -31 }, { -18, -26 }, { -18, -25 }, { -18, -24 }, { -18, -15 }, { -18, -14 }, { -18, -10 }, { -18, -9 }, { -18, -8 }, { -18, -7 }, { -18, -6 }, { -18, -1 }, { -18, 0 }, { -18, 1 }, { -18, 2 }, { -18, 3 }, { -18, 4 }, { -18, 9 }, { -18, 10 }, { -18, 11 }, { -18, 12 }, { -18, 13 },
|
||||
{ -18, 17 }, { -18, 18 }, { -18, 27 }, { -18, 28 }, { -18, 29 }, { -18, 34 }, { -18, 35 }, { -18, 36 }, { -18, 37 }, { -18, 38 }, { -18, 45 }, { -18, 46 }, { -17, -43 }, { -17, -42 }, { -17, -32 }, { -17, -31 }, { -17, -30 }, { -17, -27 }, { -17, -26 }, { -17, -25 }, { -17, -21 }, { -17, -20 }, { -17, -19 }, { -17, -18 }, { -17, -17 }, { -17, -16 }, { -17, -15 }, { -17, -14 }, { -17, -11 }, { -17, -10 },
|
||||
{ -17, -9 }, { -17, -8 }, { -17, -7 }, { -17, -6 }, { -17, 0 }, { -17, 1 }, { -17, 2 }, { -17, 3 }, { -17, 9 }, { -17, 10 }, { -17, 11 }, { -17, 12 }, { -17, 13 }, { -17, 14 }, { -17, 17 }, { -17, 18 }, { -17, 19 }, { -17, 20 }, { -17, 21 }, { -17, 22 }, { -17, 23 }, { -17, 24 }, { -17, 28 }, { -17, 29 }, { -17, 30 }, { -17, 33 }, { -17, 34 }, { -17, 35 }, { -17, 45 }, { -17, 46 },
|
||||
{ -16, -43 }, { -16, -42 }, { -16, -31 }, { -16, -30 }, { -16, -27 }, { -16, -26 }, { -16, -21 }, { -16, -20 }, { -16, -19 }, { -16, -18 }, { -16, -17 }, { -16, -16 }, { -16, -15 }, { -16, -14 }, { -16, -11 }, { -16, -10 }, { -16, -9 }, { -16, -8 }, { -16, -7 }, { -16, -6 }, { -16, 1 }, { -16, 2 }, { -16, 9 }, { -16, 10 }, { -16, 11 }, { -16, 12 }, { -16, 13 }, { -16, 14 }, { -16, 17 }, { -16, 18 },
|
||||
{ -16, 19 }, { -16, 20 }, { -16, 21 }, { -16, 22 }, { -16, 23 }, { -16, 24 }, { -16, 29 }, { -16, 30 }, { -16, 33 }, { -16, 34 }, { -16, 45 }, { -16, 46 }, { -15, -43 }, { -15, -42 }, { -15, -39 }, { -15, -38 }, { -15, -37 }, { -15, -36 }, { -15, -35 }, { -15, -34 }, { -15, -20 }, { -15, -19 }, { -15, -18 }, { -15, -17 }, { -15, -10 }, { -15, -9 }, { -15, -8 }, { -15, -7 }, { -15, -3 }, { -15, -2 },
|
||||
{ -15, 1 }, { -15, 2 }, { -15, 5 }, { -15, 6 }, { -15, 10 }, { -15, 11 }, { -15, 12 }, { -15, 13 }, { -15, 20 }, { -15, 21 }, { -15, 22 }, { -15, 23 }, { -15, 37 }, { -15, 38 }, { -15, 39 }, { -15, 40 }, { -15, 41 }, { -15, 42 }, { -15, 45 }, { -15, 46 }, { -14, -43 }, { -14, -42 }, { -14, -39 }, { -14, -38 }, { -14, -37 }, { -14, -36 }, { -14, -35 }, { -14, -34 }, { -14, -33 }, { -14, -19 },
|
||||
{ -14, -18 }, { -14, -9 }, { -14, -8 }, { -14, -4 }, { -14, -3 }, { -14, -2 }, { -14, 1 }, { -14, 2 }, { -14, 5 }, { -14, 6 }, { -14, 7 }, { -14, 11 }, { -14, 12 }, { -14, 21 }, { -14, 22 }, { -14, 36 }, { -14, 37 }, { -14, 38 }, { -14, 39 }, { -14, 40 }, { -14, 41 }, { -14, 42 }, { -14, 45 }, { -14, 46 }, { -13, -39 }, { -13, -38 }, { -13, -35 }, { -13, -34 }, { -13, -33 }, { -13, -32 },
|
||||
{ -13, -29 }, { -13, -28 }, { -13, -15 }, { -13, -14 }, { -13, -5 }, { -13, -4 }, { -13, -3 }, { -13, -2 }, { -13, 5 }, { -13, 6 }, { -13, 7 }, { -13, 8 }, { -13, 17 }, { -13, 18 }, { -13, 31 }, { -13, 32 }, { -13, 35 }, { -13, 36 }, { -13, 37 }, { -13, 38 }, { -13, 41 }, { -13, 42 }, { -12, -39 }, { -12, -38 }, { -12, -35 }, { -12, -34 }, { -12, -33 }, { -12, -32 }, { -12, -29 }, { -12, -28 },
|
||||
{ -12, -27 }, { -12, -16 }, { -12, -15 }, { -12, -14 }, { -12, -13 }, { -12, -5 }, { -12, -4 }, { -12, -3 }, { -12, -2 }, { -12, 5 }, { -12, 6 }, { -12, 7 }, { -12, 8 }, { -12, 16 }, { -12, 17 }, { -12, 18 }, { -12, 19 }, { -12, 30 }, { -12, 31 }, { -12, 32 }, { -12, 35 }, { -12, 36 }, { -12, 37 }, { -12, 38 }, { -12, 41 }, { -12, 42 }, { -11, -43 }, { -11, -42 }, { -11, -34 }, { -11, -33 },
|
||||
{ -11, -32 }, { -11, -29 }, { -11, -28 }, { -11, -27 }, { -11, -26 }, { -11, -23 }, { -11, -22 }, { -11, -21 }, { -11, -20 }, { -11, -17 }, { -11, -16 }, { -11, -15 }, { -11, -14 }, { -11, -13 }, { -11, -12 }, { -11, -9 }, { -11, -8 }, { -11, 1 }, { -11, 2 }, { -11, 11 }, { -11, 12 }, { -11, 15 }, { -11, 16 }, { -11, 17 }, { -11, 18 }, { -11, 19 }, { -11, 20 }, { -11, 23 }, { -11, 24 }, { -11, 25 },
|
||||
{ -11, 26 }, { -11, 29 }, { -11, 30 }, { -11, 31 }, { -11, 32 }, { -11, 35 }, { -11, 36 }, { -11, 37 }, { -11, 45 }, { -11, 46 }, { -10, -44 }, { -10, -43 }, { -10, -42 }, { -10, -33 }, { -10, -32 }, { -10, -29 }, { -10, -28 }, { -10, -27 }, { -10, -26 }, { -10, -23 }, { -10, -22 }, { -10, -21 }, { -10, -20 }, { -10, -17 }, { -10, -16 }, { -10, -15 }, { -10, -14 }, { -10, -13 }, { -10, -12 }, { -10, -9 },
|
||||
{ -10, -8 }, { -10, -7 }, { -10, 0 }, { -10, 1 }, { -10, 2 }, { -10, 3 }, { -10, 10 }, { -10, 11 }, { -10, 12 }, { -10, 15 }, { -10, 16 }, { -10, 17 }, { -10, 18 }, { -10, 19 }, { -10, 20 }, { -10, 23 }, { -10, 24 }, { -10, 25 }, { -10, 26 }, { -10, 29 }, { -10, 30 }, { -10, 31 }, { -10, 32 }, { -10, 35 }, { -10, 36 }, { -10, 45 }, { -10, 46 }, { -10, 47 }, { -9, -45 }, { -9, -44 },
|
||||
{ -9, -43 }, { -9, -29 }, { -9, -28 }, { -9, -27 }, { -9, -23 }, { -9, -22 }, { -9, -21 }, { -9, -20 }, { -9, -17 }, { -9, -16 }, { -9, -15 }, { -9, -14 }, { -9, -13 }, { -9, -8 }, { -9, -7 }, { -9, -6 }, { -9, -5 }, { -9, -1 }, { -9, 0 }, { -9, 1 }, { -9, 2 }, { -9, 3 }, { -9, 4 }, { -9, 8 }, { -9, 9 }, { -9, 10 }, { -9, 11 }, { -9, 16 }, { -9, 17 }, { -9, 18 },
|
||||
{ -9, 19 }, { -9, 20 }, { -9, 23 }, { -9, 24 }, { -9, 25 }, { -9, 26 }, { -9, 30 }, { -9, 31 }, { -9, 32 }, { -9, 46 }, { -9, 47 }, { -9, 48 }, { -8, -45 }, { -8, -44 }, { -8, -30 }, { -8, -29 }, { -8, -28 }, { -8, -24 }, { -8, -23 }, { -8, -22 }, { -8, -21 }, { -8, -20 }, { -8, -17 }, { -8, -16 }, { -8, -15 }, { -8, -14 }, { -8, -7 }, { -8, -6 }, { -8, -5 }, { -8, -4 },
|
||||
{ -8, -1 }, { -8, 0 }, { -8, 1 }, { -8, 2 }, { -8, 3 }, { -8, 4 }, { -8, 7 }, { -8, 8 }, { -8, 9 }, { -8, 10 }, { -8, 17 }, { -8, 18 }, { -8, 19 }, { -8, 20 }, { -8, 23 }, { -8, 24 }, { -8, 25 }, { -8, 26 }, { -8, 27 }, { -8, 31 }, { -8, 32 }, { -8, 33 }, { -8, 47 }, { -8, 48 }, { -7, -45 }, { -7, -44 }, { -7, -39 }, { -7, -38 }, { -7, -37 }, { -7, -36 },
|
||||
{ -7, -31 }, { -7, -30 }, { -7, -29 }, { -7, -25 }, { -7, -24 }, { -7, -23 }, { -7, -22 }, { -7, -21 }, { -7, -11 }, { -7, -10 }, { -7, -7 }, { -7, -6 }, { -7, -5 }, { -7, -4 }, { -7, 7 }, { -7, 8 }, { -7, 9 }, { -7, 10 }, { -7, 13 }, { -7, 14 }, { -7, 24 }, { -7, 25 }, { -7, 26 }, { -7, 27 }, { -7, 28 }, { -7, 32 }, { -7, 33 }, { -7, 34 }, { -7, 39 }, { -7, 40 },
|
||||
{ -7, 41 }, { -7, 42 }, { -7, 47 }, { -7, 48 }, { -6, -46 }, { -6, -45 }, { -6, -44 }, { -6, -39 }, { -6, -38 }, { -6, -37 }, { -6, -36 }, { -6, -35 }, { -6, -31 }, { -6, -30 }, { -6, -25 }, { -6, -24 }, { -6, -23 }, { -6, -22 }, { -6, -12 }, { -6, -11 }, { -6, -10 }, { -6, -6 }, { -6, -5 }, { -6, 8 }, { -6, 9 }, { -6, 13 }, { -6, 14 }, { -6, 15 }, { -6, 25 }, { -6, 26 },
|
||||
{ -6, 27 }, { -6, 28 }, { -6, 33 }, { -6, 34 }, { -6, 38 }, { -6, 39 }, { -6, 40 }, { -6, 41 }, { -6, 42 }, { -6, 47 }, { -6, 48 }, { -6, 49 }, { -5, -47 }, { -5, -46 }, { -5, -45 }, { -5, -44 }, { -5, -37 }, { -5, -36 }, { -5, -35 }, { -5, -34 }, { -5, -19 }, { -5, -18 }, { -5, -13 }, { -5, -12 }, { -5, -11 }, { -5, -10 }, { -5, -1 }, { -5, 0 }, { -5, 1 }, { -5, 2 },
|
||||
{ -5, 3 }, { -5, 4 }, { -5, 13 }, { -5, 14 }, { -5, 15 }, { -5, 16 }, { -5, 21 }, { -5, 22 }, { -5, 37 }, { -5, 38 }, { -5, 39 }, { -5, 40 }, { -5, 47 }, { -5, 48 }, { -5, 49 }, { -5, 50 }, { -4, -47 }, { -4, -46 }, { -4, -45 }, { -4, -44 }, { -4, -43 }, { -4, -37 }, { -4, -36 }, { -4, -35 }, { -4, -34 }, { -4, -19 }, { -4, -18 }, { -4, -17 }, { -4, -13 }, { -4, -12 },
|
||||
{ -4, -11 }, { -4, -10 }, { -4, -2 }, { -4, -1 }, { -4, 0 }, { -4, 1 }, { -4, 2 }, { -4, 3 }, { -4, 4 }, { -4, 5 }, { -4, 13 }, { -4, 14 }, { -4, 15 }, { -4, 16 }, { -4, 20 }, { -4, 21 }, { -4, 22 }, { -4, 37 }, { -4, 38 }, { -4, 39 }, { -4, 40 }, { -4, 46 }, { -4, 47 }, { -4, 48 }, { -4, 49 }, { -4, 50 }, { -3, -44 }, { -3, -43 }, { -3, -42 }, { -3, -41 },
|
||||
{ -3, -40 }, { -3, -37 }, { -3, -36 }, { -3, -35 }, { -3, -34 }, { -3, -31 }, { -3, -30 }, { -3, -29 }, { -3, -28 }, { -3, -25 }, { -3, -24 }, { -3, -23 }, { -3, -22 }, { -3, -18 }, { -3, -17 }, { -3, -16 }, { -3, -7 }, { -3, -6 }, { -3, -3 }, { -3, -2 }, { -3, -1 }, { -3, 0 }, { -3, 3 }, { -3, 4 }, { -3, 5 }, { -3, 6 }, { -3, 9 }, { -3, 10 }, { -3, 19 }, { -3, 20 },
|
||||
{ -3, 21 }, { -3, 25 }, { -3, 26 }, { -3, 27 }, { -3, 28 }, { -3, 31 }, { -3, 32 }, { -3, 33 }, { -3, 34 }, { -3, 37 }, { -3, 38 }, { -3, 39 }, { -3, 40 }, { -3, 43 }, { -3, 44 }, { -3, 45 }, { -3, 46 }, { -3, 47 }, { -2, -43 }, { -2, -42 }, { -2, -41 }, { -2, -40 }, { -2, -37 }, { -2, -36 }, { -2, -35 }, { -2, -34 }, { -2, -31 }, { -2, -30 }, { -2, -29 }, { -2, -28 },
|
||||
{ -2, -25 }, { -2, -24 }, { -2, -23 }, { -2, -22 }, { -2, -21 }, { -2, -17 }, { -2, -16 }, { -2, -15 }, { -2, -8 }, { -2, -7 }, { -2, -6 }, { -2, -3 }, { -2, -2 }, { -2, -1 }, { -2, 0 }, { -2, 3 }, { -2, 4 }, { -2, 5 }, { -2, 6 }, { -2, 9 }, { -2, 10 }, { -2, 11 }, { -2, 18 }, { -2, 19 }, { -2, 20 }, { -2, 24 }, { -2, 25 }, { -2, 26 }, { -2, 27 }, { -2, 28 },
|
||||
{ -2, 31 }, { -2, 32 }, { -2, 33 }, { -2, 34 }, { -2, 37 }, { -2, 38 }, { -2, 39 }, { -2, 40 }, { -2, 43 }, { -2, 44 }, { -2, 45 }, { -2, 46 }, { -1, -47 }, { -1, -46 }, { -1, -43 }, { -1, -42 }, { -1, -41 }, { -1, -40 }, { -1, -37 }, { -1, -36 }, { -1, -29 }, { -1, -28 }, { -1, -25 }, { -1, -24 }, { -1, -23 }, { -1, -22 }, { -1, -21 }, { -1, -20 }, { -1, -17 }, { -1, -16 },
|
||||
{ -1, -15 }, { -1, -14 }, { -1, -13 }, { -1, -12 }, { -1, -9 }, { -1, -8 }, { -1, -7 }, { -1, -6 }, { -1, -3 }, { -1, -2 }, { -1, 5 }, { -1, 6 }, { -1, 9 }, { -1, 10 }, { -1, 11 }, { -1, 12 }, { -1, 15 }, { -1, 16 }, { -1, 17 }, { -1, 18 }, { -1, 19 }, { -1, 20 }, { -1, 23 }, { -1, 24 }, { -1, 25 }, { -1, 26 }, { -1, 27 }, { -1, 28 }, { -1, 31 }, { -1, 32 },
|
||||
{ -1, 39 }, { -1, 40 }, { -1, 43 }, { -1, 44 }, { -1, 45 }, { -1, 46 }, { -1, 49 }, { -1, 50 }, { 0, -47 }, { 0, -46 }, { 0, -43 }, { 0, -42 }, { 0, -41 }, { 0, -40 }, { 0, -37 }, { 0, -36 }, { 0, -29 }, { 0, -28 }, { 0, -25 }, { 0, -24 }, { 0, -23 }, { 0, -22 }, { 0, -21 }, { 0, -20 }, { 0, -17 }, { 0, -16 }, { 0, -15 }, { 0, -14 }, { 0, -13 }, { 0, -12 },
|
||||
{ 0, -9 }, { 0, -8 }, { 0, -7 }, { 0, -6 }, { 0, -3 }, { 0, -2 }, { 0, 5 }, { 0, 6 }, { 0, 9 }, { 0, 10 }, { 0, 11 }, { 0, 12 }, { 0, 15 }, { 0, 16 }, { 0, 17 }, { 0, 18 }, { 0, 19 }, { 0, 20 }, { 0, 23 }, { 0, 24 }, { 0, 25 }, { 0, 26 }, { 0, 27 }, { 0, 28 }, { 0, 31 }, { 0, 32 }, { 0, 39 }, { 0, 40 }, { 0, 43 }, { 0, 44 },
|
||||
{ 0, 45 }, { 0, 46 }, { 0, 49 }, { 0, 50 }, { 1, -43 }, { 1, -42 }, { 1, -41 }, { 1, -40 }, { 1, -37 }, { 1, -36 }, { 1, -35 }, { 1, -34 }, { 1, -31 }, { 1, -30 }, { 1, -29 }, { 1, -28 }, { 1, -25 }, { 1, -24 }, { 1, -23 }, { 1, -22 }, { 1, -21 }, { 1, -17 }, { 1, -16 }, { 1, -15 }, { 1, -8 }, { 1, -7 }, { 1, -6 }, { 1, -3 }, { 1, -2 }, { 1, -1 },
|
||||
{ 1, 0 }, { 1, 3 }, { 1, 4 }, { 1, 5 }, { 1, 6 }, { 1, 9 }, { 1, 10 }, { 1, 11 }, { 1, 18 }, { 1, 19 }, { 1, 20 }, { 1, 24 }, { 1, 25 }, { 1, 26 }, { 1, 27 }, { 1, 28 }, { 1, 31 }, { 1, 32 }, { 1, 33 }, { 1, 34 }, { 1, 37 }, { 1, 38 }, { 1, 39 }, { 1, 40 }, { 1, 43 }, { 1, 44 }, { 1, 45 }, { 1, 46 }, { 2, -44 }, { 2, -43 },
|
||||
{ 2, -42 }, { 2, -41 }, { 2, -40 }, { 2, -37 }, { 2, -36 }, { 2, -35 }, { 2, -34 }, { 2, -31 }, { 2, -30 }, { 2, -29 }, { 2, -28 }, { 2, -25 }, { 2, -24 }, { 2, -23 }, { 2, -22 }, { 2, -18 }, { 2, -17 }, { 2, -16 }, { 2, -7 }, { 2, -6 }, { 2, -3 }, { 2, -2 }, { 2, -1 }, { 2, 0 }, { 2, 3 }, { 2, 4 }, { 2, 5 }, { 2, 6 }, { 2, 9 }, { 2, 10 },
|
||||
{ 2, 19 }, { 2, 20 }, { 2, 21 }, { 2, 25 }, { 2, 26 }, { 2, 27 }, { 2, 28 }, { 2, 31 }, { 2, 32 }, { 2, 33 }, { 2, 34 }, { 2, 37 }, { 2, 38 }, { 2, 39 }, { 2, 40 }, { 2, 43 }, { 2, 44 }, { 2, 45 }, { 2, 46 }, { 2, 47 }, { 3, -47 }, { 3, -46 }, { 3, -45 }, { 3, -44 }, { 3, -43 }, { 3, -37 }, { 3, -36 }, { 3, -35 }, { 3, -34 }, { 3, -19 },
|
||||
{ 3, -18 }, { 3, -17 }, { 3, -13 }, { 3, -12 }, { 3, -11 }, { 3, -10 }, { 3, -2 }, { 3, -1 }, { 3, 0 }, { 3, 1 }, { 3, 2 }, { 3, 3 }, { 3, 4 }, { 3, 5 }, { 3, 13 }, { 3, 14 }, { 3, 15 }, { 3, 16 }, { 3, 20 }, { 3, 21 }, { 3, 22 }, { 3, 37 }, { 3, 38 }, { 3, 39 }, { 3, 40 }, { 3, 46 }, { 3, 47 }, { 3, 48 }, { 3, 49 }, { 3, 50 },
|
||||
{ 4, -47 }, { 4, -46 }, { 4, -45 }, { 4, -44 }, { 4, -37 }, { 4, -36 }, { 4, -35 }, { 4, -34 }, { 4, -19 }, { 4, -18 }, { 4, -13 }, { 4, -12 }, { 4, -11 }, { 4, -10 }, { 4, -1 }, { 4, 0 }, { 4, 1 }, { 4, 2 }, { 4, 3 }, { 4, 4 }, { 4, 13 }, { 4, 14 }, { 4, 15 }, { 4, 16 }, { 4, 21 }, { 4, 22 }, { 4, 37 }, { 4, 38 }, { 4, 39 }, { 4, 40 },
|
||||
{ 4, 47 }, { 4, 48 }, { 4, 49 }, { 4, 50 }, { 5, -46 }, { 5, -45 }, { 5, -44 }, { 5, -39 }, { 5, -38 }, { 5, -37 }, { 5, -36 }, { 5, -35 }, { 5, -31 }, { 5, -30 }, { 5, -25 }, { 5, -24 }, { 5, -23 }, { 5, -22 }, { 5, -12 }, { 5, -11 }, { 5, -10 }, { 5, -6 }, { 5, -5 }, { 5, 8 }, { 5, 9 }, { 5, 13 }, { 5, 14 }, { 5, 15 }, { 5, 25 }, { 5, 26 },
|
||||
{ 5, 27 }, { 5, 28 }, { 5, 33 }, { 5, 34 }, { 5, 38 }, { 5, 39 }, { 5, 40 }, { 5, 41 }, { 5, 42 }, { 5, 47 }, { 5, 48 }, { 5, 49 }, { 6, -45 }, { 6, -44 }, { 6, -39 }, { 6, -38 }, { 6, -37 }, { 6, -36 }, { 6, -31 }, { 6, -30 }, { 6, -29 }, { 6, -25 }, { 6, -24 }, { 6, -23 }, { 6, -22 }, { 6, -21 }, { 6, -11 }, { 6, -10 }, { 6, -7 }, { 6, -6 },
|
||||
{ 6, -5 }, { 6, -4 }, { 6, 7 }, { 6, 8 }, { 6, 9 }, { 6, 10 }, { 6, 13 }, { 6, 14 }, { 6, 24 }, { 6, 25 }, { 6, 26 }, { 6, 27 }, { 6, 28 }, { 6, 32 }, { 6, 33 }, { 6, 34 }, { 6, 39 }, { 6, 40 }, { 6, 41 }, { 6, 42 }, { 6, 47 }, { 6, 48 }, { 7, -45 }, { 7, -44 }, { 7, -30 }, { 7, -29 }, { 7, -28 }, { 7, -24 }, { 7, -23 }, { 7, -22 },
|
||||
{ 7, -21 }, { 7, -20 }, { 7, -17 }, { 7, -16 }, { 7, -15 }, { 7, -14 }, { 7, -7 }, { 7, -6 }, { 7, -5 }, { 7, -4 }, { 7, -1 }, { 7, 0 }, { 7, 1 }, { 7, 2 }, { 7, 3 }, { 7, 4 }, { 7, 7 }, { 7, 8 }, { 7, 9 }, { 7, 10 }, { 7, 17 }, { 7, 18 }, { 7, 19 }, { 7, 20 }, { 7, 23 }, { 7, 24 }, { 7, 25 }, { 7, 26 }, { 7, 27 }, { 7, 31 },
|
||||
{ 7, 32 }, { 7, 33 }, { 7, 47 }, { 7, 48 }, { 8, -45 }, { 8, -44 }, { 8, -43 }, { 8, -29 }, { 8, -28 }, { 8, -27 }, { 8, -23 }, { 8, -22 }, { 8, -21 }, { 8, -20 }, { 8, -17 }, { 8, -16 }, { 8, -15 }, { 8, -14 }, { 8, -13 }, { 8, -8 }, { 8, -7 }, { 8, -6 }, { 8, -5 }, { 8, -1 }, { 8, 0 }, { 8, 1 }, { 8, 2 }, { 8, 3 }, { 8, 4 }, { 8, 8 },
|
||||
{ 8, 9 }, { 8, 10 }, { 8, 11 }, { 8, 16 }, { 8, 17 }, { 8, 18 }, { 8, 19 }, { 8, 20 }, { 8, 23 }, { 8, 24 }, { 8, 25 }, { 8, 26 }, { 8, 30 }, { 8, 31 }, { 8, 32 }, { 8, 46 }, { 8, 47 }, { 8, 48 }, { 9, -44 }, { 9, -43 }, { 9, -42 }, { 9, -33 }, { 9, -32 }, { 9, -29 }, { 9, -28 }, { 9, -27 }, { 9, -26 }, { 9, -23 }, { 9, -22 }, { 9, -21 },
|
||||
{ 9, -20 }, { 9, -17 }, { 9, -16 }, { 9, -15 }, { 9, -14 }, { 9, -13 }, { 9, -12 }, { 9, -9 }, { 9, -8 }, { 9, -7 }, { 9, 0 }, { 9, 1 }, { 9, 2 }, { 9, 3 }, { 9, 10 }, { 9, 11 }, { 9, 12 }, { 9, 15 }, { 9, 16 }, { 9, 17 }, { 9, 18 }, { 9, 19 }, { 9, 20 }, { 9, 23 }, { 9, 24 }, { 9, 25 }, { 9, 26 }, { 9, 29 }, { 9, 30 }, { 9, 31 },
|
||||
{ 9, 32 }, { 9, 35 }, { 9, 36 }, { 9, 45 }, { 9, 46 }, { 9, 47 }, { 10, -43 }, { 10, -42 }, { 10, -34 }, { 10, -33 }, { 10, -32 }, { 10, -29 }, { 10, -28 }, { 10, -27 }, { 10, -26 }, { 10, -23 }, { 10, -22 }, { 10, -21 }, { 10, -20 }, { 10, -17 }, { 10, -16 }, { 10, -15 }, { 10, -14 }, { 10, -13 }, { 10, -12 }, { 10, -9 }, { 10, -8 }, { 10, 1 }, { 10, 2 }, { 10, 11 },
|
||||
{ 10, 12 }, { 10, 15 }, { 10, 16 }, { 10, 17 }, { 10, 18 }, { 10, 19 }, { 10, 20 }, { 10, 23 }, { 10, 24 }, { 10, 25 }, { 10, 26 }, { 10, 29 }, { 10, 30 }, { 10, 31 }, { 10, 32 }, { 10, 35 }, { 10, 36 }, { 10, 37 }, { 10, 45 }, { 10, 46 }, { 11, -39 }, { 11, -38 }, { 11, -35 }, { 11, -34 }, { 11, -33 }, { 11, -32 }, { 11, -29 }, { 11, -28 }, { 11, -27 }, { 11, -16 },
|
||||
{ 11, -15 }, { 11, -14 }, { 11, -13 }, { 11, -5 }, { 11, -4 }, { 11, -3 }, { 11, -2 }, { 11, 5 }, { 11, 6 }, { 11, 7 }, { 11, 8 }, { 11, 16 }, { 11, 17 }, { 11, 18 }, { 11, 19 }, { 11, 30 }, { 11, 31 }, { 11, 32 }, { 11, 35 }, { 11, 36 }, { 11, 37 }, { 11, 38 }, { 11, 41 }, { 11, 42 }, { 12, -39 }, { 12, -38 }, { 12, -35 }, { 12, -34 }, { 12, -33 }, { 12, -32 },
|
||||
{ 12, -29 }, { 12, -28 }, { 12, -15 }, { 12, -14 }, { 12, -5 }, { 12, -4 }, { 12, -3 }, { 12, -2 }, { 12, 5 }, { 12, 6 }, { 12, 7 }, { 12, 8 }, { 12, 17 }, { 12, 18 }, { 12, 31 }, { 12, 32 }, { 12, 35 }, { 12, 36 }, { 12, 37 }, { 12, 38 }, { 12, 41 }, { 12, 42 }, { 13, -43 }, { 13, -42 }, { 13, -39 }, { 13, -38 }, { 13, -37 }, { 13, -36 }, { 13, -35 }, { 13, -34 },
|
||||
{ 13, -33 }, { 13, -19 }, { 13, -18 }, { 13, -9 }, { 13, -8 }, { 13, -4 }, { 13, -3 }, { 13, -2 }, { 13, 1 }, { 13, 2 }, { 13, 5 }, { 13, 6 }, { 13, 7 }, { 13, 11 }, { 13, 12 }, { 13, 21 }, { 13, 22 }, { 13, 36 }, { 13, 37 }, { 13, 38 }, { 13, 39 }, { 13, 40 }, { 13, 41 }, { 13, 42 }, { 13, 45 }, { 13, 46 }, { 14, -43 }, { 14, -42 }, { 14, -39 }, { 14, -38 },
|
||||
{ 14, -37 }, { 14, -36 }, { 14, -35 }, { 14, -34 }, { 14, -20 }, { 14, -19 }, { 14, -18 }, { 14, -17 }, { 14, -10 }, { 14, -9 }, { 14, -8 }, { 14, -7 }, { 14, -3 }, { 14, -2 }, { 14, 1 }, { 14, 2 }, { 14, 5 }, { 14, 6 }, { 14, 10 }, { 14, 11 }, { 14, 12 }, { 14, 13 }, { 14, 20 }, { 14, 21 }, { 14, 22 }, { 14, 23 }, { 14, 37 }, { 14, 38 }, { 14, 39 }, { 14, 40 },
|
||||
{ 14, 41 }, { 14, 42 }, { 14, 45 }, { 14, 46 }, { 15, -43 }, { 15, -42 }, { 15, -31 }, { 15, -30 }, { 15, -27 }, { 15, -26 }, { 15, -21 }, { 15, -20 }, { 15, -19 }, { 15, -18 }, { 15, -17 }, { 15, -16 }, { 15, -15 }, { 15, -14 }, { 15, -11 }, { 15, -10 }, { 15, -9 }, { 15, -8 }, { 15, -7 }, { 15, -6 }, { 15, 1 }, { 15, 2 }, { 15, 9 }, { 15, 10 }, { 15, 11 }, { 15, 12 },
|
||||
{ 15, 13 }, { 15, 14 }, { 15, 17 }, { 15, 18 }, { 15, 19 }, { 15, 20 }, { 15, 21 }, { 15, 22 }, { 15, 23 }, { 15, 24 }, { 15, 29 }, { 15, 30 }, { 15, 33 }, { 15, 34 }, { 15, 45 }, { 15, 46 }, { 16, -43 }, { 16, -42 }, { 16, -32 }, { 16, -31 }, { 16, -30 }, { 16, -27 }, { 16, -26 }, { 16, -25 }, { 16, -21 }, { 16, -20 }, { 16, -19 }, { 16, -18 }, { 16, -17 }, { 16, -16 },
|
||||
{ 16, -15 }, { 16, -14 }, { 16, -11 }, { 16, -10 }, { 16, -9 }, { 16, -8 }, { 16, -7 }, { 16, -6 }, { 16, 0 }, { 16, 1 }, { 16, 2 }, { 16, 3 }, { 16, 9 }, { 16, 10 }, { 16, 11 }, { 16, 12 }, { 16, 13 }, { 16, 14 }, { 16, 17 }, { 16, 18 }, { 16, 19 }, { 16, 20 }, { 16, 21 }, { 16, 22 }, { 16, 23 }, { 16, 24 }, { 16, 28 }, { 16, 29 }, { 16, 30 }, { 16, 33 },
|
||||
{ 16, 34 }, { 16, 35 }, { 16, 45 }, { 16, 46 }, { 17, -43 }, { 17, -42 }, { 17, -35 }, { 17, -34 }, { 17, -33 }, { 17, -32 }, { 17, -31 }, { 17, -26 }, { 17, -25 }, { 17, -24 }, { 17, -15 }, { 17, -14 }, { 17, -10 }, { 17, -9 }, { 17, -8 }, { 17, -7 }, { 17, -6 }, { 17, -1 }, { 17, 0 }, { 17, 1 }, { 17, 2 }, { 17, 3 }, { 17, 4 }, { 17, 9 }, { 17, 10 }, { 17, 11 },
|
||||
{ 17, 12 }, { 17, 13 }, { 17, 17 }, { 17, 18 }, { 17, 27 }, { 17, 28 }, { 17, 29 }, { 17, 34 }, { 17, 35 }, { 17, 36 }, { 17, 37 }, { 17, 38 }, { 17, 45 }, { 17, 46 }, { 18, -43 }, { 18, -42 }, { 18, -41 }, { 18, -35 }, { 18, -34 }, { 18, -33 }, { 18, -32 }, { 18, -25 }, { 18, -24 }, { 18, -23 }, { 18, -15 }, { 18, -14 }, { 18, -13 }, { 18, -9 }, { 18, -8 }, { 18, -7 },
|
||||
{ 18, -6 }, { 18, -2 }, { 18, -1 }, { 18, 0 }, { 18, 1 }, { 18, 2 }, { 18, 3 }, { 18, 4 }, { 18, 5 }, { 18, 9 }, { 18, 10 }, { 18, 11 }, { 18, 12 }, { 18, 16 }, { 18, 17 }, { 18, 18 }, { 18, 26 }, { 18, 27 }, { 18, 28 }, { 18, 35 }, { 18, 36 }, { 18, 37 }, { 18, 38 }, { 18, 44 }, { 18, 45 }, { 18, 46 }, { 19, -42 }, { 19, -41 }, { 19, -40 }, { 19, -39 },
|
||||
{ 19, -38 }, { 19, -29 }, { 19, -28 }, { 19, -25 }, { 19, -24 }, { 19, -23 }, { 19, -22 }, { 19, -21 }, { 19, -20 }, { 19, -19 }, { 19, -18 }, { 19, -15 }, { 19, -14 }, { 19, -13 }, { 19, -12 }, { 19, -3 }, { 19, -2 }, { 19, -1 }, { 19, 4 }, { 19, 5 }, { 19, 6 }, { 19, 15 }, { 19, 16 }, { 19, 17 }, { 19, 18 }, { 19, 21 }, { 19, 22 }, { 19, 23 }, { 19, 24 }, { 19, 25 },
|
||||
{ 19, 26 }, { 19, 27 }, { 19, 28 }, { 19, 31 }, { 19, 32 }, { 19, 41 }, { 19, 42 }, { 19, 43 }, { 19, 44 }, { 19, 45 }, { 20, -41 }, { 20, -40 }, { 20, -39 }, { 20, -38 }, { 20, -37 }, { 20, -29 }, { 20, -28 }, { 20, -25 }, { 20, -24 }, { 20, -23 }, { 20, -22 }, { 20, -21 }, { 20, -20 }, { 20, -19 }, { 20, -18 }, { 20, -15 }, { 20, -14 }, { 20, -13 }, { 20, -12 }, { 20, -3 },
|
||||
{ 20, -2 }, { 20, 5 }, { 20, 6 }, { 20, 15 }, { 20, 16 }, { 20, 17 }, { 20, 18 }, { 20, 21 }, { 20, 22 }, { 20, 23 }, { 20, 24 }, { 20, 25 }, { 20, 26 }, { 20, 27 }, { 20, 28 }, { 20, 31 }, { 20, 32 }, { 20, 40 }, { 20, 41 }, { 20, 42 }, { 20, 43 }, { 20, 44 }, { 21, -38 }, { 21, -37 }, { 21, -36 }, { 21, -29 }, { 21, -28 }, { 21, -19 }, { 21, -18 }, { 21, -15 },
|
||||
{ 21, -14 }, { 21, -13 }, { 21, -9 }, { 21, -8 }, { 21, -7 }, { 21, -6 }, { 21, 1 }, { 21, 2 }, { 21, 9 }, { 21, 10 }, { 21, 11 }, { 21, 12 }, { 21, 16 }, { 21, 17 }, { 21, 18 }, { 21, 21 }, { 21, 22 }, { 21, 31 }, { 21, 32 }, { 21, 39 }, { 21, 40 }, { 21, 41 }, { 22, -37 }, { 22, -36 }, { 22, -30 }, { 22, -29 }, { 22, -28 }, { 22, -19 }, { 22, -18 }, { 22, -15 },
|
||||
{ 22, -14 }, { 22, -9 }, { 22, -8 }, { 22, -7 }, { 22, -6 }, { 22, -5 }, { 22, 0 }, { 22, 1 }, { 22, 2 }, { 22, 3 }, { 22, 8 }, { 22, 9 }, { 22, 10 }, { 22, 11 }, { 22, 12 }, { 22, 17 }, { 22, 18 }, { 22, 21 }, { 22, 22 }, { 22, 31 }, { 22, 32 }, { 22, 33 }, { 22, 39 }, { 22, 40 }, { 23, -33 }, { 23, -32 }, { 23, -31 }, { 23, -30 }, { 23, -29 }, { 23, -25 },
|
||||
{ 23, -24 }, { 23, -23 }, { 23, -22 }, { 23, -19 }, { 23, -18 }, { 23, -9 }, { 23, -8 }, { 23, -7 }, { 23, -6 }, { 23, -5 }, { 23, -4 }, { 23, -1 }, { 23, 0 }, { 23, 1 }, { 23, 2 }, { 23, 3 }, { 23, 4 }, { 23, 7 }, { 23, 8 }, { 23, 9 }, { 23, 10 }, { 23, 11 }, { 23, 12 }, { 23, 21 }, { 23, 22 }, { 23, 25 }, { 23, 26 }, { 23, 27 }, { 23, 28 }, { 23, 32 },
|
||||
{ 23, 33 }, { 23, 34 }, { 23, 35 }, { 23, 36 }, { 24, -33 }, { 24, -32 }, { 24, -31 }, { 24, -30 }, { 24, -25 }, { 24, -24 }, { 24, -23 }, { 24, -22 }, { 24, -19 }, { 24, -18 }, { 24, -17 }, { 24, -9 }, { 24, -8 }, { 24, -7 }, { 24, -6 }, { 24, -5 }, { 24, -4 }, { 24, -1 }, { 24, 0 }, { 24, 1 }, { 24, 2 }, { 24, 3 }, { 24, 4 }, { 24, 7 }, { 24, 8 }, { 24, 9 },
|
||||
{ 24, 10 }, { 24, 11 }, { 24, 12 }, { 24, 20 }, { 24, 21 }, { 24, 22 }, { 24, 25 }, { 24, 26 }, { 24, 27 }, { 24, 28 }, { 24, 33 }, { 24, 34 }, { 24, 35 }, { 24, 36 }, { 25, -39 }, { 25, -38 }, { 25, -37 }, { 25, -36 }, { 25, -24 }, { 25, -23 }, { 25, -22 }, { 25, -19 }, { 25, -18 }, { 25, -17 }, { 25, -16 }, { 25, -6 }, { 25, -5 }, { 25, -4 }, { 25, -1 }, { 25, 0 },
|
||||
{ 25, 1 }, { 25, 2 }, { 25, 3 }, { 25, 4 }, { 25, 7 }, { 25, 8 }, { 25, 9 }, { 25, 19 }, { 25, 20 }, { 25, 21 }, { 25, 22 }, { 25, 25 }, { 25, 26 }, { 25, 27 }, { 25, 39 }, { 25, 40 }, { 25, 41 }, { 25, 42 }, { 26, -39 }, { 26, -38 }, { 26, -37 }, { 26, -36 }, { 26, -23 }, { 26, -22 }, { 26, -19 }, { 26, -18 }, { 26, -17 }, { 26, -16 }, { 26, -15 }, { 26, -5 },
|
||||
{ 26, -4 }, { 26, -1 }, { 26, 0 }, { 26, 1 }, { 26, 2 }, { 26, 3 }, { 26, 4 }, { 26, 7 }, { 26, 8 }, { 26, 18 }, { 26, 19 }, { 26, 20 }, { 26, 21 }, { 26, 22 }, { 26, 25 }, { 26, 26 }, { 26, 39 }, { 26, 40 }, { 26, 41 }, { 26, 42 }, { 27, -38 }, { 27, -37 }, { 27, -36 }, { 27, -29 }, { 27, -28 }, { 27, -27 }, { 27, -26 }, { 27, -16 }, { 27, -15 }, { 27, -14 },
|
||||
{ 27, -9 }, { 27, -8 }, { 27, 11 }, { 27, 12 }, { 27, 17 }, { 27, 18 }, { 27, 19 }, { 27, 29 }, { 27, 30 }, { 27, 31 }, { 27, 32 }, { 27, 39 }, { 27, 40 }, { 27, 41 }, { 28, -37 }, { 28, -36 }, { 28, -30 }, { 28, -29 }, { 28, -28 }, { 28, -27 }, { 28, -26 }, { 28, -15 }, { 28, -14 }, { 28, -10 }, { 28, -9 }, { 28, -8 }, { 28, -7 }, { 28, 10 }, { 28, 11 }, { 28, 12 },
|
||||
{ 28, 13 }, { 28, 17 }, { 28, 18 }, { 28, 29 }, { 28, 30 }, { 28, 31 }, { 28, 32 }, { 28, 33 }, { 28, 39 }, { 28, 40 }, { 29, -33 }, { 29, -32 }, { 29, -31 }, { 29, -30 }, { 29, -29 }, { 29, -28 }, { 29, -27 }, { 29, -26 }, { 29, -21 }, { 29, -20 }, { 29, -19 }, { 29, -18 }, { 29, -11 }, { 29, -10 }, { 29, -9 }, { 29, -8 }, { 29, -7 }, { 29, -6 }, { 29, -1 }, { 29, 0 },
|
||||
{ 29, 1 }, { 29, 2 }, { 29, 3 }, { 29, 4 }, { 29, 9 }, { 29, 10 }, { 29, 11 }, { 29, 12 }, { 29, 13 }, { 29, 14 }, { 29, 21 }, { 29, 22 }, { 29, 23 }, { 29, 24 }, { 29, 29 }, { 29, 30 }, { 29, 31 }, { 29, 32 }, { 29, 33 }, { 29, 34 }, { 29, 35 }, { 29, 36 }, { 30, -33 }, { 30, -32 }, { 30, -31 }, { 30, -30 }, { 30, -29 }, { 30, -28 }, { 30, -27 }, { 30, -26 },
|
||||
{ 30, -22 }, { 30, -21 }, { 30, -20 }, { 30, -19 }, { 30, -18 }, { 30, -11 }, { 30, -10 }, { 30, -9 }, { 30, -8 }, { 30, -7 }, { 30, -6 }, { 30, -5 }, { 30, -1 }, { 30, 0 }, { 30, 1 }, { 30, 2 }, { 30, 3 }, { 30, 4 }, { 30, 8 }, { 30, 9 }, { 30, 10 }, { 30, 11 }, { 30, 12 }, { 30, 13 }, { 30, 14 }, { 30, 21 }, { 30, 22 }, { 30, 23 }, { 30, 24 }, { 30, 25 },
|
||||
{ 30, 29 }, { 30, 30 }, { 30, 31 }, { 30, 32 }, { 30, 33 }, { 30, 34 }, { 30, 35 }, { 30, 36 }, { 31, -32 }, { 31, -31 }, { 31, -30 }, { 31, -29 }, { 31, -28 }, { 31, -27 }, { 31, -23 }, { 31, -22 }, { 31, -21 }, { 31, -15 }, { 31, -14 }, { 31, -6 }, { 31, -5 }, { 31, -4 }, { 31, -1 }, { 31, 0 }, { 31, 3 }, { 31, 4 }, { 31, 7 }, { 31, 8 }, { 31, 9 }, { 31, 17 },
|
||||
{ 31, 18 }, { 31, 24 }, { 31, 25 }, { 31, 26 }, { 31, 30 }, { 31, 31 }, { 31, 32 }, { 31, 33 }, { 31, 34 }, { 31, 35 }, { 32, -31 }, { 32, -30 }, { 32, -29 }, { 32, -28 }, { 32, -23 }, { 32, -22 }, { 32, -16 }, { 32, -15 }, { 32, -14 }, { 32, -5 }, { 32, -4 }, { 32, -1 }, { 32, 0 }, { 32, 3 }, { 32, 4 }, { 32, 7 }, { 32, 8 }, { 32, 17 }, { 32, 18 }, { 32, 19 },
|
||||
{ 32, 25 }, { 32, 26 }, { 32, 31 }, { 32, 32 }, { 32, 33 }, { 32, 34 }, { 33, -30 }, { 33, -29 }, { 33, -28 }, { 33, -23 }, { 33, -22 }, { 33, -17 }, { 33, -16 }, { 33, -15 }, { 33, -11 }, { 33, -10 }, { 33, -9 }, { 33, -8 }, { 33, 11 }, { 33, 12 }, { 33, 13 }, { 33, 14 }, { 33, 18 }, { 33, 19 }, { 33, 20 }, { 33, 25 }, { 33, 26 }, { 33, 31 }, { 33, 32 }, { 33, 33 },
|
||||
{ 34, -29 }, { 34, -28 }, { 34, -23 }, { 34, -22 }, { 34, -17 }, { 34, -16 }, { 34, -12 }, { 34, -11 }, { 34, -10 }, { 34, -9 }, { 34, -8 }, { 34, 11 }, { 34, 12 }, { 34, 13 }, { 34, 14 }, { 34, 15 }, { 34, 19 }, { 34, 20 }, { 34, 25 }, { 34, 26 }, { 34, 31 }, { 34, 32 }, { 35, -17 }, { 35, -16 }, { 35, -13 }, { 35, -12 }, { 35, -11 }, { 35, -10 }, { 35, -9 }, { 35, -3 },
|
||||
{ 35, -2 }, { 35, -1 }, { 35, 0 }, { 35, 3 }, { 35, 4 }, { 35, 5 }, { 35, 6 }, { 35, 12 }, { 35, 13 }, { 35, 14 }, { 35, 15 }, { 35, 16 }, { 35, 19 }, { 35, 20 }, { 36, -17 }, { 36, -16 }, { 36, -13 }, { 36, -12 }, { 36, -11 }, { 36, -10 }, { 36, -4 }, { 36, -3 }, { 36, -2 }, { 36, -1 }, { 36, 0 }, { 36, 3 }, { 36, 4 }, { 36, 5 }, { 36, 6 }, { 36, 7 },
|
||||
{ 36, 13 }, { 36, 14 }, { 36, 15 }, { 36, 16 }, { 36, 19 }, { 36, 20 }, { 37, -27 }, { 37, -26 }, { 37, -25 }, { 37, -24 }, { 37, -21 }, { 37, -20 }, { 37, -13 }, { 37, -12 }, { 37, -5 }, { 37, -4 }, { 37, -3 }, { 37, -2 }, { 37, -1 }, { 37, 0 }, { 37, 1 }, { 37, 2 }, { 37, 3 }, { 37, 4 }, { 37, 5 }, { 37, 6 }, { 37, 7 }, { 37, 8 }, { 37, 15 }, { 37, 16 },
|
||||
{ 37, 23 }, { 37, 24 }, { 37, 27 }, { 37, 28 }, { 37, 29 }, { 37, 30 }, { 38, -27 }, { 38, -26 }, { 38, -25 }, { 38, -24 }, { 38, -21 }, { 38, -20 }, { 38, -19 }, { 38, -13 }, { 38, -12 }, { 38, -5 }, { 38, -4 }, { 38, -3 }, { 38, -2 }, { 38, -1 }, { 38, 0 }, { 38, 1 }, { 38, 2 }, { 38, 3 }, { 38, 4 }, { 38, 5 }, { 38, 6 }, { 38, 7 }, { 38, 8 }, { 38, 15 },
|
||||
{ 38, 16 }, { 38, 22 }, { 38, 23 }, { 38, 24 }, { 38, 27 }, { 38, 28 }, { 38, 29 }, { 38, 30 }, { 39, -26 }, { 39, -25 }, { 39, -24 }, { 39, -20 }, { 39, -19 }, { 39, -18 }, { 39, -13 }, { 39, -12 }, { 39, -11 }, { 39, -10 }, { 39, -5 }, { 39, -4 }, { 39, 7 }, { 39, 8 }, { 39, 13 }, { 39, 14 }, { 39, 15 }, { 39, 16 }, { 39, 21 }, { 39, 22 }, { 39, 23 }, { 39, 27 },
|
||||
{ 39, 28 }, { 39, 29 }, { 40, -25 }, { 40, -24 }, { 40, -19 }, { 40, -18 }, { 40, -13 }, { 40, -12 }, { 40, -11 }, { 40, -10 }, { 40, -5 }, { 40, -4 }, { 40, 7 }, { 40, 8 }, { 40, 13 }, { 40, 14 }, { 40, 15 }, { 40, 16 }, { 40, 21 }, { 40, 22 }, { 40, 27 }, { 40, 28 }, { 41, -19 }, { 41, -18 }, { 41, -1 }, { 41, 0 }, { 41, 1 }, { 41, 2 }, { 41, 3 }, { 41, 4 },
|
||||
{ 41, 21 }, { 41, 22 }, { 42, -19 }, { 42, -18 }, { 42, -17 }, { 42, -1 }, { 42, 0 }, { 42, 1 }, { 42, 2 }, { 42, 3 }, { 42, 4 }, { 42, 20 }, { 42, 21 }, { 42, 22 }, { 43, -18 }, { 43, -17 }, { 43, -16 }, { 43, -15 }, { 43, -14 }, { 43, -13 }, { 43, -12 }, { 43, -9 }, { 43, -8 }, { 43, -1 }, { 43, 0 }, { 43, 1 }, { 43, 2 }, { 43, 3 }, { 43, 4 }, { 43, 11 },
|
||||
{ 43, 12 }, { 43, 15 }, { 43, 16 }, { 43, 17 }, { 43, 18 }, { 43, 19 }, { 43, 20 }, { 43, 21 }, { 44, -17 }, { 44, -16 }, { 44, -15 }, { 44, -14 }, { 44, -13 }, { 44, -12 }, { 44, -9 }, { 44, -8 }, { 44, -7 }, { 44, -2 }, { 44, -1 }, { 44, 0 }, { 44, 1 }, { 44, 2 }, { 44, 3 }, { 44, 4 }, { 44, 5 }, { 44, 10 }, { 44, 11 }, { 44, 12 }, { 44, 15 }, { 44, 16 },
|
||||
{ 44, 17 }, { 44, 18 }, { 44, 19 }, { 44, 20 }, { 45, -8 }, { 45, -7 }, { 45, -6 }, { 45, -5 }, { 45, -4 }, { 45, -3 }, { 45, -2 }, { 45, -1 }, { 45, 4 }, { 45, 5 }, { 45, 6 }, { 45, 7 }, { 45, 8 }, { 45, 9 }, { 45, 10 }, { 45, 11 }, { 46, -7 }, { 46, -6 }, { 46, -5 }, { 46, -4 }, { 46, -3 }, { 46, -2 }, { 46, 5 }, { 46, 6 }, { 46, 7 }, { 46, 8 },
|
||||
{ 46, 9 }, { 46, 10 }, { 47, -4 }, { 47, -3 }, { 47, -2 }, { 47, 1 }, { 47, 2 }, { 47, 5 }, { 47, 6 }, { 47, 7 }, { 48, -3 }, { 48, -2 }, { 48, 1 }, { 48, 2 }, { 48, 5 }, { 48, 6 },
|
||||
},
|
||||
}
|
||||
},
|
||||
resource_tiles = {
|
||||
enabled = false,
|
||||
|
||||
@@ -8,8 +8,8 @@ return {
|
||||
|
||||
unlimited_capacity = false, --- @setting unlimited_capacity When true the vlayer has an unlimited energy capacity, accumulators are not required
|
||||
unlimited_surface_area = false, --- @setting unlimited_surface_area When true the vlayer has an unlimited surface area, landfill is not required
|
||||
modded_auto_downgrade = false, --- @setting modded_auto_downgrade When true modded items will be converted into their base game equivalent, original items can not be recovered
|
||||
power_on_space = false, --- @setting power_on_space When true allow on spaceship
|
||||
modded_auto_downgrade = true, --- @setting modded_auto_downgrade When true modded items will be converted into their base game equivalent, original items can not be recovered
|
||||
power_on_space = true, --- @setting power_on_space When true allow on spaceship
|
||||
power_on_space_research = { --- @setting power_on_space_research the research level needed to use power_on_space
|
||||
name = "research-productivity",
|
||||
level = 10
|
||||
@@ -29,10 +29,10 @@ return {
|
||||
},
|
||||
|
||||
interface_limit = { --- @setting interface_limit Sets the limit for the number of vlayer interfaces that can be created
|
||||
energy = 1, -- >1 allows for disconnected power networks to receive power
|
||||
circuit = 20, -- No caveats
|
||||
storage_input = 20, -- No caveats
|
||||
storage_output = 1, -- >0 allows for item teleportation (allowed_items only)
|
||||
energy = 100, -- >1 allows for disconnected power networks to receive power
|
||||
circuit = 100, -- No caveats
|
||||
storage_input = 100, -- No caveats
|
||||
storage_output = 100, -- >0 allows for item teleportation (allowed_items only)
|
||||
},
|
||||
|
||||
allowed_items = { --- @setting allowed_items List of all items allowed in vlayer storage and their properties
|
||||
@@ -73,22 +73,22 @@ return {
|
||||
required_area = 0,
|
||||
surface_area = 0,
|
||||
fuel_value = 4, -- MJ
|
||||
power = false, -- turn all coal to power to reduce trash
|
||||
power = true, -- turn all coal to power to reduce trash
|
||||
},
|
||||
["solid-fuel"] = {
|
||||
starting_value = 0,
|
||||
required_area = 0,
|
||||
surface_area = 0,
|
||||
fuel_value = 12, -- MJ
|
||||
power = false, -- turn all solid fuel to power to reduce trash
|
||||
power = true, -- turn all solid fuel to power to reduce trash
|
||||
},
|
||||
["rocket-fuel"] = {
|
||||
starting_value = 0,
|
||||
required_area = 0,
|
||||
surface_area = 0,
|
||||
fuel_value = 100, -- MJ
|
||||
power = false, -- turn all rocket fuel to power to reduce trash
|
||||
}
|
||||
power = true, -- turn all rocket fuel to power to reduce trash
|
||||
},
|
||||
},
|
||||
|
||||
modded_items = { --- @setting modded_items List of all modded items allowed in vlayer storage and their base game equivalent
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
[links]
|
||||
discord=https://discord.explosivegaming.nl
|
||||
website=https://www.explosivegaming.nl
|
||||
status=https://status.explosivegaming.nl
|
||||
github=https://github.com/explosivegaming/ExpCluster
|
||||
patreon=https://www.patreon.com/ExpGaming
|
||||
website=https://aperx.org
|
||||
github=https://github.com/PHIDIAS0303/ExpCluster
|
||||
discord=
|
||||
|
||||
[info]
|
||||
players-online=There are __1__ players online
|
||||
total-map-time=This map has been on for __1__
|
||||
discord=Join us on our discord at: https://discord.explosivegaming.nl
|
||||
website=Please visit our website at: https://www.explosivegaming.nl
|
||||
status=Want to check if out servers are down? Visit: https://status.explosivegaming.nl
|
||||
github=Want to help improve our server with some extra features? Help us at: https://github.com/explosivegaming/ExpCluster
|
||||
patreon=Consider supporting our server at: https://www.patreon.com/ExpGaming
|
||||
website=Please visit our website at: https://aperx.org
|
||||
github=Want to help improve our server with some extra features? Help us at: https://github.com/PHIDIAS0303/ExpCluster
|
||||
discord=
|
||||
custom-commands=We use custom commands, such as /tag and /me, use /chelp for more info.
|
||||
read-readme=Make sure you have read the information gui (It can be found through the info mark on the top left)
|
||||
softmod=We run a softmod on our servers. A softmod is a custom scenario that runs on this server, an example is the player list.
|
||||
redmew=We don't talk about redmew here; they beat us to 1000 members ;-;
|
||||
lhd=All trains must be LHD! This is a long standing rule on our servers, please respect this.
|
||||
|
||||
[warnings]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
description-add=Sets / Gets your custom join message.
|
||||
description-remove=Removes you custom join message.
|
||||
arg-message=Your custom join message.
|
||||
greet=[color=0,1,0] Welcome to explosive gaming community server! If you like the server join our discord: __1__ [/color]
|
||||
greet=[color=0,1,0] Welcome to APERX gaming community server! __1__[/color]
|
||||
message-set=Your join message has been updated.
|
||||
message-get=Your join message is: __1__
|
||||
message-cleared=Your join message has been cleared.
|
||||
|
||||
@@ -88,8 +88,8 @@ goto-edit=Edit warp icon
|
||||
[readme]
|
||||
main-tooltip=Infomation
|
||||
welcome-tab=Welcome
|
||||
welcome-tooltip=Welcome to Explosive Gaming
|
||||
welcome-general=Welcome to Explosive Gaming; we host many factorio servers. While you are here, we ask you to follow our rules. You can find these in the tab above. You can also find our custom commands and links to our other servers. This map has been online for __2__.\nPlease note that our servers reset periodically, the next reset is: __1__
|
||||
welcome-tooltip=Welcome to APERX
|
||||
welcome-general=Welcome to APERX; we host many factorio servers. While you are here, we ask you to follow our rules. You can find these in the tab above. You can also find our custom commands and links to our other servers. This map has been online for __2__.\nPlease note that our servers reset periodically, the next reset is: __1__
|
||||
welcome-roles=We run a custom role system to help protect the work of others. As a result you may not be able to use your deconstruction planner yet or drop item on the groud. Roles also give you access to some custom features such as adding tasks to our task list or making new warp points.\nYou have been assigned the roles: __1__
|
||||
welcome-chat=Chatting can be difficult for new players because it’s different than other games! It’s very simple, the button you need to press is the “GRAVE/TILDE” key (which is located under the “ESC key”) - If you would like to change the key, go to your Controls tab in options.\nThe setting you need to change is “Toggle chat (and Lua console)” you currently have it set to "__CONTROL__toggle-console__"
|
||||
rules-tab=Rules
|
||||
@@ -117,22 +117,18 @@ servers-tab=Servers
|
||||
servers-tooltip=Links to our other servers and sites
|
||||
servers-general=This is only one of our servers for factorio, we host many of others as well. Below you can find details about all the servers that we host as well as links to our external services such as discord or github.
|
||||
servers-factorio=Factorio Servers
|
||||
servers-1=S1 Public
|
||||
servers-d1=This is our 48 hour reset server.
|
||||
servers-2=S2 Off
|
||||
servers-d2=This server is closed.
|
||||
servers-3=S3 Weekly
|
||||
servers-d3=This is our weekly reset server.
|
||||
servers-4=S4 Monthly
|
||||
servers-d4=This is our monthly reset server.
|
||||
servers-5=S5 Modded
|
||||
servers-d5=This is our modded server, see discord for details.
|
||||
servers-6=S6 Donator
|
||||
servers-d6=This is our donator only server, online when requested.
|
||||
servers-7=S7 Event
|
||||
servers-d7=This is our event server, we try to run events at least once per week.
|
||||
servers-8=S8 T̷-̶s̶-̴:̷
|
||||
servers-d8=N̵o̴ ̶o̷-̶e̵ ̴k̸n̷-̶w̵s̸ ̴w̷h̷a̶-̶ ̷h̴a̴p̷p̴e̷n̷s̸ ̷o̶n̴ ̷t̶h̴-̶s̶ ̷s̷e̶r̸v̸e̴r̷,̶ ̸i̸t̴ ̷m̶-̸g̴h̶t̷ ̸n̸-̶t̵ ̷e̴v̸e̸n̶t̷ ̵-̷x̴i̵s̶t̸.̸
|
||||
servers-1=S1
|
||||
servers-d1=This server resets regularly.
|
||||
servers-2=S2
|
||||
servers-d2=This server resets regularly.
|
||||
servers-3=S3
|
||||
servers-d3=This server resets regularly.
|
||||
servers-5=S5
|
||||
servers-d5=This server is only for members. Check discord for more details.
|
||||
servers-6=S6
|
||||
servers-d6=This server is only for members. Check discord for more details.
|
||||
servers-8=S8
|
||||
servers-d8=This server is only for event and others. Check discord for more details.
|
||||
servers-connect-Offline=Server is currently offline
|
||||
servers-connect-Current=This is your current server
|
||||
servers-connect-Version=Server is on a different version: __1__
|
||||
@@ -145,9 +141,8 @@ backers-tab=Backers
|
||||
backers-tooltip=People who have helped make our server
|
||||
backers-general=We would like to thank all our staff and backers who have helped our community grow. Our staff have helped to keep our servers safe from trolls and a fun place to play. Our backers have helped us to cover our running costs and provide a great community for us all to enjoy together.
|
||||
backers-management=Administrators
|
||||
backers-board=Board Members and Senior Backers
|
||||
backers-staff=Staff Members
|
||||
backers-backers=Sponsors and Supporters
|
||||
backers-backers=Board Members, Supporters, and Partners
|
||||
backers-active=Active Players
|
||||
data-tab=Data
|
||||
data-tooltip=All of your stored player data
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
[links]
|
||||
discord=https://discord.explosivegaming.nl
|
||||
website=https://www.explosivegaming.nl
|
||||
status=https://status.explosivegaming.nl
|
||||
github=https://github.com/explosivegaming/ExpCluster
|
||||
patreon=https://www.patreon.com/ExpGaming
|
||||
website=https://aperx.org
|
||||
github=https://github.com/PHIDIAS0303/ExpCluster
|
||||
discord=
|
||||
|
||||
[info]
|
||||
players-online=現在有 __1__ 人在線
|
||||
total-map-time=地圖時間為 __1__
|
||||
discord=加入社群: https://discord.explosivegaming.nl
|
||||
website=訪問網站: https://www.explosivegaming.nl
|
||||
status=伺服器狀態: https://status.explosivegaming.nl
|
||||
github=增加功能或回報錯誤: https://github.com/explosivegaming/ExpCluster
|
||||
patreon=支持我們: https://www.patreon.com/ExpGaming
|
||||
website=訪問網站: https://aperx.org
|
||||
github=增加功能或回報錯誤: https://github.com/PHIDIAS0303/ExpCluster
|
||||
discord=
|
||||
custom-commands=這裹使用了自制指令,如 /tag 和 /me。可使用 /chelp 查看更多。
|
||||
read-readme=確保你已閱讀相關資訊。按左上 i 圖標可再次查看。
|
||||
softmod=這裹用了自設情境,是一種軟裝模組。
|
||||
redmew=
|
||||
lhd=列車必須是左則通行。這是本服務器長久以來的規則。
|
||||
|
||||
[warnings]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
description-add=設定 / 取得你的加入信息。
|
||||
description-remove=移除你的加入信息。
|
||||
arg-message=你的加入信息。
|
||||
greet=[color=0,1,0] 歡迎來到 EXP 的服務器! 若果你喜歡本服務器可加入 DISCORD: __1__ [/color]
|
||||
greet=[color=0,1,0] 歡迎來到 APERX 的服務器! __1__[/color]
|
||||
message-set=你的加入信息已更新。
|
||||
message-get=你的加入信息為: __1__
|
||||
message-cleared=你的加入信息已清除。
|
||||
|
||||
@@ -88,8 +88,8 @@ goto-edit=修改傳送陣圖案
|
||||
[readme]
|
||||
main-tooltip=資訊
|
||||
welcome-tab=歡迎
|
||||
welcome-tooltip=歡迎來到 Explosive Gaming
|
||||
welcome-general=歡迎來到 Explosive Gaming; 你在這裏的時候要遵守規則。 你可以在左上方的介面找到更多資訊。 地圖時間 __2__。\n下次地圖重設: __1__
|
||||
welcome-tooltip=歡迎來到 APERX
|
||||
welcome-general=歡迎來到 APERX; 你在這裏的時候要遵守規則。 你可以在左上方的介面找到更多資訊。 地圖時間 __2__。\n下次地圖重設: __1__
|
||||
welcome-roles=我們有自訂的身份組來保護其他用戶。 所以你有機會不能使用拆除規劃器或掉東西。 身份組給予你各種權限\n你有以下身份組: __1__
|
||||
welcome-chat=你可以使用 「重音符/抑音符」 鍵 (ESC 鍵 下方) - 你也可以在選項中修改按鍵。\n你目前設定為 「__CONTROL__toggle-console__」
|
||||
rules-tab=規則
|
||||
@@ -117,22 +117,18 @@ servers-tab=伺服器
|
||||
servers-tooltip=到其他伺服器及網站的連結
|
||||
servers-general=這是其中一個伺服器。你可以在下方找到其他同樣是由我們運行的伺服器資料。
|
||||
servers-factorio=異星工廠伺服器
|
||||
servers-1=S1 公共
|
||||
servers-d1=這個服務器每兩日重設。
|
||||
servers-2=S2 -
|
||||
servers-d2=這個服務器沒在營運。
|
||||
servers-3=S3 周
|
||||
servers-d3=這個服務器每週重設。
|
||||
servers-4=S4 月
|
||||
servers-d4=這個服務器每月重設。
|
||||
servers-5=S5 模組
|
||||
servers-d5=這個服務器運行模組,可在 Discord 中得到更多資訊。
|
||||
servers-6=S6 Donator
|
||||
servers-d6=這個服務器為支持者運行,可在 Discord 中得到更多資訊。
|
||||
servers-7=S7 項目
|
||||
servers-d7=這個服務器只在有項目期間運行。
|
||||
servers-8=S8 T̷-̶s̶-̴:̷
|
||||
servers-d8=N̵o̴ ̶o̷-̶e̵ ̴k̸n̷-̶w̵s̸ ̴w̷h̷a̶-̶ ̷h̴a̴p̷p̴e̷n̷s̸ ̷o̶n̴ ̷t̶h̴-̶s̶ ̷s̷e̶r̸v̸e̴r̷,̶ ̸i̸t̴ ̷m̶-̸g̴h̶t̷ ̸n̸-̶t̵ ̷e̴v̸e̸n̶t̷ ̵-̷x̴i̵s̶t̸。̸
|
||||
servers-1=S1
|
||||
servers-d1=這個服務器定期重設。
|
||||
servers-2=S2
|
||||
servers-d2=這個服務器定期重設。
|
||||
servers-3=S3
|
||||
servers-d3=這個服務器定期重設。
|
||||
servers-5=S5
|
||||
servers-d5=這個服務器只為會員運行,可在 Discord 中得到更多資訊。
|
||||
servers-6=S6
|
||||
servers-d6=這個服務器只為會員運行,可在 Discord 中得到更多資訊。
|
||||
servers-8=S8
|
||||
servers-d8=這個服務器只在活動和其他時運行,可在 Discord 中得到更多資訊。
|
||||
servers-connect-Offline=該服務器目前沒有在運行
|
||||
servers-connect-Current=你目前所在的伺服器
|
||||
servers-connect-Version=該服務器運行不同的遊戲版本: __1__
|
||||
@@ -144,10 +140,9 @@ servers-open-in-browser=可在你的瀏覽器中打開
|
||||
backers-tab=支持者
|
||||
backers-tooltip=支持者
|
||||
backers-general=他們為服務器運行提供了不少幫助。
|
||||
backers-management=系統管理員
|
||||
backers-board=議員
|
||||
backers-management=管理員
|
||||
backers-staff=職員
|
||||
backers-backers=支持者
|
||||
backers-backers=議員,支持者,和夥伴
|
||||
backers-active=活躍玩家
|
||||
data-tab=資料
|
||||
data-tooltip=所有已存資料
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
[links]
|
||||
discord=https://discord.explosivegaming.nl
|
||||
website=https://www.explosivegaming.nl
|
||||
status=https://status.explosivegaming.nl
|
||||
github=https://github.com/explosivegaming/ExpCluster
|
||||
patreon=https://www.patreon.com/ExpGaming
|
||||
website=https://aperx.org
|
||||
github=https://github.com/PHIDIAS0303/ExpCluster
|
||||
discord=
|
||||
|
||||
[info]
|
||||
players-online=現在有 __1__ 人在線
|
||||
total-map-time=地圖時間為 __1__
|
||||
discord=加入社群: https://discord.explosivegaming.nl
|
||||
website=訪問網站: https://www.explosivegaming.nl
|
||||
status=伺服器狀態: https://status.explosivegaming.nl
|
||||
github=增加功能或回報錯誤: https://github.com/explosivegaming/ExpCluster
|
||||
patreon=支持我們: https://www.patreon.com/ExpGaming
|
||||
website=訪問網站: https://aperx.org
|
||||
github=增加功能或回報錯誤: https://github.com/PHIDIAS0303/ExpCluster
|
||||
discord=
|
||||
custom-commands=這裹使用了自制指令,如 /tag 和 /me。可使用 /chelp 查看更多。
|
||||
read-readme=確保你已閱讀相關資訊。按左上 i 圖標可再次查看。
|
||||
softmod=這裹用了自設情境,是一種軟裝模組。
|
||||
redmew=
|
||||
lhd=列車必須是左則通行。這是本服務器長久以來的規則。
|
||||
|
||||
[warnings]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
description-add=設定 / 取得你的加入信息。
|
||||
description-remove=移除你的加入信息。
|
||||
arg-message=你的加入信息。
|
||||
greet=[color=0,1,0] 歡迎來到 EXP 的服務器! 若果你喜歡本服務器可加入 DISCORD: __1__ [/color]
|
||||
greet=[color=0,1,0] 歡迎來到 APERX 的服務器! __1__[/color]
|
||||
message-set=你的加入信息已更新。
|
||||
message-get=你的加入信息為: __1__
|
||||
message-cleared=你的加入信息已清除。
|
||||
|
||||
@@ -88,8 +88,8 @@ goto-edit=修改傳送陣圖案
|
||||
[readme]
|
||||
main-tooltip=資訊
|
||||
welcome-tab=歡迎
|
||||
welcome-tooltip=歡迎來到 Explosive Gaming
|
||||
welcome-general=歡迎來到 Explosive Gaming; 你在這裏的時候要遵守規則。 你可以在左上方的介面找到更多資訊。 地圖時間 __2__。\n下次地圖重設: __1__
|
||||
welcome-tooltip=歡迎來到 APERX
|
||||
welcome-general=歡迎來到 APERX; 你在這裏的時候要遵守規則。 你可以在左上方的介面找到更多資訊。 地圖時間 __2__。\n下次地圖重設: __1__
|
||||
welcome-roles=我們有自訂的身份組來保護其他用戶。 所以你有機會不能使用拆除規劃器或掉東西。 身份組給予你各種權限\n你有以下身份組: __1__
|
||||
welcome-chat=你可以使用 「重音符/抑音符」 鍵 (ESC 鍵 下方) - 你也可以在選項中修改按鍵。\n你目前設定為 「__CONTROL__toggle-console__」
|
||||
rules-tab=規則
|
||||
@@ -117,22 +117,18 @@ servers-tab=伺服器
|
||||
servers-tooltip=到其他伺服器及網站的連結
|
||||
servers-general=這是其中一個伺服器。你可以在下方找到其他同樣是由我們運行的伺服器資料。
|
||||
servers-factorio=異星工廠伺服器
|
||||
servers-1=S1 公共
|
||||
servers-d1=這個服務器每兩日重設。
|
||||
servers-2=S2 -
|
||||
servers-d2=這個服務器沒在營運。
|
||||
servers-3=S3 周
|
||||
servers-d3=這個服務器每週重設。
|
||||
servers-4=S4 月
|
||||
servers-d4=這個服務器每月重設。
|
||||
servers-5=S5 模組
|
||||
servers-d5=這個服務器運行模組,可在 Discord 中得到更多資訊。
|
||||
servers-6=S6 Donator
|
||||
servers-d6=這個服務器為支持者運行,可在 Discord 中得到更多資訊。
|
||||
servers-7=S7 項目
|
||||
servers-d7=這個服務器只在有項目期間運行。
|
||||
servers-8=S8 T̷-̶s̶-̴:̷
|
||||
servers-d8=N̵o̴ ̶o̷-̶e̵ ̴k̸n̷-̶w̵s̸ ̴w̷h̷a̶-̶ ̷h̴a̴p̷p̴e̷n̷s̸ ̷o̶n̴ ̷t̶h̴-̶s̶ ̷s̷e̶r̸v̸e̴r̷,̶ ̸i̸t̴ ̷m̶-̸g̴h̶t̷ ̸n̸-̶t̵ ̷e̴v̸e̸n̶t̷ ̵-̷x̴i̵s̶t̸。̸
|
||||
servers-1=S1
|
||||
servers-d1=這個服務器定期重設。
|
||||
servers-2=S2
|
||||
servers-d2=這個服務器定期重設。
|
||||
servers-3=S3
|
||||
servers-d3=這個服務器定期重設。
|
||||
servers-5=S5
|
||||
servers-d5=這個服務器只為會員運行,可在 Discord 中得到更多資訊。
|
||||
servers-6=S6
|
||||
servers-d6=這個服務器只為會員運行,可在 Discord 中得到更多資訊。
|
||||
servers-8=S8
|
||||
servers-d8=這個服務器只在活動和其他時運行,可在 Discord 中得到更多資訊。
|
||||
servers-connect-Offline=該服務器目前沒有在運行
|
||||
servers-connect-Current=你目前所在的伺服器
|
||||
servers-connect-Version=該服務器運行不同的遊戲版本: __1__
|
||||
@@ -144,10 +140,9 @@ servers-open-in-browser=可在你的瀏覽器中打開
|
||||
backers-tab=支持者
|
||||
backers-tooltip=支持者
|
||||
backers-general=他們為服務器運行提供了不少幫助。
|
||||
backers-management=系統管理員
|
||||
backers-board=議員
|
||||
backers-management=管理員
|
||||
backers-staff=職員
|
||||
backers-backers=支持者
|
||||
backers-backers=議員,支持者,和夥伴
|
||||
backers-active=活躍玩家
|
||||
data-tab=資料
|
||||
data-tooltip=所有已存資料
|
||||
|
||||
@@ -341,9 +341,9 @@ function vlayer.create_input_interface(surface, position, circuit, last_user)
|
||||
end
|
||||
|
||||
if circuit then
|
||||
for k, _ in pairs(circuit) do
|
||||
for _, v in pairs(circuit[k]) do
|
||||
interface.connect_neighbour{ wire = defines.wire_type[k], target_entity = v }
|
||||
for k, _ in pairs({ defines.wire_connector_id.circuit_red, defines.wire_connector_id.circuit_green }) do
|
||||
for _, v in pairs(circuit.get_wire_connector{ wire_connector_id = k, or_create = false }.real_connections) do
|
||||
interface.connect_to{ target = v.target }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -419,9 +419,9 @@ function vlayer.create_output_interface(surface, position, circuit, last_user)
|
||||
end
|
||||
|
||||
if circuit then
|
||||
for k, _ in pairs(circuit) do
|
||||
for _, v in pairs(circuit[k]) do
|
||||
interface.connect_neighbour{ wire = defines.wire_type[k], target_entity = v }
|
||||
for k, _ in pairs({ defines.wire_connector_id.circuit_red, defines.wire_connector_id.circuit_green }) do
|
||||
for _, v in pairs(circuit.get_wire_connector{ wire_connector_id = k, or_create = false }.real_connections) do
|
||||
interface.connect_to{ target = v.target }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -566,9 +566,9 @@ function vlayer.create_circuit_interface(surface, position, circuit, last_user)
|
||||
end
|
||||
|
||||
if circuit then
|
||||
for k, _ in pairs(circuit) do
|
||||
for _, v in pairs(circuit[k]) do
|
||||
interface.connect_neighbour{ wire = defines.wire_type[k], target_entity = v }
|
||||
for k, _ in pairs({ defines.wire_connector_id.circuit_red, defines.wire_connector_id.circuit_green }) do
|
||||
for _, v in pairs(circuit.get_wire_connector{ wire_connector_id = k, or_create = false }.real_connections) do
|
||||
interface.connect_to{ target = v.target }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -189,6 +189,10 @@ function Warps.make_warp_area(warp_id)
|
||||
if entity.type == "electric-pole" then
|
||||
warp.electric_pole = entity
|
||||
end
|
||||
|
||||
if entity.name == "small-lamp" then
|
||||
entity.always_on = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ local welcome_time_format = ExpUtil.format_time_factory_locale{ format = "long",
|
||||
--- Content area for the welcome tab
|
||||
define_tab({ "readme.welcome-tab" }, { "readme.welcome-tooltip" }, Gui.define("readme_welcome")
|
||||
:draw(function(_, parent)
|
||||
local server_details = { name = "ExpGaming S0 - Local", welcome = "Failed to load description: disconnected from external api.", reset_time = "Non Set", branch = "Unknown" }
|
||||
local server_details = { name = "APERX S0 - Local", welcome = "Failed to load description: disconnected from external api.", reset_time = "Non Set", branch = "Unknown" }
|
||||
if External.valid() then server_details = External.get_current_server() end
|
||||
local container = parent.add{ type = "flow", direction = "vertical" }
|
||||
local player = Gui.get_player(parent)
|
||||
@@ -223,7 +223,7 @@ define_tab({ "readme.servers-tab" }, { "readme.servers-tooltip" }, Gui.define("r
|
||||
end
|
||||
else
|
||||
local factorio_servers = title_table(scroll_pane, 225, { "readme.servers-factorio" }, 2)
|
||||
for i = 1, 8 do
|
||||
for _, i in pairs{ 1, 2, 3, 5, 6, 8 } do
|
||||
Gui.elements.centered_label(factorio_servers, 110, { "readme.servers-" .. i })
|
||||
Gui.elements.centered_label(factorio_servers, 460, { "readme.servers-d" .. i })
|
||||
end
|
||||
@@ -231,7 +231,7 @@ define_tab({ "readme.servers-tab" }, { "readme.servers-tooltip" }, Gui.define("r
|
||||
|
||||
-- Add the external links
|
||||
local external_links = title_table(scroll_pane, 235, { "readme.servers-external" }, 2)
|
||||
for _, key in ipairs{ "discord", "website", "patreon", "status", "github" } do
|
||||
for _, key in ipairs{ "website", "github" } do
|
||||
local upper_key = key:gsub("^%l", string.upper)
|
||||
Gui.elements.centered_label(external_links, 110, upper_key)
|
||||
Gui.elements.centered_label(external_links, 460, { "links." .. key }, { "readme.servers-open-in-browser" })
|
||||
@@ -255,10 +255,10 @@ define_tab({ "readme.backers-tab" }, { "readme.backers-tooltip" }, Gui.define("r
|
||||
local done = {}
|
||||
local groups = {
|
||||
{ _roles = { "Senior Administrator", "Administrator" }, _title = { "readme.backers-management" }, _width = 230 },
|
||||
{ _roles = { "Board Member", "Senior Backer" }, _title = { "readme.backers-board" }, _width = 145 }, -- change role to board
|
||||
{ _roles = { "Sponsor", "Supporter" }, _title = { "readme.backers-backers" }, _width = 196 }, -- change to backer
|
||||
{ _roles = { "Moderator", "Trainee" }, _title = { "readme.backers-staff" }, _width = 235 },
|
||||
{ _roles = {}, _time = 3 * 3600 * 60, _title = { "readme.backers-active" }, _width = 235 },
|
||||
{ _roles = { "Senior Moderator", "Moderator", "Trainee Moderator" }, _title = { "readme.backers-staff" }, _width = 230 },
|
||||
{ _roles = { "Board Member", "Supporter", "Partner" }, _title = { "readme.backers-backers" }, _width = 230 }, -- change role to board
|
||||
{ _roles = { "Veteran" }, _title = { "readme.backers-active" }, _width = 230 },
|
||||
-- _time = 3 * 3600 * 60
|
||||
}
|
||||
|
||||
-- Fill by player roles
|
||||
|
||||
@@ -19,11 +19,24 @@ Storage.register(research, function(tbl)
|
||||
research = tbl
|
||||
end)
|
||||
|
||||
local mod_set = "base"
|
||||
|
||||
for _, mod_name in ipairs(config.mod_set_lookup) do
|
||||
if script.active_mods[mod_name] then
|
||||
mod_set = mod_name
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if script.active_mods["space-age"] and script.active_mods["PHI-CL"] and settings.startup["PHI-VP"] and settings.startup["PHI-VP-MAIN"] then
|
||||
mod_set = "space-age"
|
||||
end
|
||||
|
||||
--- @param force LuaForce
|
||||
--- @param silent boolean True when no message should be printed
|
||||
local function queue_research(force, silent)
|
||||
local res_q = force.research_queue
|
||||
local res = force.technologies[config.bonus_inventory.log[config.mod_set].name]
|
||||
local res = force.technologies[config.bonus_inventory.log[mod_set].name]
|
||||
|
||||
if #res_q < config.queue_amount then
|
||||
for i = #res_q, config.queue_amount - 1 do
|
||||
|
||||
@@ -77,6 +77,6 @@ add(require("modules/exp_scenario/gui/player_stats"))
|
||||
add(require("modules/exp_scenario/gui/production_stats"))
|
||||
add(require("modules/exp_scenario/gui/quick_actions"))
|
||||
add(require("modules/exp_scenario/gui/research_milestones"))
|
||||
add(require("modules/exp_scenario/gui/science_production"))
|
||||
-- add(require("modules/exp_scenario/gui/science_production"))
|
||||
add(require("modules/exp_scenario/gui/surveillance"))
|
||||
add(require("modules/exp_scenario/gui/task_list"))
|
||||
|
||||
Reference in New Issue
Block a user