mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 06:18:42 +02:00
MISC: Add removal of fuzzy matching to list of breaking changes (#2149)
This commit is contained in:
@@ -1,31 +1,33 @@
|
||||
import { APIBreakInfo } from "./APIBreak";
|
||||
import type { VersionBreakingChange } from "./APIBreak";
|
||||
|
||||
export const breakInfos261: APIBreakInfo[] = [
|
||||
{
|
||||
brokenAPIs: [{ name: "ns.bladeburner.getCurrentAction" }],
|
||||
info:
|
||||
"ns.bladeburner.getCurrentAction:\n" +
|
||||
'When not performing a bladeburner action, previously returned {type: "Idle", name: ""}, now returns null.\n' +
|
||||
"Because of this change, the null case now needs to be dealt with prior to accessing properties on the return of getCurrentAction, including destructuring.\n" +
|
||||
"Additionally, any existing code for filtering out the Idle case will need to be adjusted.\n\n" +
|
||||
"See https://github.com/bitburner-official/bitburner-src/issues/1249 or PR https://github.com/bitburner-official/bitburner-src/pull/1248 for more details.",
|
||||
showPopUp: true,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{ name: "ns.bladeburner.getActionCountRemaining" },
|
||||
{ name: "ns.bladeburner.getActionEstimatedSuccessChance" },
|
||||
{ name: "ns.bladeburner.getActionTime" },
|
||||
],
|
||||
info:
|
||||
"ns.bladeburner.getActionCountRemaining:\n" +
|
||||
'Previously returned -1 when called with type "Idle" and name "". This is no longer valid usage and will result in an error.\n\n' +
|
||||
"ns.bladeburner.getActionEstimatedSuccessChance:\n" +
|
||||
'Previously returned [-1, -1] when called with type "Idle" and name "". This is no longer valid usage and will result in an error.\n\n' +
|
||||
"ns.bladeburner.getActionTime:\n" +
|
||||
'Previously returned -1 when called with type "Idle" and name "". This is no longer valid usage and will result in an error.\n\n' +
|
||||
"See the related changes for ns.bladeburner.getCurrentAction, which were shown earlier in these API break details.\n" +
|
||||
"In most cases, the fixes for ns.bladeburner.getCurrentAction will fix this group of issues as well.",
|
||||
showPopUp: true,
|
||||
},
|
||||
];
|
||||
export const breakInfos261: VersionBreakingChange = {
|
||||
apiBreakingChanges: [
|
||||
{
|
||||
brokenAPIs: [{ name: "ns.bladeburner.getCurrentAction" }],
|
||||
info:
|
||||
"ns.bladeburner.getCurrentAction:\n" +
|
||||
'When not performing a bladeburner action, previously returned {type: "Idle", name: ""}, now returns null.\n' +
|
||||
"Because of this change, the null case now needs to be dealt with prior to accessing properties on the return of getCurrentAction, including destructuring.\n" +
|
||||
"Additionally, any existing code for filtering out the Idle case will need to be adjusted.\n\n" +
|
||||
"See https://github.com/bitburner-official/bitburner-src/issues/1249 or PR https://github.com/bitburner-official/bitburner-src/pull/1248 for more details.",
|
||||
showPopUp: true,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{ name: "ns.bladeburner.getActionCountRemaining" },
|
||||
{ name: "ns.bladeburner.getActionEstimatedSuccessChance" },
|
||||
{ name: "ns.bladeburner.getActionTime" },
|
||||
],
|
||||
info:
|
||||
"ns.bladeburner.getActionCountRemaining:\n" +
|
||||
'Previously returned -1 when called with type "Idle" and name "". This is no longer valid usage and will result in an error.\n\n' +
|
||||
"ns.bladeburner.getActionEstimatedSuccessChance:\n" +
|
||||
'Previously returned [-1, -1] when called with type "Idle" and name "". This is no longer valid usage and will result in an error.\n\n' +
|
||||
"ns.bladeburner.getActionTime:\n" +
|
||||
'Previously returned -1 when called with type "Idle" and name "". This is no longer valid usage and will result in an error.\n\n' +
|
||||
"See the related changes for ns.bladeburner.getCurrentAction, which were shown earlier in these API break details.\n" +
|
||||
"In most cases, the fixes for ns.bladeburner.getCurrentAction will fix this group of issues as well.",
|
||||
showPopUp: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,112 +1,133 @@
|
||||
import { APIBreakInfo } from "./APIBreak";
|
||||
import type { VersionBreakingChange } from "./APIBreak";
|
||||
|
||||
export const breakInfos300: APIBreakInfo[] = [
|
||||
{
|
||||
brokenAPIs: [{ name: "ns.nFormat" }],
|
||||
info:
|
||||
"ns.nFormat() was removed.\n" +
|
||||
"Use ns.formatNumber, ns.formatRam, ns.formatPercent, or JS built-in objects/functions (e.g., Intl.NumberFormat, " +
|
||||
"Intl.PluralRules, Intl.Locale) instead.",
|
||||
showPopUp: true,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{
|
||||
name: "ns.getTimeSinceLastAug",
|
||||
migration: {
|
||||
searchValue: "ns.getTimeSinceLastAug()",
|
||||
replaceValue: "(Date.now() - ns.getResetInfo().lastAugReset)",
|
||||
export const breakingChanges300: VersionBreakingChange = {
|
||||
additionalText: "For more information, please check https://github.com/bitburner-official/bitburner-src/issues/2148.",
|
||||
apiBreakingChanges: [
|
||||
{
|
||||
brokenAPIs: [{ name: "ns.nFormat" }],
|
||||
info:
|
||||
"ns.nFormat() was removed.\n" +
|
||||
"Use ns.formatNumber, ns.formatRam, ns.formatPercent, or JS built-in objects/functions (e.g., Intl.NumberFormat, " +
|
||||
"Intl.PluralRules, Intl.Locale) instead.",
|
||||
showPopUp: true,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{
|
||||
name: "ns.getTimeSinceLastAug",
|
||||
migration: {
|
||||
searchValue: "ns.getTimeSinceLastAug()",
|
||||
replaceValue: "(Date.now() - ns.getResetInfo().lastAugReset)",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ns.getPlayer().playtimeSinceLastAug",
|
||||
migration: {
|
||||
searchValue: "ns.getPlayer().playtimeSinceLastAug",
|
||||
replaceValue: "(Date.now() - ns.getResetInfo().lastAugReset)",
|
||||
{
|
||||
name: "ns.getPlayer().playtimeSinceLastAug",
|
||||
migration: {
|
||||
searchValue: "ns.getPlayer().playtimeSinceLastAug",
|
||||
replaceValue: "(Date.now() - ns.getResetInfo().lastAugReset)",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ns.getPlayer().playtimeSinceLastBitnode",
|
||||
migration: {
|
||||
searchValue: "ns.getPlayer().playtimeSinceLastBitnode",
|
||||
replaceValue: "(Date.now() - ns.getResetInfo().lastNodeReset)",
|
||||
{
|
||||
name: "ns.getPlayer().playtimeSinceLastBitnode",
|
||||
migration: {
|
||||
searchValue: "ns.getPlayer().playtimeSinceLastBitnode",
|
||||
replaceValue: "(Date.now() - ns.getResetInfo().lastNodeReset)",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ns.getPlayer().bitNodeN",
|
||||
migration: {
|
||||
searchValue: "ns.getPlayer().bitNodeN",
|
||||
replaceValue: "ns.getResetInfo().currentNode",
|
||||
{
|
||||
name: "ns.getPlayer().bitNodeN",
|
||||
migration: {
|
||||
searchValue: "ns.getPlayer().bitNodeN",
|
||||
replaceValue: "ns.getResetInfo().currentNode",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ns.corporation.getCorporation().state",
|
||||
migration: {
|
||||
searchValue: "ns.corporation.getCorporation().state",
|
||||
replaceValue: "ns.corporation.getCorporation().nextState",
|
||||
{
|
||||
name: "ns.corporation.getCorporation().state",
|
||||
migration: {
|
||||
searchValue: "ns.corporation.getCorporation().state",
|
||||
replaceValue: "ns.corporation.getCorporation().nextState",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
info:
|
||||
"ns.getTimeSinceLastAug was removed.\n" +
|
||||
'It has been automatically replaced with "Date.now() - ns.getResetInfo().lastAugReset".\n\n' +
|
||||
"ns.getPlayer().playtimeSinceLastAug was removed.\n" +
|
||||
'It has been automatically replaced with "Date.now() - ns.getResetInfo().lastAugReset".\n\n' +
|
||||
"ns.getPlayer().playtimeSinceLastBitnode was removed.\n" +
|
||||
'It has been automatically replaced with "Date.now() - ns.getResetInfo().lastNodeReset".\n\n' +
|
||||
"ns.getPlayer().bitNodeN was removed.\n" +
|
||||
'It has been automatically replaced with "ns.getResetInfo().currentNode"\n\n' +
|
||||
"ns.corporation.getCorporation().state was removed.\n" +
|
||||
'It has been automatically replaced with "ns.corporation.getCorporation().nextState"',
|
||||
showPopUp: false,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{ name: "ns.formatNumber", migration: { searchValue: "ns.formatNumber", replaceValue: "ns.format.number" } },
|
||||
{ name: "ns.formatRam", migration: { searchValue: "ns.formatRam", replaceValue: "ns.format.ram" } },
|
||||
{ name: "ns.formatPercent", migration: { searchValue: "ns.formatPercent", replaceValue: "ns.format.percent" } },
|
||||
{ name: "ns.tFormat", migration: { searchValue: "ns.tFormat", replaceValue: "ns.format.time" } },
|
||||
],
|
||||
info:
|
||||
"The formatting functions have been moved to their own interface, ns.format.\n" +
|
||||
"Each function has been replaced with their corresponding interface variant.\n" +
|
||||
"Additionally, the naming of ns.tFormat has been changed to ns.format.time.",
|
||||
showPopUp: false,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{ name: "ns.tail", migration: { searchValue: "ns.tail", replaceValue: "ns.ui.openTail" } },
|
||||
{ name: "ns.moveTail", migration: { searchValue: "ns.moveTail", replaceValue: "ns.ui.moveTail" } },
|
||||
{ name: "ns.resizeTail", migration: { searchValue: "ns.resizeTail", replaceValue: "ns.ui.resizeTail" } },
|
||||
{ name: "ns.closeTail", migration: { searchValue: "ns.closeTail", replaceValue: "ns.ui.closeTail" } },
|
||||
{ name: "ns.setTitle", migration: { searchValue: "ns.setTitle", replaceValue: "ns.ui.setTailTitle" } },
|
||||
],
|
||||
info:
|
||||
"ns.tail() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.openTail()".\n\n' +
|
||||
"ns.moveTail() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.moveTail()".\n\n' +
|
||||
"ns.resizeTail() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.resizeTail()".\n\n' +
|
||||
"ns.closeTail() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.closeTail()".\n\n' +
|
||||
"ns.setTitle() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.setTailTitle()".\n\n',
|
||||
showPopUp: false,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{
|
||||
name: "ns.corporation.setAutoJobAssignment",
|
||||
migration: {
|
||||
searchValue: "setAutoJobAssignment",
|
||||
replaceValue: "setJobAssignment",
|
||||
],
|
||||
info:
|
||||
"ns.getTimeSinceLastAug was removed.\n" +
|
||||
'It has been automatically replaced with "Date.now() - ns.getResetInfo().lastAugReset".\n\n' +
|
||||
"ns.getPlayer().playtimeSinceLastAug was removed.\n" +
|
||||
'It has been automatically replaced with "Date.now() - ns.getResetInfo().lastAugReset".\n\n' +
|
||||
"ns.getPlayer().playtimeSinceLastBitnode was removed.\n" +
|
||||
'It has been automatically replaced with "Date.now() - ns.getResetInfo().lastNodeReset".\n\n' +
|
||||
"ns.getPlayer().bitNodeN was removed.\n" +
|
||||
'It has been automatically replaced with "ns.getResetInfo().currentNode"\n\n' +
|
||||
"ns.corporation.getCorporation().state was removed.\n" +
|
||||
'It has been automatically replaced with "ns.corporation.getCorporation().nextState"',
|
||||
showPopUp: false,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{ name: "ns.formatNumber", migration: { searchValue: "ns.formatNumber", replaceValue: "ns.format.number" } },
|
||||
{ name: "ns.formatRam", migration: { searchValue: "ns.formatRam", replaceValue: "ns.format.ram" } },
|
||||
{ name: "ns.formatPercent", migration: { searchValue: "ns.formatPercent", replaceValue: "ns.format.percent" } },
|
||||
{ name: "ns.tFormat", migration: { searchValue: "ns.tFormat", replaceValue: "ns.format.time" } },
|
||||
],
|
||||
info:
|
||||
"The formatting functions have been moved to their own interface, ns.format.\n" +
|
||||
"Each function has been replaced with their corresponding interface variant.\n" +
|
||||
"Additionally, the naming of ns.tFormat has been changed to ns.format.time.",
|
||||
showPopUp: false,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{ name: "ns.tail", migration: { searchValue: "ns.tail", replaceValue: "ns.ui.openTail" } },
|
||||
{ name: "ns.moveTail", migration: { searchValue: "ns.moveTail", replaceValue: "ns.ui.moveTail" } },
|
||||
{ name: "ns.resizeTail", migration: { searchValue: "ns.resizeTail", replaceValue: "ns.ui.resizeTail" } },
|
||||
{ name: "ns.closeTail", migration: { searchValue: "ns.closeTail", replaceValue: "ns.ui.closeTail" } },
|
||||
{ name: "ns.setTitle", migration: { searchValue: "ns.setTitle", replaceValue: "ns.ui.setTailTitle" } },
|
||||
],
|
||||
info:
|
||||
"ns.tail() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.openTail()".\n\n' +
|
||||
"ns.moveTail() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.moveTail()".\n\n' +
|
||||
"ns.resizeTail() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.resizeTail()".\n\n' +
|
||||
"ns.closeTail() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.closeTail()".\n\n' +
|
||||
"ns.setTitle() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.ui.setTailTitle()".\n\n',
|
||||
showPopUp: false,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [
|
||||
{
|
||||
name: "ns.corporation.setAutoJobAssignment",
|
||||
migration: {
|
||||
searchValue: "setAutoJobAssignment",
|
||||
replaceValue: "setJobAssignment",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
info:
|
||||
"ns.corporation.setAutoJobAssignment() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.corporation.setJobAssignment()".\n\n',
|
||||
showPopUp: false,
|
||||
},
|
||||
];
|
||||
],
|
||||
info:
|
||||
"ns.corporation.setAutoJobAssignment() was removed.\n" +
|
||||
'It has been automatically replaced with "ns.corporation.setJobAssignment()".\n\n',
|
||||
showPopUp: false,
|
||||
},
|
||||
{
|
||||
brokenAPIs: [],
|
||||
info:
|
||||
"With some APIs, when you passed values to their params, you could pass a value that was not an exact match. " +
|
||||
'For example, with "ns.singularity.commitCrime", you could pass "Rob Store", "rob store", "RobStore", "robstore", "robStore", etc. ' +
|
||||
'This is called "fuzzy matching". Now, you must pass an exact value (i.e., Rob Store). This change affects:\n' +
|
||||
"- Bladeburner action and type: BladeburnerActionType, BladeburnerGeneralActionName, BladeburnerContractName, BladeburnerOperationName, BladeburnerBlackOpName, SpecialBladeburnerActionTypeForSleeve, BladeburnerActionTypeForSleeve.\n" +
|
||||
"- Crime: CrimeType\n" +
|
||||
"- Faction work: FactionWorkType\n" +
|
||||
"- University class: UniversityClassType\n" +
|
||||
"- Gym stat: GymType\n" +
|
||||
"- Job field: JobField\n" +
|
||||
"- Stock position: PositionType\n" +
|
||||
"- Stock order: OrderType\n" +
|
||||
"You can access these values via ns.enums and Bladeburner APIs.",
|
||||
showPopUp: true,
|
||||
doNotSkip: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -19,6 +19,11 @@ type ScriptImpactMap = Map<ScriptFilePath, number[]>;
|
||||
/** For an overall API break, map of server hostnames to an array of impacted scripts */
|
||||
type ImpactMap = Map<string, ScriptImpactMap>;
|
||||
|
||||
export interface VersionBreakingChange {
|
||||
additionalText?: string;
|
||||
apiBreakingChanges: APIBreakInfo[];
|
||||
}
|
||||
|
||||
export interface APIBreakInfo {
|
||||
/** The API functions impacted by the API break */
|
||||
brokenAPIs: {
|
||||
@@ -33,6 +38,19 @@ export interface APIBreakInfo {
|
||||
info: string;
|
||||
/** If broken APIs can be safely migrated, we can skip displaying the notification popup */
|
||||
showPopUp: boolean;
|
||||
/**
|
||||
* With a new version with breaking changes, the "showAPIBreaks" function checks all breaking changes and does 2
|
||||
* things with changes that affect the player's scripts:
|
||||
* - Write info of changes to a log file.
|
||||
* - Show popups per change.
|
||||
* Note that we skip changes that do not affect the player's scripts. This is problematic with some breaking changes.
|
||||
*
|
||||
* With each breaking change in "brokenAPIs", we try to detect the affected code by using "name" or
|
||||
* "migration.searchValue". However, with some breaking changes, we cannot detect the affected code reliably via
|
||||
* "brokenAPIs". In this case, instead of skipping them, we always "process" that change (i.e., write info to the log
|
||||
* file and optionally show a popup that notifies the player about this change).
|
||||
*/
|
||||
doNotSkip?: boolean;
|
||||
}
|
||||
|
||||
function detectImpactAndMigrateLines(script: Script, brokenFunctions: APIBreakInfo["brokenAPIs"]): number[] | null {
|
||||
@@ -54,7 +72,7 @@ function detectImpactAndMigrateLines(script: Script, brokenFunctions: APIBreakIn
|
||||
}
|
||||
|
||||
/** Returns a map keyed by hostname */
|
||||
function detectImpactAndMigrate(brokenFunctions: APIBreakInfo["brokenAPIs"]): ImpactMap | null {
|
||||
function detectImpactAndMigrate(brokenFunctions: APIBreakInfo["brokenAPIs"]): ImpactMap {
|
||||
const returnMap = new Map<string, ScriptImpactMap>();
|
||||
for (const server of GetAllServers()) {
|
||||
const impactedScripts = new Map<ScriptFilePath, number[]>();
|
||||
@@ -68,24 +86,25 @@ function detectImpactAndMigrate(brokenFunctions: APIBreakInfo["brokenAPIs"]): Im
|
||||
returnMap.set(server.hostname, impactedScripts);
|
||||
}
|
||||
}
|
||||
return returnMap.size ? returnMap : null;
|
||||
return returnMap;
|
||||
}
|
||||
|
||||
/** Show the player a dialog for their API breaks, and save an info file for the player to review later */
|
||||
export function showAPIBreaks(version: string, ...breakInfos: APIBreakInfo[]) {
|
||||
export function showAPIBreaks(version: string, { additionalText, apiBreakingChanges }: VersionBreakingChange) {
|
||||
const details: {
|
||||
text: string;
|
||||
showPopUp: boolean;
|
||||
}[] = [];
|
||||
let numberOfPopUps = 0;
|
||||
for (const breakInfo of breakInfos) {
|
||||
for (const breakInfo of apiBreakingChanges) {
|
||||
const impactMap = detectImpactAndMigrate(breakInfo.brokenAPIs);
|
||||
if (!impactMap) {
|
||||
// Skip processing if we don't find any affected code and the breaking change does not enable the "doNotSkip" flag.
|
||||
if (impactMap.size === 0 && !breakInfo.doNotSkip) {
|
||||
continue;
|
||||
}
|
||||
details.push({
|
||||
text:
|
||||
breakInfo.info +
|
||||
let detailText = breakInfo.info;
|
||||
if (impactMap.size > 0) {
|
||||
detailText +=
|
||||
`\n\nUsage of the following functions may have been affected:\n${breakInfo.brokenAPIs
|
||||
.map((func) => func.name)
|
||||
.join("\n")}\n\n` +
|
||||
@@ -102,7 +121,10 @@ export function showAPIBreaks(version: string, ...breakInfos: APIBreakInfo[]) {
|
||||
)
|
||||
.join("\n"),
|
||||
)
|
||||
.join("\n\n"),
|
||||
.join("\n\n");
|
||||
}
|
||||
details.push({
|
||||
text: detailText,
|
||||
showPopUp: breakInfo.showPopUp,
|
||||
});
|
||||
if (breakInfo.showPopUp) {
|
||||
@@ -125,7 +147,8 @@ export function showAPIBreaks(version: string, ...breakInfos: APIBreakInfo[]) {
|
||||
dialogBoxCreate(
|
||||
`SOME OF YOUR SCRIPTS HAVE POTENTIALLY BEEN IMPACTED BY AN API BREAK, DUE TO CHANGES IN VERSION ${version}\n\n` +
|
||||
"The following dialog boxes will provide details of the potential impact to your scripts.\n" +
|
||||
`A file with these details has also been saved on your home computer under filename ${textFileName}.`,
|
||||
`A file with these details has also been saved on your home computer under filename ${textFileName}.` +
|
||||
(additionalText ? `\n\n${additionalText}` : ""),
|
||||
);
|
||||
let popUpIndex = 0;
|
||||
for (const detail of details) {
|
||||
|
||||
@@ -30,7 +30,7 @@ import { exportMaterial } from "../Corporation/Actions";
|
||||
import { getGoSave, loadGo } from "../Go/SaveLoad";
|
||||
import { showAPIBreaks } from "./APIBreaks/APIBreak";
|
||||
import { breakInfos261 } from "./APIBreaks/2.6.1";
|
||||
import { breakInfos300 } from "./APIBreaks/3.0.0";
|
||||
import { breakingChanges300 } from "./APIBreaks/3.0.0";
|
||||
|
||||
/** Function for performing a series of defined replacements. See 0.58.0 for usage */
|
||||
function convert(code: string, changes: [RegExp, string][]): string {
|
||||
@@ -527,7 +527,7 @@ Error: ${e}`,
|
||||
loadGo(JSON.stringify(freshSaveData));
|
||||
}
|
||||
if (ver < 39) {
|
||||
showAPIBreaks("2.6.1", ...breakInfos261);
|
||||
showAPIBreaks("2.6.1", breakInfos261);
|
||||
}
|
||||
if (ver < 42) {
|
||||
// All whitespace except for spaces was allowed in filenames
|
||||
@@ -547,6 +547,6 @@ Error: ${e}`,
|
||||
if (found) Terminal.error("Filenames with whitespace found and corrected, see console for details.");
|
||||
}
|
||||
if (ver < 44) {
|
||||
showAPIBreaks("3.0.0", ...breakInfos300);
|
||||
showAPIBreaks("3.0.0", breakingChanges300);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user