Skip to content

Commit

Permalink
Completed some TODOs
Browse files Browse the repository at this point in the history
  • Loading branch information
Dream-Rainy committed May 2, 2023
1 parent 596599b commit 1fd282e
Show file tree
Hide file tree
Showing 16 changed files with 427 additions and 115 deletions.
27 changes: 15 additions & 12 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ core {

### 1.玩家商店

玩家可以使用指令`/villagershop create shop <shopname> <x y z> <item> <count> <price>`创建商店[^1],并扣除一定的货币。
玩家可以使用指令`/villagershop create shop <shopname> <x y z> <item> <count> <price>`[^1]创建商店,并扣除一定的货币。
货币的花费会随着玩家拥有商店数量的增加而增加,函数表达式为:

```math
Expand All @@ -38,7 +38,7 @@ f(x)

**注意**

- 商店刚创建或商品刚添加时商品的库存为0,你需要在创建完成后额外使用`/villagershop item addstock <shopname> <item> [count]`来进行“补货”,`count`是一个可选参数,若不填则默认消耗背包内所有特定物品。
- 商店刚创建或商品刚添加时默认会使用背包内所有已有物品进行免费补货,你也在创建完成后额外使用`/villagershop item addstock <shopname> <item> [count]`来对商店中**存在的商品**进行“补货”,`count`是一个可选参数,若不填则默认消耗背包内所有特定物品。
同时,补货需要消耗一定的货币,计算公式如下:

```math
Expand All @@ -51,37 +51,40 @@ f(x) = p \times c \times t
- 同一玩家创建的商店**不允许**名称相同,当个商店的商品**数量上限为7个物品**,价格下限**不低于**服务器设置的物价或系统商店物价。
- 创建商店时的`count`参数代表用`price`的钱可以买到`count`个数的物品
举个栗子,比如我使用`/villagershop create shop air 0 0 0 minecraft:air 2 100`创建了一个出售`air`的商店。那么,我可以使用`100`货币买到`2`个`air`。而不是商店中`air`的库存为`2`。
举个栗子,比如我使用`/villagershop create shop DreamRain 0 0 0 minecraft:cherry_leaves 2 100`创建了一个名为`DreamRain`并出售`樱花树叶`的商店。那么,我可以使用`100`货币买到`2`个`樱花树叶`。而不是商店中`樱花树叶`的库存为`2`。
- 所有商店都有一个唯一的`shopnumber`标识符,并且永远不可能重复。
### 2.系统商店
管理员可以使用指令`/villagershop create adminshop <shopname> <x y z> <item1> <count>:<price> <item2> <count>:<price> ... <item_n> <count>:<price>`来创建系统商店。
系统商店库存**无限**,但是可以根据情况限制单个玩家的购买数量
系统商店库存**无限**,但是可以使用玩家商店中的`stock`参数来限制单个玩家的购买数量
## 三、商店管理
### 1.货物设置
在商店创建成功后,玩家可以使用`/villagershop item add <shopname> <item> <count> <price>`来添加商品,使用`/villagershop item change <shopname> <item> <count> <price>`来修改**已有**商品的价格以及出售数量,使用`/villagershop item delete <shopname> <item>`来删除已有的商品[^1]
在商店创建成功后,玩家可以使用`/villagershop item add <shopname> <item> <count> <price>`来添加商品,使用`/villagershop item change <shopname> <item> <count> <price>`来修改**已有**商品的价格以及出售数量,使用`/villagershop item delete <shopname> <item>`[^1]来删除已有的商品,该操作会返还该商品的所有库存。
### 2.商店设置
玩家可以使用`/villagershop manager info set <shopname> {shopnamenew,x y z}`来修改商店的名称或者位置。当你不想要该商店时,可以使用`/villagershop delete {shopname,shopnumber}`[^1]来删除该商店,管理员可以使用`shopnumber`删除任意不符合规定的商店,无需提前通知拥有者。删除商店会返还所有的库存,但是并不会返还创建时消耗的货币。
同时,管理员可以使用`/villagershop manager search {shopname:shopname, location:location, owner:owner}`,owner参数暂时只允许使用玩家的uuid,可以使用`/villagershop manager inquire <shopnumber>`获取特定商店的详细信息。
管理员在征得玩家以及管理组同意的情况下,可以使用`/villagershop setAdmin <shopnumber>`[^1]来将该商店转化为系统商店。
玩家可以使用`/villagershop manager info set <shopname> {shopnamenew,x y z}`来修改商店的名称或者位置。当你不想要该商店时,可以使用`/villagershop delete {shopname,shopnumber}`[^1]来删除该商店,管理员可以使用`shopnumber`删除任意不符合规定的商店,无需提前通知拥有者。删除商店会返还所有的库存,但是并不会返还创建时消耗的货币。同时,被管理员删除的商店并不会返还库存
同时,管理员可以使用`/villagershop manager search {shopname:shopname, location:location, owner:owner, range:range}`,owner参数可以使用玩家**创建商店时**的ID。可以使用`/villagershop manager inquire <shopnumber>`获取特定商店的详细信息。
管理员在征得玩家以及管理组同意的情况下,可以使用`/villagershop setAdmin <shopnumber>`[^1]来将该商店转化为系统商店。**注意,该操作也不会返还库存。**
## 四、收购相关
服务器在特定时间(如每半小时)就系统商店中已在出售的一种物品发起一次收购,拥有物品的玩家可以使用`/villagershop sell <count>`出售指定数量的收购物品,达到收购数量后服务器停止收购。
服务器在特定时间(如每半小时)就系统商店中已在出售的一种物品发起一次收购,拥有物品的玩家可以使用`/villagershop sell [count]`出售指定数量的收购物品,达到收购数量后服务器停止收购。
收购价格为系统商店在售价格的**80%**
## 五、其他
### TODO:
- [ ] 商店创建时即消耗背包内的物品补货
- [x] 商店创建或物品添加时即消耗背包内的物品补货
- [x] 删除商店或商品时返还库存
- [ ] 补货时可以从玩家身上的潜影盒中获取所需物品
- [ ] 支持范围搜索商店,以及通过玩家名称搜索商店,搜索结果添加所满足条件,不输出重复结果。
- [ ] 完成收购指令以及商店的实体创建。
- [ ] 系统商店限制单个玩家购买数量
- [x] 支持范围搜索商店,以及通过玩家名称搜索商店,不输出重复结果。
- [x] 完成收购指令
- [ ] 完成商店的实体创建以及GUI呈现
[^1]: 对于该指令,你需要使用`/villagershop confirm`来确定执行。同时,你可以使用`/villagershop cancel`来取消操作,所有操作在60s后都会自动取消。并且,在执行下一个需要确认的操作前,你需要先确认已有的操作。
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx4G
org.gradle.jvmargs=-Xmx1G

# Gradle Plugins
kotlin_version=1.8.20
Expand Down
15 changes: 0 additions & 15 deletions src/main/java/com/imyvm/villagerShop/mixin/ExampleMixin.java

This file was deleted.

22 changes: 22 additions & 0 deletions src/main/java/com/imyvm/villagerShop/mixin/NoCollisionMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.imyvm.villagerShop.mixin;

import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(Entity.class)
public abstract class NoCollisionMixin {

@Inject(method = "isCollidable", at = @At("HEAD"), cancellable = true)
private void isCollidable(CallbackInfoReturnable<Boolean> callback) {
// 获取实体的NBT数据
Entity Entity = (Entity) (Object) this;

// 判断实体的NBT数据中是否包含特定键值
if (Entity.getScoreboardTags().contains("VillagerShop")) {
callback.setReturnValue(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.imyvm.villagerShop.mixin;

import net.minecraft.command.argument.EntityAnchorArgumentType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.imyvm.villagerShop.VillagerShopMain;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.Box;
import java.util.List;
@Mixin(VillagerEntity.class)
public class VillagerCanMoveMixin {

@Inject(method = "tick", at = @At("HEAD"), cancellable = true)
public void tick(CallbackInfo ci) {
VillagerEntity villager = (VillagerEntity) (Object) this;
Box searchBox = villager.getBoundingBox().expand(10);
List<PlayerEntity> nearbyPlayers = villager.world.getEntitiesByClass(PlayerEntity.class, searchBox, player -> true);

if (villager.getScoreboardTags().contains("VillagerShop")&& !nearbyPlayers.isEmpty()) {
// 阻止村民移动
villager.setVelocity(0, villager.getVelocity().y, 0);

// 允许村民继续看向玩家
PlayerEntity targetPlayer = nearbyPlayers.get(0);
Vec3d targetPlayerPosition = targetPlayer.getPos().add(0, targetPlayer.getEyeHeight(targetPlayer.getPose()), 0);
villager.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, targetPlayerPosition);
}
// 取消后续方法调用
ci.cancel();
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.imyvm.villagerShop.mixin;

import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.passive.PassiveEntity;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(VillagerEntity.class)
public abstract class VillagerPreventWitchMixin extends PassiveEntity {

public VillagerPreventWitchMixin(EntityType<? extends PassiveEntity> entityType, World world) {
super(entityType, world);
}

@Inject(method = "onStruckByLightning", at = @At("HEAD"), cancellable = true)
private void preventWitchTransformation(CallbackInfo ci) {
LivingEntity livingEntity = this;
if (livingEntity.getScoreboardTags().contains("VillagerShop")) {
ci.cancel();
}
}
}
9 changes: 8 additions & 1 deletion src/main/kotlin/com/imyvm/villagerShop/VillagerShopMain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
import com.imyvm.villagerShop.apis.ModConfig
import com.imyvm.villagerShop.commands.register
import com.imyvm.villagerShop.commands.itemPurchaseMain
import com.imyvm.villagerShop.shops.spawnInvulnerableVillager
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
import org.slf4j.Logger
import org.slf4j.LoggerFactory

Expand All @@ -13,12 +16,16 @@ class VillagerShopMain : ModInitializer {
CommandRegistrationCallback.EVENT.register { dispatcher, commandRegistryAccess, registrationEnvironment ->
register(dispatcher, commandRegistryAccess, registrationEnvironment)
}
itemPurchaseMain()
LOGGER.info("Imyvm Villager Shop initialized")
ServerLifecycleEvents.SERVER_STARTED.register { server ->
println("服务器已启动: ${server.worlds}")
}
}
companion object {
@JvmField
val LOGGER: Logger = LoggerFactory.getLogger("imyvm-villagershop")
const val MOD_ID = "imyvm-villagershop"
const val MOD_ID = "imyvm_villagershop"
val CONFIG: ModConfig = ModConfig()
}
}
Loading

0 comments on commit 1fd282e

Please sign in to comment.