mirror of
https://github.com/SikongJueluo/kubejs-utils.git
synced 2026-01-29 08:17:49 +08:00
refactor(c4): restructure C4 scripts and move server side code
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
/**
|
||||
* C4 Server Scripts
|
||||
* Handles C4 block break event to cancel explosion
|
||||
* Handles C4 use started and activated events
|
||||
*/
|
||||
|
||||
// ==================== Block Break Event Handler ====================
|
||||
|
||||
BlockEvents.broken((event) => {
|
||||
const { block, server } = event;
|
||||
|
||||
@@ -43,3 +46,189 @@ BlockEvents.broken((event) => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ==================== C4 Event Handlers ====================
|
||||
|
||||
/**
|
||||
* @param {{player: Internal.Player}} event
|
||||
*/
|
||||
function handleC4UseStarted(event) {
|
||||
const server = Utils.getServer();
|
||||
if (server === null) {
|
||||
console.error("C4 Handler: Server is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get shared variables from global
|
||||
/** @type {typeof shouldActivateC4} */
|
||||
const shouldActivateC4 = /** @type {any} */ (global["shouldActivateC4"]);
|
||||
/** @type {typeof shouldStartUseC4} */
|
||||
const shouldStartUseC4 = /** @type {any} */ (global["shouldStartUseC4"]);
|
||||
/** @type {{ [key: string]: any }} */
|
||||
const lastPlayerInfoMap = /** @type {any} */ (global["lastPlayerInfoMap"]);
|
||||
/** @type {number} */
|
||||
const C4_USE_TIME = /** @type {any} */ (global["C4_USE_TIME"]);
|
||||
|
||||
if (
|
||||
shouldActivateC4 === undefined ||
|
||||
shouldStartUseC4 === undefined ||
|
||||
lastPlayerInfoMap === undefined ||
|
||||
C4_USE_TIME === undefined
|
||||
) {
|
||||
console.error("C4 Handler: Required global variables not available");
|
||||
return;
|
||||
}
|
||||
|
||||
const player = server.getPlayerList().getPlayer(event.player.uuid);
|
||||
const level = player.level;
|
||||
|
||||
const startTime = level.levelData.gameTime;
|
||||
const originalItemstack = player.mainHandItem;
|
||||
|
||||
server.scheduleRepeatingInTicks(2, (event) => {
|
||||
const itemstack = player.getMainHandItem();
|
||||
|
||||
if (
|
||||
!shouldActivateC4(
|
||||
itemstack,
|
||||
player.level,
|
||||
/** @type {any} */ (player),
|
||||
)
|
||||
) {
|
||||
player.stopUsingItem();
|
||||
player.addItemCooldown(originalItemstack.item, 20);
|
||||
originalItemstack.releaseUsing(
|
||||
level,
|
||||
/** @type {any} */ (player),
|
||||
originalItemstack.count,
|
||||
);
|
||||
event.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get remaining ticks for this use
|
||||
const remainingTicks =
|
||||
C4_USE_TIME - (level.levelData.gameTime - startTime);
|
||||
|
||||
if (remainingTicks <= 0) {
|
||||
originalItemstack.finishUsingItem(
|
||||
level,
|
||||
/** @type {any} */ (player),
|
||||
);
|
||||
delete lastPlayerInfoMap[player.uuid.toString()];
|
||||
event.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
itemstack.setHoverName(
|
||||
/** @type {any} */ (
|
||||
Component.literal(`C4 - ${(remainingTicks / 20.0).toFixed(1)}s`)
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle C4 activation event
|
||||
* @param {C4ActivatedEvent} event
|
||||
*/
|
||||
function handleC4Activated(event) {
|
||||
const server = Utils.getServer();
|
||||
if (server === null) {
|
||||
console.error("C4 Handler: Server is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
const { level, player, explosionTime, explosionPower } = event;
|
||||
|
||||
// Get shared variables from global
|
||||
/** @type {{[key:string]: boolean | null}} */
|
||||
const toExplosionC4Map = /** @type {any} */ (global["toExplosionC4Map"]);
|
||||
|
||||
if (toExplosionC4Map === undefined || toExplosionC4Map === null) {
|
||||
console.error("C4 Handler: toExplosionC4Map is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
// Place C4 at player's feet
|
||||
const c4BlockPos = {
|
||||
x: Math.floor(player.x),
|
||||
y: Math.floor(player.y),
|
||||
z: Math.floor(player.z),
|
||||
};
|
||||
const newBlock = level.getBlock(c4BlockPos.x, c4BlockPos.y, c4BlockPos.z);
|
||||
newBlock.set(/** @type {any} */ ("kubejs:c4"));
|
||||
|
||||
// Add record
|
||||
const newBlockPosString = newBlock.pos.toShortString();
|
||||
toExplosionC4Map[newBlockPosString] = true;
|
||||
|
||||
/**
|
||||
* TODO: It should use reschedule to replace several schedules
|
||||
* But reschedule not work at current time.
|
||||
* Relative Issue: https://github.com/KubeJS-Mods/KubeJS/issues/763
|
||||
*/
|
||||
let remainingSeconds = explosionTime / 20;
|
||||
server.scheduleRepeatingInTicks(20, (scheduledEvent) => {
|
||||
// Assert C4 exsiting
|
||||
if (toExplosionC4Map[newBlockPosString] === null) {
|
||||
scheduledEvent.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
remainingSeconds -= 1;
|
||||
if (remainingSeconds <= 0) {
|
||||
scheduledEvent.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
server.players.forEach((p) => {
|
||||
p.tell(
|
||||
/** @type {any} */ (
|
||||
Component.literal(`C4还剩 ${remainingSeconds} 秒爆炸`)
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Create explosion after countdown
|
||||
server.scheduleInTicks(explosionTime, (_) => {
|
||||
// Assert C4 exsiting
|
||||
if (toExplosionC4Map[newBlockPosString] === null) return;
|
||||
|
||||
level.explode(
|
||||
/** @type {any} */ (null),
|
||||
c4BlockPos.x + 0.5,
|
||||
c4BlockPos.y + 0.5,
|
||||
c4BlockPos.z + 0.5,
|
||||
explosionPower,
|
||||
"block",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== Server Initialization ====================
|
||||
|
||||
ServerEvents.loaded((event) => {
|
||||
/**
|
||||
* WARNING: Must Do!!!
|
||||
* Because Kubejs scheduler is not stable
|
||||
* And need to fire once at first time
|
||||
* Relative Issue: https://github.com/KubeJS-Mods/KubeJS/issues/763
|
||||
*/
|
||||
event.server.scheduleInTicks(1, (_) => {
|
||||
console.log("Init Scheduler");
|
||||
});
|
||||
|
||||
/** @type {EventBus} */
|
||||
const eventBus = /** @type {any} */ (global["eventBus"]);
|
||||
|
||||
if (eventBus === null) {
|
||||
console.error("C4 Handler: eventBus is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
eventBus.register("C4Activated", handleC4Activated);
|
||||
eventBus.register("C4UseStarted", handleC4UseStarted);
|
||||
console.log("C4 Handler: Registered C4Activated event handler");
|
||||
});
|
||||
|
||||
@@ -2,14 +2,15 @@ const $TickEvent$PlayerTickEvent = Java.loadClass(
|
||||
"net.minecraftforge.event.TickEvent$PlayerTickEvent",
|
||||
);
|
||||
|
||||
const $ServerStartedEvent = Java.loadClass(
|
||||
"net.minecraftforge.event.server.ServerStartedEvent",
|
||||
);
|
||||
|
||||
const C4_EXPLOSION_TIME = 10 * 20; // 7 seconds in ticks
|
||||
const C4_EXPLOSION_POWER = 128; // Explosion power (TNT is 4)
|
||||
const C4_USE_TIME = 5 * 20; // 5 seconds in ticks
|
||||
|
||||
// Export constants for server scripts
|
||||
global["C4_EXPLOSION_TIME"] = C4_EXPLOSION_TIME;
|
||||
global["C4_EXPLOSION_POWER"] = C4_EXPLOSION_POWER;
|
||||
global["C4_USE_TIME"] = C4_USE_TIME;
|
||||
|
||||
// Tolerance for floating point comparison
|
||||
const ANGLE_TOLERANCE = 0.001;
|
||||
const POS_TOLERANCE = 0.01;
|
||||
@@ -28,6 +29,9 @@ let operationKeyMapping;
|
||||
*/
|
||||
const lastPlayerInfoMap = {};
|
||||
|
||||
// Export for server scripts
|
||||
global["lastPlayerInfoMap"] = lastPlayerInfoMap;
|
||||
|
||||
/**
|
||||
* @type {{[key:string]: boolean}}
|
||||
*/
|
||||
@@ -114,6 +118,9 @@ function shouldActivateC4(itemstack, level, player) {
|
||||
);
|
||||
}
|
||||
|
||||
// Export for server scripts
|
||||
global["shouldActivateC4"] = shouldActivateC4;
|
||||
|
||||
/**
|
||||
* @param {Internal.Player} player
|
||||
* @param {Internal.Level} level
|
||||
@@ -150,6 +157,9 @@ function shouldStartUseC4(player, level) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Export for server scripts
|
||||
global["shouldStartUseC4"] = shouldStartUseC4;
|
||||
|
||||
// ==================== Block Registration ====================
|
||||
|
||||
StartupEvents.registry("block", (event) => {
|
||||
@@ -280,158 +290,3 @@ ForgeEvents.onEvent($TickEvent$PlayerTickEvent, (event) => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ==================== Server Side Logic ====================
|
||||
|
||||
/**
|
||||
* @param {{player: Internal.Player}} event
|
||||
*/
|
||||
function handleC4UseStarted(event) {
|
||||
const server = Utils.getServer();
|
||||
if (server === null) {
|
||||
console.error("C4 Handler: Server is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
const player = server.getPlayerList().getPlayer(event.player.uuid);
|
||||
const level = player.level;
|
||||
|
||||
const startTime = level.levelData.gameTime;
|
||||
const originalItemstack = player.mainHandItem;
|
||||
|
||||
server.scheduleRepeatingInTicks(2, (event) => {
|
||||
const itemstack = player.getMainHandItem();
|
||||
|
||||
if (
|
||||
!shouldActivateC4(
|
||||
itemstack,
|
||||
player.level,
|
||||
/** @type {any} */ (player),
|
||||
)
|
||||
) {
|
||||
player.stopUsingItem();
|
||||
player.addItemCooldown(originalItemstack.item, 20);
|
||||
originalItemstack.releaseUsing(
|
||||
level,
|
||||
/** @type {any} */ (player),
|
||||
originalItemstack.count,
|
||||
);
|
||||
event.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get remaining ticks for this use
|
||||
const remainingTicks =
|
||||
C4_USE_TIME - (level.levelData.gameTime - startTime);
|
||||
|
||||
if (remainingTicks <= 0) {
|
||||
originalItemstack.finishUsingItem(
|
||||
level,
|
||||
/** @type {any} */ (player),
|
||||
);
|
||||
delete lastPlayerInfoMap[player.uuid.toString()];
|
||||
event.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
itemstack.setHoverName(
|
||||
/** @type {any} */ (
|
||||
Component.literal(`C4 - ${(remainingTicks / 20.0).toFixed(1)}s`)
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle C4 activation event
|
||||
* @param {C4ActivatedEvent} event
|
||||
*/
|
||||
function handleC4Activated(event) {
|
||||
const server = Utils.getServer();
|
||||
if (server === null) {
|
||||
console.error("C4 Handler: Server is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
const { level, player, explosionTime, explosionPower } = event;
|
||||
|
||||
// Place C4 at player's feet
|
||||
const c4BlockPos = {
|
||||
x: Math.floor(player.x),
|
||||
y: Math.floor(player.y),
|
||||
z: Math.floor(player.z),
|
||||
};
|
||||
const newBlock = level.getBlock(c4BlockPos.x, c4BlockPos.y, c4BlockPos.z);
|
||||
newBlock.set(/** @type {any} */ ("kubejs:c4"));
|
||||
|
||||
// Add record
|
||||
const newBlockPosString = newBlock.pos.toShortString();
|
||||
toExplosionC4Map[newBlockPosString] = true;
|
||||
|
||||
/**
|
||||
* TODO: It should use reschedule to replace several schedules
|
||||
* But reschedule not work at current time.
|
||||
* Relative Issue: https://github.com/KubeJS-Mods/KubeJS/issues/763
|
||||
*/
|
||||
let remainingSeconds = explosionTime / 20;
|
||||
server.scheduleRepeatingInTicks(20, (scheduledEvent) => {
|
||||
// Assert C4 exsiting
|
||||
if (toExplosionC4Map[newBlockPosString] === null) {
|
||||
scheduledEvent.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
remainingSeconds -= 1;
|
||||
if (remainingSeconds <= 0) {
|
||||
scheduledEvent.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
server.players.forEach((p) => {
|
||||
p.tell(
|
||||
/** @type {any} */ (
|
||||
Component.literal(`C4还剩 ${remainingSeconds} 秒爆炸`)
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Create explosion after countdown
|
||||
server.scheduleInTicks(explosionTime, (_) => {
|
||||
// Assert C4 exsiting
|
||||
if (toExplosionC4Map[newBlockPosString] === null) return;
|
||||
|
||||
level.explode(
|
||||
/** @type {any} */ (null),
|
||||
c4BlockPos.x + 0.5,
|
||||
c4BlockPos.y + 0.5,
|
||||
c4BlockPos.z + 0.5,
|
||||
explosionPower,
|
||||
"block",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
ForgeEvents.onEvent($ServerStartedEvent, (event) => {
|
||||
/**
|
||||
* WARNING: Must Do!!!
|
||||
* Because Kubejs scheduler is not stable
|
||||
* And need to fire once at first time
|
||||
* Relative Issue: https://github.com/KubeJS-Mods/KubeJS/issues/763
|
||||
*/
|
||||
event.server.scheduleInTicks(1, (_) => {
|
||||
console.log("Init Scheduler");
|
||||
});
|
||||
|
||||
/** @type {EventBus} */
|
||||
const eventBus = /** @type {any} */ (global["eventBus"]);
|
||||
|
||||
if (eventBus === null) {
|
||||
console.error("C4 Handler: eventBus is not available");
|
||||
return event;
|
||||
}
|
||||
|
||||
eventBus.register("C4Activated", handleC4Activated);
|
||||
eventBus.register("C4UseStarted", handleC4UseStarted);
|
||||
console.log("C4 Handler: Registered C4Activated event handler");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user