Creating game addons and textures – minecraft

{
    "format_version": 1,
    "header": {
        "description": "Описание вашего аддона"
        "name": "Название вашего аддона",
        "uuid": "вставьте сюда уникальный id",
        "version": [ 1, 0, 5 ],
        "min_engine_version": [ 1, 17, 10 ]
    },
    "modules": [
        {
            "description": "",
            "type": "data",
            "uuid": "вставьте сюда второй уникальный id",
            "version": [1, 0, 0]
        }
    ]
}

If anything, uuid is a unique id that is used to save the addon. A unique ID can be generated, for example, on the site uuidgener*tor.net, I don’t want to leave the exact link, so I put “*” instead of “a”. To create an icon for our addon, create a pack_icon.jpg or pack_icon.png file in the addon folder. Now we save our files, go into minecraft and check – now in the world creation tab in the “settings” there is an empty addon, which is still useless.

Function – this is the name of the addon function, which can execute several commands at the same time. For example, if you enter the command /function myfunction into the chat, you will be given both an apple and a tree. So you can even create normal anti-cheats on function, but this requires knowledge of minecraft bedrock commands. To make functions in an addon, create a functions folder in the addon folder. In it create myfunction.mcfunction, your function will be called myfunction. Edit the code.

#выдать всём яблоко
give @a apple

#выдать всем дерево
give @a log

#создать скорборд
scoreboard objectives add my score dummy

The function may not appear when you type /function ****. Now, if you type /function myfunction, all players in the world will be given an apple and a tree, and a new scoreboard will also be created. In order for the function to work every tick continuously, without entering it into a chat or command block, we will create a tick.json file in the function folder. It will be responsible for automatically executing functions every tick. Let’s enter a small json code

{
  "values": [
    "myfunction"
  ]
}

now myfunction will be executed every tick. If anything, one second is 20 ticks.

Moving on, chat. You probably wanted to optimize the chat for a long time, make ranks, anti-spam. It’s all in one addon – anti-spam, ranks in the chat, and so on. First, we’ll have to modify manifest.json to include the javascript content.

{

  "format_version": 2,

  "header": {

    "name": "Название аддона",

    "description": "Описание аддона",

    "uuid": "Уникальный id",

    "version": [ 1, 0, 3 ],

    "min_engine_version": [ 1, 14, 0 ]

  },

  "modules": [

    {

      "description": "made by habr @DinoZavr2",

      "type": "data",

      "uuid": "Второй уникальный id",

      "version": [ 1, 0, 0 ]

    },

    {

      "description": "",

      "language": "javascript",

      "type": "script",

      "uuid": "Третий уникальный id",

      "version": [0, 0, 1],

      "entry": "scripts/main/index.js"

    }

  ],

  "dependencies": [

    {

      "uuid": "Четвёртый уникальный id",

      "version": [ 0, 1, 0 ]

    },

    {

      "uuid": "Пятый уникальный id",
      
      "version": [ 0, 1, 0 ]

    }

  ]

}

You can remove spaces if you like. You may have noticed that 5 unique IDs are used here. This may be strange for some. We also specified the path to the index. You probably already understand the structure.

Let’s create a scripts folder in the addon folder, scripts are stored in it (also obvious). Let’s create a main folder in the scripts folder. It contains the index.js file, the javascript language. This is our index. Enter this code there

import { chatrank } from './misc/chat.js'
import { world } from 'mojang-minecraft'
import { timer } from './misc/second.js'
let tick = 0, worldLoaded = false, loadTime = 0;

world.events.beforeChat.subscribe((data) => {
    chatrank(data)
})
world.events.tick.subscribe((ticks) => {
    tick++
    if (!world.getDimension("overworld").runCommand('testfor @a').error && !worldLoaded) {
        loadTime = tick
        worldLoaded = true;
        world.getDimension("overworld").runCommand(`execute @r ~~~ say §l§aМир был загружен в ${ticks} тиках. Добро пожаловать! `)
        world.getDimension("overworld").runCommand(`scoreboard objectives add chatsSent dummy`)
    }
    if(tick >= 20){
        tick = 0
        timer()
    }
})

I think you understand that this is a display of how many ticks the world was loading. Well, basic knowledge of js is enough not to explain here. Next, in the main folder, create the misc folder, and in it the chat.js file, this will be responsible for spam and ranks.

import { world } from "mojang-minecraft"

let messages = new Map()

function chatrank(data){
    const tags = data.sender.getTags()
    data.sender.runCommand(`scoreboard players add @s chatsSent 0`)
    let score = parseInt(data.sender.runCommand(`scoreboard players test @s chatsSent *`).statusMessage.match(/-?\d+/)[0])
    let ranks = [];
    for(const tag of tags){
        if(tag.startsWith('rank:')){
            ranks.push(tag.replace('rank:', ''))
        }
    }
    if(ranks.length == 0)ranks = ["§l§aPlayer"]
    
    if(data.message.startsWith("!*")){
        data.cancel = true
        return
    }
    if(score >= 3){
        data.cancel = true
        return world.getDimension("overworld").runCommand(`ability "${data.sender.nameTag}" mute true`)
    }
    if(!messages.get(data.sender.name)){
        messages.set(data.sender.name, data.message)
    }else {
        const oldMsg = messages.get(data.sender.name)
        if(oldMsg == data.message){
            data.cancel = true
            return world.getDimension("overworld").runCommand(`tellraw "${data.sender.nameTag}" {"rawtext":[{"text":"§l§cНе пишите похожие сообщения"}]}`)
        }
    }
    let text = `§f[${ranks}§r§f] §7${data.sender.nameTag}: §f${data.message}`
    world.getDimension('overworld').runCommand(`tellraw @a {"rawtext":[{"translate":"§l§eM§r - ${JSON.stringify(text)}}]}`)
    messages.set(data.sender.name, data.message)
    data.sender.runCommand(`scoreboard players add @s chatsSent 1`)
    data.cancel = true
}
export { chatrank }

To create a rank for yourself, you need to enter tag @s add rank:YOUR_RANK. For example, rank:§l§cADMIN, this will be red ADMIN, and the default rank is green Player. But for now, ranks and anti-spam will still not work, you need to create another second.js file in misc, everything is clear by name.

import { world } from 'mojang-minecraft'
let seconds = 0

export function timer(){
    seconds++
    if(seconds >= 4){
        world.getDimension("overworld").runCommand(`scoreboard players reset * chatsSent`)
        world.getDimension("overworld").runCommand(`scoreboard players set "dummy" chatsSent 1`)
        seconds = 0
        return seconds
    }
}

This is also a small js code that imports seconds. Now we go into minecraft, create a world with this addon, turn on gametest and education edition in the world settings. Attention: the supported version of ranks and antispam is 1.19.11 and higher. On other, older versions, there is a small bug with the tellraw command.

> there will be ":". Before >> nick, but mine is empty” title=”If anything, I have an empty nickname, instead of >> there will be ":". Before >> nick, but mine is empty” width=”2340″ height=”1080″ data-src=”https://habrastorage.org/getpro/habr/upload_files/260/073/103/26007310354b975331f5e9bd2d2f4f68.jpg” data-blurred=”true”/>
If anything, I have an empty nickname, instead of >> there will be “:”. Before >> nick, but mine is empty

Next – custom commands in the chat. It sounds unusual, but if you enter .mycommand into the chat, for example, the command will be executed. It will be available to all players. Create a commands.js file in the scripts folder

import { world } from "mojang-minecraft";

world.events.beforeChat.subscribe((eventData) => {
    var player_name = eventData.sender.name
    var player = eventData.sender
    var args = eventData.message.split(" ")
    if (args[0].charAt(0) == ".") {
        eventData.cancel = true
        if (args[0] == ".mycommand") {
            player.runCommand("здесь первая команда")
            player.runCommand("здесь другая команда. Копируйте эти строки бесконечно")
        } else {
            player.runCommand("tellraw @s {\"rawtext\":[{\"text\":\"§cНеизвестная команда\"}]}");
        }
    }
});

You can specify many commands in the player.runCommand(“command”) line. Next, you need to create a main.js file

import 'scripts/commands.js'

Just one line importing the script. Let’s edit the commands in the previous code and enter .mycommand into the chat in minecraft, the entered commands will be executed.

How to copyright an addon? Easily. If the addon has not been downloaded, you can create a LICENSE.md or LICENSE.txt file in it, specify everything in them. Here is an example

this addon by @DinoZavr2
AntiSpam and chat rangs

©2022

The license can be very long, everything to your taste.

Textures

We just talked about addons. Now let’s talk about textures. Let’s create a mytextures folder along the path android/data/com.mojang…/files/games/com.mojang/resource_packs, again, the folder name does not affect the name of the resource pack. Let’s create our manifest.json in the resourcepack folder. Here is his code

{
  "format_version": 1,
  "header": {
    "description": "описание вашего текстурпака",
    "name": "название вашего текстурпака",
    "uuid": "уникальный айди текстурпака",
    "version": [
      0,
      0,
      1
    ],
    "min_engine_version": [
      1,
      8,
      0
    ]
  },
  "modules": [
    {
      "description": "",
      "type": "resources",
      "uuid": "второй уникальный айди текстурпака",
      "version": [
        0,
        0,
        1
      ]
    }
  ]
}

Again, as in the addon, a unique ID can be generated on any site, for example, uuidgener*tor.net. Instead of “a” I also put “*” so as not to break anything. To create an icon, create a pack_icon.jpg or pack_icon.png file.

To create block textures, you need to create a textures folder in the texture pack folder. It contains the blocks folder. In blocks we push the diamond_block.jpg (or .png) file. Now in the game the diamond block will look like in diamond_block.jpg.

To create the textures of the items that you have in your hands, you need to create the items folder in textures. Push item.jpg into it, that is, for example, I have stick.jpg, in the game the stick will look different, that is, the way the stick.png image looks like.

Subpacks. Subpacks are packs that use json code that defines something. For example, this is how you can display the player’s hitboxes. Here is the manifest for subpacks

{
   "format_version":2,
   "header":{
      "description":"описание текстурпака",
      "name":"название текстурпака", 
      "uuid":"уникальный id",
      "version":[1,0,0],
      "min_engine_version":[1,14,0]
   },
   "modules":[
      {
         "description":"",
         "type":"resources",
         "uuid":"второй уникальный id",
         "version":[1,0,0]
      }
   ],
   "subpacks":[
      {
         "folder_name":"no_ray",
         "name":"",
         "memory_tier":1
      },
      {
         "folder_name":"opaque_model_collision",
         "name":"",
         "memory_tier":2
      },
      {
         "folder_name":"default",
         "name":"",
         "memory_tier":3
      }
   ]
}

The manifesto shows that it will be very difficult. But still you have to make the display of hitboxes.

Create a subpacks folder in the texturepack folder. There are three more folders in it – default, no_ray, opaque_model_collision. I say right away, if you are not familiar with subpacks and json, check them out, because here you will not understand without basic knowledge about subpacks. Next, in the default folder, create the animations folder, which contains all the animations. It contains hitboxrot.json. Let’s edit the animation code in it

{
	"format_version" : "1.8.0",
	"animations" : {
		"animation.player.hitboxrot" : {
			"loop" : true,
			"bones" : {
				"hitbox" : {
					"rotation" : [ 0.0, "-query.body_y_rotation", 0.0 ]
				}
			}
		},
		"animation.player.rayrot" : {
			"loop" : true,
			"bones" : {
				"ray" : {
					"rotation" : [ "query.is_sneaking ? query.target_x_rotation - 1.5 : query.target_x_rotation", "query.target_y_rotation", 0.0 ],
					"position" : [ 0.0, "query.is_sneaking ? -4.25 : 0.0", 0.0 ]
				}
			}
		},
		"animation.player.axis" : {
			"loop" : true,
			"bones" : {
				"axis" : {
					"rotation" : [ 0.0, "-query.body_y_rotation", 0.0 ]
				}
			}
		}
	}
}

Small code in 30 lines for animations. Now if the player moves, the textures will rotate with him. Next, in subpack/default, we create an entity folder, of course, there are entities on which textures act. In the entity, you need to create the player.entity.json file, this is the player’s entity. Here is the code

{
  "format_version": "1.10.0",
  "minecraft:client_entity": {
    "description": {
      "identifier": "minecraft:player",
      "materials": {
        "default": "entity_alphatest",
        "cape": "entity_alphatest",
        "animated": "player_animated",
        "emissive": "entity_emissive_alpha_hitbox"
      },
      "textures": {
        "default": "textures/entity/steve",
        "cape": "textures/entity/cape_invisible",
        "hitbox": "textures/models/hitboxoverlay",
        "ray": "textures/models/ray"
      },
      "geometry": {
        "default": "geometry.humanoid.custom",
        "cape": "geometry.cape",
        "hitbox": "geometry.hitbox",
        "hitbox.swimming": "geometry.hitbox.swimming",
        "ray": "geometry.ray"
      },
      "scripts": {
        "scale": "0.9375",
        "initialize": [
          "variable.is_holding_right = 0.0;",
          "variable.is_blinking = 0.0;",
          "variable.last_blink_time = 0.0;",
          "variable.hand_bob = 0.0;"
        ],
        "pre_animation": [
          "variable.helmet_layer_visible = 1.0;",
          "variable.leg_layer_visible = 1.0;",
          "variable.boot_layer_visible = 1.0;",
          "variable.chest_layer_visible = 1.0;",
          "variable.attack_body_rot_y = Math.sin(360*Math.sqrt(variable.attack_time)) * 5.0;",
          "variable.tcos0 = (math.cos(query.modified_distance_moved * 38.17) * query.modified_move_speed / variable.gliding_speed_value) * 57.3;",
          "variable.first_person_rotation_factor = math.sin((1 - variable.attack_time) * 180.0);",
          "variable.hand_bob = query.life_time < 0.01 ? 0.0 : variable.hand_bob + ((query.is_on_ground && query.is_alive ? math.clamp(math.sqrt(math.pow(query.position_delta(0), 2.0) + math.pow(query.position_delta(2), 2.0)), 0.0, 0.1) : 0.0) - variable.hand_bob) * 0.02;",

          "variable.map_angle = math.clamp(1 - variable.player_x_rotation / 45.1, 0.0, 1.0);",
          "variable.item_use_normalized = query.main_hand_item_use_duration / query.main_hand_item_max_duration;"
        ],
        "animate": [
          "root",
          "hitbox_rot",
          "ray_rot",
          "axis"
        ]
      },
      "animations": {
      	"hitbox_rot": "animation.player.hitboxrot",
      	"ray_rot": "animation.player.rayrot",
      	"axis": "animation.player.axis",
        "root": "controller.animation.player.root",
        "base_controller": "controller.animation.player.base",
        "hudplayer":  "controller.animation.player.hudplayer",
        "humanoid_base_pose": "animation.humanoid.base_pose",
        "look_at_target": "controller.animation.humanoid.look_at_target",
        "look_at_target_ui": "animation.player.look_at_target.ui",
        "look_at_target_default": "animation.humanoid.look_at_target.default",
        "look_at_target_gliding": "animation.humanoid.look_at_target.gliding",
        "look_at_target_swimming": "animation.humanoid.look_at_target.swimming",
        "look_at_target_inverted": "animation.player.look_at_target.inverted",
        "cape": "animation.player.cape",
        "move.arms": "animation.player.move.arms",
        "move.legs": "animation.player.move.legs",
        "swimming": "animation.player.swim",
        "swimming.legs": "animation.player.swim.legs",
        "riding.arms": "animation.player.riding.arms",
        "riding.legs": "animation.player.riding.legs",
        "holding": "animation.player.holding",
        "brandish_spear": "animation.humanoid.brandish_spear",
        "charging": "animation.humanoid.charging",
        "attack.positions": "animation.player.attack.positions",
        "attack.rotations": "animation.player.attack.rotations",
        "sneaking": "animation.player.sneaking",
        "bob": "animation.player.bob",
        "damage_nearby_mobs": "animation.humanoid.damage_nearby_mobs",
        "bow_and_arrow": "animation.humanoid.bow_and_arrow",
        "fishing_rod": "animation.humanoid.fishing_rod",
        "use_item_progress": "animation.humanoid.use_item_progress",
        "skeleton_attack": "animation.skeleton.attack",
        "sleeping": "animation.player.sleeping",
        "first_person_base_pose": "animation.player.first_person.base_pose",
        "first_person_empty_hand": "animation.player.first_person.empty_hand",
        "first_person_swap_item": "animation.player.first_person.swap_item",
        "first_person_attack_controller": "controller.animation.player.first_person_attack",
        "first_person_attack_rotation": "animation.player.first_person.attack_rotation",
        "first_person_vr_attack_rotation": "animation.player.first_person.vr_attack_rotation",
        "first_person_walk": "animation.player.first_person.walk",
        "first_person_map_controller": "controller.animation.player.first_person_map",
        "first_person_map_hold": "animation.player.first_person.map_hold",
        "first_person_map_hold_attack": "animation.player.first_person.map_hold_attack",
        "first_person_map_hold_off_hand": "animation.player.first_person.map_hold_off_hand",
        "first_person_map_hold_main_hand": "animation.player.first_person.map_hold_main_hand",
        "first_person_crossbow_equipped": "animation.player.first_person.crossbow_equipped",
        "third_person_crossbow_equipped": "animation.player.crossbow_equipped",
        "third_person_bow_equipped": "animation.player.bow_equipped",
        "crossbow_hold": "animation.player.crossbow_hold",
        "crossbow_controller": "controller.animation.player.crossbow",
        "shield_block_main_hand": "animation.player.shield_block_main_hand",
        "shield_block_off_hand": "animation.player.shield_block_off_hand",
        "blink": "controller.animation.persona.blink"
      },
      "render_controllers": [
        { "controller.render.player.first_person": "variable.is_first_person" },
        { "controller.render.player.third_person": "!variable.is_first_person && !variable.map_face_icon" },
        { "controller.render.player.map": "variable.map_face_icon" },
        { "controller.render.player.hitbox": "!variable.is_first_person && !query.is_in_ui" },
        { "controller.render.player.ray": "!variable.is_first_person && !query.is_in_ui" }
      ],
      "enable_attachables": true
    }
  }
}

This is very difficult to understand without at least basic knowledge of json. Mathematical examples, render controllers, as many as 118 lines are used here. rotations and stuff like that. You can create many entities to display hitboxes like wither or wolf. But it’s better not to, otherwise if textures act on many entities, it will lag. Next, we need materials – we create a materials folder in default. It has entity.material (without json), material extension.

{
  "materials": {
    "version": "1.0.0",
	"entity_emissive_alpha_hitbox:entity_nocull": {
      "+defines": [
        "ALPHA_TEST",
        "USE_EMISSIVE"
      ],
      "depthFunc": "Always"
    }
  }
}

I think there is no need to explain anything here. The function will always work. Further it is even more difficult – in default create the models folder, in it entity. And in entity 3 files – the first hitbox.json

{
	"format_version": "1.10.0",
	"geometry.hitbox": {
		"texturewidth": 64,
		"textureheight": 64,
		"visible_bounds_width": 3,
		"visible_bounds_height": 3,
		"visible_bounds_offset": [0, 1.5, 0],
		"bones": [
			{
				"name": "hitbox",
				"pivot": [0, 0, 0],
				"cubes": [
					{ "origin": [-5, 0.2, -5], "size": [10, 30, 10], "uv": [0, 0], "inflate": 0.3 },
					{ "origin": [-4.5, 0.5, -4.5], "size": [9, 9, 9], "uv": [0, 42] }
				]
			}
		]
	}
}

In this file, we specified the size of the hitbox and the hitboxes themselves. The second file is ray.json

{
	"format_version": "1.12.0",
	"minecraft:geometry": [
		{
			"description": {
				"identifier": "geometry.ray",
				"texture_width": 16,
				"texture_height": 16,
				"visible_bounds_width": 2,
				"visible_bounds_height": 2,
				"visible_bounds_offset": [0, 2, 0]
			},
			"bones": [
				{
					"name": "ray",
					"pivot": [0, 27, 0],
					"cubes": [
						{"origin": [-0.5, 26.5, -0.5], "size": [1, 1, -16], "inflate": -0.41, "uv": [0, 0]}
					]
				}
			]
		}
	]
}

Here, too, I think there is no need to explain anything – we created ray. And the third file is hitboxhitbox_swimming.json

{
	"format_version": "1.10.0",
	"geometry.hitbox.swimming": {
		"texturewidth": 64,
		"textureheight": 64,
		"visible_bounds_width": 3,
		"visible_bounds_height": 3,
		"visible_bounds_offset": [0, 1.5, 0],
		"bones": [
			{
				"name": "hitbox",
				"pivot": [0, 0, 0],
				"cubes": [
					{ "origin": [-5, 0.2, -5], "size": [10, 9, 10], "uv": [0, 0], "inflate": 0.3 },
					{ "origin": [-4.5, 0.5, -4.5], "size": [9, 9, 9], "uv": [0, 42] }
				]
			}
		]
	}
}

Here we have specified the display of hitboxes in float mode. It won’t look weird without this file. If this file is not present, when swimming, the player will have a hitbox, as if he were walking while standing.

Now back to the default folder. In it, you need to create a folder render_controllers – it also contains hitbox.json and ray.json. Here is hitbox.json

{
  "format_version": "1.8.0",
  "render_controllers": {
    "controller.render.player.hitbox": {
      "geometry": "Array.geo[query.is_swimming]",
      "materials": [ { "*": "Material.emissive" } ],
      "textures": [ "Texture.hitbox" ],
      "arrays": {
        "geometries": { "Array.geo": [ "geometry.hitbox", "geometry.hitbox.swimming"] }
      },
      "is_hurt_color":{},
      "on_fire_color":{}
    }
  }
}

Here we also did not forget to indicate about swimming. Now ray.json

{
  "format_version": "1.8.0",
  "render_controllers": {
    "controller.render.player.ray": {
      "geometry": "Geometry.ray",
      "materials": [ { "*": "Material.emissive" } ],
      "textures": [ "Texture.ray" ],
      "is_hurt_color":{},
      "on_fire_color":{},
      "part_visibility": [
        { "*": "!query.is_swimming" }
      ]
    }
  }
}

Yes, yes, swimming was indicated again. These are render controllers. And create the last folder in the default folder – textures. How about without hitbox textures? Throw models/hitboxoverlay.png, ray.png there

Here is your hitboxoverlay

hitboxoverlay.png
hitboxoverlay.png

And here is ray.png

ray.png
ray.png

Yes, they are in models. You probably don’t see models here, but they are there. We are done with the default folder

Well, we’re done with the default folder. In it, we specified models, materials, float and display of hitboxes, as well as hitbox models. Now go to the subpacks folder, which contained default. In subpacks create a no_ray folder. You probably already know how long it will be. Let’s create several folders in no_ray – animations, entity, materials, models, render_controllers, textures.

In the animations folder, create a hitboxrot.json file

{
	"format_version" : "1.8.0",
	"animations" : {
		"animation.player.hitboxrot" : {
			"loop" : true,
			"bones" : {
				"hitbox" : {
					"rotation" : [ 0.0, "-query.body_y_rotation", 0.0 ]
				}
			}
		},
		"animation.player.axis" : {
			"loop" : true,
			"bones" : {
				"axis" : {
					"rotation" : [ 0.0, "-query.body_y_rotation", 0.0 ]
				}
			}
		}
	}
}

hitboxrot – hitboxrotation. It’s a small abbreviation, but the file is exactly called hitboxrot.json. There is body_rotation and everything like that, that is, animations without ray, this is confirmed by the no_ray folder. Next, in no_ray in materials, create an entity.material folder, that is, with the material extension.

{
  "materials": {
    "version": "1.0.0",
	"entity_emissive_alpha_hitbox:entity_nocull": {
      "+defines": [
        "ALPHA_TEST",
        "USE_EMISSIVE"
      ],
      "depthFunc": "Always"
    }
  }
}

Again animations in materials. Okay, then in models we create an entity folder, in which hitbox_swimming.json and hitbox.json. Here is hitbox.json

{
	"format_version": "1.10.0",
	"geometry.hitbox": {
		"texturewidth": 64,
		"textureheight": 64,
		"visible_bounds_width": 3,
		"visible_bounds_height": 3,
		"visible_bounds_offset": [0, 1.5, 0],
		"bones": [
			{
				"name": "hitbox",
				"pivot": [0, 0, 0],
				"cubes": [
					{ "origin": [-5, 0.2, -5], "size": [10, 30, 10], "uv": [0, 0], "inflate": 0.3 },
					{ "origin": [-4.5, 0.5, -4.5], "size": [9, 9, 9], "uv": [0, 42] }
				]
			}
		]
	}
}

Here is the size of the hitbox in json. Next hitbox_swimming.json – floating hitbox

{
	"format_version": "1.10.0",
	"geometry.hitbox.swimming": {
		"texturewidth": 64,
		"textureheight": 64,
		"visible_bounds_width": 3,
		"visible_bounds_height": 3,
		"visible_bounds_offset": [0, 1.5, 0],
		"bones": [
			{
				"name": "hitbox",
				"pivot": [0, 0, 0],
				"cubes": [
					{ "origin": [-5, 0.2, -5], "size": [10, 9, 10], "uv": [0, 0], "inflate": 0.3 },
					{ "origin": [-4.5, 0.5, -4.5], "size": [9, 9, 9], "uv": [0, 42] }
				]
			}
		]
	}
}

Here’s the hitbox in swim mode. Who doesn’t mind a floating player’s standing hitbox? Okay, here is the hitbox.json in render_controllers

{
  "format_version": "1.8.0",
  "render_controllers": {
    "controller.render.player.hitbox": {
      "geometry": "Array.geo[query.is_swimming]",
      "materials": [ { "*": "Material.emissive" } ],
      "textures": [ "Texture.hitbox" ],
      "arrays": {
        "geometries": { "Array.geo": [ "geometry.hitbox", "geometry.hitbox.swimming"] }
      },
      "is_hurt_color":{},
      "on_fire_color":{}
    }
  }
}

Next, in the no_ray/textures/models folder, insert hitboxoverlay.png, how could it be without it

hitboxoverlay.png
hitboxoverlay.png

We are done with no_ray. But that’s not all – in the subpacks there is an opaque_model_collision folder. As a reminder, we are making a texture pack with hitboxes just to get acquainted with subpacks and json. Now, in opaque_model_collision we create folders animations, entity, models, render_controllers, textures. Let’s edit a bit – first the animations folder. It contains hitboxrot.json. Here is hitboxrot.json

{
	"format_version" : "1.8.0",
	"animations" : {
		"animation.player.hitboxrot" : {
			"loop" : true,
			"bones" : {
				"hitbox" : {
					"rotation" : [ 0.0, "-query.body_y_rotation", 0.0 ]
				}
			}
		},
		"animation.player.rayrot" : {
			"loop" : true,
			"bones" : {
				"ray" : {
					"rotation" : [ "query.is_sneaking ? query.target_x_rotation - 1.5 : query.target_x_rotation", "query.target_y_rotation", 0.0 ],
					"position" : [ 0.0, "query.is_sneaking ? -4.25 : 0.0", 0.0 ]
				}
			}
		},
		"animation.player.axis" : {
			"loop" : true,
			"bones" : {
				"axis" : {
					"rotation" : [ 0.0, "-query.body_y_rotation", 0.0 ]
				}
			}
		}
	}
}

We’ve specified the object’s circling, loop, and hitboxes. Next, specify the entities – entity/player.entity.json

{
  "format_version": "1.10.0",
  "minecraft:client_entity": {
    "description": {
      "identifier": "minecraft:player",
      "materials": {
        "default": "entity_alphatest",
        "cape": "entity_alphatest",
        "animated": "player_animated",
        "emissive": "entity_emissive_alpha"
      },
      "textures": {
        "default": "textures/entity/steve",
        "cape": "textures/entity/cape_invisible",
        "hitbox": "textures/models/hitboxoverlay",
        "ray": "textures/models/ray"
      },
      "geometry": {
        "default": "geometry.humanoid.custom",
        "cape": "geometry.cape",
        "hitbox": "geometry.hitbox",
        "hitbox.swimming": "geometry.hitbox.swimming",
        "ray": "geometry.ray"
      },
      "scripts": {
        "scale": "0.9375",
        "initialize": [
          "variable.is_holding_right = 0.0;",
          "variable.is_blinking = 0.0;",
          "variable.last_blink_time = 0.0;",
          "variable.hand_bob = 0.0;"
        ],
        "pre_animation": [
          "variable.helmet_layer_visible = 1.0;",
          "variable.leg_layer_visible = 1.0;",
          "variable.boot_layer_visible = 1.0;",
          "variable.chest_layer_visible = 1.0;",
          "variable.attack_body_rot_y = Math.sin(360*Math.sqrt(variable.attack_time)) * 5.0;",
          "variable.tcos0 = (math.cos(query.modified_distance_moved * 38.17) * query.modified_move_speed / variable.gliding_speed_value) * 57.3;",
          "variable.first_person_rotation_factor = math.sin((1 - variable.attack_time) * 180.0);",
          "variable.hand_bob = query.life_time < 0.01 ? 0.0 : variable.hand_bob + ((query.is_on_ground && query.is_alive ? math.clamp(math.sqrt(math.pow(query.position_delta(0), 2.0) + math.pow(query.position_delta(2), 2.0)), 0.0, 0.1) : 0.0) - variable.hand_bob) * 0.02;",

          "variable.map_angle = math.clamp(1 - variable.player_x_rotation / 45.1, 0.0, 1.0);",
          "variable.item_use_normalized = query.main_hand_item_use_duration / query.main_hand_item_max_duration;"
        ],
        "animate": [
          "root",
          "hitbox_rot",
          "ray_rot",
          "axis"
        ]
      },
      "animations": {
      	"hitbox_rot": "animation.player.hitboxrot",
      	"ray_rot": "animation.player.rayrot",
      	"axis": "animation.player.axis",
        "root": "controller.animation.player.root",
        "base_controller": "controller.animation.player.base",
        "hudplayer":  "controller.animation.player.hudplayer",
        "humanoid_base_pose": "animation.humanoid.base_pose",
        "look_at_target": "controller.animation.humanoid.look_at_target",
        "look_at_target_ui": "animation.player.look_at_target.ui",
        "look_at_target_default": "animation.humanoid.look_at_target.default",
        "look_at_target_gliding": "animation.humanoid.look_at_target.gliding",
        "look_at_target_swimming": "animation.humanoid.look_at_target.swimming",
        "look_at_target_inverted": "animation.player.look_at_target.inverted",
        "cape": "animation.player.cape",
        "move.arms": "animation.player.move.arms",
        "move.legs": "animation.player.move.legs",
        "swimming": "animation.player.swim",
        "swimming.legs": "animation.player.swim.legs",
        "riding.arms": "animation.player.riding.arms",
        "riding.legs": "animation.player.riding.legs",
        "holding": "animation.player.holding",
        "brandish_spear": "animation.humanoid.brandish_spear",
        "charging": "animation.humanoid.charging",
        "attack.positions": "animation.player.attack.positions",
        "attack.rotations": "animation.player.attack.rotations",
        "sneaking": "animation.player.sneaking",
        "bob": "animation.player.bob",
        "damage_nearby_mobs": "animation.humanoid.damage_nearby_mobs",
        "bow_and_arrow": "animation.humanoid.bow_and_arrow",
        "fishing_rod": "animation.humanoid.fishing_rod",
        "use_item_progress": "animation.humanoid.use_item_progress",
        "skeleton_attack": "animation.skeleton.attack",
        "sleeping": "animation.player.sleeping",
        "first_person_base_pose": "animation.player.first_person.base_pose",
        "first_person_empty_hand": "animation.player.first_person.empty_hand",
        "first_person_swap_item": "animation.player.first_person.swap_item",
        "first_person_attack_controller": "controller.animation.player.first_person_attack",
        "first_person_attack_rotation": "animation.player.first_person.attack_rotation",
        "first_person_vr_attack_rotation": "animation.player.first_person.vr_attack_rotation",
        "first_person_walk": "animation.player.first_person.walk",
        "first_person_map_controller": "controller.animation.player.first_person_map",
        "first_person_map_hold": "animation.player.first_person.map_hold",
        "first_person_map_hold_attack": "animation.player.first_person.map_hold_attack",
        "first_person_map_hold_off_hand": "animation.player.first_person.map_hold_off_hand",
        "first_person_map_hold_main_hand": "animation.player.first_person.map_hold_main_hand",
        "first_person_crossbow_equipped": "animation.player.first_person.crossbow_equipped",
        "third_person_crossbow_equipped": "animation.player.crossbow_equipped",
        "third_person_bow_equipped": "animation.player.bow_equipped",
        "crossbow_hold": "animation.player.crossbow_hold",
        "crossbow_controller": "controller.animation.player.crossbow",
        "shield_block_main_hand": "animation.player.shield_block_main_hand",
        "shield_block_off_hand": "animation.player.shield_block_off_hand",
        "blink": "controller.animation.persona.blink"
      },
      "render_controllers": [
        { "controller.render.player.first_person": "variable.is_first_person" },
        { "controller.render.player.third_person": "!variable.is_first_person && !variable.map_face_icon" },
        { "controller.render.player.map": "variable.map_face_icon" },
        { "controller.render.player.hitbox": "!variable.is_first_person && !query.is_in_ui" },
        { "controller.render.player.ray": "!variable.is_first_person && !query.is_in_ui" }
      ],
      "enable_attachables": true
    }
  }
}

Wow, also 118 lines. Some variables and controllers. Okay, next in the models folder, create an entity folder. It has hitbox.json, hitbox_swimming.json, ray.json, here is hitbox

{
	"format_version": "1.10.0",
	"geometry.hitbox": {
		"texturewidth": 64,
		"textureheight": 64,
		"visible_bounds_width": 3,
		"visible_bounds_height": 3,
		"visible_bounds_offset": [0, 1.5, 0],
		"bones": [
			{
				"name": "hitbox",
				"pivot": [0, 0, 0],
				"cubes": [
					{ "origin": [-5, 0.2, -5], "size": [10, 30, 10], "uv": [0, 0], "inflate": 0.3 },
					{ "origin": [-4.5, 0.5, -4.5], "size": [9, 9, 9], "uv": [0, 42] }
				]
			}
		]
	}
}

Specify the size. Now in hitbox swimming – hitbox_swimming.json

{
	"format_version": "1.10.0",
	"geometry.hitbox.swimming": {
		"texturewidth": 64,
		"textureheight": 64,
		"visible_bounds_width": 3,
		"visible_bounds_height": 3,
		"visible_bounds_offset": [0, 1.5, 0],
		"bones": [
			{
				"name": "hitbox",
				"pivot": [0, 0, 0],
				"cubes": [
					{ "origin": [-5, 0.2, -5], "size": [10, 9, 10], "uv": [0, 0], "inflate": 0.3 },
					{ "origin": [-4.5, 0.5, -4.5], "size": [9, 9, 9], "uv": [0, 42] }
				]
			}
		]
	}
}

Here, the geometry.hitbox.swimming function is used, ray.json is left

{
	"format_version": "1.12.0",
	"minecraft:geometry": [
		{
			"description": {
				"identifier": "geometry.ray",
				"texture_width": 16,
				"texture_height": 16,
				"visible_bounds_width": 2,
				"visible_bounds_height": 2,
				"visible_bounds_offset": [0, 2, 0]
			},
			"bones": [
				{
					"name": "ray",
					"pivot": [0, 27, 0],
					"cubes": [
						{"origin": [-0.5, 26.5, -0.5], "size": [1, 1, -16], "inflate": -0.41, "uv": [0, 0]}
					]
				}
			]
		}
	]
}

And here is the minecraft:geometry function. Strange, but still true. Next, go to render_controllers, there are 2 files – hitbox.json and ray.json. Edit hitbox.json

{
  "format_version": "1.8.0",
  "render_controllers": {
    "controller.render.player.hitbox": {
      "geometry": "Array.geo[query.is_swimming]",
      "materials": [ { "*": "Material.emissive" } ],
      "textures": [ "Texture.hitbox" ],
      "arrays": {
        "geometries": { "Array.geo": [ "geometry.hitbox", "geometry.hitbox.swimming"] }
      },
      "is_hurt_color":{},
      "on_fire_color":{}
    }
  }
}

This is where the render_controllers function is used. Next ray.json

{
  "format_version": "1.8.0",
  "render_controllers": {
    "controller.render.player.ray": {
      "geometry": "Geometry.ray",
      "materials": [ { "*": "Material.emissive" } ],
      "textures": [ "Texture.ray" ],
      "is_hurt_color":{},
      "on_fire_color":{},
      "part_visibility": [
        { "*": "!query.is_swimming" }
      ]
    }
  }
}

And again the render_controllers function. Okay, what do we have left? That’s right, textures, in which models. There are again 2 files in models – hitboxoverlay.png, ray.png. Here is hitboxoverlay.png

�PNG

   
IHDR         \r�f  
�zTXtRaw profile type exif  x��Z[r�:��*f	$@�r�����A�v�ĉ�s�߉+�MI|t7�e������/&N��TRr�%�����W��wa�_���~WO׏�RP�q@�yUE}�]p�÷�z���gC���(�z���� Q�G�gCeR��q��l��'�!�Mr��
J#�#a����������n�`
��9�#,�l��M��G���>��|�g�|�2]XK���S�\���uD|��_A^k��1�M���:�����e_��R�G|��*xeW]GW�u���x��|��W���e�C<YQ2w�]�E�pK���`���$T�u,~�[v�g�<<Ne��<.y����A�]�b�q���0��g��N������@����aΘ`u�h�EӖl��E�Ǟt�
 "�1/`�%/�'�Y��U��%p>F$�Ĥ����5���9�U#7��(I�� +��h��P�C�1E��b�5I
)��4Y��*4jRլEk�r�)kι�Z�r`,�hɥ�Z�*:�h������MZh���-��j�|z豧�=����!ib��#�2��4�)f�q��3�2�֖���JKW^e�+k'�_^/��O�x3e��5Ԓ�	o�$g`���j@�l���C`c�8s��1�h����(�s\��ݍ��x����c����9u_y���a>�7cG�N}8>s%��L�ek}��yH������6��Ec��������&�	��v�?,��}b�C���g� =6W�P�:��̚'���J���S";ur�V�0WO�����ZY|i�H�6o44��MQJgSM�{��zh��� H�3�sƴB[��{�H�%x?K��=�٣���S[�3h�n ����S9{��z
�@����jF�h� 	׾]���z�	wV����}]��'$�>p�p�F���5d����
���!�;@��rV<Y��Yh4Y���eQ*�5
]�3��`�²��D���?�…S��)|��#�'���-�?+�"�kqtHC��c��u �ǂ��b���8��u�K�}���0�:T�7R�{����&�����hcℐZ��07���[n-������MЕs�/�{��2�O��=��CO+�O"�F�I$o8]+w�
���>�cp���-^�h�u F�<ה�]�:�K�:�GRV��V\�gU��{�##p����W[d�����B�`y"V†�1�B��i�aڭԱ.���kPo��
c�%��y�l��*�Y�ˑE���EyZ k�TK�ő`H;��0s�-����C
�+��c�CGz�EW� 3 ��M1I���*�S1um[0*w���i�
�_m��B��f��y�7u4���v�cy��c�'ޱ�&x])��{lk��pA�B��1�uv��L�_ƛYM�pֹ8l�X���I�`�n5��5���|25h ���z;o`���
���G?Ȅ��ɏ2�w�ٴ�s1O�E�l���Q&H�]����j�mR��.=i�s�O��u�)>����� �=X��Rb0~���g�=��'���a�H��kҟ=?ZcXߑ��[c������m��W��
[v��]m�օ���9�Y�'c��Xj.�vZ����/6I�On��?���(�HOX�c�?�~�=��Q���G�z�{P�}T�둎�O苞��w$�9(G����w$�!�/��G�z�{P�}T�A�G{U_�g�zC��,To�?�[K�r�>����=(�>*�����܃B�&���� ��_��k�
�A��9����-~N�x�|n������M�r��m�%�{|)��Ǯ�h��������G.8��?o����������vG�{����׷7�]�V�=��mʏ!�M�S�~ܻ�#����Ql[H�co7�4�f�)�.����J8�J��fG�νR�ĽW*��+���^��c��k�{�:zMv�U�Zi�UG�����5�=V�&�Ǫ��d�Xu��즻��J��E*N��z���c�%��˂<%ѧ��&�Z�brõ��mW�e�(c�0^m�WBŷF�>B[�Ǥ���`��
k�fY�Ft��n�tŶ:�o�[�yl}�`Jk��=�1U��>���Ț���56���	�˜���;T0rK��z)C�%B�c�^EdK
� !@��Yi�
��������P({z]{(�����w�����|b\%�8B���!�=d�)��%}��e�4�6��5d���4+�85�K�4۵��p���'H��C�)~�`��Ӽ��~�0rG�0�E����˷Xn̄� i���S���l�p#�`�HD�r)HJ+�9Fn�l��PC��#���x���O}[����\, -(�>eב�>|������q���ѯ���(DrI8�O5�=�s�ƪ��ŗvV�X��jM|�
�y���yԞ��xLț�_�dYQ�Q���eP���~É����R>��3�'t���`O�H7��HD��epnсș;!�"�Op934�0�P"�Ý�ҥ�зǩ	s,��/{���R�!S��N%$�C�f��i\:CS�&~��/�.n	��- ?����Z���%�!���Jt��4�>5���K�eq��.�-�f�y��!<��6�
s��p�I����/ �e��(�k:�'��Ê����3��Ҳ��v3NK^s��]\
�G��gd�$L���+C��2)�"�,GWҡ�?�?P=|Q	�9��m�1
�r6�BO��F  �iCCPICC profile  x�}�=H�@�_S�R*�P�!Cu� *�(U,���Vh����/hҐ��8
�?�.κ:�
�������������"ƃ�~����{�S;	@�,#�L��ªxEˆ"*1SOes�_����.γ���9��� �H<�t�"� �ٴt���V��s�q�.H��u��7�e��1r�y��X�a��Y�P���c��Q��wY��Y�5X��������:�$���!��*j��U#�D���aǟ&�L�*9P�
�����n��Ԥ�J �/��1
v�vӶ��m�}���+�믷��Oқ]-v�����&��;@�I�ɑ�4�R	x?�o* C�@p������ G]-� ��X���=�=��ۿg:�� E�r��A   bKGD � � �����   	pHYs     ��   tIME�
()�R�  �IDATx���;�0EQb��ڼ�G���$�!��Ў��B�FsI��mU�l���9 If��� ^9Y   �      �      �      �      �      �      �      �      �   ����d:�
\�l�����@���H2�w��<�~   @     @     @     @      @     @     @     @     @     @     @     @     @    �
@     @     @     @     @     @     @     @     @      @     @     @     @     @     @     `w�dZ_��U�        ��ve�Qcu�'����8,�7%9,�    @     @     @     @     @     @     @     @   ˘����   �      �      �      �      �      �      �      �      ������k�Z��^�huN�H                vw��B?R	��    IEND�B`�

Or

hitboxoverlay.png
hitboxoverlay.png

And here is ray.png

�PNG

   
IHDR           szz�  �zTXtRaw profile type exif  x��Q��&E�YE��$��r0�sfY~�rWu�$3�|�L�`�%�]����F���BR�\r�8RI�+���+Ŵ���=��{�'&A/׭ս�®<b��j�gط#�/�eF����$�|�)mG���=�zlGm/\��3�i]ݼ/�J]H�O!�����:��:���1N�aue;� /���c|�E��(|V�}���'-����N�~����˝�N�>\}y��c���Ք�h��Ħ�,< ���2��T�m�����=�x�5*�PJԩҠs��RL|��gn,��b\��
6)�A���D&�;Zqˊ����2����w����mJD�o��ϺF�ܼb����t	�h|��Y�)���5��C飶dq�S��'D��v �[�	�L��)�AG���Y @�ܑ$'����y��3Fk-+g�f�M �����H���c�QCUE��f5��Ek����-�M��X2�lfnŪ�'W�n�^�.�=PK.V��R+��@�*�WX>�H���ÏrԆ�i�i�͚��j�.�D�ݺ���I��Nq�S�|��g9�@�
i��Æ�2�MmS��~�mj�H�uvS�5�=\��Nt21N�6	��y2�N)�$7����(���N6��$��$�A7�r?�-��7�'ra��/�����;���=���+��F��7�U�P�F�Z�~�o�!�KoGoGoGoGoGoGoG�G�? ��a�9�����m  �iCCPICC profile  x�}�=H�@�_S�R*�P�!Cu� *�(U,���Vh����/hҐ��8
�?�.κ:�
�������������"ƃ�~����{�S;	@�,#�L��ªxEˆ"*1SOes�_����.γ���9��� �H<�t�"� �ٴt���V��s�q�.H��u��7�e��1r�y��X�a��Y�P���c��Q��wY��Y�5X��������:�$���!��*j��U#�D���aǟ&�L�*9P�
�����n��Ԥ�J �/��1
v�vӶ��m�}���+�믷��Oқ]-v�����&��;@�I�ɑ�4�R	x?�o* C�@p������ G]-� ��X���=�=��ۿg:�� E�r��A   bKGD � � �����   	pHYs     ��   tIME�
*5�<l(   -IDATX���A  �#��=��%X%;y�y&              p��Y4>��    IEND�B`�

Or past pictures ray.png.

That’s all. Import the addon and go to minecraft. We launch and check – all players have hitboxes.

That’s all. Now the translation. In order to make the name of items in the resource pack American stick, and Russian digging stick, create a texts folder in the resource pack folder, in it ru_RU.lang. Next line

item.предмет.name=§l§aПалка копалка

That’s all. I talked about parameter sets, resource packs and subpacks in texture packs, hitbox display, translation and anti-spam with chat ranks. I hope this article was helpful.

Similar Posts

Leave a Reply