aiohttp
免费Use when building Python async HTTP services or clients with aiohttp - web server routing, middleware, WebSocket, SSE, streaming, client sessions, pytest-aiohttp testing, or troubleshooting SSL and timeout issues
中文简介正在准备中。当前显示原文说明。
Use when developing OpenRCT2 plugins in TypeScript - plugin registration and game actions, window and widget UI, event hooks, park, map, ride and entity access, network API, storage, or ES5 runtime constraints
中文简介正在准备中。当前显示原文说明。
查看安装方法安装前可以查看交给 AI 代理的指令内容。
Develop plugins (scripts) for OpenRCT2 using JavaScript/TypeScript to extend the game with custom windows, game actions, event hooks, and multiplayer features.
OpenRCT2 plugins run in Duktape (ES5 runtime). Key capabilities:
Place .js files in the plugin directory:
C:\Users\YourName\Documents\OpenRCT2\plugin\/Users/YourName/Library/Application Support/OpenRCT2/plugin/$XDG_CONFIG_HOME/OpenRCT2/plugin/ or $HOME/.config/OpenRCT2/plugin/Access via game: Red toolbox button → Open custom content folder
function main() {
console.log("Your plugin has started!");
// Your plugin code here
}
registerPlugin({
name: 'Your Plugin',
version: '1.0',
authors: ['Your Name'],
type: 'remote',
licence: 'MIT',
targetApiVersion: 34,
minApiVersion: 10,
main: main
});
// Install TypeScript and types
// npm install typescript --save-dev
// Copy openrct2.d.ts to your project
/// <reference path="openrct2.d.ts" />
function main() {
console.log("TypeScript plugin loaded!");
}
registerPlugin({
name: 'My TypeScript Plugin',
version: '1.0',
authors: ['Developer'],
type: 'local',
licence: 'MIT',
targetApiVersion: 34,
main: main
});
{
"compilerOptions": {
"target": "ES5",
"module": "none",
"outFile": "./dist/plugin.js",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
Load on any client with plugin installed. Cannot alter game state directly.
registerPlugin({
name: 'Local Info Plugin',
version: '1.0',
type: 'local', // Available to all players in multiplayer
main: function() {
// Can only use game actions, not direct mutations
// Good for: info windows, tools, dashboards
}
});
Load only on server, distributed to clients. Can mutate game state in execute context.
registerPlugin({
name: 'Remote Game Plugin',
version: '1.0',
type: 'remote', // Server-side, synced to clients
main: function() {
// Can mutate game state in custom game action execute()
}
});
Stay loaded across park changes and in title screen.
registerPlugin({
name: 'Global Plugin',
version: '1.0',
type: 'intransient', // Never unloaded
main: function() {
// Active in title screen and across parks
// Use context.sharedStorage for persistence
}
});
Game actions are the recommended way to mutate game state, ensuring multiplayer synchronization.
var action = {
type: 'smallsceneryplace',
args: {
object: 0, // Scenery object ID
x: 32 * 10, // X coordinate in map units
y: 32 * 10, // Y coordinate in map units
z: 0, // Z height
direction: 0, // Rotation (0-3)
quadrant: 0, // Quadrant for quarter tile scenery
primaryColour: 0, // Primary color
secondaryColour: 0 // Secondary color
}
};
context.executeAction(action, function(result) {
if (result.error) {
console.log("Failed to place scenery: " + result.error);
} else {
console.log("Scenery placed successfully");
}
});
// Set park cash
context.executeAction({
type: 'parksetcash',
args: { cash: 100000 }
}, callback);
// Set guest count
context.executeAction({
type: 'parksetguestgenerationrate',
args: { generationRate: 100 }
}, callback);
// Change land height
context.executeAction({
type: 'landsetheight',
args: { x: 32 * 10, y: 32 * 10, height: 10 }
}, callback);
// Build ride
context.executeAction({
type: 'trackplace',
args: { ride: 0, trackType: 1, x: 32 * 10, y: 32 * 10, z: 0, direction: 0 }
}, callback);
context.registerAction({
id: 'myplugin.award_cash',
query: function(args) {
// Validation - return error object if invalid
if (args.amount < 0) {
return { error: 'Amount must be positive' };
}
if (args.amount > 100000) {
return { error: 'Amount too large' };
}
return {}; // Success
},
execute: function(args) {
// Actual game state mutation - only runs on server
park.cash += args.amount;
return {}; // Success
}
});
// Use custom action
context.executeAction({
type: 'myplugin.award_cash',
args: { amount: 5000 }
}, function(result) {
console.log(result.error || "Cash awarded!");
});
context.registerAction({
id: 'myplugin.admin_action',
query: function(args) {
// Check player permissions
if (network.mode !== 'none') {
var player = network.getPlayer(args.playerId);
if (!player || !player.hasPermission('modify_park')) {
return { error: 'No permission' };
}
}
return {};
},
execute: function(args) {
// Perform action
}
});
function main() {
if (typeof ui !== 'undefined') {
ui.registerMenuItem('My Window', openWindow);
}
context.subscribe('interval.day', onDay);
}
// Good: Use game action
context.executeAction({
type: 'parksetcash',
args: { cash: 100000 }
}, callback);
// Bad: Direct mutation in local plugin
// park.cash = 100000; // Will fail in multiplayer!
Use namespaced keys to avoid conflicts. See references/network-storage.md for full storage API details.
context.executeAction(action, function(result) {
if (result.error) {
console.log('Action failed: ' + result.error);
return;
}
// Success handling
});
var intervals = [];
function main() {
intervals.push(context.setInterval(update, 1000));
}
context.subscribe('map.changed', function() {
intervals.forEach(clearInterval);
intervals = [];
});
OpenRCT2 uses Duktape (ES5). ES6+ features require transpilation.
// Arrow functions - NO
var func = () => {};
// Classes - NO
class MyClass {}
// let/const - NO
let x = 1;
// Template literals - NO
`Hello ${name}`
// Spread operator - NO
[...arr]
// Destructuring - NO
var { x } = obj;
// find/includes - NO
arr.find(x => x > 0);
arr.includes(5);
// Function expressions - YES
var func = function() {};
// Constructor functions - YES
function MyClass() {}
// var - YES
var x = 1;
// String concatenation - YES
'Hello ' + name
// Array methods - YES
arr.filter(function(x) { return x > 0; })[0];
arr.indexOf(5) !== -1;
.jsregisterPlugin({
name: 'My Plugin',
version: '1.2.3', // Semantic versioning
minApiVersion: 34, // Minimum OpenRCT2 API version
targetApiVersion: 34, // Target API for behavior
});
Load these reference files on demand for detailed API information:
references/ui.mdreferences/hooks-map.mdreferences/network-storage.md还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
Use when building Python async HTTP services or clients with aiohttp - web server routing, middleware, WebSocket, SSE, streaming, client sessions, pytest-aiohttp testing, or troubleshooting SSL and timeout issues
中文简介正在准备中。当前显示原文说明。
Use when doing structural code search and rewriting - ast-grep linting, refactoring, multi-language patterns
中文简介正在准备中。当前显示原文说明。
Use when building GBA games with the BPCore Lua engine - entity, sprite and tilemap functions, SRAM save and load, link cable multiplayer protocol, camera and scrolling, or optimization patterns
中文简介正在准备中。当前显示原文说明。
Use when running background tasks with Celery - worker and broker configuration (Redis, RabbitMQ), task routing by name vs queue, chains/groups/chords, retry patterns (autoretry_for, retry_backoff), acks_late semantics, failure detection, and monitoring with Flower
中文简介正在准备中。当前显示原文说明。
Use when building Django applications - security hardening, authentication and permissions, ORM optimization, PostgreSQL features, Django 6.0, migrations, testing, and ecosystem libraries
中文简介正在准备中。当前显示原文说明。
Use when customizing Django Admin - save_formset, get_search_results, formsets, queryset optimization, db_index, custom URLs
中文简介正在准备中。当前显示原文说明。