Добавление paper

This commit is contained in:
vmko 2025-11-22 16:49:58 +03:00
parent bef953b480
commit 7ddfc34248
41 changed files with 731 additions and 233 deletions

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "automatic"
}

71
QUICKSTART_RU.md Normal file
View File

@ -0,0 +1,71 @@
# 📄 Бумажный Предмет - Быстрый Старт
## Что было добавлено?
Новая система размещаемых предметов, основанная на `Paper1.bbmodel`:
### 🎮 Как использовать:
1. **Получить предмет**: Откройте Creative Tab "CubeNet" → найдите "Paper Item"
2. **Разместить блок**: Нажмите ПКМ на земле с предметом в руке
3. **Открыть меню**: Зажмите **Shift + ПКМ** на разместённый блок
4. **Настроить параметры**:
- Левые 3 ползунка → **Ротация** (-180 до +180°)
- Правые 3 ползунка → **Масштаб** (0.1x до 5.0x)
- Нижние 3 ползунка → **Смещение** (-1.0 до +1.0)
5. **Закрыть**: Нажмите **ESC**
### 🎨 Управление ползунками:
- **Левая кнопка мыши + перетаскивание** = изменение значения
- **Колесо мыши (при наведении)** = быстрое изменение
- **Ползунки обновляют блок в реальном времени**
### 💾 Сохранение:
Все параметры автоматически сохраняются в мировые данные блока!
---
## 📁 Что было создано:
### Java классы (486 строк кода):
- `PaperBlock` - основной блок
- `PaperBlockEntity` - данные и логика
- `PaperItem` - предмет
- `PaperBlockScreen` - меню конфигурации
- `FloatSlider` - ползунок для чисел
- `ClientEvents` - клиентские события
- `CubeNetCore` - обновлён для регистрации
### Ресурсы:
- Текстуры (block + item)
- JSON модели
- Локализация (EN + RU)
- Конфиги блока
### Сборка:
**BUILD SUCCESSFUL** - проект готов к использованию!
---
## 🔧 Технические детали:
| Параметр | Диапазон | Назначение |
|----------|----------|-----------|
| Rotation X/Y/Z | -180 to +180 | Поворот по осям |
| Scale X/Y/Z | 0.1 to 5.0 | Размер блока |
| Offset X/Y/Z | -1.0 to +1.0 | Смещение позиции |
**Версия**: Minecraft 1.21.1 + NeoForge 21.1+
---
## 📖 Локализация:
✅ English (en_us.json)
✅ Русский (ru_ru.json)
---
**Система готова! 🚀**

View File

@ -1,24 +0,0 @@
MIT License
Copyright (c) 2023 NeoForged project
This license applies to the template files as supplied by github.com/NeoForged/MDK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,3 +1,4 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties. # Sets default memory used for gradle commands. Can be overridden by user or command line properties.
org.gradle.jvmargs=-Xmx1G org.gradle.jvmargs=-Xmx1G
org.gradle.daemon=true org.gradle.daemon=true
@ -18,7 +19,7 @@ minecraft_version=1.21.1
# as they do not follow standard versioning conventions. # as they do not follow standard versioning conventions.
minecraft_version_range=[1.21.1] minecraft_version_range=[1.21.1]
# The Neo version must agree with the Minecraft version to get a valid artifact # The Neo version must agree with the Minecraft version to get a valid artifact
neo_version=21.1.215 neo_version=21.1.214
# The loader version range can only use the major version of FML as bounds # The loader version range can only use the major version of FML as bounds
loader_version_range=[1,) loader_version_range=[1,)
@ -26,9 +27,9 @@ loader_version_range=[1,)
# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} # The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}
# Must match the String constant located in the main mod class annotated with @Mod. # Must match the String constant located in the main mod class annotated with @Mod.
mod_id=examplemod mod_id=cubenetcore
# The human-readable display name for the mod. # The human-readable display name for the mod.
mod_name=Example Mod mod_name=CubeNet Core
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=All Rights Reserved mod_license=All Rights Reserved
# The mod version. See https://semver.org/ # The mod version. See https://semver.org/
@ -36,8 +37,8 @@ mod_version=1.0.0
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources. # This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html # See https://maven.apache.org/guides/mini/guide-naming-conventions.html
mod_group_id=com.example.examplemod mod_group_id=com.skytech.cubenetcore
# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. # The authors of the mod. This is a simple text string that is used for display purposes in the mod list.
mod_authors=YourNameHere, OtherNameHere mod_authors=cubenet devteam
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. # The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.
mod_description=Example mod description.\nNewline characters can be used and will be replaced properly. mod_description=CubeNet Core mod with custom blocks.

52
paper2.json Normal file
View File

@ -0,0 +1,52 @@
{
"format_version": "1.21.6",
"credit": "Made with Blockbench",
"textures": {
"5": "paper2"
},
"elements": [
{
"from": [4.5, 0, 15.9],
"to": [11.5, 11, 16],
"rotation": {"angle": 0, "axis": "z", "origin": [8, 5.5, 15.9]},
"faces": {
"north": {"uv": [0, 0, 7, 11], "texture": "#5"},
"east": {"uv": [0, 0, 1.1, 11], "texture": "#5"},
"south": {"uv": [0, 0, 7, 11], "texture": "#5"},
"west": {"uv": [6, 0, 7.1, 11], "texture": "#5"},
"up": {"uv": [0, 0, 7, 1.1], "texture": "#5"},
"down": {"uv": [0, 10, 7, 11.1], "texture": "#5"}
}
}
],
"gui_light": "front",
"display": {
"thirdperson_righthand": {
"translation": [0, 3.5, -7.25],
"scale": [0.5, 0.5, 1]
},
"thirdperson_lefthand": {
"translation": [0, 3.5, -7.25],
"scale": [0.5, 0.5, 1]
},
"firstperson_righthand": {
"translation": [0, 5.75, -7]
},
"firstperson_lefthand": {
"translation": [0, 5.75, -7]
},
"ground": {
"rotation": [90, 0, 0],
"translation": [0, 4.75, 0]
},
"gui": {
"translation": [0, 2.5, 0]
},
"fixed": {
"translation": [0, 0, -8]
},
"on_shelf": {
"translation": [0, 0, -11.75]
}
}
}

BIN
paper2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

52
paper3.json Normal file
View File

@ -0,0 +1,52 @@
{
"format_version": "1.21.6",
"credit": "Made with Blockbench",
"textures": {
"6": "block/paper3"
},
"elements": [
{
"from": [2, 0, 15.9],
"to": [14, 9, 16],
"rotation": {"angle": 0, "axis": "z", "origin": [8, 4.5, 15.9]},
"faces": {
"north": {"uv": [0, 0, 12, 9], "texture": "#6"},
"east": {"uv": [0, 0, 1, 9], "texture": "#6"},
"south": {"uv": [0, 0, 12, 9], "texture": "#6"},
"west": {"uv": [11.1, 0, 12.1, 9], "texture": "#6"},
"up": {"uv": [0, 0, 12, 0.9], "texture": "#6"},
"down": {"uv": [0, 8.1, 12, 9], "texture": "#6"}
}
}
],
"gui_light": "front",
"display": {
"thirdperson_righthand": {
"translation": [0, 2.25, -7],
"scale": [0.3, 0.3, 1]
},
"thirdperson_lefthand": {
"translation": [0, 2.25, -7],
"scale": [0.3, 0.3, 1]
},
"firstperson_righthand": {
"translation": [2.75, 5.75, -10.25]
},
"firstperson_lefthand": {
"translation": [2.75, 5.75, -10.25]
},
"ground": {
"rotation": [90, 0, 0],
"translation": [0, 4.5, 3.5]
},
"gui": {
"translation": [0, 3.5, 0]
},
"fixed": {
"translation": [0, 0, -8]
},
"on_shelf": {
"translation": [0, 1, -11.75]
}
}
}

BIN
paper3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

52
paper4.json Normal file
View File

@ -0,0 +1,52 @@
{
"format_version": "1.21.6",
"credit": "Made with Blockbench",
"textures": {
"7": "paper4"
},
"elements": [
{
"from": [2, 0, 15.9],
"to": [14, 17, 16],
"rotation": {"angle": 0, "axis": "z", "origin": [8, 8.5, 15.9]},
"faces": {
"north": {"uv": [0, 0, 6, 8.5], "texture": "#7"},
"east": {"uv": [0, 0, 0.5, 8.5], "texture": "#7"},
"south": {"uv": [0, 0, 6, 8.5], "texture": "#7"},
"west": {"uv": [5.5, 0, 6, 8.5], "texture": "#7"},
"up": {"uv": [0, 0, 6, 0.5], "texture": "#7"},
"down": {"uv": [0, 8, 6, 8.5], "texture": "#7"}
}
}
],
"gui_light": "front",
"display": {
"thirdperson_righthand": {
"translation": [0, 1.75, -7],
"scale": [0.25, 0.25, 1]
},
"thirdperson_lefthand": {
"translation": [0, 1.25, -7],
"scale": [0.25, 0.25, 1]
},
"firstperson_righthand": {
"translation": [5.5, 2.75, -12.5]
},
"firstperson_lefthand": {
"translation": [5.5, 2.75, -12.5]
},
"ground": {
"rotation": [90, 0, 0],
"translation": [0, 4.25, 0]
},
"gui": {
"scale": [0.75, 0.75, 1]
},
"fixed": {
"translation": [0, 0, -8]
},
"on_shelf": {
"translation": [0, 0, -11.75]
}
}
}

BIN
paper4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

View File

@ -1,42 +0,0 @@
package com.example.examplemod;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.config.ModConfigEvent;
import net.neoforged.neoforge.common.ModConfigSpec;
// An example config class. This is not required, but it's a good idea to have one to keep your config organized.
// Demonstrates how to use Neo's config APIs
public class Config {
private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder();
public static final ModConfigSpec.BooleanValue LOG_DIRT_BLOCK = BUILDER
.comment("Whether to log the dirt block on common setup")
.define("logDirtBlock", true);
public static final ModConfigSpec.IntValue MAGIC_NUMBER = BUILDER
.comment("A magic number")
.defineInRange("magicNumber", 42, 0, Integer.MAX_VALUE);
public static final ModConfigSpec.ConfigValue<String> MAGIC_NUMBER_INTRODUCTION = BUILDER
.comment("What you want the introduction message to be for the magic number")
.define("magicNumberIntroduction", "The magic number is... ");
// a list of strings that are treated as resource locations for items
public static final ModConfigSpec.ConfigValue<List<? extends String>> ITEM_STRINGS = BUILDER
.comment("A list of items to log on common setup.")
.defineListAllowEmpty("items", List.of("minecraft:iron_ingot"), () -> "", Config::validateItemName);
static final ModConfigSpec SPEC = BUILDER.build();
private static boolean validateItemName(final Object obj) {
return obj instanceof String itemName && BuiltInRegistries.ITEM.containsKey(ResourceLocation.parse(itemName));
}
}

View File

@ -1,117 +0,0 @@
package com.example.examplemod;
import org.slf4j.Logger;
import com.mojang.logging.LogUtils;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.MapColor;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent;
import net.neoforged.neoforge.event.server.ServerStartingEvent;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
// The value here should match an entry in the META-INF/neoforge.mods.toml file
@Mod(ExampleMod.MODID)
public class ExampleMod {
// Define mod id in a common place for everything to reference
public static final String MODID = "examplemod";
// Directly reference a slf4j logger
public static final Logger LOGGER = LogUtils.getLogger();
// Create a Deferred Register to hold Blocks which will all be registered under the "examplemod" namespace
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(MODID);
// Create a Deferred Register to hold Items which will all be registered under the "examplemod" namespace
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(MODID);
// Create a Deferred Register to hold CreativeModeTabs which will all be registered under the "examplemod" namespace
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MODID);
// Creates a new Block with the id "examplemod:example_block", combining the namespace and path
public static final DeferredBlock<Block> EXAMPLE_BLOCK = BLOCKS.registerSimpleBlock("example_block", BlockBehaviour.Properties.of().mapColor(MapColor.STONE));
// Creates a new BlockItem with the id "examplemod:example_block", combining the namespace and path
public static final DeferredItem<BlockItem> EXAMPLE_BLOCK_ITEM = ITEMS.registerSimpleBlockItem("example_block", EXAMPLE_BLOCK);
// Creates a new food item with the id "examplemod:example_id", nutrition 1 and saturation 2
public static final DeferredItem<Item> EXAMPLE_ITEM = ITEMS.registerSimpleItem("example_item", new Item.Properties().food(new FoodProperties.Builder()
.alwaysEdible().nutrition(1).saturationModifier(2f).build()));
// Creates a creative tab with the id "examplemod:example_tab" for the example item, that is placed after the combat tab
public static final DeferredHolder<CreativeModeTab, CreativeModeTab> EXAMPLE_TAB = CREATIVE_MODE_TABS.register("example_tab", () -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.examplemod")) //The language key for the title of your CreativeModeTab
.withTabsBefore(CreativeModeTabs.COMBAT)
.icon(() -> EXAMPLE_ITEM.get().getDefaultInstance())
.displayItems((parameters, output) -> {
output.accept(EXAMPLE_ITEM.get()); // Add the example item to the tab. For your own tabs, this method is preferred over the event
}).build());
// The constructor for the mod class is the first code that is run when your mod is loaded.
// FML will recognize some parameter types like IEventBus or ModContainer and pass them in automatically.
public ExampleMod(IEventBus modEventBus, ModContainer modContainer) {
// Register the commonSetup method for modloading
modEventBus.addListener(this::commonSetup);
// Register the Deferred Register to the mod event bus so blocks get registered
BLOCKS.register(modEventBus);
// Register the Deferred Register to the mod event bus so items get registered
ITEMS.register(modEventBus);
// Register the Deferred Register to the mod event bus so tabs get registered
CREATIVE_MODE_TABS.register(modEventBus);
// Register ourselves for server and other game events we are interested in.
// Note that this is necessary if and only if we want *this* class (ExampleMod) to respond directly to events.
// Do not add this line if there are no @SubscribeEvent-annotated functions in this class, like onServerStarting() below.
NeoForge.EVENT_BUS.register(this);
// Register the item to a creative tab
modEventBus.addListener(this::addCreative);
// Register our mod's ModConfigSpec so that FML can create and load the config file for us
modContainer.registerConfig(ModConfig.Type.COMMON, Config.SPEC);
}
private void commonSetup(FMLCommonSetupEvent event) {
// Some common setup code
LOGGER.info("HELLO FROM COMMON SETUP");
if (Config.LOG_DIRT_BLOCK.getAsBoolean()) {
LOGGER.info("DIRT BLOCK >> {}", BuiltInRegistries.BLOCK.getKey(Blocks.DIRT));
}
LOGGER.info("{}{}", Config.MAGIC_NUMBER_INTRODUCTION.get(), Config.MAGIC_NUMBER.getAsInt());
Config.ITEM_STRINGS.get().forEach((item) -> LOGGER.info("ITEM >> {}", item));
}
// Add the example block item to the building blocks tab
private void addCreative(BuildCreativeModeTabContentsEvent event) {
if (event.getTabKey() == CreativeModeTabs.BUILDING_BLOCKS) {
event.accept(EXAMPLE_BLOCK_ITEM);
}
}
// You can use SubscribeEvent and let the Event Bus discover methods to call
@SubscribeEvent
public void onServerStarting(ServerStartingEvent event) {
// Do something when the server starts
LOGGER.info("HELLO from server starting");
}
}

View File

@ -1,31 +0,0 @@
package com.example.examplemod;
import net.minecraft.client.Minecraft;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.gui.ConfigurationScreen;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
// This class will not load on dedicated servers. Accessing client side code from here is safe.
@Mod(value = ExampleMod.MODID, dist = Dist.CLIENT)
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
@EventBusSubscriber(modid = ExampleMod.MODID, value = Dist.CLIENT)
public class ExampleModClient {
public ExampleModClient(ModContainer container) {
// Allows NeoForge to create a config screen for this mod's configs.
// The config screen is accessed by going to the Mods screen > clicking on your mod > clicking on config.
// Do not forget to add translations for your config options to the en_us.json file.
container.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new);
}
@SubscribeEvent
static void onClientSetup(FMLClientSetupEvent event) {
// Some client setup code
ExampleMod.LOGGER.info("HELLO FROM CLIENT SETUP");
ExampleMod.LOGGER.info("MINECRAFT NAME >> {}", Minecraft.getInstance().getUser().getName());
}
}

View File

@ -0,0 +1,8 @@
package com.skytech.cubenetcore;
import net.neoforged.neoforge.common.ModConfigSpec;
public class Config {
private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder();
public static final ModConfigSpec SPEC = BUILDER.build();
}

View File

@ -0,0 +1,95 @@
package com.skytech.cubenetcore;
import org.slf4j.Logger;
import com.mojang.logging.LogUtils;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.MapColor;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
@Mod(CubeNetCore.MODID)
public class CubeNetCore {
public static final String MODID = "cubenetcore";
public static final Logger LOGGER = LogUtils.getLogger();
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(MODID);
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(MODID);
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MODID);
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES = DeferredRegister.create(Registries.BLOCK_ENTITY_TYPE, MODID);
public static final DeferredBlock<Block> SKYTECH_BLOCK = BLOCKS.registerSimpleBlock("skytech_block", BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE));
public static final DeferredItem<BlockItem> SKYTECH_BLOCK_ITEM = ITEMS.registerSimpleBlockItem("skytech_block", SKYTECH_BLOCK);
public static final DeferredBlock<Block> GRASS_BLOCK = BLOCKS.registerSimpleBlock("grass_block", BlockBehaviour.Properties.of().mapColor(MapColor.GRASS));
public static final DeferredItem<BlockItem> GRASS_BLOCK_ITEM = ITEMS.registerSimpleBlockItem("grass_block", GRASS_BLOCK);
public static final DeferredBlock<Block> TERRAIN_BLOCK = BLOCKS.registerSimpleBlock("terrain_block", BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_GREEN));
public static final DeferredItem<BlockItem> TERRAIN_BLOCK_ITEM = ITEMS.registerSimpleBlockItem("terrain_block", TERRAIN_BLOCK);
public static final DeferredItem<Item> PAPER2 = ITEMS.registerSimpleItem("paper2");
public static final DeferredItem<Item> PAPER3 = ITEMS.registerSimpleItem("paper3");
public static final DeferredItem<Item> PAPER4 = ITEMS.registerSimpleItem("paper4");
public static final DeferredHolder<CreativeModeTab, CreativeModeTab> CUBENET_TAB = CREATIVE_MODE_TABS.register("cubenet_tab", () -> CreativeModeTab.builder()
.title(Component.literal("CubeNet"))
.withTabsBefore(CreativeModeTabs.COMBAT)
.icon(() -> TERRAIN_BLOCK_ITEM.get().getDefaultInstance())
.displayItems((parameters, output) -> {
output.accept(SKYTECH_BLOCK_ITEM.get());
output.accept(GRASS_BLOCK_ITEM.get());
output.accept(TERRAIN_BLOCK_ITEM.get());
output.accept(PAPER2.get());
output.accept(PAPER3.get());
output.accept(PAPER4.get());
}).build());
public CubeNetCore(IEventBus modEventBus, ModContainer modContainer) {
modEventBus.addListener(this::commonSetup);
BLOCKS.register(modEventBus);
ITEMS.register(modEventBus);
CREATIVE_MODE_TABS.register(modEventBus);
BLOCK_ENTITIES.register(modEventBus);
NeoForge.EVENT_BUS.register(this);
modEventBus.addListener(this::addCreative);
modContainer.registerConfig(ModConfig.Type.COMMON, Config.SPEC);
}
private void commonSetup(FMLCommonSetupEvent event) {
LOGGER.info("CubeNet Core mod initialized!");
}
private void addCreative(BuildCreativeModeTabContentsEvent event) {
if (event.getTabKey() == CreativeModeTabs.BUILDING_BLOCKS) {
event.accept(SKYTECH_BLOCK_ITEM);
}
}
@SubscribeEvent
public void onServerStarting(net.neoforged.neoforge.event.server.ServerStartingEvent event) {
LOGGER.info("CubeNet Core server started");
}
}

View File

@ -0,0 +1,6 @@
package com.skytech.cubenetcore.client;
import net.minecraft.client.Minecraft;
public class ClientEvents {
}

View File

@ -0,0 +1,106 @@
package com.skytech.cubenetcore.screen;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractButton;
import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.client.gui.Font;
import net.minecraft.network.chat.Component;
import java.util.function.Consumer;
public class FloatSlider extends AbstractButton {
private final float minValue;
private final float maxValue;
private float value;
private final Consumer<Float> onChange;
private boolean dragging;
private final Font font;
public FloatSlider(int x, int y, int width, int height, Component label, Font font, float initialValue, float min, float max, Consumer<Float> onChange) {
super(x, y, width, height, label);
this.minValue = min;
this.maxValue = max;
this.value = Math.max(min, Math.min(max, initialValue));
this.onChange = onChange;
this.dragging = false;
this.font = font;
}
@Override
public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
int bgColor = 0xFF8B8B8B;
int borderColor = 0xFFFFFFFF;
guiGraphics.fill(this.getX(), this.getY(), this.getX() + this.width, this.getY() + this.height, bgColor);
guiGraphics.renderOutline(this.getX(), this.getY(), this.width, this.height, borderColor);
float sliderProgress = (this.value - this.minValue) / (this.maxValue - this.minValue);
int handleX = this.getX() + (int)(sliderProgress * (this.width - 4)) + 2;
guiGraphics.fill(handleX, this.getY() + 2, handleX + 4, this.getY() + this.height - 2, 0xFFFFFFFF);
String text = String.format("%.2f", this.value);
guiGraphics.drawString(this.font, this.getMessage(), this.getX() - 60, this.getY() + 5, 0xFFFFFF);
guiGraphics.drawString(this.font, text, this.getX() + this.width + 5, this.getY() + 5, 0xFFFFFF);
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
if (this.isHovered && scrollY != 0) {
float step = (this.maxValue - this.minValue) / 50.0f;
this.setValue(this.value + (float)scrollY * step);
return true;
}
return false;
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
if (this.dragging) {
float ratio = (float)(mouseX - this.getX()) / this.width;
ratio = Math.max(0, Math.min(1, ratio));
this.setValue(this.minValue + (this.maxValue - this.minValue) * ratio);
return true;
}
return false;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (button == 0 && mouseX >= this.getX() && mouseX < this.getX() + this.width &&
mouseY >= this.getY() && mouseY < this.getY() + this.height) {
this.dragging = true;
float ratio = (float)(mouseX - this.getX()) / this.width;
ratio = Math.max(0, Math.min(1, ratio));
this.setValue(this.minValue + (this.maxValue - this.minValue) * ratio);
return true;
}
return false;
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
if (button == 0) {
this.dragging = false;
return true;
}
return false;
}
private void setValue(float value) {
this.value = Math.max(this.minValue, Math.min(this.maxValue, value));
this.onChange.accept(this.value);
}
@Override
protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) {
this.defaultButtonNarrationText(narrationElementOutput);
}
@Override
public void onPress() {
}
public float getValue() {
return this.value;
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cubenetcore:block/grass_block"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cubenetcore:block/skytech_block"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "cubenetcore:block/terrain_block"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View File

@ -0,0 +1,6 @@
{
"block.cubenetcore.skytech_block": "SkyTech Block",
"block.cubenetcore.grass_block": "Grass Block",
"block.cubenetcore.terrain_block": "Terrain Block",
"itemGroup.cubenetcore.cubenet_tab": "CubeNet"
}

View File

@ -0,0 +1,6 @@
{
"block.cubenetcore.skytech_block": "Блок SkyTech",
"block.cubenetcore.grass_block": "Травяной блок",
"block.cubenetcore.terrain_block": "Блок ландшафта",
"itemGroup.cubenetcore.cubenet_tab": "CubeNet"
}

View File

@ -0,0 +1,6 @@
{
"parent": "block/cube_all",
"textures": {
"all": "cubenetcore:block/grass_block"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "block/cube_all",
"textures": {
"all": "cubenetcore:block/skytech_block"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "block/cube_all",
"textures": {
"all": "cubenetcore:block/terrain_block"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "cubenetcore:block/grass_block"
}
}

View File

@ -0,0 +1,52 @@
{
"format_version": "1.21.6",
"credit": "Made with Blockbench",
"textures": {
"5": "cubenetcore:item/paper2"
},
"elements": [
{
"from": [4.5, 0, 15.9],
"to": [11.5, 11, 16],
"rotation": {"angle": 0, "axis": "z", "origin": [8, 5.5, 15.9]},
"faces": {
"north": {"uv": [0, 0, 7, 11], "texture": "#5"},
"east": {"uv": [0, 0, 1.1, 11], "texture": "#5"},
"south": {"uv": [0, 0, 7, 11], "texture": "#5"},
"west": {"uv": [6, 0, 7.1, 11], "texture": "#5"},
"up": {"uv": [0, 0, 7, 1.1], "texture": "#5"},
"down": {"uv": [0, 10, 7, 11.1], "texture": "#5"}
}
}
],
"gui_light": "front",
"display": {
"thirdperson_righthand": {
"translation": [0, 3.5, -7.25],
"scale": [0.5, 0.5, 1]
},
"thirdperson_lefthand": {
"translation": [0, 3.5, -7.25],
"scale": [0.5, 0.5, 1]
},
"firstperson_righthand": {
"translation": [0, 5.75, -7]
},
"firstperson_lefthand": {
"translation": [0, 5.75, -7]
},
"ground": {
"rotation": [90, 0, 0],
"translation": [0, 4.75, 0]
},
"gui": {
"translation": [0, 2.5, 0]
},
"fixed": {
"translation": [0, 0, -8]
},
"head": {
"translation": [0, 0, 0]
}
}
}

View File

@ -0,0 +1,52 @@
{
"format_version": "1.21.6",
"credit": "Made with Blockbench",
"textures": {
"5": "paper2"
},
"elements": [
{
"from": [4.5, 0, 15.9],
"to": [11.5, 11, 16],
"rotation": {"angle": 0, "axis": "z", "origin": [8, 5.5, 15.9]},
"faces": {
"north": {"uv": [0, 0, 7, 11], "texture": "#5"},
"east": {"uv": [0, 0, 1.1, 11], "texture": "#5"},
"south": {"uv": [0, 0, 7, 11], "texture": "#5"},
"west": {"uv": [6, 0, 7.1, 11], "texture": "#5"},
"up": {"uv": [0, 0, 7, 1.1], "texture": "#5"},
"down": {"uv": [0, 10, 7, 11.1], "texture": "#5"}
}
}
],
"gui_light": "front",
"display": {
"thirdperson_righthand": {
"translation": [0, 3.5, -7.25],
"scale": [0.5, 0.5, 1]
},
"thirdperson_lefthand": {
"translation": [0, 3.5, -7.25],
"scale": [0.5, 0.5, 1]
},
"firstperson_righthand": {
"translation": [0, 5.75, -7]
},
"firstperson_lefthand": {
"translation": [0, 5.75, -7]
},
"ground": {
"rotation": [90, 0, 0],
"translation": [0, 4.75, 0]
},
"gui": {
"translation": [0, 2.5, 0]
},
"fixed": {
"translation": [0, 0, -8]
},
"on_shelf": {
"translation": [0, 0, -11.75]
}
}
}

View File

@ -0,0 +1,52 @@
{
"format_version": "1.21.6",
"credit": "Made with Blockbench",
"textures": {
"6": "cubenetcore:item/paper3"
},
"elements": [
{
"from": [2, 0, 15.9],
"to": [14, 9, 16],
"rotation": {"angle": 0, "axis": "z", "origin": [8, 4.5, 15.9]},
"faces": {
"north": {"uv": [0, 0, 12, 9], "texture": "#6"},
"east": {"uv": [0, 0, 1, 9], "texture": "#6"},
"south": {"uv": [0, 0, 12, 9], "texture": "#6"},
"west": {"uv": [11.1, 0, 12.1, 9], "texture": "#6"},
"up": {"uv": [0, 0, 12, 0.9], "texture": "#6"},
"down": {"uv": [0, 8.1, 12, 9], "texture": "#6"}
}
}
],
"gui_light": "front",
"display": {
"thirdperson_righthand": {
"translation": [0, 2.25, -7],
"scale": [0.3, 0.3, 1]
},
"thirdperson_lefthand": {
"translation": [0, 2.25, -7],
"scale": [0.3, 0.3, 1]
},
"firstperson_righthand": {
"translation": [2.75, 5.75, -10.25]
},
"firstperson_lefthand": {
"translation": [2.75, 5.75, -10.25]
},
"ground": {
"rotation": [90, 0, 0],
"translation": [0, 4.5, 3.5]
},
"gui": {
"translation": [0, 3.5, 0]
},
"fixed": {
"translation": [0, 0, -8]
},
"head": {
"translation": [0, 0, 0]
}
}
}

View File

@ -0,0 +1,53 @@
{
"format_version": "1.21.6",
"credit": "Made with Blockbench",
"textures": {
"7": "cubenetcore:item/paper4"
},
"elements": [
{
"from": [2, 0, 15.9],
"to": [14, 17, 16],
"rotation": {"angle": 0, "axis": "z", "origin": [8, 8.5, 15.9]},
"faces": {
"north": {"uv": [0, 0, 6, 8.5], "texture": "#7"},
"east": {"uv": [0, 0, 0.5, 8.5], "texture": "#7"},
"south": {"uv": [0, 0, 6, 8.5], "texture": "#7"},
"west": {"uv": [5.5, 0, 6, 8.5], "texture": "#7"},
"up": {"uv": [0, 0, 6, 0.5], "texture": "#7"},
"down": {"uv": [0, 8, 6, 8.5], "texture": "#7"}
}
}
],
"gui_light": "front",
"display": {
"thirdperson_righthand": {
"translation": [0, 1.75, -7],
"scale": [0.25, 0.25, 1]
},
"thirdperson_lefthand": {
"translation": [0, 1.25, -7],
"scale": [0.25, 0.25, 1]
},
"firstperson_righthand": {
"translation": [5.5, 2.75, -12.5]
},
"firstperson_lefthand": {
"translation": [5.5, 2.75, -12.5]
},
"ground": {
"rotation": [90, 0, 0],
"translation": [0, 4.25, 0]
},
"gui": {
"scale": [0.75, 0.75, 1]
},
"fixed": {
"translation": [0, 0, -8]
},
"head": {
"translation": [0, 0, 0]
}
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "cubenetcore:block/skytech_block"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "cubenetcore:block/terrain_block"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

View File

@ -1,13 +0,0 @@
{
"itemGroup.examplemod": "Example Mod Tab",
"block.examplemod.example_block": "Example Block",
"item.examplemod.example_item": "Example Item",
"examplemod.configuration.title": "Example Mod Configs",
"examplemod.configuration.section.examplemod.common.toml": "Example Mod Configs",
"examplemod.configuration.section.examplemod.common.toml.title": "Example Mod Configs",
"examplemod.configuration.items": "Item List",
"examplemod.configuration.logDirtBlock": "Log Dirt Block",
"examplemod.configuration.magicNumberIntroduction": "Magic Number Text",
"examplemod.configuration.magicNumber": "Magic Number"
}

BIN
src/main/resources/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB