加特效,加特技Duang!Duang!Duang!
记得原版了有2个物品的贴图会不断改变
钟和指南针,今天就是参考这两个物品的代码写的
1.给proxy新的功能
我们先来了解一下有哪些方法可以只让单边读取
点击图片查看原网址
但如果有要写在物品的构造函数里的单边函数,以上的方法都行不通
所以我们要自己创造一个方法
在CommonProxy里新建一个方法
public interface CommonProxy {
public void init();
abstract public boolean isServerSider();
}
abstract表示必须要重写这个方法
之后再ClientProxy里添加这个方法
@Override
public boolean isServerSider() {
return false;
}
ServerProxy里也要
@Override
public boolean isServerSider() {
return true;
}
2.研究动态贴图
好接下来我们看一下ItemClock和ItemCompass
有什么共同的东西
他们都有this.addPropertyOverride(new ResourceLocation("xxxx"), new IItemPropertyGetter(){
...
public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn){
...
}
}
注意new ResourceLocation("angle")里面的参数名
呢我们看一下 IItemPropertyGetter()里是什么
所以 IItemPropertyGetter(){后面的 public float apply()应该就是直接实现了这个方法,注意到这个方法的回传是一个float
然后我们去看看ItemCompass的json文件
我们打开 compass.json
{
"parent": "item/generated",
"textures": {
"layer0": "items/compass_16"
},
"overrides": [
{ "predicate": { "angle": 0.000000 }, "model": "item/compass" },
{ "predicate": { "angle": 0.015625 }, "model": "item/compass_17" },
{ "predicate": { "angle": 0.046875 }, "model": "item/compass_18" },
{ "predicate": { "angle": 0.078125 }, "model": "item/compass_19" },
{ "predicate": { "angle": 0.109375 }, "model": "item/compass_20" },
{ "predicate": { "angle": 0.140625 }, "model": "item/compass_21" },
{ "predicate": { "angle": 0.171875 }, "model": "item/compass_22" },
{ "predicate": { "angle": 0.203125 }, "model": "item/compass_23" },
{ "predicate": { "angle": 0.234375 }, "model": "item/compass_24" },
{ "predicate": { "angle": 0.265625 }, "model": "item/compass_25" },
{ "predicate": { "angle": 0.296875 }, "model": "item/compass_26" },
{ "predicate": { "angle": 0.328125 }, "model": "item/compass_27" },
{ "predicate": { "angle": 0.359375 }, "model": "item/compass_28" },
{ "predicate": { "angle": 0.390625 }, "model": "item/compass_29" },
{ "predicate": { "angle": 0.421875 }, "model": "item/compass_30" },
{ "predicate": { "angle": 0.453125 }, "model": "item/compass_31" },
{ "predicate": { "angle": 0.484375 }, "model": "item/compass_00" },
{ "predicate": { "angle": 0.515625 }, "model": "item/compass_01" },
{ "predicate": { "angle": 0.546875 }, "model": "item/compass_02" },
{ "predicate": { "angle": 0.578125 }, "model": "item/compass_03" },
{ "predicate": { "angle": 0.609375 }, "model": "item/compass_04" },
{ "predicate": { "angle": 0.640625 }, "model": "item/compass_05" },
{ "predicate": { "angle": 0.671875 }, "model": "item/compass_06" },
{ "predicate": { "angle": 0.703125 }, "model": "item/compass_07" },
{ "predicate": { "angle": 0.734375 }, "model": "item/compass_08" },
{ "predicate": { "angle": 0.765625 }, "model": "item/compass_09" },
{ "predicate": { "angle": 0.796875 }, "model": "item/compass_10" },
{ "predicate": { "angle": 0.828125 }, "model": "item/compass_11" },
{ "predicate": { "angle": 0.859375 }, "model": "item/compass_12" },
{ "predicate": { "angle": 0.890625 }, "model": "item/compass_13" },
{ "predicate": { "angle": 0.921875 }, "model": "item/compass_14" },
{ "predicate": { "angle": 0.953125 }, "model": "item/compass_15" },
{ "predicate": { "angle": 0.984375 }, "model": "item/compass" }
]
}
不难发现"angle"就是上面打在this.addPropertyOverride()里面的参数
而这些0.625526的数字就是apply的回传值,用此值判断所在区间
0.000000~0.015624就跑去读取 "model": "item/compass"
0.015625~0.046874就派去读取 "model": "item/compass_17"
...
3.自制动态贴图
好既然我们已经知道动态贴图的秘密了我们就自己做一个吧
在compass里的apply方法,官方在每一个变数和和方法上面加上
@SideOnly(Side.CLIENT)注解来实现单边读取,而我们可以用之前做的proxy判断法来实现
现在我们回到ItemBloodsave的构造函数里添加一句
public ItemBloodsave(){
setUnlocalizedName("itembloodsave");
setRegistryName("itembloodsave");
setCreativeTab(CreativeTabs.MATERIALS);
setMaxStackSize(1);
if(!Main.proxy.isServerSider())this.addPropertyOverride(new ResourceLocation("bloodsave"), new ItemBloodsaveTextures());
}
这样只有客户端会执行此句话
我们设定参数名为"bloodsave"
new 一个 ItemBloodsaveTextures()这里我们还没创建会报错
我们现在来创建ItemBloodsaveTextures()
在ItemBloodsaveTextures里输入
public class ItemBloodsaveTextures implements IItemPropertyGetter{
@Override
public float apply(ItemStack stack, World worldIn, EntityLivingBase entityIn) {
if(worldIn == null && entityIn != null)
worldIn = entityIn.getEntityWorld();//玩家背包內的物品沒有世界
if (worldIn != null && stack.getTagCompound() != null && stack.getTagCompound().hasKey("blood")){//阻擋創造模式物品欄
return stack.getTagCompound().getInteger("bloodsave");
}
return 0;
}
}
这里我来解释一下,apply是每一个ItemBloodsave,不管在地上,手里,箱子里,玩家物品栏里,创造模式物品栏里,
每一tick都会执行一次(20tick=1sec)
经过我的测试,在不同地方的物品的输入值也不一样
玩家物品栏 worldIn == null,entityIn != null
地上 worldIn != null,entityIn == null
手里 worldIn != null,entityIn != null
创造模式物品栏 worldIn == null,entityIn == null
我们的物品必须被玩家右击以后才有nbt资料
而创造模式物品栏里的item是不可能有nbt资料的,如果硬要去读取则会崩溃
所以以上代码让还没有nbt的血瓶以及创造模式物品栏内的血瓶回传值为0
其他则读取nbt资料来回传1~20
接下来就剩下json文件和把贴图放进去了
我们回到models.item.itembloodsave.json里改写
{
"parent": "item/generated",
"textures": {
"layer0": "soa:items/itembloodsave"
},
"overrides": [
{ "predicate": { "bloodsave": 0 }, "model": "soa:item/itembloodsave" },
{ "predicate": { "bloodsave": 1 }, "model": "soa:item/itembloodsave_1" },
{ "predicate": { "bloodsave": 8 }, "model": "soa:item/itembloodsave_2" },
{ "predicate": { "bloodsave": 13 }, "model": "soa:item/itembloodsave_3" },
{ "predicate": { "bloodsave": 20 }, "model": "soa:item/itembloodsave_4" }
]
}
apply回传值↓
0→"model": "soa:item/itembloodsave"
1~7→"model": "soa:item/itembloodsave_1"
8~12→"model": "soa:item/itembloodsave_2"
13~19→ "model": "soa:item/itembloodsave_3"
20→"model": "soa:item/itembloodsave_4"
再来把1,2,3,4models补上
我就写itembloodsave_1.json的内容吧
{
"parent": "item/generated",
"textures": {
"layer0": "soa:items/itembloodsave_1"
}
}
"layer0": "soa:items/itembloodsave_1"就是导向的贴图文件路径我之前也说过了
其他的json只是导向不同的贴图文件路径而已我就不写出来了
附上贴图文件,应该知道要丢哪里了吧(textures.items里)
itembloodsave_1
itembloodsave_2
itembloodsave_3
itembloodsave_4
好我们进游戏看看
好,物品的高级玩法似乎就剩多态没讲了我
也是尽量希望做一个实用,并且可以把教程融合在一起的物品
不知道这个血瓶你喜不喜欢呢~
源代码
src_教程6.rar
(10.5 KB, 下载次数: 29)
记得原版了有2个物品的贴图会不断改变
钟和指南针,今天就是参考这两个物品的代码写的
1.给proxy新的功能
我们先来了解一下有哪些方法可以只让单边读取

点击图片查看原网址
但如果有要写在物品的构造函数里的单边函数,以上的方法都行不通
所以我们要自己创造一个方法
在CommonProxy里新建一个方法
public interface CommonProxy {
public void init();
abstract public boolean isServerSider();
}
abstract表示必须要重写这个方法
之后再ClientProxy里添加这个方法
@Override
public boolean isServerSider() {
return false;
}
ServerProxy里也要
@Override
public boolean isServerSider() {
return true;
}
2.研究动态贴图
好接下来我们看一下ItemClock和ItemCompass
有什么共同的东西


他们都有this.addPropertyOverride(new ResourceLocation("xxxx"), new IItemPropertyGetter(){
...
public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn){
...
}
}
注意new ResourceLocation("angle")里面的参数名
呢我们看一下 IItemPropertyGetter()里是什么

所以 IItemPropertyGetter(){后面的 public float apply()应该就是直接实现了这个方法,注意到这个方法的回传是一个float
然后我们去看看ItemCompass的json文件


我们打开 compass.json
{
"parent": "item/generated",
"textures": {
"layer0": "items/compass_16"
},
"overrides": [
{ "predicate": { "angle": 0.000000 }, "model": "item/compass" },
{ "predicate": { "angle": 0.015625 }, "model": "item/compass_17" },
{ "predicate": { "angle": 0.046875 }, "model": "item/compass_18" },
{ "predicate": { "angle": 0.078125 }, "model": "item/compass_19" },
{ "predicate": { "angle": 0.109375 }, "model": "item/compass_20" },
{ "predicate": { "angle": 0.140625 }, "model": "item/compass_21" },
{ "predicate": { "angle": 0.171875 }, "model": "item/compass_22" },
{ "predicate": { "angle": 0.203125 }, "model": "item/compass_23" },
{ "predicate": { "angle": 0.234375 }, "model": "item/compass_24" },
{ "predicate": { "angle": 0.265625 }, "model": "item/compass_25" },
{ "predicate": { "angle": 0.296875 }, "model": "item/compass_26" },
{ "predicate": { "angle": 0.328125 }, "model": "item/compass_27" },
{ "predicate": { "angle": 0.359375 }, "model": "item/compass_28" },
{ "predicate": { "angle": 0.390625 }, "model": "item/compass_29" },
{ "predicate": { "angle": 0.421875 }, "model": "item/compass_30" },
{ "predicate": { "angle": 0.453125 }, "model": "item/compass_31" },
{ "predicate": { "angle": 0.484375 }, "model": "item/compass_00" },
{ "predicate": { "angle": 0.515625 }, "model": "item/compass_01" },
{ "predicate": { "angle": 0.546875 }, "model": "item/compass_02" },
{ "predicate": { "angle": 0.578125 }, "model": "item/compass_03" },
{ "predicate": { "angle": 0.609375 }, "model": "item/compass_04" },
{ "predicate": { "angle": 0.640625 }, "model": "item/compass_05" },
{ "predicate": { "angle": 0.671875 }, "model": "item/compass_06" },
{ "predicate": { "angle": 0.703125 }, "model": "item/compass_07" },
{ "predicate": { "angle": 0.734375 }, "model": "item/compass_08" },
{ "predicate": { "angle": 0.765625 }, "model": "item/compass_09" },
{ "predicate": { "angle": 0.796875 }, "model": "item/compass_10" },
{ "predicate": { "angle": 0.828125 }, "model": "item/compass_11" },
{ "predicate": { "angle": 0.859375 }, "model": "item/compass_12" },
{ "predicate": { "angle": 0.890625 }, "model": "item/compass_13" },
{ "predicate": { "angle": 0.921875 }, "model": "item/compass_14" },
{ "predicate": { "angle": 0.953125 }, "model": "item/compass_15" },
{ "predicate": { "angle": 0.984375 }, "model": "item/compass" }
]
}
不难发现"angle"就是上面打在this.addPropertyOverride()里面的参数
而这些0.625526的数字就是apply的回传值,用此值判断所在区间
0.000000~0.015624就跑去读取 "model": "item/compass"
0.015625~0.046874就派去读取 "model": "item/compass_17"
...
3.自制动态贴图
好既然我们已经知道动态贴图的秘密了我们就自己做一个吧
在compass里的apply方法,官方在每一个变数和和方法上面加上
@SideOnly(Side.CLIENT)注解来实现单边读取,而我们可以用之前做的proxy判断法来实现
现在我们回到ItemBloodsave的构造函数里添加一句
public ItemBloodsave(){
setUnlocalizedName("itembloodsave");
setRegistryName("itembloodsave");
setCreativeTab(CreativeTabs.MATERIALS);
setMaxStackSize(1);
if(!Main.proxy.isServerSider())this.addPropertyOverride(new ResourceLocation("bloodsave"), new ItemBloodsaveTextures());
}
这样只有客户端会执行此句话
我们设定参数名为"bloodsave"
new 一个 ItemBloodsaveTextures()这里我们还没创建会报错
我们现在来创建ItemBloodsaveTextures()

在ItemBloodsaveTextures里输入
public class ItemBloodsaveTextures implements IItemPropertyGetter{
@Override
public float apply(ItemStack stack, World worldIn, EntityLivingBase entityIn) {
if(worldIn == null && entityIn != null)
worldIn = entityIn.getEntityWorld();//玩家背包內的物品沒有世界
if (worldIn != null && stack.getTagCompound() != null && stack.getTagCompound().hasKey("blood")){//阻擋創造模式物品欄
return stack.getTagCompound().getInteger("bloodsave");
}
return 0;
}
}
这里我来解释一下,apply是每一个ItemBloodsave,不管在地上,手里,箱子里,玩家物品栏里,创造模式物品栏里,
每一tick都会执行一次(20tick=1sec)
经过我的测试,在不同地方的物品的输入值也不一样
玩家物品栏 worldIn == null,entityIn != null
地上 worldIn != null,entityIn == null
手里 worldIn != null,entityIn != null
创造模式物品栏 worldIn == null,entityIn == null
我们的物品必须被玩家右击以后才有nbt资料
而创造模式物品栏里的item是不可能有nbt资料的,如果硬要去读取则会崩溃
所以以上代码让还没有nbt的血瓶以及创造模式物品栏内的血瓶回传值为0
其他则读取nbt资料来回传1~20
接下来就剩下json文件和把贴图放进去了
我们回到models.item.itembloodsave.json里改写
{
"parent": "item/generated",
"textures": {
"layer0": "soa:items/itembloodsave"
},
"overrides": [
{ "predicate": { "bloodsave": 0 },"model": "soa:item/itembloodsave" },
{ "predicate": { "bloodsave": 1 },"model": "soa:item/itembloodsave_1"},
{ "predicate": { "bloodsave": 8 }, "model": "soa:item/itembloodsave_2" },
{ "predicate": { "bloodsave": 13 }, "model": "soa:item/itembloodsave_3" },
{ "predicate": { "bloodsave": 20 }, "model": "soa:item/itembloodsave_4" }
]
}
apply回传值↓
0→"model": "soa:item/itembloodsave"
1~7→"model": "soa:item/itembloodsave_1"
8~12→"model": "soa:item/itembloodsave_2"
13~19→ "model": "soa:item/itembloodsave_3"
20→"model": "soa:item/itembloodsave_4"
再来把1,2,3,4models补上

我就写itembloodsave_1.json的内容吧
{
"parent": "item/generated",
"textures": {
"layer0": "soa:items/itembloodsave_1"
}
}
"layer0": "soa:items/itembloodsave_1"就是导向的贴图文件路径我之前也说过了
其他的json只是导向不同的贴图文件路径而已我就不写出来了
附上贴图文件,应该知道要丢哪里了吧(textures.items里)
itembloodsave_1
itembloodsave_2
itembloodsave_3
itembloodsave_4
好我们进游戏看看



好,物品的高级玩法似乎就剩多态没讲了我
也是尽量希望做一个实用,并且可以把教程融合在一起的物品
不知道这个血瓶你喜不喜欢呢~
源代码
记得原版了有2个物品的贴图会不断改变
钟和指南针,今天就是参考这两个物品的代码写的
1.给proxy新的功能
我们先来了解一下有哪些方法可以只让单边读取
点击图片查看原网址
但如果有要写在物品的构造函数里的单边函数,以上的方法都行不通
所以我们要自己创造一个方法
在CommonProxy里新建一个方法
public interface CommonProxy {
public void init();
abstract public boolean isServerSider();
}
abstract表示必须要重写这个方法
之后再ClientProxy里添加这个方法
@Override
public boolean isServerSider() {
return false;
}
ServerProxy里也要
@Override
public boolean isServerSider() {
return true;
}
2.研究动态贴图
好接下来我们看一下ItemClock和ItemCompass
有什么共同的东西
他们都有this.addPropertyOverride(new ResourceLocation("xxxx"), new IItemPropertyGetter(){
...
public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn){
...
}
}
注意new ResourceLocation("angle")里面的参数名
呢我们看一下 IItemPropertyGetter()里是什么
所以 IItemPropertyGetter(){后面的 public float apply()应该就是直接实现了这个方法,注意到这个方法的回传是一个float
然后我们去看看ItemCompass的json文件
我们打开 compass.json
{
"parent": "item/generated",
"textures": {
"layer0": "items/compass_16"
},
"overrides": [
{ "predicate": { "angle": 0.000000 }, "model": "item/compass" },
{ "predicate": { "angle": 0.015625 }, "model": "item/compass_17" },
{ "predicate": { "angle": 0.046875 }, "model": "item/compass_18" },
{ "predicate": { "angle": 0.078125 }, "model": "item/compass_19" },
{ "predicate": { "angle": 0.109375 }, "model": "item/compass_20" },
{ "predicate": { "angle": 0.140625 }, "model": "item/compass_21" },
{ "predicate": { "angle": 0.171875 }, "model": "item/compass_22" },
{ "predicate": { "angle": 0.203125 }, "model": "item/compass_23" },
{ "predicate": { "angle": 0.234375 }, "model": "item/compass_24" },
{ "predicate": { "angle": 0.265625 }, "model": "item/compass_25" },
{ "predicate": { "angle": 0.296875 }, "model": "item/compass_26" },
{ "predicate": { "angle": 0.328125 }, "model": "item/compass_27" },
{ "predicate": { "angle": 0.359375 }, "model": "item/compass_28" },
{ "predicate": { "angle": 0.390625 }, "model": "item/compass_29" },
{ "predicate": { "angle": 0.421875 }, "model": "item/compass_30" },
{ "predicate": { "angle": 0.453125 }, "model": "item/compass_31" },
{ "predicate": { "angle": 0.484375 }, "model": "item/compass_00" },
{ "predicate": { "angle": 0.515625 }, "model": "item/compass_01" },
{ "predicate": { "angle": 0.546875 }, "model": "item/compass_02" },
{ "predicate": { "angle": 0.578125 }, "model": "item/compass_03" },
{ "predicate": { "angle": 0.609375 }, "model": "item/compass_04" },
{ "predicate": { "angle": 0.640625 }, "model": "item/compass_05" },
{ "predicate": { "angle": 0.671875 }, "model": "item/compass_06" },
{ "predicate": { "angle": 0.703125 }, "model": "item/compass_07" },
{ "predicate": { "angle": 0.734375 }, "model": "item/compass_08" },
{ "predicate": { "angle": 0.765625 }, "model": "item/compass_09" },
{ "predicate": { "angle": 0.796875 }, "model": "item/compass_10" },
{ "predicate": { "angle": 0.828125 }, "model": "item/compass_11" },
{ "predicate": { "angle": 0.859375 }, "model": "item/compass_12" },
{ "predicate": { "angle": 0.890625 }, "model": "item/compass_13" },
{ "predicate": { "angle": 0.921875 }, "model": "item/compass_14" },
{ "predicate": { "angle": 0.953125 }, "model": "item/compass_15" },
{ "predicate": { "angle": 0.984375 }, "model": "item/compass" }
]
}
不难发现"angle"就是上面打在this.addPropertyOverride()里面的参数
而这些0.625526的数字就是apply的回传值,用此值判断所在区间
0.000000~0.015624就跑去读取 "model": "item/compass"
0.015625~0.046874就派去读取 "model": "item/compass_17"
...
3.自制动态贴图
好既然我们已经知道动态贴图的秘密了我们就自己做一个吧
在compass里的apply方法,官方在每一个变数和和方法上面加上
@SideOnly(Side.CLIENT)注解来实现单边读取,而我们可以用之前做的proxy判断法来实现
现在我们回到ItemBloodsave的构造函数里添加一句
public ItemBloodsave(){
setUnlocalizedName("itembloodsave");
setRegistryName("itembloodsave");
setCreativeTab(CreativeTabs.MATERIALS);
setMaxStackSize(1);
if(!Main.proxy.isServerSider())this.addPropertyOverride(new ResourceLocation("bloodsave"), new ItemBloodsaveTextures());
}
这样只有客户端会执行此句话
我们设定参数名为"bloodsave"
new 一个 ItemBloodsaveTextures()这里我们还没创建会报错
我们现在来创建ItemBloodsaveTextures()
在ItemBloodsaveTextures里输入
public class ItemBloodsaveTextures implements IItemPropertyGetter{
@Override
public float apply(ItemStack stack, World worldIn, EntityLivingBase entityIn) {
if(worldIn == null && entityIn != null)
worldIn = entityIn.getEntityWorld();//玩家背包內的物品沒有世界
if (worldIn != null && stack.getTagCompound() != null && stack.getTagCompound().hasKey("blood")){//阻擋創造模式物品欄
return stack.getTagCompound().getInteger("bloodsave");
}
return 0;
}
}
这里我来解释一下,apply是每一个ItemBloodsave,不管在地上,手里,箱子里,玩家物品栏里,创造模式物品栏里,
每一tick都会执行一次(20tick=1sec)
经过我的测试,在不同地方的物品的输入值也不一样
玩家物品栏 worldIn == null,entityIn != null
地上 worldIn != null,entityIn == null
手里 worldIn != null,entityIn != null
创造模式物品栏 worldIn == null,entityIn == null
我们的物品必须被玩家右击以后才有nbt资料
而创造模式物品栏里的item是不可能有nbt资料的,如果硬要去读取则会崩溃
所以以上代码让还没有nbt的血瓶以及创造模式物品栏内的血瓶回传值为0
其他则读取nbt资料来回传1~20
接下来就剩下json文件和把贴图放进去了
我们回到models.item.itembloodsave.json里改写
{
"parent": "item/generated",
"textures": {
"layer0": "soa:items/itembloodsave"
},
"overrides": [
{ "predicate": { "bloodsave": 0 }, "model": "soa:item/itembloodsave" },
{ "predicate": { "bloodsave": 1 }, "model": "soa:item/itembloodsave_1" },
{ "predicate": { "bloodsave": 8 }, "model": "soa:item/itembloodsave_2" },
{ "predicate": { "bloodsave": 13 }, "model": "soa:item/itembloodsave_3" },
{ "predicate": { "bloodsave": 20 }, "model": "soa:item/itembloodsave_4" }
]
}
apply回传值↓
0→"model": "soa:item/itembloodsave"
1~7→"model": "soa:item/itembloodsave_1"
8~12→"model": "soa:item/itembloodsave_2"
13~19→ "model": "soa:item/itembloodsave_3"
20→"model": "soa:item/itembloodsave_4"
再来把1,2,3,4models补上
我就写itembloodsave_1.json的内容吧
{
"parent": "item/generated",
"textures": {
"layer0": "soa:items/itembloodsave_1"
}
}
"layer0": "soa:items/itembloodsave_1"就是导向的贴图文件路径我之前也说过了
其他的json只是导向不同的贴图文件路径而已我就不写出来了
附上贴图文件,应该知道要丢哪里了吧(textures.items里)
好我们进游戏看看
好,物品的高级玩法似乎就剩多态没讲了我
也是尽量希望做一个实用,并且可以把教程融合在一起的物品
不知道这个血瓶你喜不喜欢呢~
源代码
2021.12 数据,可能有更多内容
加特效,加特技Duang!Duang!Duang!记得原版了有2个物品的贴图会不断改变
钟和指南针,今天就是参考这两个物品的代码写的
1.给proxy新的功能
我们先来了解一下有哪些方法可以只让单边读取

点击图片查看原网址
但如果有要写在物品的构造函数里的单边函数,以上的方法都行不通
所以我们要自己创造一个方法
在CommonProxy里新建一个方法
public interface CommonProxy {
public void init();
abstract public boolean isServerSider();
}
abstract表示必须要重写这个方法
之后再ClientProxy里添加这个方法
@Override
public boolean isServerSider() {
return false;
}
ServerProxy里也要
@Override
public boolean isServerSider() {
return true;
}
2.研究动态贴图
好接下来我们看一下ItemClock和ItemCompass
有什么共同的东西


他们都有this.addPropertyOverride(new ResourceLocation("xxxx"), new IItemPropertyGetter(){
...
public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn){
...
}
}
注意new ResourceLocation("angle")里面的参数名
呢我们看一下 IItemPropertyGetter()里是什么

所以 IItemPropertyGetter(){后面的 public float apply()应该就是直接实现了这个方法,注意到这个方法的回传是一个float
然后我们去看看ItemCompass的json文件


我们打开 compass.json
{
"parent": "item/generated",
"textures": {
"layer0": "items/compass_16"
},
"overrides": [
{ "predicate": { "angle": 0.000000 }, "model": "item/compass" },
{ "predicate": { "angle": 0.015625 }, "model": "item/compass_17" },
{ "predicate": { "angle": 0.046875 }, "model": "item/compass_18" },
{ "predicate": { "angle": 0.078125 }, "model": "item/compass_19" },
{ "predicate": { "angle": 0.109375 }, "model": "item/compass_20" },
{ "predicate": { "angle": 0.140625 }, "model": "item/compass_21" },
{ "predicate": { "angle": 0.171875 }, "model": "item/compass_22" },
{ "predicate": { "angle": 0.203125 }, "model": "item/compass_23" },
{ "predicate": { "angle": 0.234375 }, "model": "item/compass_24" },
{ "predicate": { "angle": 0.265625 }, "model": "item/compass_25" },
{ "predicate": { "angle": 0.296875 }, "model": "item/compass_26" },
{ "predicate": { "angle": 0.328125 }, "model": "item/compass_27" },
{ "predicate": { "angle": 0.359375 }, "model": "item/compass_28" },
{ "predicate": { "angle": 0.390625 }, "model": "item/compass_29" },
{ "predicate": { "angle": 0.421875 }, "model": "item/compass_30" },
{ "predicate": { "angle": 0.453125 }, "model": "item/compass_31" },
{ "predicate": { "angle": 0.484375 }, "model": "item/compass_00" },
{ "predicate": { "angle": 0.515625 }, "model": "item/compass_01" },
{ "predicate": { "angle": 0.546875 }, "model": "item/compass_02" },
{ "predicate": { "angle": 0.578125 }, "model": "item/compass_03" },
{ "predicate": { "angle": 0.609375 }, "model": "item/compass_04" },
{ "predicate": { "angle": 0.640625 }, "model": "item/compass_05" },
{ "predicate": { "angle": 0.671875 }, "model": "item/compass_06" },
{ "predicate": { "angle": 0.703125 }, "model": "item/compass_07" },
{ "predicate": { "angle": 0.734375 }, "model": "item/compass_08" },
{ "predicate": { "angle": 0.765625 }, "model": "item/compass_09" },
{ "predicate": { "angle": 0.796875 }, "model": "item/compass_10" },
{ "predicate": { "angle": 0.828125 }, "model": "item/compass_11" },
{ "predicate": { "angle": 0.859375 }, "model": "item/compass_12" },
{ "predicate": { "angle": 0.890625 }, "model": "item/compass_13" },
{ "predicate": { "angle": 0.921875 }, "model": "item/compass_14" },
{ "predicate": { "angle": 0.953125 }, "model": "item/compass_15" },
{ "predicate": { "angle": 0.984375 }, "model": "item/compass" }
]
}
不难发现"angle"就是上面打在this.addPropertyOverride()里面的参数
而这些0.625526的数字就是apply的回传值,用此值判断所在区间
0.000000~0.015624就跑去读取 "model": "item/compass"
0.015625~0.046874就派去读取 "model": "item/compass_17"
...
3.自制动态贴图
好既然我们已经知道动态贴图的秘密了我们就自己做一个吧
在compass里的apply方法,官方在每一个变数和和方法上面加上
@SideOnly(Side.CLIENT)注解来实现单边读取,而我们可以用之前做的proxy判断法来实现
现在我们回到ItemBloodsave的构造函数里添加一句
public ItemBloodsave(){
setUnlocalizedName("itembloodsave");
setRegistryName("itembloodsave");
setCreativeTab(CreativeTabs.MATERIALS);
setMaxStackSize(1);
if(!Main.proxy.isServerSider())this.addPropertyOverride(new ResourceLocation("bloodsave"), new ItemBloodsaveTextures());
}
这样只有客户端会执行此句话
我们设定参数名为"bloodsave"
new 一个 ItemBloodsaveTextures()这里我们还没创建会报错
我们现在来创建ItemBloodsaveTextures()

在ItemBloodsaveTextures里输入
public class ItemBloodsaveTextures implements IItemPropertyGetter{
@Override
public float apply(ItemStack stack, World worldIn, EntityLivingBase entityIn) {
if(worldIn == null && entityIn != null)
worldIn = entityIn.getEntityWorld();//玩家背包內的物品沒有世界
if (worldIn != null && stack.getTagCompound() != null && stack.getTagCompound().hasKey("blood")){//阻擋創造模式物品欄
return stack.getTagCompound().getInteger("bloodsave");
}
return 0;
}
}
这里我来解释一下,apply是每一个ItemBloodsave,不管在地上,手里,箱子里,玩家物品栏里,创造模式物品栏里,
每一tick都会执行一次(20tick=1sec)
经过我的测试,在不同地方的物品的输入值也不一样
玩家物品栏 worldIn == null,entityIn != null
地上 worldIn != null,entityIn == null
手里 worldIn != null,entityIn != null
创造模式物品栏 worldIn == null,entityIn == null
我们的物品必须被玩家右击以后才有nbt资料
而创造模式物品栏里的item是不可能有nbt资料的,如果硬要去读取则会崩溃
所以以上代码让还没有nbt的血瓶以及创造模式物品栏内的血瓶回传值为0
其他则读取nbt资料来回传1~20
接下来就剩下json文件和把贴图放进去了
我们回到models.item.itembloodsave.json里改写
{
"parent": "item/generated",
"textures": {
"layer0": "soa:items/itembloodsave"
},
"overrides": [
{ "predicate": { "bloodsave": 0 },"model": "soa:item/itembloodsave" },
{ "predicate": { "bloodsave": 1 },"model": "soa:item/itembloodsave_1"},
{ "predicate": { "bloodsave": 8 }, "model": "soa:item/itembloodsave_2" },
{ "predicate": { "bloodsave": 13 }, "model": "soa:item/itembloodsave_3" },
{ "predicate": { "bloodsave": 20 }, "model": "soa:item/itembloodsave_4" }
]
}
apply回传值↓
0→"model": "soa:item/itembloodsave"
1~7→"model": "soa:item/itembloodsave_1"
8~12→"model": "soa:item/itembloodsave_2"
13~19→ "model": "soa:item/itembloodsave_3"
20→"model": "soa:item/itembloodsave_4"
再来把1,2,3,4models补上

我就写itembloodsave_1.json的内容吧
{
"parent": "item/generated",
"textures": {
"layer0": "soa:items/itembloodsave_1"
}
}
"layer0": "soa:items/itembloodsave_1"就是导向的贴图文件路径我之前也说过了
其他的json只是导向不同的贴图文件路径而已我就不写出来了
附上贴图文件,应该知道要丢哪里了吧(textures.items里)




好我们进游戏看看



好,物品的高级玩法似乎就剩多态没讲了我
也是尽量希望做一个实用,并且可以把教程融合在一起的物品
不知道这个血瓶你喜不喜欢呢~
源代码
666666顶顶顶
楼主忽略了一种情况:展示框
我试了一下,不知道对不对,创造物品栏是无世界有实体的(知道打开物品栏时是这样),展示框是无世界无实体,所以第二个 if 那里不用判断 worldln 就行了
顶顶顶!!!
没有报错,存血取血功能正常,但就是不回根据血液存储量更新贴图,伤心
物品代码:
复制代码
item 的json 文件
复制代码
panda_blood_item_1.json
复制代码
物品代码:
- public class PandaBlood extends Item{
- private static final String name = "panda_blood";
-
- public PandaBlood() {
- super();
- setRegistryName(name);
- setUnlocalizedName(INFO.MODID+":"+name+"_item");
- setCreativeTab(CreativeTabs.MATERIALS);
- setMaxStackSize(1);
- this.addPropertyOverride(new ResourceLocation("blood_save"),
- new IItemPropertyGetter() {
- @SideOnly(Side.CLIENT)
- public float apply(ItemStack stack, World worldIn, EntityLivingBase entityIn) {
- boolean flag = entityIn != null;
- entityIn.sendMessage(new TextComponentString("YOU ARE "+entityIn.getName()+
- "your panda blood is "+stack.getTagCompound().getInteger("blood_save")));
- Entity entity = (Entity)(flag ? entityIn : stack.getItemFrame());
- if(worldIn == null && entityIn != null) {
- worldIn = entity.world;
- }
- if(worldIn != null && stack.getTagCompound() != null && stack.getTagCompound().hasKey("blood")) {
- return (float)stack.getTagCompound().getInteger("blood_save");
- }
- return 0F;
- }
- });
- }
-
- @Override
- public void addInformation(ItemStack stack, World worldIn, List<String> tooltip,ITooltipFlag flagIn) {
- if(flagIn.isAdvanced()) {
- tooltip.add("This is ");
- tooltip.add("a Panda Blood");
- }
- else {
- tooltip.add(I18n.format(this.getUnlocalizedName()+".1."+"desc"));
- }
- if(org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LSHIFT)) {
- tooltip.add(I18n.format(this.getUnlocalizedName()+".shift.1."+"desc"));
- }
- NBTTagCompound nbt = stack.getTagCompound();
- if(nbt!=null && nbt.hasKey("blood_save")) {
- tooltip.add("blood:"+nbt.getInteger("blood_save"));
- }
- }
-
- @Override
- public int getMaxItemUseDuration(ItemStack stack) {
- return 32;
- }
-
- @Override
- public EnumAction getItemUseAction(ItemStack stack) {
- return EnumAction.DRINK;
- }
-
- // 血瓶功能
- @Override
- public ActionResult<ItemStack> onItemRightClick(World worldIn,EntityPlayer player,EnumHand hand){
- player.setActiveHand(hand);
- if(!worldIn.isRemote) {
- ItemStack item = player.getHeldItem(hand);
- // 如果第一次使用,初始化一个内部nbt
- if(item.getTagCompound()==null) {
- player.sendMessage(new TextComponentString("Seems the first time to use...activated!"));
- item.setTagCompound(new NBTTagCompound());
-
- NBTTagCompound nbt = new NBTTagCompound();
- nbt.setInteger("blood_save", 0);
-
- item.getTagCompound().setTag("blood", nbt);
- }
-
- int bloodSave = item.getTagCompound().getInteger("blood_save");
- if(player.isSneaking() && bloodSave<20) {
- int damage = new Random().nextInt(10)+1;
- player.sendMessage(new TextComponentString("health take: "+damage));
- player.setHealth(player.isCreative()?player.getHealth()-0:player.getHealth()-damage);
- if(bloodSave+damage > 20) {
- item.getTagCompound().setInteger("blood_save", 20);
- player.sendMessage(new TextComponentString("Panda Blood seems full..."));
- }else {
- item.getTagCompound().setInteger("blood_save", bloodSave+damage);
- player.sendMessage(new TextComponentString("Now it's "+item.getTagCompound().getInteger("blood_save")+"/20"));
- }
- player.stopActiveHand();
- }else if(player.isSneaking() && bloodSave == 20) {
- player.sendMessage(new TextComponentString("hey! your panda blood is already full!"));
- }
- }
- return super.onItemRightClick(worldIn, player, hand);
- }
-
- @Override
- public ItemStack onItemUseFinish(ItemStack item, World world, EntityLivingBase player) {
- if(!world.isRemote) {
- int bloodSave = item.getTagCompound().getInteger("blood_save");
- float health = player.getHealth();
- float maxHealth = player.getMaxHealth();
- float heal = Math.min(maxHealth-health, bloodSave);
- player.heal(heal);
- item.getTagCompound().setInteger("blood_save", bloodSave-(int)heal);
- player.sendMessage(new TextComponentString("Panda Blood heals you "+(int)heal+" health"));
- player.sendMessage(new TextComponentString("Now it's "+item.getTagCompound().getInteger("blood_save")+"/20"));
- }
- return super.onItemUseFinish(item, world, player);
- }
- }
item 的json 文件
- {
- "parent":"item/generated",
- "textures":{
- "layer0":"panda_mod:panda_blood_texture"
- },
- "Overrides":[
- {"predicate":{"blood_save":0.0},"model":"panda_mod:item/panda_blood_item"},
- {"predicate":{"blood_save":1.0},"model":"panda_mod:item/panda_blood_item_1"},
- {"predicate":{"blood_save":5.0},"model":"panda_mod:item/panda_blood_item_2"},
- {"predicate":{"blood_save":13.0},"model":"panda_mod:item/panda_blood_item_3"},
- {"predicate":{"blood_save":20.0},"model":"panda_mod:item/panda_blood_item_4"}
- ]
- }
panda_blood_item_1.json
- {
- "parent":"item/generated",
- "textures":{
- "layer0":"panda_mod:panda_blood_texture_1"
- }
egod 发表于 2019-4-19 22:54
没有报错,存血取血功能正常,但就是不回根据血液存储量更新贴图,伤心
物品代码:
forge 版本 1.12.2