如何做一个商店

By MCSugar_cane    2018/02/04

在服务器里什么必不可少?当然是商店啦,毕竟有了交♂易,游戏才有乐趣嘛。本教程将从最基础的教你如何制作商店,如果你还是嫌麻烦,可以试试这个原版模组:箱子商店系统

PS: 代码在1.11-1.12版本下编写,其他版本请自行测试


目录:

  1. 以物换物的商店
  2. 以货换物的商店
  3. 更高级的商店


以物换物的商店:

通常这种商店在目前的PE(移动端)中出现得较多,PC(电脑端)中也可以使用,不过大部分PC端服务器的以物换物都选用的村民,在这里只针对于使用命令方块的系统进行讨论。其用的方法通常如下:

例如用6个甘蔗(reeds)换一个铁锭(iron_ingot),我们先做一个商店的雏形,并让它看上去不那么突兀~

我的世界如何做商店

接下来就到命令方块上场了,在按钮输出信号的后方放置命令方块,使其为如下图中的样子(为第二个命令方块连锁开启条件制约

我的世界如何做商店

在第一个命令方块脉冲中输入

  1. clear @p reeds 0 6

在第二个命令方块连锁(条件制约)中输入

  1. give @p iron_ingot 1 0

这样,当第一个命令方块中的clear执行成功后,第二个被条件制约的命令方块连锁才会执行。也就是说,只有当最近玩家背包被清除6个甘蔗后,give才会被执行。

接下来再给它美化一下,使玩家购买成功、物品不足时,都能被告知

  1. scoreboard players tag @p add deficiency [脉冲]
  2. clear @p reeds 0 6 [连锁]
  3. give @p iron_ingot 1 0 [连锁](条件制约)
  4. tellraw @p ["\u00a76\u00a7l[小铺子] \u00a7a\u00a7l购买成功!"] [连锁](条件制约)
  5. scoreboard players tag @p remove deficiency [连锁](条件制约)
  6. tellraw @p[tag=deficidency] ["\u00a76\u00a7l[小铺子] \u00a7c\u00a7l你需要甘蔗\u00a76x6"] [连锁]
  7. scoreboard players tag @p remove deficiency [连锁](条件制约)

当玩家触发后,首先会被加上deficiency标签。

若该玩家有6个及以上的甘蔗,则clear执行成功,继而clear后的条件制约(03,04,05)被依次执行,玩家deficiency标签被移除。因为此时玩家没有deficiency标签,后面的tellraw因没有目标而无法执行,继而07无法被执行;

若玩家没有6个及以上的甘蔗,clear执行失败,继而条件制约(03,04,05)无法被执行,玩家依然具有deficiency标签,tellraw执行成功,继而07被执行,移除玩家的deficiency标签。

月亮岛服主: 看起来不错,我的服务器里正好需要这个,你能来为我们做一个吗?

甘小蔗: 看,很快就有生意找上门了嘛,快去试试手吧!


在你做好后,服务器里的玩家都十分激动,一夜之间商店销售额成功突破10万!可好景不长,第二天,月亮岛服主的服务器就有人反映商店系统出了问题

aa622: 我发现这个商店原来有漏洞,躲在其他人后面按钮会帮别人买商品!嘘,不要告诉其他人。

木一: 发生了什么!?我在看商品的时候,身上的甘蔗突然少了6个,还多了1个铁锭,可我根本没有购买啊!

如上诉问题所说,因为选择器@p的问题,导致按钮被按下后,选中的是离命令方块最近的玩家,而非按下按钮的玩家,如下图:

我的世界如何做商店

若蓝色羊毛玩家按下按钮,选择器@p被执行,选择了距离最近的绿色羊毛玩家。悄悄告诉你,绝大部分服务器都有这样的问题,你还能看到它们如出一辙的"请靠近商店购买"。

不过是否有方法杜绝这一问题呢,几乎所有的服务器都用的踏板来解决的这个问题,那是不是只有用踏板了呢?废话当然还有啦,不然我还有怎么继续尬下去......

我们还可以借告示牌中的clickEvent来解决这个问题,而利用的就是最先我在1.8版本中发现的一个"特性"——如果告示牌中的指令如没有绝对(相对)坐标,则是在玩家位置执行。如下

我的世界如何做商店

我在绿色羊毛和蓝色羊毛出分别生成了"iam0"与"iam1",然后在按钮背后的命令方块中写入指令/say @e[c=1]

我的世界如何做商店

完成后站在"iam1"旁边按下了按钮,结果毫无悬念的选择了离命令方块最近的实体"iam0"

之后我又用

  1. /give @p minecraft:sign 1 0 {BlockEntityTag:{Text1:"{\"text\":\"点我点我\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"say @e[c=1]\"}}"}}

指令获取了一个右击会执行/say @e[c=1]的告示牌,并在放按钮处替换掉了按钮。再后又站在"iam1"旁并右击告示牌,结果如下

我的世界如何做商店

告示牌中的命令在我的位置被执行了,所以选中的最近实体自然是我自己了。利用这个原理,我们就可以做一个更高级的商店啦!详情见: 更高级的商店



以货换物的商店:

另外一种在无插件服务器中较流行的商店就是计分板中的交易咯,与物物交换相比,此交易更便捷、拓展性更高

通常服务器中的计分板交易都比较简单,稍复杂一点的如下:(2个money记分购买1个苹果)

  1. scoreboard players test @p money * 1 [脉冲]
  2. tellraw @p ["\u00a76\u00a7l[小铺子] \u00a7c\u00a7l现金不足,你至少需要\u00a76¥2"] [连锁](条件制约)
  3. scoreboard players test @p money 2 * [连锁]
  4. give @p apple [连锁](条件制约)
  5. tellraw @p ["\u00a76\u00a7l[小铺子] \u00a7a\u00a7l购买成功!"] [连锁](条件制约)
  6. scoreboard players remove @p money 2 [连锁](条件制约)

01.scoreboard players test @p money * 1为检测最近玩家的money分数值是否在最小值(-2147483647)到1之间

03.scoreboard players test @p money 2 *为检测最近玩家的money分数值是否在2到最大值(2147483647)之间

当然,这个系统与上诉的clear臭味相投,都是指定的最近玩家而非触发玩家。不过,做在告示牌里用trigger就好啦~详情见: 更高级的商店



更高级的商店:

在前面就已经提到告示牌可以解决对触发玩家的选中,所以我们可以利用告示牌中的clickEvent执行trigger指令来使玩家通过右击告示牌购买商品。至于为什么要用trigger呢,这你就要质问下告示牌为什么不允许无权限的玩家执行其他指令啦

首先大致想一下系统的构成,分别是触发模块,处理模块(执行模块)。如触发利用/trigger设置玩家Shop分值。当玩家Shop计分板分值=1时,为购买物品1;Shop分值=2时,则为购买物品2。然后针对Shop不同值的玩家做不同的处理

再制作一个玩家右键执行/trigger Shop set 1的告示牌,如一个显示出售苹果的告示牌

  1. /give @p minecraft:sign 1 0 {BlockEntityTag:{Text1:"{\"text\":\"[小商铺]\",\"italic\":\"false\",\"color\":\"dark_red\",\"extra\":[\"\"],\"clickEvent\":{\"action\":\"run_command\",\"value\":\"trigger Shop set 1\"}}",Text2:"{\"text\":\"SHOP\",\"bold\":\"true\",\"strikethrough\":\"false\",\"color\":\"dark_red\",\"extra\":[\"\"],\"clickEvent\":{\"action\":\"run_command\",\"value\":\"\"}}",Text3:"{\"text\":\"出售\",\"italic\":\"false\",\"color\":\"dark_blue\",\"extra\":[\"\\u00a7l苹果\"],\"clickEvent\":{\"action\":\"run_command\",\"value\":\"\"}}",Text4:"{\"text\":\"价格\",\"color\":\"dark_blue\",\"extra\":[\"\\u00a7l¥2\"],\"clickEvent\":{\"action\":\"run_command\",\"value\":\"\"}}"}}

为了使玩家能够执行/trigger Shop set 1我们还需要创建trigger类型的计分板并enble,这里的enble我与处理模块写在一起了~

  1. /scoreboard objectives add Shop trigger

处理模块:[循环执行]

  1. /scoreboard players enable @a Shop
  2. tellraw @a[score_Shop_min=1,score_Shop=1,score_money=1] ["\u00a7c\u00a7l现金不足,你至少需要\u00a76¥2"]
  3. tellraw @a[score_Shop_min=1,score_Shop=1,score_money_min=2] ["\u00a72\u00a7l你已成功购买苹果\u00a76x1"]
  4. give @a[score_Shop_min=1,score_Shop=1,score_money_min=2] apple 1 0
  5. scoreboard players remove @a[score_Shop_min=1,score_Shop=1,score_money_min=2] money 2
  6. scoreboard players set @a Shop 0