Ga naar hoofdinhoud

Admin Reducers

Reducers voor administratieve functies.

Admin Systeem

is_admin Helper

fn is_admin(ctx: &ReducerContext) -> bool {
ctx.db.admin_user().identity().find(ctx.sender).is_some()
}

add_admin

Voeg admin rechten toe (alleen bestaande admins).

#[reducer]
pub fn add_admin(
ctx: &ReducerContext,
target_identity: Identity,
permissions: String,
) -> Result<(), String>

Permissions:

PermissionBeschrijving
fullAlle rechten
items_onlyAlleen items beheren
read_onlyAlleen data bekijken

Item Beheer

create_item_definition

Maak nieuw item type aan.

#[reducer]
pub fn create_item_definition(
ctx: &ReducerContext,
item_id: String,
category: String,
display_name: String,
description: String,
icon_path: String,
max_stack: u32,
is_tradeable: bool,
rarity: u8,
) -> Result<(), String>

Permission: Admin

Client (Admin Panel):

// Next.js admin panel
async function createItem(item: ItemDefinition) {
const result = await spacetimeClient.callReducer('create_item_definition', [
item.itemId,
item.category,
item.displayName,
item.description,
item.iconPath,
item.maxStack,
item.isTradeable,
item.rarity
]);

if (result.status === 'failed') {
throw new Error(result.message);
}
}

update_item_definition

Wijzig bestaand item.

#[reducer]
pub fn update_item_definition(
ctx: &ReducerContext,
item_id: String,
display_name: Option<String>,
description: Option<String>,
icon_path: Option<String>,
max_stack: Option<u32>,
is_tradeable: Option<bool>,
rarity: Option<u8>,
) -> Result<(), String>

Note: item_id en category kunnen niet wijzigen.

delete_item_definition

Verwijder item type.

#[reducer]
pub fn delete_item_definition(
ctx: &ReducerContext,
item_id: String,
) -> Result<(), String>

Warning: Verwijdert NIET bestaande items in inventories.

Container Types

create_container_type

Maak nieuw container type.

#[reducer]
pub fn create_container_type(
ctx: &ReducerContext,
type_id: String,
display_name: String,
slot_count: u8,
icon_path: String,
) -> Result<(), String>

Voorbeeld containers:

// Starter bag
create_container_type(ctx, "starter_bag", "Starter Rugzak", 8, "containers/starter.png")?;

// Upgraded bags
create_container_type(ctx, "leather_backpack", "Leren Rugzak", 12, "containers/leather.png")?;
create_container_type(ctx, "adventure_pack", "Avonturen Rugzak", 16, "containers/adventure.png")?;

Speler Beheer

give_item_to_player

Geef items aan speler.

#[reducer]
pub fn give_item_to_player(
ctx: &ReducerContext,
player_username: String,
item_id: String,
quantity: u32,
) -> Result<(), String>

Permission: Admin

give_resource_to_player

Geef resources aan speler.

#[reducer]
pub fn give_resource_to_player(
ctx: &ReducerContext,
player_username: String,
resource_type: String,
amount: u64,
) -> Result<(), String>

ban_player

Ban een speler.

#[reducer]
pub fn ban_player(
ctx: &ReducerContext,
player_identity: Identity,
reason: String,
duration_hours: u32, // 0 = permanent
) -> Result<(), String>

Side effects:

  • Disconnect de speler
  • Voeg toe aan ban list
  • Log de actie

unban_player

Verwijder ban.

#[reducer]
pub fn unban_player(
ctx: &ReducerContext,
player_identity: Identity,
) -> Result<(), String>

Quest Beheer

create_quest_definition

Maak nieuwe quest.

#[reducer]
pub fn create_quest_definition(
ctx: &ReducerContext,
quest_id: String,
title: String,
description: String,
category: String,
difficulty: u8,
min_level: u8,
prerequisites: String, // JSON
objectives: String, // JSON
rewards: String, // JSON
time_limit_minutes: u32,
repeatable: bool,
cooldown_minutes: u32,
giver_npc: Option<String>,
) -> Result<(), String>

toggle_quest_active

Activeer/deactiveer quest.

#[reducer]
pub fn toggle_quest_active(
ctx: &ReducerContext,
quest_id: String,
is_active: bool,
) -> Result<(), String>

Asset Tickets

create_asset_ticket

Maak asset request ticket.

#[reducer]
pub fn create_asset_ticket(
ctx: &ReducerContext,
category_id: String,
title: String,
description: String,
reference_urls: String,
style_notes: String,
priority: u8,
game_path: String,
) -> Result<(), String>

assign_ticket

Wijs ticket toe aan designer.

#[reducer]
pub fn assign_ticket(
ctx: &ReducerContext,
ticket_id: u64,
designer_email: String,
) -> Result<(), String>

update_ticket_status

Update ticket status.

#[reducer]
pub fn update_ticket_status(
ctx: &ReducerContext,
ticket_id: u64,
new_status: String,
comment: Option<String>,
) -> Result<(), String>

Status transitions:

open → in_progress → review → approved
→ revision → in_progress

Server Maintenance

broadcast_message

Stuur bericht naar alle online spelers.

#[reducer]
pub fn broadcast_message(
ctx: &ReducerContext,
message: String,
message_type: String, // "info", "warning", "maintenance"
) -> Result<(), String>

schedule_maintenance

Plan onderhoud window.

#[reducer]
pub fn schedule_maintenance(
ctx: &ReducerContext,
start_time: Timestamp,
duration_minutes: u32,
message: String,
) -> Result<(), String>

Logging

Alle admin acties worden gelogd:

#[table(name = admin_log)]
pub struct AdminLog {
#[primary_key]
#[auto_inc]
pub id: u64,
pub admin: Identity,
pub action: String,
pub target: String,
pub details: String,
pub performed_at: Timestamp,
}
fn log_admin_action(ctx: &ReducerContext, action: &str, target: &str, details: &str) {
ctx.db.admin_log().insert(AdminLog {
id: 0,
admin: ctx.sender,
action: action.to_string(),
target: target.to_string(),
details: details.to_string(),
performed_at: ctx.timestamp,
});
}

Admin Panel Integratie

Het admin panel (Next.js) gebruikt deze reducers:

// pages/api/admin/items.ts
export async function POST(req: Request) {
const session = await getServerSession();
if (!session?.user?.isAdmin) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}

const item = await req.json();
const result = await spacetimeAdmin.createItem(item);

return Response.json(result);
}

Volgende