(()=>{ const itemTexture = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADySURBVFhH7ZQxDoMwDEVNr4G6VmJC6mk4Itdh7VpxjsBPDaKVCLZxypInIccg5zs/CVQoKAj8uHLjeETouo6HvlQcU3yJ932PIKkTceRAFH8NA6dE3IzbVogdQBOPtuVXfk5IJ8jWhKY4SxPaQvcmLEWuTUj/A1sqiEEcTQBENDWjvh3mvZtxccLiwMqvE0DrhNUBCCy1KSdAUsPiwFYcpM5ENrYWh3tdI4cT4dk0MSKPXzMSRSC+PMi14mcO4e7esv2iJqyHEGDVPCR6jyMC5luERXOfuoY7QFi8MKsDe6tXk8OBv7Ge/E96DZeKFwoOEE1wUX7TFh5zsgAAAABJRU5ErkJggg=="; ModAPI.meta.title("guns"); ModAPI.meta.version("v1.0"); ModAPI.meta.icon(itemTexture); ModAPI.meta.description("Requires AsyncSink."); ModAPI.require("player"); function PistolItem() { var recoilSpeed = 0; //recoil controller var DamageSourceClass = ModAPI.reflect.getClassByName("DamageSource"); var creativeMiscTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabMisc; var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item"); var itemSuper = ModAPI.reflect.getSuper(itemClass, (x) => x.length === 1); var nmi_ItemPistol = function nmi_ItemPistol() { itemSuper(this); //Use super function to get block properties on this class. this.$setCreativeTab(creativeMiscTab); } ModAPI.addEventListener("update", ()=>{ //recoil update loop (client) ModAPI.player.rotationPitch -= recoilSpeed; recoilSpeed *= 0.7; }); function entityRayCast(player, world, range) { const HEADSHOT_MAX_DISTANCE_FROM_HEAD = 0.72; var eyePosition = player.getPositionEyes(0.0); var targetPosition = player.rayTrace(range, 0).hitVec; var entities = world.getEntitiesWithinAABBExcludingEntity( player.getRef(), player.getEntityBoundingBox().expand(range, range, range).getRef() ).getCorrective().array; var closestEntity = null; var isHeadshot = false; var closestDistance = range; // Iterate through all entities to find the one the player is looking at for (var i = 0; i < entities.length; i++) { if (!entities[i]) { continue; } var entity = entities[i]; // Check if the entity's bounding box intersects with the player's ray var entityBB = entity.getEntityBoundingBox().expand(0.3, 0.3, 0.3); var intercept = entityBB.calculateIntercept(eyePosition.getRef(), targetPosition.getRef()); if (intercept != null) { var distance = eyePosition.distanceTo(intercept.hitVec.getRef()); if (distance < closestDistance) { closestDistance = distance; closestEntity = entity; isHeadshot = entity.getPositionEyes(0.0).distanceTo(intercept.hitVec.getRef()) < HEADSHOT_MAX_DISTANCE_FROM_HEAD; } } } var rayTraceResult = closestEntity; if (rayTraceResult != null){ return {entity: rayTraceResult, headshot: isHeadshot}; } else{ return null; } } ModAPI.reflect.prototypeStack(itemClass, nmi_ItemPistol); nmi_ItemPistol.prototype.$onItemRightClick = function ($itemstack, $world, $player) { var cactus = DamageSourceClass.staticVariables.cactus; var world = ModAPI.util.wrap($world); var entityplayer = ModAPI.util.wrap($player); var shotentitydata = entityRayCast(entityplayer, world, 16.0); if (shotentitydata != null){ if (world.isRemote) { recoilSpeed += 4; } else { shotentitydata.entity.attackEntityFrom(cactus, 10 + (16 * shotentitydata.headshot)); if (shotentitydata.headshot) { console.log("H E A D S H O T"); } world.playSoundAtEntity(entityplayer.getRef(), ModAPI.util.str("tile.piston.out"), 1.0, 1.8); } } else if (!world.isRemote) { world.playSoundAtEntity(entityplayer.getRef(), ModAPI.util.str("random.click"), 1.0, 1.8); } return $itemstack; } async function addGunRecipe(gunItem) { var ObjectClass = ModAPI.reflect.getClassById("java.lang.Object").class; function ToChar(char) { return ModAPI.reflect.getClassById("java.lang.Character").staticMethods.valueOf.method(char[0].charCodeAt(0)); } // Define the recipe legend to map characters to items var recipeLegend = { "I": { type: "item", id: "iron_ingot" // Using dirt blocks }, "C": { type: "block", id: "iron_block" // Using dirt blocks }, "Q": { type: "item", id: "gunpowder" // Using dirt blocks }, }; // Define the crafting grid pattern for the recipe var recipePattern = [ "IIC", " QI" ]; // Convert the recipe pattern and legend into the required format var recipeInternal = []; Object.keys(recipeLegend).forEach((key) => { recipeInternal.push(ToChar(key)); var ingredient = (recipeLegend[key].type === "block" ? ModAPI.blocks : ModAPI.items)[recipeLegend[key].id].getRef(); recipeInternal.push(ingredient); }); var recipeContents = recipePattern.flatMap(row => ModAPI.util.str(row)); var recipe = ModAPI.util.makeArray(ObjectClass, recipeContents.concat(recipeInternal)); var resultItem = ModAPI.reflect.getClassById("net.minecraft.item.ItemStack").constructors[4](gunItem, 1); // Register the recipe with CraftingManager var craftingManager = ModAPI.reflect.getClassById("net.minecraft.item.crafting.CraftingManager").staticMethods.getInstance.method(); ModAPI.hooks.methods.nmic_CraftingManager_addRecipe(craftingManager, resultItem, recipe); } function internal_reg() { var pistol_item = (new nmi_ItemPistol()).$setUnlocalizedName( ModAPI.util.str("pistol") ).$setMaxStackSize(1); itemClass.staticMethods.registerItem.method(ModAPI.keygen.item("pistol"), ModAPI.util.str("pistol"), pistol_item); ModAPI.items["pistol"] = pistol_item; addGunRecipe(pistol_item); return pistol_item; } if (ModAPI.items) { return internal_reg(); } else { ModAPI.addEventListener("bootstrap", internal_reg); } } ModAPI.dedicatedServer.appendCode(PistolItem); var pistol_item = PistolItem(); ModAPI.addEventListener("lib:asyncsink", async () => { ModAPI.addEventListener("lib:asyncsink:registeritems", (renderItem)=>{ renderItem.registerItem(pistol_item, ModAPI.util.str("pistol")); }); AsyncSink.L10N.set("item.pistol.name", "Pistol"); AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/item/pistol.json", JSON.stringify( { "parent": "builtin/generated", "textures": { "layer0": "items/pistol" }, "display": { "thirdperson": { "rotation": [ 5, 80, -45 ], "translation": [ 0, 1, -3 ], "scale": [ 1.0, 1.0, 1.0 ] }, "firstperson": { "rotation": [ 0, -135, 25 ], "translation": [ 0, 4, 2 ], "scale": [ 1.8, 1.8, 1.8 ] } } } )); AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/textures/items/pistol.png", await (await fetch( itemTexture )).arrayBuffer()); }); })();