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
|
* C4 Server Scripts
|
||||||
* Handles C4 block break event to cancel explosion
|
* Handles C4 block break event to cancel explosion
|
||||||
|
* Handles C4 use started and activated events
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// ==================== Block Break Event Handler ====================
|
||||||
|
|
||||||
BlockEvents.broken((event) => {
|
BlockEvents.broken((event) => {
|
||||||
const { block, server } = 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",
|
"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_TIME = 10 * 20; // 7 seconds in ticks
|
||||||
const C4_EXPLOSION_POWER = 128; // Explosion power (TNT is 4)
|
const C4_EXPLOSION_POWER = 128; // Explosion power (TNT is 4)
|
||||||
const C4_USE_TIME = 5 * 20; // 5 seconds in ticks
|
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
|
// Tolerance for floating point comparison
|
||||||
const ANGLE_TOLERANCE = 0.001;
|
const ANGLE_TOLERANCE = 0.001;
|
||||||
const POS_TOLERANCE = 0.01;
|
const POS_TOLERANCE = 0.01;
|
||||||
@@ -28,6 +29,9 @@ let operationKeyMapping;
|
|||||||
*/
|
*/
|
||||||
const lastPlayerInfoMap = {};
|
const lastPlayerInfoMap = {};
|
||||||
|
|
||||||
|
// Export for server scripts
|
||||||
|
global["lastPlayerInfoMap"] = lastPlayerInfoMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {{[key:string]: boolean}}
|
* @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.Player} player
|
||||||
* @param {Internal.Level} level
|
* @param {Internal.Level} level
|
||||||
@@ -150,6 +157,9 @@ function shouldStartUseC4(player, level) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Export for server scripts
|
||||||
|
global["shouldStartUseC4"] = shouldStartUseC4;
|
||||||
|
|
||||||
// ==================== Block Registration ====================
|
// ==================== Block Registration ====================
|
||||||
|
|
||||||
StartupEvents.registry("block", (event) => {
|
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