make the image a length 1 unit 8 array when the tourney image is removed

This commit is contained in:
Luna 2025-05-24 02:36:36 +02:00
parent f220d135ff
commit 1b14a45826
2 changed files with 55 additions and 115 deletions

View file

@ -113,29 +113,18 @@
{ id: GameplayModifiers_GameOptions.StrictAngles, name: "Strict Angles", description: "Stricter angle enforcement for cuts", enabled: false, group: "Environment" }
];
// Group modifiers that can't be active at the same time
const incompatibleModifiers = [
[GameplayModifiers_GameOptions.SlowSong, GameplayModifiers_GameOptions.FastSong, GameplayModifiers_GameOptions.SuperFastSong],
[GameplayModifiers_GameOptions.InstaFail, GameplayModifiers_GameOptions.BatteryEnergy],
[GameplayModifiers_GameOptions.BatteryEnergy, GameplayModifiers_GameOptions.ZenMode],
[GameplayModifiers_GameOptions.SmallCubes, GameplayModifiers_GameOptions.ProMode],
];
// Custom tournament assistant features
let limitAttemptsEnabled = false;
if(map?.taData.gameplayParameters?.attempts !== 0) {
if (map?.taData.gameplayParameters?.attempts !== 0) {
limitAttemptsEnabled = true;
}
let numberOfAttempts = map?.taData.gameplayParameters?.attempts; // Default value
let numberOfAttempts = map?.taData.gameplayParameters?.attempts || 1;
// Initialise modifiers from map data
// map.gameplayParameters?.gameplayModifiers?.options is a decimal number generated by protobuf
if (map && map.taData.gameplayParameters?.gameplayModifiers?.options) {
// Initialize modifiers from map data
if (map?.taData.gameplayParameters?.gameplayModifiers?.options) {
const modifierValue = map.taData.gameplayParameters.gameplayModifiers.options;
// Check each modifier to see if its bit is set in the options value
for (const modifier of gameModifiers) {
// Bitwise AND to check if this modifier is enabled
modifier.enabled = (modifierValue & modifier.id) === modifier.id;
}
}
@ -154,48 +143,43 @@
return groups;
}
function handleModifierChange(modifier: Modifier) {
// Create a new copy of modifiers to work with
const updatedModifiers = [...gameModifiers];
// Find the modifier in the array and toggle its enabled state
const modifierIndex = updatedModifiers.findIndex(m => m.id === modifier.id);
if (modifierIndex >= 0) {
updatedModifiers[modifierIndex] = {
...updatedModifiers[modifierIndex],
enabled: modifier.enabled
};
}
// if the modifier was just turned on
if(modifier.enabled) {
// check if incompatibilities exist
if(modifier.incompatibilites) {
// fetch all of the incompatible modifiers
let allIncompatableModifiers: Modifier[] = updatedModifiers.filter(x => modifier.incompatibilites?.includes(x.id));
// loop through all of the incompatable modifiers and set their enabled and disabled states
allIncompatableModifiers.map(async(modifier) => {
modifier.enabled = false;
modifier.disabled = true;
});
}
}
// if the modifier was just turned off
else {
if(modifier.incompatibilites) {
let allIncompatableModifiers: Modifier[] = updatedModifiers.filter(x => modifier.incompatibilites?.includes(x.id));
allIncompatableModifiers.map(async(modifier) => {
function updateIncompatibilityStates() {
// Reset all disabled states first
gameModifiers.forEach(modifier => {
modifier.disabled = false;
});
// Check each enabled modifier for incompatibilities
gameModifiers
.filter(modifier => modifier.enabled && modifier.incompatibilites)
.forEach(enabledModifier => {
enabledModifier.incompatibilites!.forEach(incompatibleId => {
const incompatibleModifier = gameModifiers.find(m => m.id === incompatibleId);
if (incompatibleModifier) {
// Forcefully disable incompatible modifier
incompatibleModifier.enabled = false;
// Lock it so it can't be enabled
incompatibleModifier.disabled = true;
}
});
});
}
// Update the state with the new array
gameModifiers = updatedModifiers;
function handleModifierChange(changedModifier: Modifier) {
// Find and update the specific modifier
const modifierIndex = gameModifiers.findIndex(m => m.id === changedModifier.id);
if (modifierIndex >= 0) {
gameModifiers[modifierIndex] = { ...changedModifier };
}
// Update incompatibility states for all modifiers
updateIncompatibilityStates();
// Trigger reactivity
gameModifiers = [...gameModifiers];
}
function getActiveModifiersAsBitmap(): number {
// Combine all enabled modifiers using bitwise OR
return gameModifiers
.filter(modifier => modifier.enabled)
.reduce((bitmap, modifier) => bitmap | modifier.id, 0);
@ -208,9 +192,7 @@
}
}
// Handle characteristic selection change
function handleCharacteristicChange() {
// Reset difficulty when characteristic changes
selectedDifficulty = availableDifficulties[selectedCharacteristic]?.[0] || "";
}
@ -219,10 +201,7 @@
mapLoadError = null;
try {
// Try to determine if the input is a hash or a key
const isHash = /^[0-9a-fA-F]{40}$/.test(key);
// Construct the appropriate API endpoint
const endpoint = isHash
? `https://api.beatsaver.com/maps/hash/${key}`
: `https://api.beatsaver.com/maps/id/${key}`;
@ -234,8 +213,6 @@
}
const data: BeatSaverMap = await response.json();
// Use the latest version
const latestVersion = data.versions[0];
// Map basic details
@ -250,7 +227,6 @@
new Set(latestVersion.diffs.map(diff => diff.characteristic))
);
// Group difficulties by characteristic
availableDifficulties = {};
for (const diff of latestVersion.diffs) {
if (!availableDifficulties[diff.characteristic]) {
@ -259,11 +235,9 @@
availableDifficulties[diff.characteristic].push(diff.difficulty);
}
// Set initial selections
selectedCharacteristic = availableCharacteristics[0] || "";
selectedDifficulty = availableDifficulties[selectedCharacteristic]?.[0] || "";
// Set Beat Saver ID for the map
mapBeatmapId = `custom_level_${latestVersion.hash.toUpperCase()}`;
return data;
@ -276,6 +250,18 @@
}
}
function getDifficultyNumber(difficulty: string): number {
switch (difficulty) {
case "Easy": return 0;
case "Normal": return 1;
case "Hard": return 2;
case "Expert": return 3;
case "Expert+":
case "ExpertPlus": return 4;
default: return 0;
}
}
async function handleSubmit() {
if (!mapName || !mapBeatmapId) {
error = "Map name and beatmap ID are required";
@ -291,54 +277,26 @@
error = null;
try {
// Connect to the TA server
const connectResult = await client.connect($TAServerUrl, $TAServerPort);
if (connectResult.details.oneofKind === "connect" && connectResult.type === Response_ResponseType.Fail) {
throw new Error(connectResult.details.connect.message);
}
// Join the tournament
const joinResult = await client.joinTournament(tournamentGuid);
if (joinResult.details.oneofKind !== 'join' || joinResult.type === Response_ResponseType.Fail) {
throw new Error('Could not join tournament');
}
// Get modifiers as a bitmap
const modifiersBitmap = getActiveModifiersAsBitmap();
// Add custom data for "Limit Attempts" if enabled
const customData: any = {};
if (limitAttemptsEnabled) {
customData.limitAttempts = {
enabled: true,
count: numberOfAttempts
};
}
let mapDifficulty: number = 0;
if(selectedDifficulty == "Easy") {
mapDifficulty = 0;
} else if(selectedDifficulty == "Normal") {
mapDifficulty = 1;
} else if(selectedDifficulty == "Hard") {
mapDifficulty = 2;
} else if(selectedDifficulty == "Expert") {
mapDifficulty = 3;
} else if(selectedDifficulty == "Expert+") {
mapDifficulty = 4;
} else if(selectedDifficulty == "ExpertPlus") {
mapDifficulty = 4;
}
// Create a new map object or update existing one
const mapData: Map = {
guid: map?.taData.guid || uuidv4(),
gameplayParameters: {
beatmap: {
name: mapName,
levelId: mapBeatmapId,
difficulty: mapDifficulty,
difficulty: getDifficultyNumber(selectedDifficulty),
characteristic: {
serializedName: selectedCharacteristic,
difficulties: []
@ -347,7 +305,7 @@
gameplayModifiers: {
options: modifiersBitmap
},
attempts: numberOfAttempts || 0,
attempts: limitAttemptsEnabled ? numberOfAttempts : 0,
disableCustomNotesOnStream: false,
disableFail: false,
disablePause: false,
@ -360,13 +318,11 @@
let response;
if (map) {
// Update existing map
response = await client.updateTournamentPoolMap(tournamentGuid, poolGuid, mapData);
if (response.type === Response_ResponseType.Success) {
dispatch('mapUpdated');
}
} else {
// Add new map
response = await client.addTournamentPoolMaps(tournamentGuid, poolGuid, [mapData]);
if (response.type === Response_ResponseType.Success) {
dispatch('mapAdded');
@ -391,39 +347,23 @@
dispatch('close');
}
// Initialise from existing map data if available
onMount(() => {
// Initialise disabled states based on incompatible groups
for (const incompatibleGroup of incompatibleModifiers) {
// Find any enabled modifier in this group
const enabledModifier = gameModifiers.find(m =>
incompatibleGroup.includes(m.id) && m.enabled
);
// Initialize incompatibility states based on existing enabled modifiers
updateIncompatibilityStates();
// If there's an enabled modifier, disable others in the same group
if (enabledModifier) {
for (const modifierToUpdate of gameModifiers) {
if (incompatibleGroup.includes(modifierToUpdate.id) &&
modifierToUpdate.id !== enabledModifier.id) {
modifierToUpdate.disabled = true;
}
}
}
}
if (map && map.taData.gameplayParameters?.beatmap?.levelId) {
// Extract hash from levelId (format: custom_level_HASH)
if (map?.taData.gameplayParameters?.beatmap?.levelId) {
const levelIdParts = map.taData.gameplayParameters.beatmap.levelId.split('_');
if (levelIdParts.length === 3) {
beatSaverKey = levelIdParts[2];
fetchMapFromBeatSaver(beatSaverKey);
// For existing maps, try to set the characteristic and difficulty
if (map.taData.gameplayParameters?.beatmap?.characteristic) {
selectedCharacteristic = map.taData.gameplayParameters.beatmap.characteristic.serializedName;
}
if (map.taData.gameplayParameters?.beatmap?.difficulty) {
selectedDifficulty = MapDifficulty[map.taData.gameplayParameters.beatmap.characteristic?.difficulties[0]!];
if (map.taData.gameplayParameters?.beatmap?.difficulty !== undefined) {
const difficultyNames = ["Easy", "Normal", "Hard", "Expert", "Expert+"];
selectedDifficulty = difficultyNames[map.taData.gameplayParameters.beatmap.difficulty] || "Easy";
}
}
}

View file

@ -151,6 +151,6 @@ export async function linkToUint8Array(link: string): Promise<Uint8Array> {
throw new Error(`Failed to fetch image: ${error instanceof Error ? error.message : String(error)}`);
}
} else {
throw new Error('Unsupported link format. Must be a data URL or HTTP/HTTPS URL');
return new Uint8Array(1);
}
}