Merge pull request 'Check for duplicate Spawns and Scripts' (#20) from check-duplicates into master
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #20
This commit is contained in:
commit
cb9300d1ef
85
common.js
85
common.js
@ -200,26 +200,87 @@ async function validateMapAsset(assetId, game) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapParts = root.FindDescendantsOfClass("BasePart", (part) => part.Name === "MapStart" || part.Name === "MapFinish");
|
const mapStarts = root.FindDescendantsOfClass("BasePart", (part) => part.Name === "MapStart");
|
||||||
if (mapParts.length !== 2 || mapParts[0].Name === mapParts[1].Name) {
|
if (mapStarts.length !== 1) {
|
||||||
errors.push("Your map must have exactly one part named `MapStart` and one part named `MapFinish`.");
|
errors.push("Your map must have exactly one part named `MapStart`.");
|
||||||
}
|
|
||||||
else if (mapParts[0].CanCollide || mapParts[1].CanCollide) {
|
|
||||||
errors.push("The `MapStart` and `MapFinish` parts in your map must have the `CanCollide` property disabled.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const spawnOnes = root.FindDescendantsOfClass("BasePart", (part) => part.Name === "Spawn1");
|
const mapFinishes = root.FindDescendantsOfClass("BasePart", (part) => part.Name === "MapFinish");
|
||||||
if (spawnOnes.length !== 1) {
|
if (mapFinishes.length < 1) {
|
||||||
errors.push("Your map must have exactly one part named `Spawn1`.");
|
errors.push("Your map must have at least one part named `MapFinish`.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapParts = Array.from(mapStarts);
|
||||||
|
mapParts.push(...mapFinishes);
|
||||||
|
for (const part of mapParts) {
|
||||||
|
if (!part.CanCollide) {
|
||||||
|
errors.push("The `MapStart` and `MapFinish` parts in your map must have the `CanCollide` property disabled.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const allSpawns = root.FindDescendantsOfClass("BasePart", (part) => part.Name.startsWith("Spawn") && !isNaN(part.Name.slice(5)));
|
||||||
|
const spawnNameSet = new Set();
|
||||||
|
const duplicateSpawns = new Set();
|
||||||
|
for (const spawn of allSpawns) {
|
||||||
|
const name = spawn.Name;
|
||||||
|
if (spawnNameSet.has(name)) {
|
||||||
|
duplicateSpawns.add(name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
spawnNameSet.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!spawnNameSet.has("Spawn1")) {
|
||||||
|
errors.push("Your map must have a part named `Spawn1`.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const numDups = duplicateSpawns.size;
|
||||||
|
if (numDups > 0) {
|
||||||
|
const sortedSpawns = Array.from(duplicateSpawns);
|
||||||
|
sortedSpawns.sort();
|
||||||
|
const firstFive = sortedSpawns.slice(0, 5).map((name) => `\`${name}\``);
|
||||||
|
if (numDups > 1 && numDups <= 5) {
|
||||||
|
firstFive[firstFive.length - 1] = "and " + firstFive[firstFive.length - 1];
|
||||||
|
}
|
||||||
|
let msg = numDups === 1 ? "Your map has a duplicate `Spawn` part: " : "Your map has duplicate `Spawn` parts: ";
|
||||||
|
msg += firstFive.join(", ");
|
||||||
|
if (numDups > 5) {
|
||||||
|
msg += `, and ${numDups - 5} more`;
|
||||||
|
}
|
||||||
|
msg += ". There can only be one instance of each `Spawn` part.";
|
||||||
|
errors.push(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Why does ModuleScript not inherit from Script, and/or why does BaseScript not have a Source property?
|
// Why does ModuleScript not inherit from Script, and/or why does BaseScript not have a Source property?
|
||||||
const illegalScript = root.FindFirstDescendantOfClass("Script", (script) => sourceHasIllegalKeywords(script.Source));
|
const scripts = root.FindDescendantsOfClass("Script");
|
||||||
const illegalModuleScript = root.FindFirstDescendantOfClass("ModuleScript", (script) => sourceHasIllegalKeywords(script.Source));
|
scripts.push(...root.FindDescendantsOfClass("ModuleScript"));
|
||||||
if (illegalScript || illegalModuleScript) {
|
|
||||||
|
const sourceSet = new Set();
|
||||||
|
let numDuplicateScripts = 0;
|
||||||
|
let hasIllegalKeywords = false;
|
||||||
|
for (const script of scripts) {
|
||||||
|
const source = script.Source;
|
||||||
|
if (!hasIllegalKeywords && sourceHasIllegalKeywords(source)) {
|
||||||
|
hasIllegalKeywords = true;
|
||||||
|
}
|
||||||
|
if (sourceSet.has(source)) {
|
||||||
|
++numDuplicateScripts;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sourceSet.add(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasIllegalKeywords) {
|
||||||
errors.push("Your map has a `Script` that contains the keyword `getfenv` or `require`. You must remove these.");
|
errors.push("Your map has a `Script` that contains the keyword `getfenv` or `require`. You must remove these.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (numDuplicateScripts > 50) {
|
||||||
|
errors.push("Your map has over 50 duplicate `Script`s. You must consolidate your scripts to less than 50 duplicates.");
|
||||||
|
}
|
||||||
|
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
return {
|
return {
|
||||||
valid: false,
|
valid: false,
|
||||||
|
Loading…
Reference in New Issue
Block a user