Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ bin/
run/
!**/src/**/run/
**/src/generated/**/.cache/
**/src/hfas/resources/.cache/
repo/
!**/src/**/repo/
55 changes: 51 additions & 4 deletions CHANGE_LOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ All notable changes to the Wild Wind Module project will be documented in this f
#### 5. 木质方块功能
- **去皮功能** - 使用斧头可将原木/木头去皮
- **堆肥功能** - 树叶和树苗可用于堆肥(30%概率)
- **燃料功能** - 木质方块可作为熔炉燃料(300 tick)
- **燃料功能** - 木质方块可作为熔炉燃料(由 NeoForge `furnace_fuels` 数据地图提供)

### 技术实现

Expand Down Expand Up @@ -71,7 +71,6 @@ All notable changes to the Wild Wind Module project will be documented in this f
|--------------------------------|------------|
| `FletchingTableReplaceHandler` | 区块加载时替换制箭台 |
| `BlockFeaturesHandler` | 方块功能(堆肥等) |
| `FuelHandler` | 燃料事件处理 |

#### Mixin 注入
| 类 | 功能 |
Expand Down Expand Up @@ -110,8 +109,7 @@ src/hfas/java/org/polaris2023/wildwind/hfas/
│ ├── ModDataMapsProvider.java
├── event/ # 事件处理
│ ├── FletchingTableReplaceHandler.java
│ ├── BlockFeaturesHandler.java
│ └── FuelHandler.java
│ └── BlockFeaturesHandler.java
├── mixin/ # Mixin 注入
│ └── AzaleaBlockMixin.java
├── config/ # 配置文件
Expand Down Expand Up @@ -182,3 +180,52 @@ src/hfas/java/org/polaris2023/wildwind/hfas/
- [ ] 更多下界植物
- [ ] 制箭台配方系统
- [ ] 成就系统

---

## [Unreleased] - 2026.10.23

### Added
- **木材家族聚合** - 新增 `WoodFamily` 与 `ModWoodFamilies`,模型、战利品、标签、数据地图、创造物品栏统一遍历,不再各写一份 13~15 参数列表
- **方块战利品表** - 注册 `BlockLoot`,`ModLootProvider` 此前只挂了实体战利品,方块战利品表完全缺失
- **燃料数据地图** - 使用 NeoForge `furnace_fuels` 数据地图注册燃料(原木/木头/去皮/木板/楼梯/栅栏/栅栏门/压力板 300 tick,台阶 150,按钮与树苗 100)
- **补全方块标签** - `logs_that_burn`、`c:stripped_logs`、`c:stripped_woods`、`fences`、`fence_gates`、`wooden_fences`,原先只写在手写 JSON 里

### Changed
- 模型、战利品、标签、创造物品栏提供器改为遍历 `ModWoodFamilies.ALL`
- `ModItemTagsProvider` 改继承 `net.neoforged.neoforge.common.data.ItemTagsProvider`
- 创造物品栏的 62 行 `insertAfter` 链收敛为 `appendWoodSet()`
- 燃料由 `FurnaceFuelBurnTimeEvent` 事件改为数据地图驱动,移除 `FuelHandler`

### Fixed
- **活板门不掉落** - 原先误用 `createDoorTable`(带 `half=lower` 条件),天花板上的活板门破坏后无掉落,改为 `dropSelf`,与 `VanillaBlockLoot` 一致
- **木质方块被误加入 `needs_stone_tool`** - 导致木板、门、按钮等必须石级工具才能挖掘掉落,已移除该标签注册
- **Gradle 9 下资源重复项报错** - 原 `.cache` 排除模式相对 srcDir 根无效,已修正并显式设置 `duplicatesStrategy`

### Removed
- **回滚 PR #29 的资源污染** - 删除 438 个与 datagen 产物同名的手写 `blockstates` / `models` / `items` / `data` 文件,以及 130 个未注册方块(sign / boat / potted sapling)的孤儿资源,仅保留 80 个 datagen 无法重建的文件
- **被提交进 `src` 的 datagen HashCache** - 删除 `src/hfas/resources/.cache/`(9 个文件),它会令 datagen 误判"已生成"而跳过重写
- **重复的标签与语言文件** - 删除 15 个与 datagen 输出同名的 JSON(datagen 每次重新生成,无信息丢失)
- **改名前的重复贴图** - 删除 26 张与 `blaze_*` / `soul_*` 逐字节相同的 `cinder_*` / `ember_*`(含 `.mcmeta`),无信息丢失;另有 28 张没有对应新命名版本的贴图(船 / 箱船 / 告示牌 / 悬挂告示牌的实体贴图与物品图标、`gui/hanging_signs`、`screens`)全部保留,作为后续船与告示牌开发的素材
- **`ModBlockTagsProvider.INSTANCE`** - 无人使用的静态单例

---

## [Unreleased] - 2026.10.25

### Added
- **树苗花盆方块** - 注册 `potted_blaze_sapling` / `potted_soul_sapling`,使用原版 `FlowerPotBlock(树苗, props)` 构造器,构造时自动把树苗登记进原版空花盆的可放入映射表,无需额外的手工 `addPlant`
- **花盆模型与战利品表** - `ModModelProvider` 用 `createPlant()` 一次生成树苗交叉模型 + 花盆模型(含 blockstate),`BlockLoot` 用 `dropPottedContents()` 生成「花盆 + 树苗」两池掉落,与原版 `potted_oak_sapling` 一致
- **花盆方块本地化** - `block.ww_hfas.potted_blaze_sapling` / `potted_soul_sapling`,en_us 为 `Potted Blaze Sapling` / `Potted Soul Sapling`,zh_cn 为 `焚烬木树苗盆栽` / `灵焰木树苗盆栽`
- **食人鱼拍打音效** - 新增 `entity.piranha.flop` SoundEvent(`createVariableRangeEvent`)与 `subtitles.entity.piranha.flop` 字幕(en_us `Piranha flops` / zh_cn `食人鱼拍打`)

### Changed
- **食人鱼 `getFlopSound()`** - 由原版 `SoundEvents.SALMON_FLOP` 改为自有 `ModSoundEvents.PIRANHA_FLOP`,移除遗留的 `// WIP SOUND` 标记
- **`sounds.json` 暂借原版音源** - `entity.piranha.flop` 以 `sounds: [{ "type": "event", "name": "minecraft:entity.salmon.flop" }]` 引用原版鲑鱼拍打声;待有独立 `.ogg` 后把该条目替换为文件列表即可,事件 ID 与字幕键均无需变动

### Fixed
- **`minecraft:flower_pots` 标签加载失败** - 标签内引用的 `ww_hfas:potted_blaze_sapling` / `ww_hfas:potted_soul_sapling` 此前没有对应注册,`TagLoader` 报 `Couldn't load tag minecraft:flower_pots as it is missing following references`;现两个方块均已注册(BUG-TG-001)
- **杜鹃木 / 焚烬木 / 灵焰木木板无法合成** - `azalea_planks` / `blaze_planks` / `soul_planks` 的 `ingredients` 误写为单个方块 id(`ww_hfas:blaze_log` 等),改为物品标签 `#ww_hfas:azalea_logs` / `#ww_hfas:blaze_logs` / `#ww_hfas:soul_logs`,原木、木头与两种去皮变体都能参与合成(BUG-TG-002)
- **食人鱼 flop 无声音且字幕不显示** - `sounds.json` 曾把 `type` / `name` 写在事件层级并缺少 `sounds` 数组,`SoundEventRegistrationSerializer.getSounds()` 解析出空音源,事件播放被丢弃;已改为把 `type: "event"` 内嵌在 sound 条目中


11 changes: 10 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import org.gradle.api.file.DuplicatesStrategy
import org.slf4j.event.Level.INFO
import java.util.Locale

Expand Down Expand Up @@ -71,7 +72,10 @@ allprojects {
srcDir(rootProject.file("src/${project.name}/resources"))

exclude("**/*.bbmodel")
exclude("build/generated/**/.cache")
// datagen 的 hash 缓存目录,位于 client/server 两个 srcDir 根下,
// 同名 entry 会在 processResources 里触发 duplicate 错误,必须排除
exclude("**/.cache/**")
exclude(".cache/**")
}
}
}
Expand All @@ -93,6 +97,11 @@ allprojects {

java.toolchain.languageVersion = JavaLanguageVersion.of(25)

// Gradle 9 对资源重复项默认报错;保持既有语义:先生成的 srcDir(build/generated)优先
tasks.withType<ProcessResources>().configureEach {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

neoForge {
version = neoVersion

Expand Down
7 changes: 7 additions & 0 deletions src/hfas/java/org/polaris2023/wildwind/hfas/HFASMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ public HFASMod(IEventBus bus, ModContainer container) {
// 注册属性
ModAttributes.register(bus);

// 注册状态效果、药水
ModMobEffects.register(bus);
ModPotions.register(bus);

// 注册食人鱼音效
ModSoundEvents.register(bus);

// 注册配置文件
container.registerConfig(net.neoforged.fml.config.ModConfig.Type.COMMON, ModCommonConfig.SPEC);

Expand Down
20 changes: 20 additions & 0 deletions src/hfas/java/org/polaris2023/wildwind/hfas/block/ModBlocks.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,16 @@ public class ModBlocks {
.randomTicks())
);

// 焚烬木树苗花盆(原版构造器,会自动把树苗登记进原版花盆的映射表)
@SuppressWarnings("deprecation")
public static final DeferredBlock<FlowerPotBlock> POTTED_BLAZE_SAPLING = BLOCKS.registerBlock(
"potted_blaze_sapling",
p -> new FlowerPotBlock(BLAZE_SAPLING.get(), p
.instabreak()
.noOcclusion()
.pushReaction(PushReaction.DESTROY))
);

// ==================== 灵焰木套件 (soul_wood) ====================

// 灵焰木原木
Expand Down Expand Up @@ -333,6 +343,16 @@ public class ModBlocks {
.randomTicks())
);

// 灵焰木树苗花盆(原版构造器,会自动把树苗登记进原版花盆的映射表)
@SuppressWarnings("deprecation")
public static final DeferredBlock<FlowerPotBlock> POTTED_SOUL_SAPLING = BLOCKS.registerBlock(
"potted_soul_sapling",
p -> new FlowerPotBlock(SOUL_SAPLING.get(), p
.instabreak()
.noOcclusion()
.pushReaction(PushReaction.DESTROY))
);

// ==================== 杜鹃木套件 (azalea_wood) ====================

// 杜鹃木原木
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.polaris2023.wildwind.hfas.block;

import java.util.List;

/**
* 模组木材家族清单。
* <p>
* 各 datagen provider 统一遍历 {@link #ALL},避免同一条 13 参数列表在多个文件里重复维护。
* 这里只是对 {@link ModBlocks} 已注册方块的聚合,不参与注册。
*/
public final class ModWoodFamilies {

private ModWoodFamilies() {
}

/** 焚烬木(blaze) */
public static final WoodFamily BLAZE = new WoodFamily(
"blaze",
0xFF8000,
ModBlocks.BLAZE_LOG,
ModBlocks.BLAZE_WOOD,
ModBlocks.STRIPPED_BLAZE_LOG,
ModBlocks.STRIPPED_BLAZE_WOOD,
ModBlocks.BLAZE_PLANKS,
ModBlocks.BLAZE_STAIRS,
ModBlocks.BLAZE_SLAB,
ModBlocks.BLAZE_FENCE,
ModBlocks.BLAZE_FENCE_GATE,
ModBlocks.BLAZE_DOOR,
ModBlocks.BLAZE_TRAPDOOR,
ModBlocks.BLAZE_PRESSURE_PLATE,
ModBlocks.BLAZE_BUTTON,
ModBlocks.BLAZE_LEAVES,
ModBlocks.BLAZE_SAPLING
);

/** 灵焰木(soul) */
public static final WoodFamily SOUL = new WoodFamily(
"soul",
0x00FFFF,
ModBlocks.SOUL_LOG,
ModBlocks.SOUL_WOOD,
ModBlocks.STRIPPED_SOUL_LOG,
ModBlocks.STRIPPED_SOUL_WOOD,
ModBlocks.SOUL_PLANKS,
ModBlocks.SOUL_STAIRS,
ModBlocks.SOUL_SLAB,
ModBlocks.SOUL_FENCE,
ModBlocks.SOUL_FENCE_GATE,
ModBlocks.SOUL_DOOR,
ModBlocks.SOUL_TRAPDOOR,
ModBlocks.SOUL_PRESSURE_PLATE,
ModBlocks.SOUL_BUTTON,
ModBlocks.SOUL_LEAVES,
ModBlocks.SOUL_SAPLING
);

/** 杜鹃木(azalea):沿用原版树叶 / 树苗,没有自成套的树叶 */
public static final WoodFamily AZALEA = new WoodFamily(
"azalea",
0,
ModBlocks.AZALEA_LOG,
ModBlocks.AZALEA_WOOD,
ModBlocks.STRIPPED_AZALEA_LOG,
ModBlocks.STRIPPED_AZALEA_WOOD,
ModBlocks.AZALEA_PLANKS,
ModBlocks.AZALEA_STAIRS,
ModBlocks.AZALEA_SLAB,
ModBlocks.AZALEA_FENCE,
ModBlocks.AZALEA_FENCE_GATE,
ModBlocks.AZALEA_DOOR,
ModBlocks.AZALEA_TRAPDOOR,
ModBlocks.AZALEA_PRESSURE_PLATE,
ModBlocks.AZALEA_BUTTON,
null,
null
);

public static final List<WoodFamily> ALL = List.of(BLAZE, SOUL, AZALEA);
}
64 changes: 64 additions & 0 deletions src/hfas/java/org/polaris2023/wildwind/hfas/block/WoodFamily.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.polaris2023.wildwind.hfas.block;

import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.ButtonBlock;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.FenceBlock;
import net.minecraft.world.level.block.FenceGateBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.PressurePlateBlock;
import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.SaplingBlock;
import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.StairBlock;
import net.minecraft.world.level.block.TrapDoorBlock;
import net.neoforged.neoforge.registries.DeferredBlock;
import org.jspecify.annotations.Nullable;

import java.util.List;

/**
* 一种木材(方块家族)的聚合视图。
* <p>
* 方块注册仍由 {@link ModBlocks} 以显式字段完成,这里只做聚合,
* 让模型 / 战利品 / 标签 / 数据地图 / 物品栏等 provider 只需遍历一次,
* 不用在每个文件里重复抄 13~15 个参数。
*
* @param name 木材名(blaze / soul / azalea),用于拼接翻译与自建标签
* @param leavesTint 树叶物品图标的常数染色(无树叶时忽略)
*/
public record WoodFamily(
String name,
int leavesTint,
DeferredBlock<RotatedPillarBlock> log,
DeferredBlock<RotatedPillarBlock> wood,
DeferredBlock<RotatedPillarBlock> strippedLog,
DeferredBlock<RotatedPillarBlock> strippedWood,
DeferredBlock<Block> planks,
DeferredBlock<StairBlock> stairs,
DeferredBlock<SlabBlock> slab,
DeferredBlock<FenceBlock> fence,
DeferredBlock<FenceGateBlock> fenceGate,
DeferredBlock<DoorBlock> door,
DeferredBlock<TrapDoorBlock> trapdoor,
DeferredBlock<PressurePlateBlock> pressurePlate,
DeferredBlock<ButtonBlock> button,
@Nullable DeferredBlock<LeavesBlock> leaves,
@Nullable DeferredBlock<SaplingBlock> sapling
) {

/**
* 建筑套件方块(不含树叶 / 树苗),顺序即物品栏与标签的常规顺序。
*/
public List<DeferredBlock<? extends Block>> buildingBlocks() {
return List.of(log, wood, strippedLog, strippedWood, planks,
stairs, slab, fence, fenceGate, door, trapdoor, pressurePlate, button);
}

/**
* 是否带树叶与树苗(杜鹃木沿用原版,没有自成套的树叶)。
*/
public boolean hasLeaves() {
return leaves != null && sapling != null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.polaris2023.wildwind.hfas.client.entity.model;

import com.geckolib.model.DefaultedEntityGeoModel;
import com.geckolib.renderer.base.GeoRenderState;
import net.minecraft.resources.Identifier;
import org.polaris2023.wildwind.hfas.HFASMod;
import org.polaris2023.wildwind.hfas.entity.animal.Piranha;

/**
* 食人鱼实体的几何模型定义喵~
*/
public class PiranhaModel extends DefaultedEntityGeoModel<Piranha> {

/**
* 创建食人鱼模型实例喵~
*/
public PiranhaModel() {
super(HFASMod.id("piranha"));
}

/**
* 获取当前食人鱼对应的材质资源喵~
*/
@Override
public Identifier getTextureResource(GeoRenderState state) {
return HFASMod.id("textures/entity/piranha.png");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.polaris2023.wildwind.hfas.client.entity.renderer;

import com.geckolib.renderer.GeoEntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import org.polaris2023.wildwind.hfas.client.entity.model.PiranhaModel;
import org.polaris2023.wildwind.hfas.client.entity.renderstate.PiranhaRenderState;
import org.polaris2023.wildwind.hfas.entity.animal.Piranha;

import javax.annotation.Nullable;

/**
* 食人鱼渲染器
* @author huimanman
*/
public class PiranhaRenderer extends GeoEntityRenderer<Piranha, PiranhaRenderState> {
public PiranhaRenderer(EntityRendererProvider.Context renderManager) {
super(renderManager, new PiranhaModel());
}

@Override
public PiranhaRenderState createRenderState(Piranha animatable, @Nullable Void relatedObject) {
return new PiranhaRenderState();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.polaris2023.wildwind.hfas.client.entity.renderstate;

import net.minecraft.client.renderer.entity.state.LivingEntityRenderState;

/**
* 食人鱼渲染状态喵~
*/
public class PiranhaRenderState extends LivingEntityRenderState {
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
import org.polaris2023.wildwind.hfas.client.entity.renderer.MudcrabRenderer;
import org.polaris2023.wildwind.hfas.client.entity.renderer.PiranhaRenderer;
import org.polaris2023.wildwind.hfas.registry.ModEntities;

@EventBusSubscriber(value = Dist.CLIENT)
public class EntitiesClientHandler {
@SubscribeEvent
static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) {
event.registerEntityRenderer(ModEntities.PIRANHA.get(), PiranhaRenderer::new);
event.registerEntityRenderer(ModEntities.MUDCRAB.get(), MudcrabRenderer::new);
}
}
Loading
Loading