Compare commits
11 Commits
c996d4edff
...
01e1e4a502
| Author | SHA1 | Date | |
|---|---|---|---|
| 01e1e4a502 | |||
| e53b4cc868 | |||
| 2ac4b2f2cd | |||
| d60c0176dd | |||
| b064a9f515 | |||
| c29dd2d690 | |||
| 0bdc48c86f | |||
| 02e50f2fe5 | |||
| 50007e1109 | |||
| d4dfcb1e11 | |||
| 3dc0767a24 |
+2
-1
@@ -55,8 +55,9 @@ CLAUDE.md
|
|||||||
|
|
||||||
# ─── Build artifacts that get regenerated ─────────────────────────────────
|
# ─── Build artifacts that get regenerated ─────────────────────────────────
|
||||||
# Tweak jars rebuilt by scripts/Build-Tweaks.ps1
|
# Tweak jars rebuilt by scripts/Build-Tweaks.ps1
|
||||||
pack/overrides/
|
pack/overrides/mods/
|
||||||
# manifest.json regenerated by scripts/Build-Pack.ps1 -- produced at scripts/
|
# manifest.json regenerated by scripts/Build-Pack.ps1 -- produced at scripts/
|
||||||
# (default OutputPath) and copied to the deploy share by Deploy-Brass.ps1
|
# (default OutputPath) and copied to the deploy share by Deploy-Brass.ps1
|
||||||
scripts/manifest.json
|
scripts/manifest.json
|
||||||
pack/manifest.json
|
pack/manifest.json
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
[general]
|
||||||
|
#List of waystone origins that should prevent others from editing. PLAYER is special in that it allows only edits by the owner of the waystone.
|
||||||
|
restrictedWaystones = ["PLAYER"]
|
||||||
|
#Set to "GLOBAL" to have newly placed or found waystones be global by default.
|
||||||
|
#Allowed Values: ACTIVATION, GLOBAL, SHARD_ONLY, ORANGE_SHARESTONE, MAGENTA_SHARESTONE, LIGHT_BLUE_SHARESTONE, YELLOW_SHARESTONE, LIME_SHARESTONE, PINK_SHARESTONE, GRAY_SHARESTONE, LIGHT_GRAY_SHARESTONE, CYAN_SHARESTONE, PURPLE_SHARESTONE, BLUE_SHARESTONE, BROWN_SHARESTONE, GREEN_SHARESTONE, RED_SHARESTONE, BLACK_SHARESTONE
|
||||||
|
defaultVisibility = "ACTIVATION"
|
||||||
|
#Add "GLOBAL" to allow every player to create global waystones.
|
||||||
|
allowedVisibilities = []
|
||||||
|
#The time in ticks that it takes to use a warp stone. This is the charge-up time when holding right-click.
|
||||||
|
warpStoneUseTime = 32
|
||||||
|
#The time in ticks that it takes to use a warp plate. This is the time the player has to stand on top for.
|
||||||
|
warpPlateUseTime = 15
|
||||||
|
#The time in ticks it takes to use a scroll. This is the charge-up time when holding right-click.
|
||||||
|
scrollUseTime = 32
|
||||||
|
|
||||||
|
[inventoryButton]
|
||||||
|
#Set to 'NONE' for no inventory button. Set to 'NEAREST' for an inventory button that teleports to the nearest waystone. Set to 'ANY' for an inventory button that opens the waystone selection menu. Set to a waystone name for an inventory button that teleports to a specifically named waystone.
|
||||||
|
inventoryButton = ""
|
||||||
|
#The x position of the inventory button in the inventory.
|
||||||
|
inventoryButtonX = 58
|
||||||
|
#The y position of the inventory button in the inventory.
|
||||||
|
inventoryButtonY = 60
|
||||||
|
#The y position of the inventory button in the creative menu.
|
||||||
|
creativeInventoryButtonX = 88
|
||||||
|
#The y position of the inventory button in the creative menu.
|
||||||
|
creativeInventoryButtonY = 33
|
||||||
|
|
||||||
|
[worldGen]
|
||||||
|
#Set to 'DEFAULT' to only generate the normally textured waystones. Set to 'MOSSY' or 'SANDY' to generate all as that variant. Set to 'BIOME' to make the style depend on the biome it is generated in.
|
||||||
|
#Allowed Values: DEFAULT, MOSSY, SANDY, BLACKSTONE, DEEPSLATE, END_STONE, BIOME
|
||||||
|
wildWaystoneStyle = "BIOME"
|
||||||
|
#Approximate chunk distance between wild waystones being generated. Set to 0 to disable generation.
|
||||||
|
chunksBetweenWildWaystones = 25
|
||||||
|
#List of dimensions that wild waystones are allowed to spawn in. If left empty, all dimensions except those in wildWaystonesDimensionDenyList will be able to spawn waystones, provided the biomes are in the `has_structure/waystone` tag.
|
||||||
|
wildWaystonesDimensionAllowList = ["minecraft:the_nether", "minecraft:overworld", "minecraft:the_end"]
|
||||||
|
#List of dimensions that wild waystones are not allowed to spawn in, even if the biome is in the `has_structure/waystone` tag. Only used if wildWaystonesDimensionAllowList is empty.
|
||||||
|
wildWaystonesDimensionDenyList = []
|
||||||
|
#Set to 'PRESET_FIRST' to first use names from the nameGenerationPresets. Set to 'PRESET_ONLY' to use only those custom names. Set to 'MIXED' to have some waystones use custom names, and others random names.
|
||||||
|
#Allowed Values: PRESET_FIRST, RANDOM_ONLY, PRESET_ONLY, MIXED
|
||||||
|
nameGenerationMode = "PRESET_FIRST"
|
||||||
|
#The template to use when generating new names. Supported placeholders are {Biome} (english biome name) and {MrPork} (the default name generator).
|
||||||
|
nameGenerationTemplate = "{MrPork}"
|
||||||
|
#These names will be used for the PRESET name generation mode. See the nameGenerationMode option for more info.
|
||||||
|
nameGenerationPresets = []
|
||||||
|
#Set to REGULAR to have waystones spawn in some villages. Set to FREQUENT to have waystones spawn in most villages. Set to DISABLED to disable waystone generation in villages. Waystones will only spawn in vanilla or supported villages.
|
||||||
|
#Allowed Values: DISABLED, REGULAR, FREQUENT
|
||||||
|
spawnInVillages = "DISABLED"
|
||||||
|
|
||||||
|
[teleports]
|
||||||
|
#Set to false to simply disable all xp costs. See warpRequirements for more fine-grained control.
|
||||||
|
enableCosts = true
|
||||||
|
#Set to false to simply disable all cooldowns. See warpRequirements for more fine-grained control.
|
||||||
|
enableCooldowns = true
|
||||||
|
#List of warp requirements with comma-separated parameters in parentheses. Conditions can be defined as comma-separated list in square brackets. Will be applied in order.
|
||||||
|
warpRequirements = ["[is_not_interdimensional] scaled_add_xp_cost(distance, 0.01)", "[is_interdimensional] add_xp_cost(27)", "[source_is_warp_plate] multiply_xp_cost(0)", "[target_is_global] multiply_xp_cost(0)", "min_xp_cost(0)", "max_xp_cost(27)", "[source_is_inventory_button] add_cooldown(inventory_button, 300)"]
|
||||||
|
#Set to ENABLED to have nearby pets teleport with you. Set to SAME_DIMENSION to have nearby pets teleport with you only if you're not changing dimensions. Set to DISABLED to disable.
|
||||||
|
#Allowed Values: ENABLED, SAME_DIMENSION, DISABLED
|
||||||
|
transportPets = "DISABLED"
|
||||||
|
#Set to ENABLED to have leashed mobs teleport with you. Set to SAME_DIMENSION to have leashed mobs teleport with you only if you're not changing dimensions. Set to DISABLED to disable.
|
||||||
|
#Allowed Values: ENABLED, SAME_DIMENSION, DISABLED
|
||||||
|
transportLeashed = "ENABLED"
|
||||||
|
#List of entities that cannot be teleported, either as pet, leashed, or on warp plates.
|
||||||
|
entityDenyList = ["minecraft:wither"]
|
||||||
|
#Set to true to enable warp modifier items for applying status effects on teleports.
|
||||||
|
enableModifiers = true
|
||||||
|
|
||||||
|
[client]
|
||||||
|
#If enabled, the text overlay on waystones will no longer always render at full brightness.
|
||||||
|
disableTextGlow = false
|
||||||
|
|
||||||
|
[compatibility]
|
||||||
|
#If enabled, JourneyMap waypoints will be created for each activated waystone.
|
||||||
|
journeyMap = true
|
||||||
|
#If enabled, JourneyMap waypoints will only be created if the mod 'JourneyMap Integration' is not installed
|
||||||
|
preferJourneyMapIntegrationMod = true
|
||||||
|
#If enabled, Waystones will add markers for waystones and sharestones to Dynmap.
|
||||||
|
dynmap = true
|
||||||
|
|
||||||
|
[blueMap]
|
||||||
|
#Controls whether Waystones' BlueMap integration should be loaded
|
||||||
|
enabled = true
|
||||||
|
#If enabled, waystones will be tracked as markers on BlueMap
|
||||||
|
includeWaystones = true
|
||||||
|
#If enabled, sharestones will be tracked as markers on BlueMap.
|
||||||
|
includeSharestones = true
|
||||||
|
#If enabled, undiscovered waystones will be tracked as markers on BlueMap.
|
||||||
|
includeUndiscoveredWaystones = false
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// Brass & Sigil — JEI hides
|
||||||
|
//
|
||||||
|
// Hides all Waystones items + all Numismatics coin items from the JEI
|
||||||
|
// item list. Combined with the server-side recipe removal in
|
||||||
|
// economy_policy.js, players don't see crafting recipes OR the item
|
||||||
|
// icons in the JEI ingredient list -- they only ever encounter these
|
||||||
|
// items through the welcome grant or the bank exchange.
|
||||||
|
|
||||||
|
const COLORS = [
|
||||||
|
'white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime',
|
||||||
|
'pink', 'gray', 'light_gray', 'cyan', 'purple', 'blue',
|
||||||
|
'brown', 'green', 'red', 'black',
|
||||||
|
];
|
||||||
|
|
||||||
|
const WAYSTONE_ITEMS = [
|
||||||
|
// regular waystone variants
|
||||||
|
'waystones:waystone',
|
||||||
|
'waystones:mossy_waystone',
|
||||||
|
'waystones:sandy_waystone',
|
||||||
|
'waystones:blackstone_waystone',
|
||||||
|
'waystones:deepslate_waystone',
|
||||||
|
'waystones:end_stone_waystone',
|
||||||
|
// handheld + plate
|
||||||
|
'waystones:warp_stone',
|
||||||
|
'waystones:warp_scroll',
|
||||||
|
'waystones:bound_scroll',
|
||||||
|
'waystones:return_scroll',
|
||||||
|
'waystones:warp_plate',
|
||||||
|
// sharestones (16 colors) + shards
|
||||||
|
'waystones:sharestone', // base id if registered
|
||||||
|
];
|
||||||
|
COLORS.forEach(c => {
|
||||||
|
WAYSTONE_ITEMS.push(`waystones:${c}_sharestone`);
|
||||||
|
WAYSTONE_ITEMS.push(`waystones:${c}_portstone`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const COIN_ITEMS = [
|
||||||
|
'numismatics:spur',
|
||||||
|
'numismatics:bevel',
|
||||||
|
'numismatics:cog',
|
||||||
|
'numismatics:crown',
|
||||||
|
'numismatics:sun',
|
||||||
|
];
|
||||||
|
|
||||||
|
JEIEvents.hideItems(event => {
|
||||||
|
[...WAYSTONE_ITEMS, ...COIN_ITEMS].forEach(id => {
|
||||||
|
try { event.hide(id); } catch (e) {
|
||||||
|
// Some IDs may not exist (e.g. base 'waystones:sharestone' isn't
|
||||||
|
// registered if only colored variants are). Swallow per-item
|
||||||
|
// failures so one bad id doesn't break the whole pass.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// Brass & Sigil — economy policy (recipe removal)
|
||||||
|
//
|
||||||
|
// Players can't craft Waystones items (they're distributed by the welcome
|
||||||
|
// grant -- see welcome.js -- and any replacements come from the bank
|
||||||
|
// vendor in the future). Players also can't manufacture currency: coins
|
||||||
|
// only enter circulation through the bank exchange (item-in / coin-out).
|
||||||
|
//
|
||||||
|
// Other Numismatics blocks (piggy banks, bank tellers, vendor blocks) stay
|
||||||
|
// craftable -- those are infrastructure, not currency.
|
||||||
|
|
||||||
|
ServerEvents.recipes(event => {
|
||||||
|
// Block ALL crafting of Waystones items. The welcome-grant script
|
||||||
|
// gives each new player exactly one regular waystone; any further
|
||||||
|
// recovery happens via OP /give or future bank vendor.
|
||||||
|
event.remove({ mod: 'waystones' });
|
||||||
|
|
||||||
|
// Block coin manufacturing only -- 5 denominations.
|
||||||
|
// Real registry IDs: spur, bevel, cog, crown, sun.
|
||||||
|
[
|
||||||
|
'numismatics:spur',
|
||||||
|
'numismatics:bevel',
|
||||||
|
'numismatics:cog',
|
||||||
|
'numismatics:crown',
|
||||||
|
'numismatics:sun',
|
||||||
|
].forEach(coin => event.remove({ output: coin }));
|
||||||
|
});
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
// Brass & Sigil — Waystones placement policy
|
||||||
|
//
|
||||||
|
// Rules:
|
||||||
|
// - Regular waystones (6 stone variants): 1 per player. Forces players to
|
||||||
|
// build actual transport infrastructure (trains/roads/canals) for
|
||||||
|
// long-distance routes instead of waystone-spamming.
|
||||||
|
// - Sharestones (16 colors): banned. Pair-teleport between solo-placed
|
||||||
|
// sharestones defeats the "build transport" intent, and a sharestone
|
||||||
|
// placed just outside someone's claim gives an unrestricted teleport-
|
||||||
|
// adjacent vector.
|
||||||
|
// - Portstones (16 colors): banned pending separate design discussion.
|
||||||
|
// - Warp plates: not restricted (single-block teleport pad; revisit if
|
||||||
|
// it becomes a workaround).
|
||||||
|
// - Warp scrolls / warp stones: untouched (consumable / cooldown-bound).
|
||||||
|
//
|
||||||
|
// Per-player count lives in player.persistentData.bnsWaystoneCount.
|
||||||
|
// Decrement on break works because waystones-common.toml has
|
||||||
|
// restrictedWaystones = ["PLAYER"] -- only the owner can break their own
|
||||||
|
// waystone, so breaker == owner in normal play.
|
||||||
|
|
||||||
|
const WAYSTONE_CAP = 1;
|
||||||
|
|
||||||
|
const REGULAR_WAYSTONES = new Set([
|
||||||
|
'waystones:waystone',
|
||||||
|
'waystones:mossy_waystone',
|
||||||
|
'waystones:sandy_waystone',
|
||||||
|
'waystones:blackstone_waystone',
|
||||||
|
'waystones:deepslate_waystone',
|
||||||
|
'waystones:end_stone_waystone',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Build the colored-block ban list once instead of typing 32 strings.
|
||||||
|
const COLORS = [
|
||||||
|
'white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime',
|
||||||
|
'pink', 'gray', 'light_gray', 'cyan', 'purple', 'blue',
|
||||||
|
'brown', 'green', 'red', 'black',
|
||||||
|
];
|
||||||
|
const BANNED_BLOCKS = new Set();
|
||||||
|
COLORS.forEach(c => {
|
||||||
|
BANNED_BLOCKS.add(`waystones:${c}_sharestone`);
|
||||||
|
BANNED_BLOCKS.add(`waystones:${c}_portstone`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Helper: replace the just-placed block with air and refund the item.
|
||||||
|
function refund(event, blockId) {
|
||||||
|
event.block.set('minecraft:air');
|
||||||
|
if (event.player) {
|
||||||
|
event.player.give(Item.of(blockId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockEvents.placed(event => {
|
||||||
|
const blockId = event.block.id;
|
||||||
|
const player = event.player;
|
||||||
|
|
||||||
|
// Skip non-player placements (dispensers, mob events) -- nothing to refund.
|
||||||
|
if (!player) return;
|
||||||
|
|
||||||
|
if (BANNED_BLOCKS.has(blockId)) {
|
||||||
|
refund(event, blockId);
|
||||||
|
player.tell(Text.red(
|
||||||
|
'That block is disabled. Use a regular Waystone (1 per player) ' +
|
||||||
|
'and build transport between distant bases.'
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (REGULAR_WAYSTONES.has(blockId)) {
|
||||||
|
const data = player.persistentData;
|
||||||
|
const current = data.getInt('bnsWaystoneCount');
|
||||||
|
if (current >= WAYSTONE_CAP) {
|
||||||
|
refund(event, blockId);
|
||||||
|
player.tell(Text.red(
|
||||||
|
`You already have ${WAYSTONE_CAP} waystone. Break your existing one ` +
|
||||||
|
`to relocate, or build infrastructure to reach distant bases.`
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data.putInt('bnsWaystoneCount', current + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
BlockEvents.broken(event => {
|
||||||
|
const blockId = event.block.id;
|
||||||
|
if (!REGULAR_WAYSTONES.has(blockId)) return;
|
||||||
|
const player = event.player;
|
||||||
|
if (!player) return; // explosion / world clear -- accept count drift, rare
|
||||||
|
const data = player.persistentData;
|
||||||
|
const current = data.getInt('bnsWaystoneCount');
|
||||||
|
if (current > 0) {
|
||||||
|
data.putInt('bnsWaystoneCount', current - 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// Brass & Sigil — first-join welcome grant
|
||||||
|
//
|
||||||
|
// Gives each new player exactly 1 Waystone + 1 server manual book on
|
||||||
|
// first login. Gated by a per-player persistent flag so it fires once
|
||||||
|
// even if the player relogs.
|
||||||
|
//
|
||||||
|
// Future: replace the vanilla written book with a Patchouli book in a
|
||||||
|
// custom tweak jar once we have enough content to warrant the rich
|
||||||
|
// formatting. Patchouli is already in the pack so swapping later is
|
||||||
|
// purely a content+recipe change, no mod-add needed.
|
||||||
|
|
||||||
|
const WELCOME_FLAG = 'bnsWelcomeGranted';
|
||||||
|
|
||||||
|
const MANUAL_PAGES = [
|
||||||
|
'Welcome to Brass & Sigil.\n\nThis manual covers the basics. Read it once, then keep it or toss it.',
|
||||||
|
'WAYSTONES\n\nYou have one Waystone item. Place it at your base -- it is the only one you get.\n\nNeed to travel further? Build trains, roads, or Create Aeronautics planes.',
|
||||||
|
'MONEY\n\nCoins cannot be crafted.\n\nTake valuables (diamonds etc.) to the bank at spawn. The exchange will trade them for coins.\n\nDynamic rates are planned.',
|
||||||
|
'SPAWN PLOTS\n\nComing soon: buy a small commercial plot at spawn to set up your shop. One plot per player.\n\nYour home base goes OUT in the world -- claim it with FTB Chunks (free, anywhere).',
|
||||||
|
'RULES\n\n- Be excellent to each other.\n- No griefing.\n- Lost your Waystone? Ask an OP or buy one from the bank (soon).\n- Report bugs to staff.\n\nHave fun.',
|
||||||
|
];
|
||||||
|
|
||||||
|
function giveManual(player) {
|
||||||
|
// 1.21 components-based written book: pages are filterable text
|
||||||
|
// components, title supports the same. Plain strings are accepted.
|
||||||
|
const book = Item.of('minecraft:written_book');
|
||||||
|
book.set('minecraft:written_book_content', {
|
||||||
|
title: { raw: 'Brass & Sigil Manual' },
|
||||||
|
author: 'Server Staff',
|
||||||
|
pages: MANUAL_PAGES.map(text => ({ raw: text })),
|
||||||
|
resolved: true,
|
||||||
|
});
|
||||||
|
player.give(book);
|
||||||
|
}
|
||||||
|
|
||||||
|
function giveStarterWaystone(player) {
|
||||||
|
player.give(Item.of('waystones:waystone'));
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerEvents.loggedIn(event => {
|
||||||
|
const player = event.player;
|
||||||
|
const data = player.persistentData;
|
||||||
|
if (data.getBoolean(WELCOME_FLAG)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
giveStarterWaystone(player);
|
||||||
|
giveManual(player);
|
||||||
|
data.putBoolean(WELCOME_FLAG, true);
|
||||||
|
player.tell(Text.gold('Welcome to Brass & Sigil. Check your inventory for a Waystone and the server manual.'));
|
||||||
|
} catch (e) {
|
||||||
|
// If something goes wrong, don't set the flag -- player gets another chance.
|
||||||
|
console.error(`[bns/welcome] failed for ${player.username}: ${e}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
+23
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "Brass-and-Sigil pack.lock.json - generated, do not edit by hand unless you know what you are doing",
|
"$schema": "Brass-and-Sigil pack.lock.json - generated, do not edit by hand unless you know what you are doing",
|
||||||
"name": "Brass and Sigil",
|
"name": "Brass and Sigil",
|
||||||
"version": "0.16.0",
|
"version": "0.18.1",
|
||||||
"minecraft": "1.21.1",
|
"minecraft": "1.21.1",
|
||||||
"loader": {
|
"loader": {
|
||||||
"type": "neoforge",
|
"type": "neoforge",
|
||||||
@@ -481,6 +481,28 @@
|
|||||||
"sha1": "488bc70db3730f209e65cbda04c36dbc3918c448",
|
"sha1": "488bc70db3730f209e65cbda04c36dbc3918c448",
|
||||||
"size": 878265,
|
"size": 878265,
|
||||||
"side": "both"
|
"side": "both"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "modrinth",
|
||||||
|
"slug": "numismatics",
|
||||||
|
"versionId": "guON3qvQ",
|
||||||
|
"version": "1.0.20+neoforge-mc1.21.1",
|
||||||
|
"path": "mods/CreateNumismatics-1.0.20+neoforge-mc1.21.1.jar",
|
||||||
|
"url": "https://cdn.modrinth.com/data/Jdbbtt0i/versions/guON3qvQ/CreateNumismatics-1.0.20%2Bneoforge-mc1.21.1.jar",
|
||||||
|
"sha1": "9883bfd6fef5bd5068f9174ddccba5047849c922",
|
||||||
|
"size": 693446,
|
||||||
|
"side": "both"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "modrinth",
|
||||||
|
"slug": "patchouli",
|
||||||
|
"versionId": "BIogJv2D",
|
||||||
|
"version": "1.21.1-93-neoforge",
|
||||||
|
"path": "mods/Patchouli-1.21.1-93-NEOFORGE.jar",
|
||||||
|
"url": "https://cdn.modrinth.com/data/nU0bVIaL/versions/BIogJv2D/Patchouli-1.21.1-93-NEOFORGE.jar",
|
||||||
|
"sha1": "5413bb9b8fc35ebe46b06b48bf9afafbd8471140",
|
||||||
|
"size": 646777,
|
||||||
|
"side": "both"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"defaultServer": {
|
"defaultServer": {
|
||||||
|
|||||||
Reference in New Issue
Block a user