EntityCommands.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. package me.km.snuviscript.commands;
  2. import me.hammerle.snuviscript.code.ScriptManager;
  3. import me.km.entities.EntityItemProjectile;
  4. import me.km.scheduler.SnuviScheduler;
  5. import static me.km.snuviscript.commands.CommandUtils.getNamedClass;
  6. import me.km.utils.Location;
  7. import me.km.utils.Mapper;
  8. import me.km.utils.Utils;
  9. import net.minecraft.enchantment.EnchantmentHelper;
  10. import net.minecraft.entity.*;
  11. import net.minecraft.entity.ai.attributes.Attributes;
  12. import net.minecraft.entity.effect.LightningBoltEntity;
  13. import net.minecraft.entity.item.*;
  14. import net.minecraft.entity.monster.CreeperEntity;
  15. import net.minecraft.entity.passive.SheepEntity;
  16. import net.minecraft.entity.player.ServerPlayerEntity;
  17. import net.minecraft.entity.projectile.*;
  18. import net.minecraft.inventory.EquipmentSlotType;
  19. import net.minecraft.item.ItemStack;
  20. import net.minecraft.nbt.CompoundNBT;
  21. import net.minecraft.nbt.JsonToNBT;
  22. import net.minecraft.potion.Effect;
  23. import net.minecraft.potion.EffectInstance;
  24. import net.minecraft.potion.PotionUtils;
  25. import net.minecraft.util.DamageSource;
  26. import net.minecraft.util.Direction;
  27. import net.minecraft.util.ResourceLocation;
  28. import net.minecraft.util.math.BlockPos;
  29. import net.minecraft.util.math.vector.Vector3d;
  30. import net.minecraft.util.text.StringTextComponent;
  31. import net.minecraft.world.World;
  32. import net.minecraft.world.server.ServerWorld;
  33. public class EntityCommands {
  34. public static void registerFunctions(ScriptManager sm, SnuviScheduler scheduler) {
  35. sm.registerConsumer("entity.setnopickup", (sc, in) -> {
  36. ((AbstractArrowEntity) in[0].get(sc)).pickupStatus = AbstractArrowEntity.PickupStatus.DISALLOWED;
  37. });
  38. sm.registerFunction("entity.shootprojectile", (sc, in) -> launchProjectile((LivingEntity) in[0].get(sc),
  39. getNamedClass(in[1].getString(sc)), in[2].getDouble(sc), in.length >= 4 ? in[3].get(sc) : null));
  40. sm.registerFunction("entity.isblocking", (sc, in) -> ((LivingEntity) in[0].get(sc)).isActiveItemStackBlocking());
  41. sm.registerFunction("entity.getarmorthoughness", (sc, in) -> ((LivingEntity) in[0].get(sc)).getAttribute(Attributes.ARMOR_TOUGHNESS).getValue());
  42. sm.registerFunction("entity.getarmor", (sc, in) -> (double) ((LivingEntity) in[0].get(sc)).getTotalArmorValue());
  43. sm.registerFunction("entity.getenchantmentmodifier", (sc, in) -> EnchantmentHelper.getEnchantmentModifierDamage(((LivingEntity) in[0].get(sc)).getArmorInventoryList(), (DamageSource) in[1].get(sc)));
  44. sm.registerConsumer("entity.setburning", (sc, in) -> ((Entity) in[0].get(sc)).setFire(in[1].getInt(sc)));
  45. sm.registerFunction("entity.isburning", (sc, in) -> ((Entity) in[0].get(sc)).isBurning());
  46. sm.registerFunction("entity.getlook", (sc, in) -> {
  47. Object[] o = new Object[3];
  48. Vector3d v = ((Entity) in[0].get(sc)).getLookVec();
  49. o[0] = v.x;
  50. o[1] = v.y;
  51. o[2] = v.z;
  52. return o;
  53. });
  54. sm.registerFunction("entity.getlocation", (sc, in) -> new Location((Entity) in[0].get(sc)));
  55. sm.registerConsumer("entity.heal", (sc, in) -> {
  56. LivingEntity liv = (LivingEntity) in[0].get(sc);
  57. float heal = in[1].getFloat(sc);
  58. scheduler.scheduleTask(() -> liv.heal(heal));
  59. });
  60. sm.registerConsumer("entity.damage", (sc, in) -> {
  61. LivingEntity liv = (LivingEntity) in[0].get(sc);
  62. float damage = in[1].getFloat(sc);
  63. DamageSource damageSource = (in.length >= 3) ? (DamageSource) in[2].get(sc) : DamageSource.GENERIC;
  64. scheduler.scheduleTask(() -> liv.attackEntityFrom(damageSource, damage));
  65. });
  66. sm.registerFunction("entity.fromsource", (sc, in) -> {
  67. DamageSource ds = (DamageSource) in[0].get(sc);
  68. Entity ent = ds.getTrueSource();
  69. if(ent == null) {
  70. return ds.getImmediateSource();
  71. }
  72. return ent;
  73. });
  74. sm.registerAlias("damage.get", "entity.getdamagesource");
  75. sm.registerFunction("entity.getmaxhealth", (sc, in) -> (double) ((LivingEntity) in[0].get(sc)).getMaxHealth());
  76. sm.registerFunction("entity.gethealth", (sc, in) -> (double) ((LivingEntity) in[0].get(sc)).getHealth());
  77. sm.registerConsumer("entity.sethealth", (sc, in) -> ((LivingEntity) in[0].get(sc)).setHealth(in[1].getFloat(sc)));
  78. sm.registerConsumer("entity.setname", (sc, in) -> {
  79. Entity ent = (Entity) in[0].get(sc);
  80. ent.setCustomName(new StringTextComponent(in[1].getString(sc)));
  81. if(in.length >= 3) {
  82. ent.setCustomNameVisible(in[2].getBoolean(sc));
  83. return;
  84. }
  85. ent.setCustomNameVisible(false);
  86. });
  87. sm.registerFunction("entity.getname", (sc, in) -> ((Entity) in[0].get(sc)).getDisplayName().getString());
  88. sm.registerConsumer("entity.throw", (sc, in) -> {
  89. Entity ent = (Entity) in[0].get(sc);
  90. ent.setMotion(in[1].getDouble(sc), in[2].getDouble(sc), in[3].getDouble(sc));
  91. ent.velocityChanged = true;
  92. });
  93. sm.registerConsumer("entity.teleport", (sc, in) -> {
  94. Entity ent = (Entity) in[0].get(sc);
  95. Location l = (Location) in[1].get(sc);
  96. if(l.getWorld() == null) {
  97. throw new IllegalArgumentException("world must not be null");
  98. }
  99. if(ent instanceof ServerPlayerEntity) {
  100. ServerPlayerEntity p = (ServerPlayerEntity) ent;
  101. p.stopRiding();
  102. if(p.isSleeping()) {
  103. p.stopSleepInBed(true, true);
  104. }
  105. float yaw = l.getYaw() != 0.0f ? l.getYaw() : ent.rotationYaw;
  106. float pitch = l.getPitch() != 0.0f ? l.getPitch() : ent.rotationPitch;
  107. p.teleport((ServerWorld) l.getWorld(), l.getX(), l.getY(), l.getZ(), yaw, pitch);
  108. } else {
  109. if(ent.world != l.getWorld()) {
  110. ServerWorld ws = (ServerWorld) l.getWorld();
  111. ent.changeDimension(ws);
  112. }
  113. float yaw = l.getYaw() != 0.0f ? l.getYaw() : ent.rotationYaw;
  114. float pitch = l.getPitch() != 0.0f ? l.getPitch() : ent.rotationPitch;
  115. ent.setLocationAndAngles(l.getX(), l.getY(), l.getZ(), yaw, pitch);
  116. }
  117. });
  118. sm.registerConsumer("entity.setequip", (sc, in) -> {
  119. LivingEntity liv = (LivingEntity) in[0].get(sc);
  120. ItemStack stack = ((ItemStack) in[2].get(sc)).copy();
  121. switch(in[1].getString(sc)) {
  122. case "hand":
  123. liv.setItemStackToSlot(EquipmentSlotType.MAINHAND, stack);
  124. return;
  125. case "head":
  126. liv.setItemStackToSlot(EquipmentSlotType.HEAD, stack);
  127. return;
  128. case "chest":
  129. liv.setItemStackToSlot(EquipmentSlotType.CHEST, stack);
  130. return;
  131. case "legs":
  132. liv.setItemStackToSlot(EquipmentSlotType.LEGS, stack);
  133. return;
  134. case "feet":
  135. liv.setItemStackToSlot(EquipmentSlotType.FEET, stack);
  136. return;
  137. case "offhand":
  138. liv.setItemStackToSlot(EquipmentSlotType.OFFHAND, stack);
  139. }
  140. });
  141. sm.registerFunction("entity.getequip", (sc, in) -> {
  142. LivingEntity liv = (LivingEntity) in[0].get(sc);
  143. switch(in[1].getString(sc)) {
  144. case "hand":
  145. return liv.getItemStackFromSlot(EquipmentSlotType.MAINHAND);
  146. case "head":
  147. return liv.getItemStackFromSlot(EquipmentSlotType.HEAD);
  148. case "chest":
  149. return liv.getItemStackFromSlot(EquipmentSlotType.CHEST);
  150. case "legs":
  151. return liv.getItemStackFromSlot(EquipmentSlotType.LEGS);
  152. case "feet":
  153. return liv.getItemStackFromSlot(EquipmentSlotType.FEET);
  154. case "offhand":
  155. return liv.getItemStackFromSlot(EquipmentSlotType.OFFHAND);
  156. }
  157. return ItemStack.EMPTY;
  158. });
  159. sm.registerConsumer("entity.removeall", (sc, in) -> {
  160. Class<? extends Entity> c = (Class<? extends Entity>) getNamedClass(in[0].getString(sc));
  161. if(c == Entity.class) {
  162. return;
  163. }
  164. Location l = (Location) in[1].get(sc);
  165. Utils.getEntities(l.getWorld(), l.getX(), l.getY(), l.getZ(), in[2].getDouble(sc), c).stream().forEach(ent -> {
  166. ent.remove();
  167. });
  168. });
  169. sm.registerConsumer("entity.remove", (sc, in) -> ((Entity) in[0].get(sc)).remove());
  170. sm.registerConsumer("entity.setinvulnerable", (sc, in) -> {
  171. ((Entity) in[0].get(sc)).setInvulnerable(in[1].getBoolean(sc));
  172. });
  173. sm.registerConsumer("entity.setsilent", (sc, in) -> {
  174. ((Entity) in[0].get(sc)).setSilent(in[1].getBoolean(sc));
  175. });
  176. sm.registerConsumer("entity.setinvisible", (sc, in) -> {
  177. ((Entity) in[0].get(sc)).setInvisible(in[1].getBoolean(sc));
  178. });
  179. sm.registerConsumer("entity.mount", (sc, in) -> {
  180. ((Entity) in[0].get(sc)).startRiding(((Entity) in[1].get(sc)));
  181. });
  182. sm.registerConsumer("entity.unmount", (sc, in) -> {
  183. ((Entity) in[0].get(sc)).stopRiding();
  184. });
  185. sm.registerConsumer("entity.addeffect", (sc, in) -> {
  186. LivingEntity base = (LivingEntity) in[0].get(sc);
  187. Effect potion = Mapper.getPotion(in[1].getString(sc));
  188. if(potion == null) { // doing this only to prevent EffectInstance doing shit
  189. throw new IllegalArgumentException("potion does not exist");
  190. }
  191. if(base.isPotionActive(potion)) {
  192. base.removePotionEffect(potion);
  193. }
  194. boolean showParticles = in.length >= 5 ? in[4].getBoolean(sc) : true;
  195. base.addPotionEffect(new EffectInstance(potion, in[2].getInt(sc), in[3].getInt(sc), false, showParticles));
  196. });
  197. sm.registerConsumer("entity.cleareffects", (sc, in) -> {
  198. ((LivingEntity) in[0].get(sc)).clearActivePotions();
  199. });
  200. sm.registerFunction("entity.geteffectamplifier", (sc, in) -> {
  201. EffectInstance effect = ((LivingEntity) in[0].get(sc)).getActivePotionEffect(Mapper.getPotion(in[1].getString(sc)));
  202. return effect == null ? 0 : effect.getAmplifier() + 1;
  203. });
  204. sm.registerConsumer("entity.spawnitemframe", (sc, in) -> {
  205. Location l = ((Location) in[0].get(sc));
  206. ItemFrameEntity frame = new ItemFrameEntity(l.getWorld(), l.getBlockPos(), Direction.byName(in[1].getString(sc)));
  207. frame.setDisplayedItem(((ItemStack) in[2].get(sc))); // copy happens in internals
  208. l.getWorld().addEntity(frame);
  209. });
  210. sm.registerFunction("entity.getitemfromframe", (sc, in) -> ((ItemFrameEntity) in[0].get(sc)).getDisplayedItem());
  211. sm.registerFunction("entity.get", (sc, in) -> {
  212. Location l = (Location) in[0].get(sc);
  213. return Utils.getEntity(l.getWorld(), l.getX(), l.getY(), l.getZ(), in[1].getDouble(sc), getNamedClass(in[2].getString(sc)));
  214. });
  215. sm.registerFunction("entity.getpotiontype", (sc, in) -> PotionUtils.getPotionFromItem(((PotionEntity) in[0].get(sc)).getItem()).getRegistryName().toString());
  216. sm.registerConsumer("entity.setgravity", (sc, in) -> {
  217. ((Entity) in[0].get(sc)).setNoGravity(!in[1].getBoolean(sc));
  218. });
  219. sm.registerFunction("entity.iswet", (sc, in) -> ((Entity) in[0].get(sc)).isWet());
  220. sm.registerConsumer("entity.setpickupdelay", (sc, in) -> {
  221. ((ItemEntity) in[0].get(sc)).setPickupDelay(in[1].getInt(sc));
  222. });
  223. sm.registerFunction("entity.spawn", (sc, in) -> {
  224. ResourceLocation rl = new ResourceLocation(in[0].getString(sc));
  225. Location l = (Location) in[1].get(sc);
  226. ServerWorld sw = (ServerWorld) l.getWorld();
  227. CompoundNBT compoundnbt = in.length >= 3 ? JsonToNBT.getTagFromJson(in[2].getString(sc)) : new CompoundNBT();
  228. compoundnbt.putString("id", rl.toString());
  229. if(EntityType.getKey(EntityType.LIGHTNING_BOLT).equals(rl)) {
  230. LightningBoltEntity ent = EntityType.LIGHTNING_BOLT.create(sw);
  231. ent.moveForced(l.getPos());
  232. sw.addEntity(ent);
  233. return ent;
  234. }
  235. Entity entity = EntityType.loadEntityAndExecute(compoundnbt, sw, (ent) -> {
  236. ent.setLocationAndAngles(l.getX(), l.getY(), l.getZ(), ent.rotationYaw, ent.rotationPitch);
  237. return sw.summonEntity(ent) ? ent : null;
  238. });
  239. if(entity != null && entity instanceof MobEntity) {
  240. ((MobEntity) entity).onInitialSpawn(sw, sw.getDifficultyForLocation(entity.getPosition()), SpawnReason.COMMAND, null, null);
  241. }
  242. return entity;
  243. });
  244. sm.registerFunction("entity.near", (sc, in) -> {
  245. Object o = in[0].get(sc);
  246. if(o instanceof Location) {
  247. return Utils.getEntities((Location) o, in[1].getDouble(sc));
  248. }
  249. return Utils.getEntities((Entity) o, in[1].getDouble(sc));
  250. });
  251. sm.registerConsumer("entity.setspeed", (sc, in) -> {
  252. ((LivingEntity) in[0].get(sc)).getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(in[1].getDouble(sc));
  253. });
  254. sm.registerConsumer("entity.setgrowingage", (sc, in) -> {
  255. ((AgeableEntity) in[0].get(sc)).setGrowingAge(in[1].getInt(sc));
  256. });
  257. sm.registerFunction("entity.gettype", (sc, in) -> ((Entity) in[0].get(sc)).getType().getRegistryName().getPath());
  258. sm.registerFunction("entity.issneaking", (sc, in) -> ((Entity) in[0].get(sc)).isCrouching());
  259. sm.registerFunction("entity.issneaking", (sc, in) -> ((Entity) in[0].get(sc)).isCrouching());
  260. sm.registerFunction("sheep.issheared", (sc, in) -> ((SheepEntity) in[0].get(sc)).getSheared());
  261. sm.registerFunction("sheep.getcolor", (sc, in) -> ((SheepEntity) in[0].get(sc)).getFleeceColor().toString());
  262. sm.registerConsumer("creeper.explode", (sc, in) -> ((CreeperEntity) in[0].get(sc)).ignite());
  263. }
  264. private static <T> T launchProjectile(LivingEntity liv, Class<? extends T> projectile, double scale, Object data) {
  265. World w = liv.world;
  266. Entity launch = null;
  267. if(EntityItemProjectile.class == projectile) {
  268. if(data == null) {
  269. throw new NullPointerException("Data musn't be null for EntityItemProjectile");
  270. }
  271. ItemStack stack = (ItemStack) data;
  272. if(stack.isEmpty()) {
  273. throw new IllegalArgumentException("Empty ItemStack not allowed here");
  274. }
  275. launch = new EntityItemProjectile(liv, stack.copy());
  276. ((EntityItemProjectile) launch).setHeadingFromThrower(liv, liv.rotationPitch, liv.rotationYaw, 0.0f, 1.5f, 1.0f);
  277. } else if(SnowballEntity.class == projectile) {
  278. launch = new SnowballEntity(w, liv);
  279. ((SnowballEntity) launch).shoot(liv.rotationPitch, liv.rotationYaw, 0.0f, 1.5f, 1.0f);
  280. } else if(EggEntity.class == projectile) {
  281. launch = new EggEntity(w, liv);
  282. ((EggEntity) launch).shoot(liv.rotationPitch, liv.rotationYaw, 0.0f, 1.5f, 1.0f);
  283. } else if(EnderPearlEntity.class == projectile) {
  284. launch = new EnderPearlEntity(w, liv);
  285. ((EnderPearlEntity) launch).shoot(liv.rotationPitch, liv.rotationYaw, 0.0f, 1.5f, 1.0f);
  286. } else if(PotionEntity.class == projectile) {
  287. launch = new PotionEntity(w, liv);
  288. ((PotionEntity) launch).setItem((ItemStack) data);
  289. ((PotionEntity) launch).shoot(liv.rotationPitch, liv.rotationYaw, -20.0f, 0.5f, 1.0f);
  290. } else if(ExperienceBottleEntity.class == projectile) {
  291. launch = new ExperienceBottleEntity(w, liv);
  292. ((ExperienceBottleEntity) launch).shoot(liv.rotationPitch, liv.rotationYaw, -20.0f, 0.7f, 1.0f);
  293. } else if(AbstractArrowEntity.class.isAssignableFrom(projectile)) {
  294. if(SpectralArrowEntity.class == projectile) {
  295. launch = new SpectralArrowEntity(w, liv);
  296. } else {
  297. launch = new ArrowEntity(w, liv);
  298. if(data != null) {
  299. ((ArrowEntity) launch).setPotionEffect((ItemStack) data);
  300. }
  301. }
  302. ((AbstractArrowEntity) launch).shoot(liv.rotationPitch, liv.rotationYaw, 0.0F, 3.0F, 1.0F);
  303. } else if(DamagingProjectileEntity.class.isAssignableFrom(projectile)) {
  304. Vector3d v = liv.getLookVec().scale(10);
  305. if(SmallFireballEntity.class == projectile) {
  306. launch = new SmallFireballEntity(w, liv, v.x, v.y, v.z);
  307. } else if(WitherSkullEntity.class == projectile) {
  308. launch = new WitherSkullEntity(w, liv, v.x, v.y, v.z);
  309. } else if(DragonFireballEntity.class == projectile) {
  310. launch = new DragonFireballEntity(w, liv, v.x, v.y, v.z);
  311. } else {
  312. launch = new FireballEntity(w, liv, v.x, v.y, v.z);
  313. }
  314. } else {
  315. return null;
  316. }
  317. launch.setMotion(launch.getMotion().scale(scale));
  318. w.addEntity(launch);
  319. return (T) launch;
  320. }
  321. }