mirror of
https://github.com/SikongJueluo/kubejs-utils.git
synced 2025-12-09 03:17:48 +08:00
fix(c4): C4 item could not use
This commit is contained in:
@@ -1,16 +1,46 @@
|
|||||||
const KeyMapping = Java.loadClass("net.minecraft.client.KeyMapping");
|
const KeyMapping = Java.loadClass("net.minecraft.client.KeyMapping");
|
||||||
|
|
||||||
const C4_EXPLOSION_TIME = 3 * 20;
|
const C4_EXPLOSION_TIME = 3 * 20; // 3 seconds in ticks
|
||||||
const C4_EXPLOSION_RANGE = 256;
|
const C4_EXPLOSION_POWER = 4; // Explosion power (TNT is 4)
|
||||||
|
|
||||||
|
// Tolerance for floating point comparison
|
||||||
|
const ANGLE_TOLERANCE = 0.001;
|
||||||
|
const POS_TOLERANCE = 0.01;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {{ [key: string]:{
|
* @type {{ [key: string]:{
|
||||||
* angle: {x: number, y:number, z:number},
|
* angle: {x: number, y:number, z:number},
|
||||||
* pos: {x: number, y: number, z: number}
|
* pos: {x: number, y: number, z: number},
|
||||||
|
* blockPos: {x: number, y: number, z: number}
|
||||||
* } | undefined}}
|
* } | undefined}}
|
||||||
*/
|
*/
|
||||||
const lastPlayerInfoMap = {};
|
const lastPlayerInfoMap = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to compare floating point numbers with tolerance
|
||||||
|
* @param {number} a
|
||||||
|
* @param {number} b
|
||||||
|
* @param {number} tolerance
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isApproximatelyEqual(a, b, tolerance) {
|
||||||
|
return Math.abs(a - b) <= tolerance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the block position under the player
|
||||||
|
* @param {Internal.Player} player
|
||||||
|
* @returns {{x: number, y: number, z: number}}
|
||||||
|
*/
|
||||||
|
function getBlockUnderPlayer(player) {
|
||||||
|
const playerPos = player.position();
|
||||||
|
return {
|
||||||
|
x: Math.floor(playerPos.x()),
|
||||||
|
y: Math.floor(playerPos.y()) - 1,
|
||||||
|
z: Math.floor(playerPos.z()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Internal.ItemStack} itemstack
|
* @param {Internal.ItemStack} itemstack
|
||||||
* @param {Internal.Level} level
|
* @param {Internal.Level} level
|
||||||
@@ -18,23 +48,60 @@ const lastPlayerInfoMap = {};
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function shouldActivateC4(itemstack, level, player) {
|
function shouldActivateC4(itemstack, level, player) {
|
||||||
const playerPos = player.position();
|
const blockUnder = getBlockUnderPlayer(player);
|
||||||
const block = level.getBlock(
|
const block = level.getBlock(blockUnder.x, blockUnder.y, blockUnder.z);
|
||||||
playerPos.x() - 1, // Must subtract 1, is it a Bug ???
|
|
||||||
playerPos.y() - 1, // The block under the player
|
|
||||||
playerPos.z(),
|
|
||||||
);
|
|
||||||
|
|
||||||
const lookAngle = player.lookAngle;
|
const lookAngle = player.lookAngle;
|
||||||
|
const playerPos = player.position();
|
||||||
const lastPlayerInfo = lastPlayerInfoMap[player.uuid.toString()];
|
const lastPlayerInfo = lastPlayerInfoMap[player.uuid.toString()];
|
||||||
|
|
||||||
if (lastPlayerInfo === undefined) return false;
|
if (lastPlayerInfo === undefined) return false;
|
||||||
|
|
||||||
|
// Check if player moved (using block position for stability)
|
||||||
|
const currentBlockPos = getBlockUnderPlayer(player);
|
||||||
|
const isBlockPosChanged =
|
||||||
|
currentBlockPos.x !== lastPlayerInfo.blockPos.x ||
|
||||||
|
currentBlockPos.y !== lastPlayerInfo.blockPos.y ||
|
||||||
|
currentBlockPos.z !== lastPlayerInfo.blockPos.z;
|
||||||
|
|
||||||
|
// Check if player moved within the same block (with tolerance)
|
||||||
|
const isPosChanged =
|
||||||
|
!isApproximatelyEqual(
|
||||||
|
playerPos.x(),
|
||||||
|
lastPlayerInfo.pos.x,
|
||||||
|
POS_TOLERANCE,
|
||||||
|
) ||
|
||||||
|
!isApproximatelyEqual(
|
||||||
|
playerPos.y(),
|
||||||
|
lastPlayerInfo.pos.y,
|
||||||
|
POS_TOLERANCE,
|
||||||
|
) ||
|
||||||
|
!isApproximatelyEqual(
|
||||||
|
playerPos.z(),
|
||||||
|
lastPlayerInfo.pos.z,
|
||||||
|
POS_TOLERANCE,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if player rotated view (with tolerance)
|
||||||
|
const isAngleChanged =
|
||||||
|
!isApproximatelyEqual(
|
||||||
|
lookAngle.x(),
|
||||||
|
lastPlayerInfo.angle.x,
|
||||||
|
ANGLE_TOLERANCE,
|
||||||
|
) ||
|
||||||
|
!isApproximatelyEqual(
|
||||||
|
lookAngle.y(),
|
||||||
|
lastPlayerInfo.angle.y,
|
||||||
|
ANGLE_TOLERANCE,
|
||||||
|
) ||
|
||||||
|
!isApproximatelyEqual(
|
||||||
|
lookAngle.z(),
|
||||||
|
lastPlayerInfo.angle.z,
|
||||||
|
ANGLE_TOLERANCE,
|
||||||
|
);
|
||||||
|
|
||||||
const isPlayerInfoChanged =
|
const isPlayerInfoChanged =
|
||||||
lookAngle.x() !== lastPlayerInfo.angle.x ||
|
isBlockPosChanged || isPosChanged || isAngleChanged;
|
||||||
lookAngle.y() !== lastPlayerInfo.angle.y ||
|
|
||||||
lookAngle.z() !== lastPlayerInfo.angle.z ||
|
|
||||||
playerPos.x() !== lastPlayerInfo.pos.x ||
|
|
||||||
playerPos.y() !== lastPlayerInfo.pos.y ||
|
|
||||||
playerPos.z() !== lastPlayerInfo.pos.z;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
/** @type {string} */ (block.id) === "kubejs:c4_target" &&
|
/** @type {string} */ (block.id) === "kubejs:c4_target" &&
|
||||||
@@ -65,7 +132,6 @@ StartupEvents.registry("block", (event) => {
|
|||||||
.displayName(/** @type {any} */ ("C4")); // Set a custom name
|
.displayName(/** @type {any} */ ("C4")); // Set a custom name
|
||||||
});
|
});
|
||||||
|
|
||||||
let c4PlacedGameTime = 0;
|
|
||||||
StartupEvents.registry("item", (event) => {
|
StartupEvents.registry("item", (event) => {
|
||||||
event
|
event
|
||||||
.create("c4_item")
|
.create("c4_item")
|
||||||
@@ -73,18 +139,18 @@ StartupEvents.registry("item", (event) => {
|
|||||||
.useAnimation("eat")
|
.useAnimation("eat")
|
||||||
.useDuration((_itemStack) => 100) // 5 Seconds
|
.useDuration((_itemStack) => 100) // 5 Seconds
|
||||||
.use((level, player, _hand) => {
|
.use((level, player, _hand) => {
|
||||||
const playerPos = player.position();
|
const blockUnder = getBlockUnderPlayer(player);
|
||||||
const block = level.getBlock(
|
const block = level.getBlock(
|
||||||
playerPos.x() - 1, // Must subtract 1, is it a Bug ???
|
blockUnder.x,
|
||||||
playerPos.y() - 1, // The block under the player
|
blockUnder.y,
|
||||||
playerPos.z(),
|
blockUnder.z,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (/** @type {string} */ (block.id) !== "kubejs:c4_target") {
|
if (/** @type {string} */ (block.id) !== "kubejs:c4_target") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const itemstack = player.getUseItem();
|
const playerPos = player.position();
|
||||||
const lookAngle = player.lookAngle;
|
const lookAngle = player.lookAngle;
|
||||||
lastPlayerInfoMap[player.uuid.toString()] = {
|
lastPlayerInfoMap[player.uuid.toString()] = {
|
||||||
angle: {
|
angle: {
|
||||||
@@ -97,30 +163,44 @@ StartupEvents.registry("item", (event) => {
|
|||||||
y: playerPos.y(),
|
y: playerPos.y(),
|
||||||
z: playerPos.z(),
|
z: playerPos.z(),
|
||||||
},
|
},
|
||||||
|
blockPos: blockUnder,
|
||||||
};
|
};
|
||||||
|
|
||||||
// console.log(`Map count: ${lastPlayerInfoMap.size}`);
|
|
||||||
console.log(`Player UUID: ${player.uuid}`);
|
console.log(`Player UUID: ${player.uuid}`);
|
||||||
console.log(
|
console.log(
|
||||||
`Player Info: ${lastPlayerInfoMap[player.uuid.toString()]}`,
|
`Player Info: ${JSON.stringify(lastPlayerInfoMap[player.uuid.toString()])}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const server = Utils.server;
|
const server = Utils.server;
|
||||||
server.scheduleInTicks(5, (event) => {
|
server.scheduleInTicks(5, (event) => {
|
||||||
const itemstack = player.getUseItem();
|
const itemstack = player.getUseItem();
|
||||||
|
|
||||||
|
// Check if player is still using the item
|
||||||
|
if (
|
||||||
|
itemstack === undefined ||
|
||||||
|
/** @type {string} */ (itemstack.id) !== "kubejs:c4_item"
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!shouldActivateC4(itemstack, level, player)) {
|
if (!shouldActivateC4(itemstack, level, player)) {
|
||||||
player.stopUsingItem();
|
player.stopUsingItem();
|
||||||
player.addItemCooldown(itemstack.getItem(), 20);
|
player.addItemCooldown(itemstack.getItem(), 20);
|
||||||
itemstack.resetHoverName();
|
itemstack.resetHoverName();
|
||||||
|
delete lastPlayerInfoMap[player.uuid.toString()];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useDuration = itemstack.useDuration;
|
// Get remaining ticks for this use
|
||||||
if (useDuration <= 0) return;
|
const ticksUsingItem = player.getTicksUsingItem();
|
||||||
|
const remainingTicks = 100 - ticksUsingItem; // useDuration is 100
|
||||||
|
|
||||||
|
// if (remainingTicks <= 0) return;
|
||||||
|
|
||||||
itemstack.setHoverName(
|
itemstack.setHoverName(
|
||||||
/** @type {any} */ (
|
/** @type {any} */ (
|
||||||
Component.literal(
|
Component.literal(
|
||||||
`C4 - ${(useDuration / 20.0).toFixed(2)}s`,
|
`C4 - ${(remainingTicks / 20.0).toFixed(2)}s`,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -136,46 +216,78 @@ StartupEvents.registry("item", (event) => {
|
|||||||
return itemstack;
|
return itemstack;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
/** @type {Internal.Player} */
|
||||||
!shouldActivateC4(itemstack, level, /** @type {any} */ (entity))
|
const player = /** @type {any} */ (entity);
|
||||||
) {
|
|
||||||
|
if (!shouldActivateC4(itemstack, level, player)) {
|
||||||
|
itemstack.resetHoverName();
|
||||||
|
delete lastPlayerInfoMap[player.uuid.toString()];
|
||||||
return itemstack; // Do nothing
|
return itemstack; // Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
const playerPos = entity.position();
|
// Place C4 at player's feet
|
||||||
const newBlock = level.getBlock(playerPos);
|
const playerPos = player.position();
|
||||||
|
const c4BlockPos = {
|
||||||
|
x: Math.floor(playerPos.x()),
|
||||||
|
y: Math.floor(playerPos.y()),
|
||||||
|
z: Math.floor(playerPos.z()),
|
||||||
|
};
|
||||||
|
const newBlock = level.getBlock(
|
||||||
|
c4BlockPos.x,
|
||||||
|
c4BlockPos.y,
|
||||||
|
c4BlockPos.z,
|
||||||
|
);
|
||||||
newBlock.set(/** @type {any} */ ("kubejs:c4"));
|
newBlock.set(/** @type {any} */ ("kubejs:c4"));
|
||||||
|
|
||||||
itemstack.shrink(1);
|
itemstack.shrink(1);
|
||||||
itemstack.resetHoverName();
|
itemstack.resetHoverName();
|
||||||
|
delete lastPlayerInfoMap[player.uuid.toString()];
|
||||||
|
|
||||||
const server = level.server;
|
const server = level.server;
|
||||||
c4PlacedGameTime = level.levelData.getGameTime();
|
const c4PlacedGameTime = level.levelData.getGameTime();
|
||||||
|
|
||||||
|
// Store block position for explosion (capture in closure)
|
||||||
|
const explosionX = c4BlockPos.x;
|
||||||
|
const explosionY = c4BlockPos.y;
|
||||||
|
const explosionZ = c4BlockPos.z;
|
||||||
|
|
||||||
server.scheduleInTicks(20, (event) => {
|
server.scheduleInTicks(20, (event) => {
|
||||||
const gameTime = level.levelData.getGameTime();
|
const currentGameTime = level.levelData.getGameTime();
|
||||||
const explosionRestTime =
|
const elapsedTime = currentGameTime - c4PlacedGameTime;
|
||||||
C4_EXPLOSION_RANGE - gameTime - c4PlacedGameTime;
|
const explosionRestTime = C4_EXPLOSION_TIME - elapsedTime;
|
||||||
|
|
||||||
if (explosionRestTime > 0) {
|
if (explosionRestTime > 0) {
|
||||||
server.players.forEach((player) => {
|
server.players.forEach((p) => {
|
||||||
player.tell(
|
p.tell(
|
||||||
/** @type {any} */ (
|
/** @type {any} */ (
|
||||||
Component.literal(
|
Component.literal(
|
||||||
`C4还剩 ${Math.floor(explosionRestTime / 20)} 秒爆炸`,
|
`C4还剩 ${Math.ceil(explosionRestTime / 20)} 秒爆炸`,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
event.reschedule(20);
|
event.reschedule();
|
||||||
} else {
|
} else {
|
||||||
const blockPos = newBlock.pos;
|
// Check if C4 block is still there before exploding
|
||||||
level.explode(
|
const c4Block = level.getBlock(
|
||||||
/** @type {any} */ (null),
|
explosionX,
|
||||||
blockPos.x,
|
explosionY,
|
||||||
blockPos.y,
|
explosionZ,
|
||||||
blockPos.z,
|
|
||||||
C4_EXPLOSION_RANGE,
|
|
||||||
"block",
|
|
||||||
);
|
);
|
||||||
|
if (/** @type {string} */ (c4Block.id) === "kubejs:c4") {
|
||||||
|
// Remove the C4 block first
|
||||||
|
c4Block.set(/** @type {any} */ ("minecraft:air"));
|
||||||
|
|
||||||
|
// Create explosion
|
||||||
|
level.explode(
|
||||||
|
/** @type {any} */ (null),
|
||||||
|
explosionX + 0.5,
|
||||||
|
explosionY + 0.5,
|
||||||
|
explosionZ + 0.5,
|
||||||
|
C4_EXPLOSION_POWER,
|
||||||
|
"block",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user