BlockCommands.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. package me.km.snuviscript.commands;
  2. import com.mojang.brigadier.StringReader;
  3. import me.hammerle.snuviscript.code.ScriptManager;
  4. import me.hammerle.snuviscript.code.SnuviUtils;
  5. import me.km.inventory.InventoryUtils;
  6. import me.km.utils.Location;
  7. import me.km.utils.Mapper;
  8. import me.km.utils.ReflectionUtils;
  9. import net.minecraft.block.*;
  10. import net.minecraft.block.material.Material;
  11. import net.minecraft.command.arguments.BlockStateParser;
  12. import net.minecraft.entity.Entity;
  13. import net.minecraft.entity.EntityType;
  14. import net.minecraft.entity.LivingEntity;
  15. import net.minecraft.entity.player.ServerPlayerEntity;
  16. import net.minecraft.fluid.FluidState;
  17. import net.minecraft.fluid.Fluids;
  18. import net.minecraft.inventory.IInventory;
  19. import net.minecraft.item.ItemStack;
  20. import net.minecraft.nbt.CompoundNBT;
  21. import net.minecraft.network.play.server.SUpdateTileEntityPacket;
  22. import net.minecraft.state.BooleanProperty;
  23. import net.minecraft.state.EnumProperty;
  24. import net.minecraft.state.IntegerProperty;
  25. import net.minecraft.state.Property;
  26. import net.minecraft.state.properties.ChestType;
  27. import net.minecraft.tags.BlockTags;
  28. import net.minecraft.tags.Tag;
  29. import net.minecraft.tileentity.*;
  30. import net.minecraft.util.Direction;
  31. import net.minecraft.util.ResourceLocation;
  32. import net.minecraft.util.math.BlockPos;
  33. import net.minecraft.util.text.StringTextComponent;
  34. import net.minecraft.world.IWorld;
  35. import net.minecraft.world.World;
  36. public class BlockCommands {
  37. private static class Offset {
  38. private final int x;
  39. private final int y;
  40. private final int z;
  41. public Offset(int x, int y, int z) {
  42. this.x = x;
  43. this.y = y;
  44. this.z = z;
  45. }
  46. }
  47. private static final Offset[] OFFSETS = new Offset[] {
  48. // new Offset(-1, -1, -1),
  49. new Offset(0, -1, -1),
  50. // new Offset(1, -1, -1),
  51. new Offset(-1, 0, -1), new Offset(0, 0, -1), new Offset(1, 0, -1),
  52. // new Offset(-1, 1, -1),
  53. new Offset(0, 1, -1),
  54. // new Offset(1, 1, -1),
  55. new Offset(-1, -1, 0), new Offset(0, -1, 0), new Offset(1, -1, 0), new Offset(-1, 0, 0),
  56. new Offset(0, 0, 0), new Offset(1, 0, 0), new Offset(-1, 1, 0), new Offset(0, 1, 0),
  57. new Offset(1, 1, 0),
  58. // new Offset(-1, -1, 1),
  59. new Offset(0, -1, 1),
  60. // new Offset(1, -1, 1),
  61. new Offset(-1, 0, 1), new Offset(0, 0, 1), new Offset(1, 0, 1),
  62. // new Offset(-1, 1, 1),
  63. new Offset(0, 1, 1), // new Offset(1, 1, 1),
  64. };
  65. @SuppressWarnings("deprecation")
  66. private static void breakBlock(World w, Entity e, BlockPos pos) {
  67. BlockState state = w.getBlockState(pos);
  68. if(state.isAir(w, pos)) {
  69. return;
  70. } else {
  71. FluidState fState = w.getFluidState(pos);
  72. if(!(state.getBlock() instanceof AbstractFireBlock)) {
  73. w.playEvent(2001, pos, Block.getStateId(state));
  74. }
  75. TileEntity te = state.hasTileEntity() ? w.getTileEntity(pos) : null;
  76. ItemStack stack = ItemStack.EMPTY;
  77. if(e instanceof LivingEntity) {
  78. stack = ((LivingEntity) e).getActiveItemStack();
  79. }
  80. Block.spawnDrops(state, w, pos, te, e, stack);
  81. w.setBlockState(pos, fState.getBlockState(), 3, 512);
  82. }
  83. }
  84. @SuppressWarnings({"unchecked", "rawtypes"})
  85. public static void registerFunctions(ScriptManager sm) {
  86. sm.registerFunction("block.gettag", (sc, in) -> BlockTags.getCollection()
  87. .get(new ResourceLocation(in[0].getString(sc))));
  88. sm.registerFunction("block.hastag",
  89. (sc, in) -> ((Tag<Block>) in[0].get(sc)).contains((Block) in[1].get(sc)));
  90. sm.registerFunction("block.gettype", (sc, in) -> {
  91. Location l = (Location) in[0].get(sc);
  92. return l.getWorld().getBlockState(l.getBlockPos()).getBlock().getRegistryName()
  93. .toString();
  94. });
  95. sm.registerFunction("block.isair", (sc, in) -> {
  96. Location l = (Location) in[0].get(sc);
  97. return l.getWorld().isAirBlock(l.getBlockPos());
  98. });
  99. sm.registerFunction("block.countair", (sc, in) -> {
  100. Location l = (Location) in[0].get(sc);
  101. IWorld w = l.getWorld();
  102. BlockPos oldPos = l.getBlockPos();
  103. BlockPos.Mutable pos =
  104. new BlockPos.Mutable(oldPos.getX(), oldPos.getY(), oldPos.getZ());
  105. int ox = pos.getX();
  106. int oy = pos.getY();
  107. int oz = pos.getZ();
  108. double counter = 0;
  109. for(Offset off : OFFSETS) {
  110. pos.setPos(ox + off.x, oy + off.y, oz + off.z);
  111. if(w.isAirBlock(pos)) {
  112. counter++;
  113. }
  114. }
  115. return counter;
  116. });
  117. sm.registerFunction("block.get", (sc, in) -> {
  118. Location l = (Location) in[0].get(sc);
  119. return l.getWorld().getBlockState(l.getBlockPos()).getBlock();
  120. });
  121. sm.registerFunction("block.getstate", (sc, in) -> {
  122. Location l = (Location) in[0].get(sc);
  123. return l.getWorld().getBlockState(l.getBlockPos());
  124. });
  125. sm.registerFunction("block.getproperties", (sc, in) -> {
  126. Location l = (Location) in[0].get(sc);
  127. return l.getWorld().getBlockState(l.getBlockPos()).getBlock().getStateContainer()
  128. .getProperties();
  129. });
  130. sm.registerFunction("block.getproperty",
  131. (sc, in) -> Mapper.getProperty(in[0].getString(sc)));
  132. sm.registerFunction("block.property.getvalue", (sc, in) -> {
  133. Location l = (Location) in[0].get(sc);
  134. Property<?> prop = (Property) in[1].get(sc);
  135. BlockState state = l.getWorld().getBlockState(l.getBlockPos());
  136. if(state.hasProperty(prop)) {
  137. Object o = l.getWorld().getBlockState(l.getBlockPos()).get(prop);
  138. if(o instanceof Number) {
  139. return ((Number) o).doubleValue();
  140. } else if(o instanceof Boolean) {
  141. return o;
  142. }
  143. return o.toString();
  144. }
  145. return null;
  146. });
  147. sm.registerConsumer("block.property.setint", (sc, in) -> {
  148. Location l = (Location) in[0].get(sc);
  149. World w = l.getWorld();
  150. BlockPos pos = l.getBlockPos();
  151. IntegerProperty prop = (IntegerProperty) in[1].get(sc);
  152. BlockState state = w.getBlockState(pos);
  153. w.setBlockState(pos, state.with(prop, in[2].getInt(sc)), 18);
  154. });
  155. sm.registerConsumer("block.property.setbool", (sc, in) -> {
  156. Location l = (Location) in[0].get(sc);
  157. World w = l.getWorld();
  158. BlockPos pos = l.getBlockPos();
  159. BooleanProperty prop = (BooleanProperty) in[1].get(sc);
  160. BlockState state = w.getBlockState(pos);
  161. w.setBlockState(pos, state.with(prop, in[2].getBoolean(sc)), 18);
  162. });
  163. sm.registerConsumer("block.property.setenum", (sc, in) -> {
  164. Location l = (Location) in[0].get(sc);
  165. World w = l.getWorld();
  166. BlockPos pos = l.getBlockPos();
  167. EnumProperty prop = (EnumProperty) in[1].get(sc);
  168. Enum e = (Enum) prop.parseValue(in[2].getString(sc)).get();
  169. BlockState state = w.getBlockState(pos);
  170. w.setBlockState(pos, state.with(prop, e), 18);
  171. });
  172. sm.registerConsumer("block.clone", (sc, in) -> {
  173. Location l0 = (Location) in[0].get(sc);
  174. Location l1 = (Location) in[1].get(sc);
  175. IWorld w0 = l0.getWorld();
  176. BlockPos pos0 = l0.getBlockPos();
  177. BlockState state = w0.getBlockState(pos0);
  178. TileEntity tileEnt0 = w0.getTileEntity(pos0);
  179. IWorld w1 = l1.getWorld();
  180. BlockPos pos1 = l1.getBlockPos();
  181. w1.setBlockState(pos1, state, 2);
  182. TileEntity tileEnt1 = w1.getTileEntity(pos1);
  183. if(tileEnt0 != null && tileEnt1 != null) {
  184. CompoundNBT nbt = tileEnt0.write(new CompoundNBT());
  185. nbt.putInt("x", pos1.getX());
  186. nbt.putInt("y", pos1.getY());
  187. nbt.putInt("z", pos1.getZ());
  188. tileEnt1.read(w1.getBlockState(pos1), nbt);
  189. tileEnt1.markDirty();
  190. }
  191. });
  192. sm.registerConsumer("block.break", (sc, in) -> {
  193. Location l = (Location) in[0].get(sc);
  194. breakBlock(l.getWorld(), (Entity) in[1].get(sc), l.getBlockPos());
  195. });
  196. sm.registerConsumer("block.set", (sc, in) -> {
  197. Location l = (Location) in[0].get(sc);
  198. BlockStateParser parser =
  199. new BlockStateParser(new StringReader(in[1].getString(sc)), true);
  200. BlockState state = parser.parse(true).getState();
  201. int flag = 2;
  202. if(in.length >= 3 && in[2].getBoolean(sc)) {
  203. flag |= 16;
  204. }
  205. l.getWorld().setBlockState(l.getBlockPos(), state, flag);
  206. });
  207. sm.registerFunction("block.newstate", (sc, in) -> {
  208. try {
  209. BlockStateParser parser =
  210. new BlockStateParser(new StringReader(in[0].getString(sc)), true);
  211. return parser.parse(true).getState();
  212. } catch(Exception e) {
  213. return null;
  214. }
  215. });
  216. sm.registerConsumer("block.setstate", (sc, in) -> {
  217. Location l = (Location) in[0].get(sc);
  218. int flag = 2;
  219. if(in.length >= 3 && in[2].getBoolean(sc)) {
  220. flag |= 16;
  221. }
  222. l.getWorld().setBlockState(l.getBlockPos(), (BlockState) in[1].get(sc), flag);
  223. });
  224. sm.registerFunction("block.setsign", (sc, in) -> {
  225. Location l = (Location) in[0].get(sc);
  226. TileEntity te = l.getWorld().getTileEntity(l.getBlockPos());
  227. if(te == null || !(te instanceof SignTileEntity)) {
  228. return false;
  229. }
  230. SignTileEntity sign = (SignTileEntity) te;
  231. sign.setText(in[1].getInt(sc), new StringTextComponent(SnuviUtils.connect(sc, in, 2)));
  232. SUpdateTileEntityPacket packet = sign.getUpdatePacket();
  233. l.getWorld().getPlayers()
  234. .forEach(p -> ((ServerPlayerEntity) p).connection.sendPacket(packet));
  235. return true;
  236. });
  237. sm.registerFunction("block.getsign", (sc, in) -> {
  238. Location l = (Location) in[0].get(sc);
  239. TileEntity te = l.getWorld().getTileEntity(l.getBlockPos());
  240. if(te == null || !(te instanceof SignTileEntity)) {
  241. return null;
  242. }
  243. return ReflectionUtils.getSignText((SignTileEntity) te, in[1].getInt(sc)).getString();
  244. });
  245. sm.registerConsumer("block.settrapdoorstatus", (sc, in) -> {
  246. Location l = (Location) in[0].get(sc);
  247. BlockPos pos = l.getBlockPos();
  248. BlockState state = l.getWorld().getBlockState(pos);
  249. World w = l.getWorld();
  250. state = state.with(TrapDoorBlock.OPEN, in[1].getBoolean(sc));
  251. w.setBlockState(pos, state, 2);
  252. if(state.get(TrapDoorBlock.WATERLOGGED)) {
  253. w.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER,
  254. Fluids.WATER.getTickRate(w));
  255. }
  256. Material m = state.getMaterial();
  257. if(state.get(TrapDoorBlock.OPEN)) {
  258. int i = m == Material.IRON ? 1037 : 1007;
  259. w.playEvent(null, i, pos, 0);
  260. } else {
  261. int j = m == Material.IRON ? 1036 : 1013;
  262. w.playEvent(null, j, pos, 0);
  263. }
  264. });
  265. sm.registerFunction("block.gettrapdoorstatus", (sc, in) -> {
  266. Location l = (Location) in[0].get(sc);
  267. return l.getBlockState().get(TrapDoorBlock.OPEN);
  268. });
  269. sm.registerConsumer("block.setdoorstatus", (sc, in) -> {
  270. Location l = (Location) in[0].get(sc);
  271. BlockPos pos = l.getBlockPos();
  272. BlockState state = l.getWorld().getBlockState(pos);
  273. ((DoorBlock) state.getBlock()).openDoor((World) l.getWorld(), state, pos,
  274. in[1].getBoolean(sc));
  275. });
  276. sm.registerFunction("block.getdoorstatus", (sc, in) -> {
  277. Location l = (Location) in[0].get(sc);
  278. return l.getBlockState().get(DoorBlock.OPEN);
  279. });
  280. sm.registerFunction("block.issolid", (sc, in) -> {
  281. return CommandUtils.getBlockState((Location) in[0].get(sc)).isSolid();
  282. });
  283. sm.registerFunction("block.tostack", (sc, in) -> {
  284. Location l = (Location) in[0].get(sc);
  285. return new ItemStack(l.getBlockState().getBlock().asItem());
  286. });
  287. sm.registerFunction("block.getitemamount", (sc, in) -> {
  288. Location l = (Location) in[0].get(sc);
  289. TileEntity te = l.getWorld().getTileEntity(l.getBlockPos());
  290. if(te == null || !(te instanceof ChestTileEntity)) {
  291. return 0.0d;
  292. }
  293. return (double) InventoryUtils.searchInventoryFor((ChestTileEntity) te,
  294. (ItemStack) in[2].get(sc), in[1].getBoolean(sc));
  295. });
  296. sm.registerFunction("block.getsecchest", (sc, in) -> {
  297. Location l = (Location) in[0].get(sc);
  298. BlockPos pos = l.getBlockPos();
  299. BlockState state = l.getWorld().getBlockState(pos);
  300. ChestType chesttype = state.get(ChestBlock.TYPE);
  301. if(chesttype == ChestType.SINGLE) {
  302. return null;
  303. }
  304. Direction dir = ChestBlock.getDirectionToAttached(state);
  305. return l.copyAdd(dir.getXOffset(), dir.getYOffset(), dir.getZOffset());
  306. });
  307. sm.registerFunction("block.additem", (sc, in) -> {
  308. Location l = (Location) in[0].get(sc);
  309. ItemStack stack = ((ItemStack) in[1].get(sc));
  310. TileEntity te = l.getWorld().getTileEntity(l.getBlockPos());
  311. if(te == null || !(te instanceof ChestTileEntity)) {
  312. return stack;
  313. }
  314. stack.setCount(InventoryUtils.addToInventory((ChestTileEntity) te, stack));
  315. return stack;
  316. });
  317. sm.registerFunction("block.subitem", (sc, in) -> {
  318. Location l = (Location) in[0].get(sc);
  319. ItemStack stack = ((ItemStack) in[1].get(sc));
  320. TileEntity te = l.getWorld().getTileEntity(l.getBlockPos());
  321. if(te == null || !(te instanceof ChestTileEntity)) {
  322. return stack;
  323. }
  324. stack.setCount(InventoryUtils.removeFromInventory((ChestTileEntity) te, stack));
  325. return stack;
  326. });
  327. sm.registerConsumer("block.setspawnertype", (sc, in) -> {
  328. Location l = (Location) in[0].get(sc);
  329. MobSpawnerTileEntity spawner =
  330. (MobSpawnerTileEntity) l.getWorld().getTileEntity(l.getBlockPos());
  331. spawner.getSpawnerBaseLogic()
  332. .setEntityType(EntityType.byKey(in[1].getString(sc)).get());
  333. });
  334. sm.registerFunction("block.getinv", (sc, in) -> {
  335. Location l = (Location) in[0].get(sc);
  336. return (IInventory) l.getWorld().getTileEntity(l.getBlockPos());
  337. });
  338. }
  339. }