materials2 = new LinkedList<>();
67 | ItemStack m1 = new ItemStack(Material.DIAMOND_BLOCK, 1);
68 | ItemStack m2 = new ItemStack(Material.DIRT, 2);
69 | materials2.add(m1);
70 | materials2.add(m2);
71 | recipe2.setIngredients(materials2);
72 | recipes.add(recipe2);
73 |
74 | villager.setRecipes(recipes);
75 | return true;
76 | }
77 | }
78 | return false;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/MapTutorialPlugin/src/main/java/com/senko/maptutorialplugin/MapTutorialPlugin.java:
--------------------------------------------------------------------------------
1 | package com.senko.maptutorialplugin;
2 |
3 | import com.senko.maptutorialplugin.render.FirstRender;
4 | import org.bukkit.Bukkit;
5 | import org.bukkit.Color;
6 | import org.bukkit.Material;
7 | import org.bukkit.command.Command;
8 | import org.bukkit.command.CommandSender;
9 | import org.bukkit.entity.Player;
10 | import org.bukkit.inventory.ItemStack;
11 | import org.bukkit.inventory.PlayerInventory;
12 | import org.bukkit.inventory.meta.MapMeta;
13 | import org.bukkit.map.*;
14 | import org.bukkit.plugin.java.JavaPlugin;
15 |
16 |
17 |
18 | public final class MapTutorialPlugin extends JavaPlugin {
19 |
20 | private MapView view;
21 |
22 | {
23 | /**
24 | * 给Map添加View视图
25 | *
26 | * 通过Bukkit的createMap来生成一个MapView
27 | */
28 | view = Bukkit.createMap(Bukkit.getWorlds().get(0));
29 |
30 | // 修改视图的信息
31 | view.setScale(MapView.Scale.CLOSEST);
32 | view.setLocked(true);
33 | view.setTrackingPosition(true); // 是否追踪玩家,并显示玩家的cursor true: 显示Cursor,false: 不显示Cursor
34 | view.setUnlimitedTracking(false); // 是否在玩家离开View时仍然标注玩家的cursor true: 标注玩家的cursor,false: 不标注玩家的cursor
35 |
36 | // 删除原有用于渲染世界的Render
37 | view.getRenderers().forEach(view::removeRenderer);
38 | // 添加自己的render
39 | view.addRenderer(new FirstRender());
40 | }
41 |
42 | @Override
43 | public void onEnable() {
44 | getCommand("get").setExecutor(this);
45 | }
46 |
47 | @Override
48 | public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
49 |
50 | if (sender instanceof Player) {
51 | Player player = (Player) sender;
52 | PlayerInventory inventory = player.getInventory();
53 |
54 | // 直接new出Map的物品槽
55 | ItemStack itemStack = new ItemStack(Material.FILLED_MAP, 1);
56 | // 既然是可以展示画面的特殊物品,相比也有个对应的Meta
57 | MapMeta mapMeta = (MapMeta) itemStack.getItemMeta();
58 |
59 | // 设置meta信息
60 | mapMeta.setLocationName("这是地点:" + player.getLocation().getBlockX() + "," + player.getLocation().getBlockY() + "," + player.getLocation().getBlockZ());
61 | mapMeta.setColor(Color.fromRGB(255, 0, 0));
62 |
63 | // 以后获取到的都是相同的View
64 | mapMeta.setMapView(view);
65 |
66 | // 查看默认生成的View信息
67 | int id = view.getId();
68 | int centerX = view.getCenterX();
69 | int centerZ = view.getCenterZ();
70 | MapView.Scale scale = view.getScale();
71 | sender.sendMessage("视图id:" + id);
72 | sender.sendMessage("视图中心点X坐标:" + centerX);
73 | sender.sendMessage("视图中心点Z坐标:" + centerZ);
74 | sender.sendMessage("视图缩放比例:" + scale);
75 |
76 | // 获取代码创建的Map信息
77 | String locationName = mapMeta.getLocationName();
78 | sender.sendMessage("locationName: " + locationName);
79 |
80 | Color color = mapMeta.getColor();
81 | sender.sendMessage("color: " + color);
82 |
83 |
84 | itemStack.setItemMeta(mapMeta);
85 | inventory.addItem(itemStack);
86 | return true;
87 | }
88 | sender.sendMessage("只有玩家才能使用此命令");
89 | return true;
90 |
91 | }
92 |
93 | }
--------------------------------------------------------------------------------
/EasySqlTutorialPlugin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.senko
8 | easySqlTutorial
9 | 1.0-SNAPSHOT
10 | jar
11 |
12 | EasySqlTutorial
13 |
14 | 上手了解EasySql工具的简单应用
15 |
16 | 1.8
17 | UTF-8
18 |
19 |
20 |
21 |
22 |
23 | org.apache.maven.plugins
24 | maven-compiler-plugin
25 | 3.8.1
26 |
27 | ${java.version}
28 | ${java.version}
29 |
30 |
31 |
32 | org.apache.maven.plugins
33 | maven-shade-plugin
34 | 3.2.4
35 |
36 |
37 | package
38 |
39 | shade
40 |
41 |
42 | false
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | src/main/resources
51 | true
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | EasySQL
61 | GitHub Branch Repository
62 | https://github.com/CarmJos/EasySQL/blob/repo/
63 |
64 |
65 |
66 | spigotmc-repo
67 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/
68 |
69 |
70 | sonatype
71 | https://oss.sonatype.org/content/groups/public/
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | cc.carm.lib
80 | easysql-hikaricp
81 | 0.4.1
82 |
83 |
84 |
85 |
86 | org.spigotmc
87 | spigot-api
88 | 1.18-R0.1-SNAPSHOT
89 | provided
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/TextComponentPlugin/src/main/java/com/senko/textcomponentplugin/executor/PrintMessage.java:
--------------------------------------------------------------------------------
1 | package com.senko.textcomponentplugin.executor;
2 |
3 | import com.senko.textcomponentplugin.TextComponentPlugin;
4 | import net.md_5.bungee.api.chat.*;
5 | import net.md_5.bungee.api.chat.hover.content.Text;
6 | import org.bukkit.ChatColor;
7 | import org.bukkit.command.Command;
8 | import org.bukkit.command.CommandExecutor;
9 | import org.bukkit.command.CommandSender;
10 | import org.bukkit.entity.Player;
11 |
12 | import java.text.MessageFormat;
13 | import java.util.Objects;
14 |
15 | /**
16 | * ChatColor的基础用法
17 | *
18 | * 与字符串常量拼接, 转换某个字符为颜色代码§
19 | *
20 | * @author senko
21 | * @date 2022/6/10 7:21
22 | */
23 | public class PrintMessage implements CommandExecutor {
24 | @Override
25 | public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
26 | if (sender instanceof Player) {
27 | Player player = (Player) sender;
28 |
29 | if (Objects.nonNull(args) && args.length > 0) {
30 | String arg = args[0];
31 | switch (arg) {
32 | case "1":
33 | fun1(player);
34 | break;
35 | case "2":
36 | fun2(player);
37 | break;
38 | }
39 | return true;
40 | }
41 | return false;
42 | }
43 | return false;
44 | }
45 |
46 | private void fun1(Player player) {
47 | //用法一:ChatColor拼接
48 | String message1 = ChatColor.GOLD + "你好 " + ChatColor.BOLD + ChatColor.RED + "世界"; //转义后实际得到的文本 §6你好 §c世界
49 | //等同于
50 | String message11 = ChatColor.GOLD.toString() + "你好 " + ChatColor.BOLD.toString() + ChatColor.RED.toString() + "世界";
51 | player.sendMessage(message1);
52 |
53 | //用法二:ChatColor.translateAlternateColorCodes(字符,字符串)转换颜色代码
54 | String message2 = ChatColor.translateAlternateColorCodes('&', "&6你好 &l&c世界"); //转义后实际得到的文本 §6你好 §c世界
55 | player.sendMessage(message2);
56 | }
57 |
58 | /**
59 | * 完全自定义的色彩
60 | *
61 | * {@link ChatColor}枚举所提供的色彩存在一定的限制
62 | * 如果需要自定义色彩,我们可以通过{@link net.md_5.bungee.api.ChatColor#of(String)}传入十六进制颜色码来细分色彩
63 | */
64 | private void fun2(Player player) {
65 | net.md_5.bungee.api.ChatColor color1 = net.md_5.bungee.api.ChatColor.of("#FCF3CF"); //十六进制的颜色码
66 | net.md_5.bungee.api.ChatColor color2 = net.md_5.bungee.api.ChatColor.of("#F9E79F"); //十六进制的颜色码
67 | net.md_5.bungee.api.ChatColor color3 = net.md_5.bungee.api.ChatColor.of("#F7DC6F"); //...
68 | net.md_5.bungee.api.ChatColor color4 = net.md_5.bungee.api.ChatColor.of("#F4D03F");
69 | net.md_5.bungee.api.ChatColor color5 = net.md_5.bungee.api.ChatColor.of("#F1C40F");
70 | net.md_5.bungee.api.ChatColor color6 = net.md_5.bungee.api.ChatColor.of("#D4AC0D");
71 |
72 | //发送 纯文本 这里也是用了toString()特性
73 | String pureText = MessageFormat.format("{0}大{1}家{2}好{3}啊{4}欢{5}迎", color1, color2, color3, color4, color5, color6);
74 | // pureText.equals(message) == true
75 | String message = color1 + "大" + color2 + "家" + color3 + "好" + color4 + "啊" + color5 + "欢" + color6 + "迎";
76 | player.sendMessage(pureText + ChatColor.translateAlternateColorCodes('&', " &f sent in pure text form!"));
77 |
78 |
79 | //color1实际对应的颜色代码
80 | TextComponentPlugin.getInstance().getLogger().info( "color1实际对应的颜色代码" + color1);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/BlockPlugin/src/main/java/com/senko/blockplugin/examples/blockdata/BlockDataExample.java:
--------------------------------------------------------------------------------
1 | package com.senko.blockplugin.examples.blockdata;
2 |
3 | import org.bukkit.Bukkit;
4 | import org.bukkit.Location;
5 | import org.bukkit.Material;
6 | import org.bukkit.block.Block;
7 | import org.bukkit.block.BlockFace;
8 | import org.bukkit.block.data.BlockData;
9 | import org.bukkit.block.data.type.Chest;
10 | import org.bukkit.entity.Player;
11 |
12 | import java.util.HashMap;
13 | import java.util.Random;
14 |
15 | /**
16 | * 有关BlockData的基本使用(获取方块信息,以及序列化和反序列化)
17 | *
18 | * @author senko
19 | * @date 2022/7/15 9:49
20 | */
21 | public class BlockDataExample {
22 | /**
23 | * BlockData在游戏中的体现就是F3键按下后,在屏幕中心右侧显示的Target Block下的那些内容
24 | * (#开头的是注解,因此不会被包含在BlockData里)
25 | *
26 | * 对于存储离散不连续的多个方块的需求,一般都是记录Location,BlockData#getAsString()序列化BlockData,然后通过某种方式存储起来。
27 | * 等需要的时候,再Bukkit#createBlockData(String)反序列化回BlockData,然后用{@link org.bukkit.World#setBlockData(Location, BlockData)}把方块设置在某处。
28 | * (但是BlockData并不是方块的全部,还有BlockState会记负责录方块的详细数据,比如箱子存储了什么、命令方块里的命令是什么等等,
29 | * 所以这种方法只能设置什么位置是什么方块,并不能连同详细数据一同序列化。
30 | *
31 | * 而且Spigot/Bukkit提供的这些修改BlockData的API都很笨重,如果要修改大批量的方块,
32 | * 将会严重增大服务器的性能消耗,除非你抛开Spigot/Bukkit繁重的代码,直接利用底层代码NMS来修改,
33 | * 又或者是使用WorldEdit API(推荐)。
34 | */
35 | public void doGetAndSetBlockData(Block block, Player player) {
36 |
37 | // TIP: 获取到的BlockData和Location一样,都是对象属性的内存地址,如果要进行修改,请尽量先clone()出副本再针对副本进行修改
38 | BlockData blockData = block.getBlockData();
39 |
40 | // 比如这里你点击了一个箱子
41 | if (block.getType() == Material.CHEST) {
42 |
43 | Chest chestData = ((Chest) blockData); // 是箱子,就转换成BlockData的子类Chest
44 | player.sendMessage("点击箱子的方向是:" + chestData.getFacing().toString()); // 箱子BlockData所特有的信息
45 | player.sendMessage("点击箱子是否含水:" + (chestData.isWaterlogged() ? "是" : "否"));
46 | player.sendMessage("点击箱子的类型:" + chestData.getType().name());
47 | player.sendMessage("点击箱子的完整data:" + blockData.getAsString()); // blockData的String形式
48 | //chestData....
49 |
50 |
51 | // BlockData blockData1 = Bukkit.createBlockData(blockData.getAsString()); // 还有其他方式可以用来(获取)BlockData
52 | // BlockData blockData1 = Bukkit.createBlockData(Material.CHEST);
53 |
54 | changeAnotherBlock(block, chestData); // 利用BlockData去修改其他的方块
55 |
56 | } else {
57 | player.sendMessage("你点击的方块不是箱子,没有方向信息");
58 | }
59 |
60 | }
61 |
62 | private void changeAnotherBlock(Block curBlock, Chest chestData) {
63 |
64 | Block relative = curBlock.getRelative(chestData.getFacing()); // 获取chest对面的方块
65 |
66 | Chest randomChestData = getRandomChestData(chestData); // 随机修改chest的data。
67 |
68 | relative.setBlockData(randomChestData); // 修改相对方块为随机掉data的箱子
69 |
70 | }
71 |
72 | private Chest getRandomChestData(Chest chestData) {
73 |
74 | // 这里先克隆再修改,是为了不在修改时影响到原方块
75 | Chest clonedChestData = (Chest) chestData.clone();
76 |
77 | Random random = new Random();
78 |
79 | int nextType = random.nextInt(Chest.Type.values().length);
80 | clonedChestData.setType(Chest.Type.values()[nextType]); // 通过API修改方块Type
81 |
82 | clonedChestData.setWaterlogged(!clonedChestData.isWaterlogged()); // 修改方块是否含水
83 |
84 | return clonedChestData; // 返回新的BlockData
85 |
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------