diff --git a/dev/TODO.md b/dev/TODO.md index caba99b91..c836bd574 100644 --- a/dev/TODO.md +++ b/dev/TODO.md @@ -2,20 +2,20 @@ 🚧✅❌⚠️ List of priorities: -- [ ] Add feature to clear drawer `Item: 0` when unlocking it https://github.com/jaquadro/StorageDrawers/commit/da9875158ad0fadc190aae437ea2d9e89d616cca -- [ ] 🐀 Rat Ore Doubling can dupe IC2 "Iridium Ore". Removing oreIridium from it wont help -- [ ] Test on server if `sendPlaySoundPacket` actually work -- [ ] 🐛 Remove `Chester` from the game cause lot of bugs -- [ ] 𝓩𝒮 Fix `Refining` not working on BoP ores +- [x] 🐀 Rat Ore Doubling can dupe IC2 "Iridium Ore". Removing oreIridium from it wont help - [ ] Rebalance TCon `Refining`: Remove x1.75 multiplication but add Fortune accounting -- [ ] 𝓩𝒮 Refactor `#mixin Mixin` preprocessors -- [ ] 🌎 Reduce amount of End Islands in overworld -- [ ] 🔨 Buff Ichorium mining level -- [ ] ✏️ Make `Pulsating Crystal` require less Biome Essence -- [ ] ✏️ Fix `thaumadditions:salt_essence` cannot be viewed in HEI since when it not have aspects its create an error -- [ ] ✏️ Remove `rainmaker's charge` duplicate recipe -- [ ] ✏️ Add and configure https://legacy.curseforge.com/minecraft/mc-mods/backpack-opener -- [ ] ✏️ Add https://legacy.curseforge.com/minecraft/texture-packs/ic2-seedbag-display +- [ ] 𝓩𝒮 Refactor `#mixin` preprocessors into one-line when it short +- [x] ✏️ Fix `thaumadditions:salt_essence` cannot be viewed in HEI since when it not have aspects its create an error +- [x] 🟢 Add and configure https://legacy.curseforge.com/minecraft/mc-mods/backpack-opener +- [ ] 🖼️ Add https://legacy.curseforge.com/minecraft/texture-packs/ic2-seedbag-display +- [ ] Prevent Timewood Clock to walkaround restrictions by activating it with users +- [ ] Undo `Fluid Interaction Tweaker` serverside hotfix https://github.com/tttsaurus/Fluid-Interaction-Tweaker/issues/8 +- [ ] Add https://www.curseforge.com/minecraft/mc-mods/patchouli-books +- [ ] ✏️ Thermionic Fabricator TE machine frame recipe +- [ ] fix `format.zs` mutating lists `[T]` => `T[]` +- [ ] ✏️ Completely remove AA crusher since no difference with EU2 one +- [ ] ✏️ Fix IC2 dusts produced by Scrap Boxes +- [ ] ✏️ Black Hole Talisman cheaper - [ ] 🎣 Fish rework * [x] Integrate https://www.curseforge.com/minecraft/mc-mods/customfishing * [x] Add `Fish Singularity`. @@ -31,10 +31,12 @@ Planned non-urgent changes, or just good ideas: ### "Performance ⚡" +- [ ] ⚡ Improve performance of Replicator tick - [ ] ⚡ Disallow to connect `Storage Bus` to ISS - can cause 10% TPS strain - [ ] ⚡ `OTG` should probably be optional mod when game starting since it laggy - [ ] ⚡ Wand of the forest change recipe to Recipe Function - [ ] ⚡ Remove automatic IE armor recycling to speed up game load +- [ ] ⚡ Remove `Chunk Loading Ward` since its make harder to find all chunk loaders on server ### Difficulty increase - Vanilla Chests @@ -50,6 +52,7 @@ Planned non-urgent changes, or just good ideas: - [ ] 🐉 Bestiary book have missed item icons - [ ] 📖 Suggest IC2 reactors schemas - [ ] 📖 Add note that Mana Enchanter can put Airtight Seal on TCon armor +- [ ] 📖 Add quest about Troll smashing tools ### "Battle" expansion - [ ] ✏️ Buff EU saber - give it more damage? But better split entities in two. @@ -141,6 +144,9 @@ Planned non-urgent changes, or just good ideas: ### Other +- [ ] 📖 Register item subtypes by NBT to JEI for `Gendustry` (there was CT handler for that but i cant find it) +- [ ] 𝓩𝒮 Fix `Refining` not working on BoP ores +- [ ] Add feature to clear drawer `Item: 0` when unlocking it https://github.com/jaquadro/StorageDrawers/commit/da9875158ad0fadc190aae437ea2d9e89d616cca - [ ] Unmerge Furnace inputs in HEI (reported to HEI dev) - [ ] 💧 Add `Fluid Interactions` between gaseous (floating up) and normal fluids - [ ] Fix PSI "silk touch falling" turning Netherending Ores into meta-0 ones diff --git a/dev/_other/players_from_spawn.ts b/dev/_other/players_from_spawn.ts new file mode 100644 index 000000000..b9eba6640 --- /dev/null +++ b/dev/_other/players_from_spawn.ts @@ -0,0 +1,22 @@ +import fse from 'fs-extra' +import { parse as parseNbt } from 'prismarine-nbt' + +import { globs } from '../build/build_utils' + +const { readFileSync } = fse + +// Get player data +const playerDataList = globs('E:/mc/BBOP-Extended/playerdata/*.dat') +const players = await Promise.all(playerDataList.map((filename) => { + const p = parseNbt(readFileSync(filename)) + p.then(() => process.stdout.write('.')) + return p +})) +const fromSpawn = players.map((decoded, i) => { + const [x, _y, z] = (decoded.parsed.value.Pos.value as any).value + const dist = Math.sqrt(x ** 2 + z ** 2) | 0 + if (dist > 100000) console.log('\n>100k :>> ', playerDataList[i]) + return dist +}) +fromSpawn.sort((a, b) => a - b) +console.log('\nfrom spawn :>> ', fromSpawn.reverse()) diff --git a/dev/_other/server/prune.ts b/dev/_other/server/prune.ts new file mode 100644 index 000000000..e15c35f85 --- /dev/null +++ b/dev/_other/server/prune.ts @@ -0,0 +1,98 @@ +/** + * Find too far regions on server using SFTP and remove them + * + * Also show players positions + */ + +import chalk from 'chalk' +import Client from 'ssh2-sftp-client' + +import { getBoxForLabel, pressEnterOrEsc } from '../../build/build_utils' +import { + loadJson, +} from '../../lib/utils.js' +import { filterForPrunning, pruneWorld, removeFilesOnServer } from './world' + +let updateBox = getBoxForLabel('sftp') + +const sftp = new Client() + +const sftpConfig = loadJson('secrets/sftp_servers/1. Guncolony/sftp.json') as { [key: string]: string } + +/************************************************ +* Getting info +************************************************/ +updateBox('Connecting') +await sftp.connect(sftpConfig) + +await pruneWorld(sftp, { + title : 'Overworld', + region : 'region', + maxDistanceFromSpawn: 30000, + obsoleteMonths : 6, +}) + +await pruneWorld(sftp, { + title : 'The Nether', + region : 'DIM-1/region', + maxDistanceFromSpawn: 5000, + obsoleteMonths : 6, +}) + +await pruneWorld(sftp, { + title : 'The End', + region : 'DIM1/region', + maxDistanceFromSpawn: 5000, + obsoleteMonths : 6, +}) + +await pruneWorld(sftp, { + title : 'Twilight Forest', + region : 'DIM7/region', + maxDistanceFromSpawn: 10000, + obsoleteMonths : 6, +}) + +await pruneWorld(sftp, { + title : 'Deep Dark', + region : 'DIM-11325/region', + maxDistanceFromSpawn: 1000, + obsoleteMonths : 3, +}) + +await pruneWorld(sftp, { + title : 'Ratlantis', + region : 'DIM-8/region', + maxDistanceFromSpawn: 3000, + obsoleteMonths : 3, +}) + +/************************************************ +* Remove useless dimensions +************************************************/ +updateBox = getBoxForLabel('Prune dimensions') +updateBox('Getting list') +const advRocketryDims = filterForPrunning(await sftp.list('/BBOP-Extended/advRocketry'), f => f.name.startsWith('DIM') && f.name !== 'DIM-2') + +updateBox( + 'AR dimension to remove: ', + advRocketryDims.list.map(f => chalk.green(f.substring(3))).join(chalk.gray(', ')) +) + +if (await pressEnterOrEsc(`Press ENTER to remove ALL AdvRock dimensions except Space Stations. Press ESC to skip.`)) { + updateBox = getBoxForLabel(`Task: ${chalk.yellow`Remove Adv. Rocketry worlds`}`) + await removeFilesOnServer( + sftp, + advRocketryDims.list.map(f => `/BBOP-Extended/advRocketry/${f}`), + fileCounter => updateBox('Removing files', fileCounter, '/', advRocketryDims.list.length), + updateBox + ) +} + +/************************************************ +* Done +************************************************/ +updateBox = getBoxForLabel('sftp') +updateBox('Done!') +await sftp.end() +process.exit(0) diff --git a/dev/_other/server/world.ts b/dev/_other/server/world.ts new file mode 100644 index 000000000..0737253da --- /dev/null +++ b/dev/_other/server/world.ts @@ -0,0 +1,100 @@ +import type Client from 'ssh2-sftp-client' + +import chalk from 'chalk' + +import { getBoxForLabel, pressEnterOrEsc } from '../../build/build_utils' + +export async function pruneWorld( + sftp: Client, + config: { + maxDistanceFromSpawn: number + obsoleteMonths : number + region : string + title : string + } +) { + let updateBox = getBoxForLabel(`Prunning ${config.title}`) + updateBox('Getting list') + const regions = await sftp.list(`/BBOP-Extended/${config.region}`) + updateBox('Connected!') + + function fileSizeText(size:number) { + return `${(size / 1048576) | 0}mb` + } + + async function pruneTask(taskName:string, predicate: (f:Client.FileInfo)=>boolean) { + const pruneData = filterForPrunning(regions, predicate) + + updateBox = getBoxForLabel(taskName) + updateBox( + chalk.gray`Filtering / Total:`, + chalk.green(pruneData.list.length), + chalk.gray`/`, + `${chalk.green(regions.length)}\n`, + chalk.gray`Total size: `, + `${chalk.green(fileSizeText(pruneData.size))}` + ) + + if (await pressEnterOrEsc(`Press ENTER to remove filtered regions. Press ESC to skip.`)) { + updateBox = getBoxForLabel(`Task: ${chalk.yellow`Remove Overworld regions`}`) + await removeFilesOnServer( + sftp, + pruneData.list.map(f => `/BBOP-Extended/${config.region}/${f}`), + fileCounter => updateBox('Removing files', fileCounter, '/', pruneData.list.length), + updateBox + ) + return pruneData.list + } + } + + /************************************************ + * Remove distant regions + ************************************************/ + const removed = await pruneTask(`Prune by distance >${config.maxDistanceFromSpawn}`, (f) => { + const [x, z] = f.name.split('.').slice(1, 3).map(Number) + return Math.sqrt(x * x + z * z) > config.maxDistanceFromSpawn / 512 + }) + + /************************************************ + * Remove unupdated regions + ************************************************/ + const currentDate = new Date().valueOf() + await pruneTask(`Prune if older ${config.obsoleteMonths} month`, (f) => { + if (removed?.includes(f.name)) return false + const monthsPast = new Date(currentDate - f.modifyTime).getMonth() + return monthsPast >= config.obsoleteMonths + }) +} + +export function filterForPrunning(list: Client.FileInfo[], predicate: (f:Client.FileInfo)=>boolean) { + let pruneTotalSize = 0 + const filtered = list + .filter((f) => { + const toRemoval = predicate(f) + if (toRemoval) pruneTotalSize += f.size + return toRemoval + }) + .map(f => f.name).sort() + return { + list: filtered, + size: pruneTotalSize, + } +} + +export async function removeFilesOnServer( + sftp:Client, + list: string[], + onRemove: (fileCounter: number)=>void, + log:(...args: any[]) => void +) { + log('Removing files: ', '0', '/', list.length) + + let fileCounter = 0 + await Promise.all(list.map((f) => { + const p = sftp.delete(f) + p.then(() => onRemove(++fileCounter)) + return p + })) + + log('Removed files: ', fileCounter) +} diff --git a/mc-tools b/mc-tools index ab7e1377d..f8f789834 160000 --- a/mc-tools +++ b/mc-tools @@ -1 +1 @@ -Subproject commit ab7e1377d5699781ccd61e4ddf2ad752cbf2e8ae +Subproject commit f8f78983414ff13dd4632899b7cbd4e6c1684e06 diff --git a/resources/commands/lang/en_us.lang b/resources/commands/lang/en_us.lang index cbdbc88c3..349bdb4e3 100644 --- a/resources/commands/lang/en_us.lang +++ b/resources/commands/lang/en_us.lang @@ -1,7 +1,7 @@ commands.lang.usage="/lang" or "/lang hand" to dump inventory or held item into crafttweaker.log file commands.lang.output=Output %s items into crafttweaker.log file commands.lang.empty=Your inventory is empty. Put untranslated item in -commands.lang.hand=Output held item into crafttweaker.log file +commands.lang.hand=%s\nOutput held item into crafttweaker.log file commands.addtooltip.usage="§e/addtooltip §6[Item Description]§r" to describe item into crafttweaker.log file commands.addtooltip.needtext=§e/addtooltip§r command need tooltip string. Try §e/addtooltip §6Hello world! diff --git a/resources/commands/lang/ru_ru.lang b/resources/commands/lang/ru_ru.lang index 398d8fe01..2495c0231 100644 --- a/resources/commands/lang/ru_ru.lang +++ b/resources/commands/lang/ru_ru.lang @@ -1,7 +1,7 @@ commands.lang.usage="/lang" или "/lang hand" чтобы вывести список предметов инвентаня в файл crafttweaker.log commands.lang.output=Выведено %s предметов в файл crafttweaker.log commands.lang.empty=Ваш инвентарь пуст. Положите туда непереведенные предметы -commands.lang.hand=Выведен предмет из руки в файл crafttweaker.log +commands.lang.hand=%s\nВыведен предмет из руки в файл crafttweaker.log commands.addtooltip.usage="§e/addtooltip §6[Описание предмета]§r" для описания предмета в файле crafttweaker.log commands.addtooltip.needtext=Команде §e/addtooltip§r нужна строка подсказки. Попробуйте §e/addtooltip §6Hello world! diff --git a/resources/commands/lang/zh_cn.lang b/resources/commands/lang/zh_cn.lang index a69afb1c7..bbdd28c5e 100644 --- a/resources/commands/lang/zh_cn.lang +++ b/resources/commands/lang/zh_cn.lang @@ -1,7 +1,7 @@ commands.lang.usage="/lang" 或 "/lang hand" 命令可以把物品栏或手中物品的信息导出到 crafttweaker.log 文件里 commands.lang.output=已将 %s 个物品的信息导出到 crafttweaker.log commands.lang.empty=你的物品栏是空的。请把未本地化的物品放到物品栏里 -commands.lang.hand=已将手持物品的信息输出到 crafttweaker.log +commands.lang.hand=%s\n已将手持物品的信息输出到 crafttweaker.log commands.addtooltip.usage="§e/addtooltip §6[Item Description]§r" 命令可以将为手持物品添加工具提示的语言条目导出到 crafttweaker.log commands.addtooltip.needtext=§e/addtooltip§r 命令需要提供工具提示的内容。比如 §e/addtooltip §6Hello world! diff --git a/scripts/debug/commands.zs b/scripts/debug/commands.zs index c8ff220da..bf8618546 100644 --- a/scripts/debug/commands.zs +++ b/scripts/debug/commands.zs @@ -1,3 +1,5 @@ +#reloadable + import mods.zenutils.I18n; import mods.zenutils.StringList; import mods.zenutils.command.CommandUtils; @@ -31,13 +33,13 @@ lang.execute = function (command, server, sender, args) { for i in 0 .. invLength { val it = pl.getInventoryStack(i); if (!isNull(it)) { - s += '\n' ~ it.name ~ '=' ~ it.displayName; + s += `\n${it.name}=${it.displayName}`; s_len += 1; } } if (s_len > 0) { print(s); - pl.sendChat(I18n.format(game.localize('commands.lang.output'), s_len ~ '')); + pl.sendChat(I18n.format(game.localize('commands.lang.output'), `${s_len}`)); } else { pl.sendChat(game.localize('commands.lang.empty')); @@ -46,11 +48,9 @@ lang.execute = function (command, server, sender, args) { else if (args[0] == 'hand') { val it = pl.currentItem; if (!isNull(it)) { - print( - 'Lang key and translation:' ~ '\n' - ~ it.name ~ '=' ~ it.displayName - ); - pl.sendChat(game.localize('commands.lang.hand')); + val line = `Lang key and translation:\n${it.name}=${it.displayName}`; + print(line); + pl.sendChat(I18n.format(game.localize('commands.lang.hand'), line)); } } else { diff --git a/scripts/debug/dump.zs b/scripts/debug/dump.zs index 1c53dc33f..ef7d82039 100644 --- a/scripts/debug/dump.zs +++ b/scripts/debug/dump.zs @@ -162,7 +162,7 @@ events.onPlayerLoggedIn(function (e as crafttweaker.event.PlayerLoggedInEvent) { e.player.world.catenation().sleep(100).then(function (world, ctx) { e.player.sendMessage('§cDebug environment activated!'); e.player.sendMessage('§8If you want to disable DEBUG mode, remove §7scripts/debug§8 directory'); - e.player.sendMessage('§8Write §7/skip_automation§8 to skip automatic executions, write §7/run_automation§8 to run manually'); + e.player.sendMessage('§8Write §7/skip§8 to skip automatic executions, write §7/run_automation§8 to run manually'); }) .sleep(300).then(function (world, ctx) { @@ -187,7 +187,7 @@ for r in furnace.all { print('##################################################'); // Command to cancel automation -var cmd = mods.zenutils.command.ZenCommand.create('skip_automation'); +var cmd = mods.zenutils.command.ZenCommand.create('skip'); cmd.requiredPermissionLevel = 0; cmd.execute = function (command, server, sender, args) { skipped[0] = true; }; cmd.register();