# coding: utf-8 # 灵气系统 by DreamCityToger import random import pyspigot as ps from org.bukkit import Material, Sound, Particle from org.bukkit.util import Vector from org.bukkit.entity import Player from org.bukkit.potion import PotionEffect, PotionEffectType from org.bukkit.Bukkit import getServer from org.bukkit.inventory import ItemStack, EquipmentSlot from org.bukkit.enchantments import Enchantment from org.bukkit.event.player import PlayerInteractEvent from org.bukkit.event.inventory import InventoryClickEvent from org.bukkit.event.inventory import InventoryDragEvent from org.bukkit.event.inventory import InventoryCloseEvent from util2.develop.gui.builder import initializeItemStack from util2.develop.gui.builder import getGUIValue from util2.develop.gui.manager import GUIManager from util2.develop.gui.manager import GUIController from util2.develop.gui.builder import isGUI from util2.develop.gui.bugfixer import closeGuiForAll from util2.develop.gui.bugfixer import cancelShiftClickFromPlayerInventory from util2.develop.gui.bugfixer import denyAllInventoryDrag from util2.plugins.head import PlayerHeadsAPI WORLD_NAME = u"Old_World" MIN_TODAY_PRO = 0.0 #天时最小值 MAX_TODAY_PRO = 10.0 #天时最大值 MIN_REIKI_PRO = 0.0 #地利最小值 MAX_REIKI_PRO = 10.0 #地利最大值 guiManager = GUIManager() #菜单管理 playerHeadsAPI = PlayerHeadsAPI() # 初始化Player Heads playerPage = {} #玩家页数 class WorldManager: #世界管理 def __init__(self): self.world = getServer().getWorld(WORLD_NAME) def getWorld(self): #获取世界对象 return self.world worldManager = WorldManager() class ItemsManager: def __init__(self): self.itemsData = ps.config.loadConfig("reiki/items.yml") self.itemsData.save() self.initialElementItems() def initialElementItems(self): self.grassItems = [] self.fireItems = [] self.waterItems = [] self.earthItems = [] self.thunderItems = [] self.iceItems = [] self.windItems = [] items = self.itemsData.getKeys(False) for itemId in items: element = self.itemsData.getString("{}.element".format(itemId), None) if element is None: continue if element == u"GRASS": self.grassItems.append(itemId) elif element == u"FIRE": self.fireItems.append(itemId) elif element == u"WATER": self.waterItems.append(itemId) elif element == u"EARTH": self.earthItems.append(itemId) elif element == u"THUNDER": self.thunderItems.append(itemId) elif element == u"ICE": self.iceItems.append(itemId) elif element == u"WIND": self.windItems.append(itemId) def getAllItems(self): #获取所有道具 items = self.itemsData.getKeys(False) return items def getItemstack(self, itemId=0): if str(itemId) not in self.itemsData.getKeys(False): #若不存在该Id道具 return None material = self.itemsData.getString("{}.material".format(itemId), u"DANDELION") itemstack = ItemStack(Material.valueOf(material), 1) itemMeta = itemstack.getItemMeta() enchantmentsSection = self.itemsData.get("{}.enchantments".format(itemId)) if enchantmentsSection is not None: enchantments = enchantmentsSection.getKeys(False) for enchantment in enchantments: enchant = Enchantment.getByName(enchantment) if enchant is not None: level = enchantmentsSection.getInt(enchantment, 1) itemMeta.addEnchant(enchant, level, True) itemstack.setItemMeta(itemMeta) display = self.itemsData.getString("{}.display".format(itemId), u"§f未命名道具") lores = self.itemsData.get("{}.lores".format(itemId), []) key = self.itemsData.getString("{}.key".format(itemId), None) if key is None: key = u"ITEM" #默认关键字 item = initializeItemStack(itemstack, display, *lores, data=u"reiki:{}".format(key)) return item def getItemDisplay(self, itemId=0): if str(itemId) not in self.itemsData.getKeys(False): return None display = self.itemsData.getString("{}.display".format(itemId), u"§f未命名道具") return display itemManager = ItemsManager() class BlockManager: def __init__(self): self.blockData = ps.config.loadConfig("reiki/block.yml") self.blockData.save() self.todayPro = 5.0 #每日运势 self.randomTodayPro() #存储不同灵气台的内容 self.taskIds = {} self.offY = {} self.keys = {} self.mutation = {} self.working = {} self.element = {} self.itemId = {} self.players= {} #灵气台管理-------------------------------- def getLocTable(self, loc): #获取对应位置的灵气台 x = loc.getBlockX() y = loc.getBlockY() z = loc.getBlockZ() for blockId in self.blockData.getKeys(False): if self.blockData.getInt("{}.x".format(blockId)) == x: if self.blockData.getInt("{}.y".format(blockId)) == y: if self.blockData.getInt("{}.z".format(blockId)) == z: return blockId return None def createReikiTable(self, loc): #创造一个灵气台 if self.getLocTable(loc): #若已经存在 return False blockId = str(self.getNewTableID()) self.blockData.set("{}.x".format(blockId), loc.getBlockX()) self.blockData.set("{}.y".format(blockId), loc.getBlockY()) self.blockData.set("{}.z".format(blockId), loc.getBlockZ()) self.blockData.set("{}.world".format(blockId), loc.getWorld().getName()) self.blockData.set("{}.name".format(blockId), u"普通灵气台") self.blockData.set("{}.grass".format(blockId), 1) self.blockData.set("{}.fire".format(blockId), 1) self.blockData.set("{}.water".format(blockId), 1) self.blockData.set("{}.earth".format(blockId), 1) self.blockData.set("{}.thunder".format(blockId), 1) self.blockData.set("{}.ice".format(blockId), 1) self.blockData.set("{}.wind".format(blockId), 1) self.blockData.set("{}.timesOfUse".format(blockId), 0) #使用过的次数 self.blockData.set("{}.timesOfMutation".format(blockId), 0) #突变召唤次数 self.blockData.save() return blockId def delReikiTable(self, blockId): #删除对应Id的灵气台 if str(blockId) not in self.blockData.getKeys(False): return False self.blockData.set(blockId, None) self.blockData.save() return True def getTableLoc(self, blockId): #获取灵气台的位置 if str(blockId) not in self.blockData.getKeys(False): return None x = self.blockData.getInt("{}.x".format(blockId)) y = self.blockData.getInt("{}.y".format(blockId)) z = self.blockData.getInt("{}.z".format(blockId)) world = worldManager.getWorld() return world.getBlockAt(x, y, z).getLocation() def getNewTableID(self): #获取一个新的灵气台ID currentID = 1 keys = self.blockData.getKeys(False) while True: if self.blockData.get(str(currentID)) is None: return currentID if str(currentID) not in keys: return currentID else: currentID += 1 def getTableElement(self, blockId, element=u"GRASS"): #获取灵气台的元素 if str(blockId) not in self.blockData.getKeys(False): #若不存在 return None if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]: #若元素不存在 return None value = self.blockData.getInt("{}.{}".format(blockId, element.lower()), 0) #获取 return value def getTableName(self, blockId): #获取灵气台的名称 if str(blockId) not in self.blockData.getKeys(False): #若不存在 return None name = self.blockData.getString("{}.name".format(blockId), u"§f普通灵气台") #获取 return name def setTableElement(self, blockId, element=u"GRASS", value=11): if str(blockId) not in self.blockData.getKeys(False): #若不存在 return False if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]: #若元素不存在 return False self.blockData.set("{}.{}".format(blockId, element.lower()), value) #设置 self.blockData.save() #保存 return True def setTableName(self, blockId, name): #设置灵气台的名称 if str(blockId) not in self.blockData.getKeys(False): #若不存在 return False self.blockData.set("{}.name".format(blockId), name) #设置 self.blockData.save() #保存 return True def addTableTimesOfUse(self, blockId): #增加灵气台使用次数 if str(blockId) not in self.blockData.getKeys(False): #若不存在 return False timesOfUse = self.blockData.getInt("{}.timesOfUse".format(blockId), 0) #获取 self.blockData.set("{}.timesOfUse".format(blockId), timesOfUse + 1) #设置 self.blockData.save() #保存 return True def addTableTimesOfMutation(self, blockId): #增加灵气台使用次数 if str(blockId) not in self.blockData.getKeys(False): #若不存在 return False timesOfMutation = self.blockData.getInt("{}.timesOfMutation".format(blockId), 0) #获取 self.blockData.set("{}.timesOfMutation".format(blockId), timesOfMutation + 1) #设置 self.blockData.save() #保存 return True def addTableTimesOfElement(self, blockId, element=u"grass"): if str(blockId) not in self.blockData.getKeys(False): #若不存在 return False if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]: #若元素不存在 return False timesOfElement = self.blockData.getInt("{}.timesOf{}".format(blockId, element.lower()), 0) #获取 self.blockData.set("{}.timesOf{}".format(blockId, element.lower()), timesOfElement + 1) #设置 self.blockData.save() #保存 return True #灵气召唤-------------------------------- def reikiCall(self, player, blockId, key=u"DANDELION", mutation=False): #灵气召唤 if str(blockId) not in self.blockData.getKeys(False): #若不存在 return False if blockId not in self.working: self.working[blockId] = False #设置为未工作 if self.working[blockId]: #若正在工作 return False #效果 loc = self.getTableLoc(blockId) world = loc.getWorld() world.playSound(loc, Sound.BLOCK_BELL_RESONATE, 1.0, 1.0) #播放声音 world.spawnParticle(Particle.ENCHANT, loc.add(Vector(0.5,1.5,0.5)), 300, 0.3, 0.4, 0.3, 0) element, itemId = self.selectElementAndItem(blockId) #抽取元素和物品 self.working[blockId] = True #设置正在工作 self.offY[blockId] = 2.0 #重置Y偏移 self.keys[blockId] = key #设置关键字 self.mutation[blockId] = mutation #设置是否为突变 self.element[blockId] = element #设置元素 self.itemId[blockId] = itemId #设置物品 self.players[blockId] = player #设置玩家 playerManager = PlayerManager(player) playerManager.setGetting(True) self.taskIds[blockId] = ps.scheduler.scheduleRepeatingTask(lambda s=self, b=blockId, m=mutation, : s.spawnParticles(b, m), 0, 1) return True def reikiCallEnd(self, blockId): key = self.keys[blockId] #获取关键字 mutation = self.mutation[blockId] #获取是否为突变 loc = self.getTableLoc(blockId) world = loc.getWorld() blockManager.addTableTimesOfUse(blockId) #增加使用次数 player = self.players[blockId] #获取玩家 playerManager = PlayerManager(player) #获取玩家管理器 playerManager.addTimesOfUse() if key == u"DANDELION": #如果是蒲公英 if mutation: #如果是突变 world.spawnParticle(Particle.REVERSE_PORTAL, loc.add(Vector(0.5,0.9,0.5)), 100, 0.25, 0.06, 0.25, 0) #播放粒子 world.playSound(loc, Sound.ENTITY_PLAYER_LEVELUP, 0.5, 2.0) #播放声音 playerManager.upgradeLuck() playerManager.addTimesOfElement(self.element[blockId]) playerManager.addTimesOfMutation() blockManager.addTableTimesOfMutation(blockId) #增加突变次数 blockManager.addTableTimesOfElement(blockId, self.element[blockId]) #增加元素次数 message = u"§d[灵气] §e{} §a在{}§a成功召唤出 {} §a!".format(player.getName(), self.getTableName(blockId), itemManager.getItemDisplay(self.itemId[blockId])) #消息 getServer().broadcastMessage(message) self.dropItem(blockId, self.itemId[blockId]) #掉落 else: #如果不是 self.dropItem(blockId, 1) #掉落 playerManager.setGetting(False) #结束获取 def spawnParticles(self, blockId, mutation=False): if str(blockId) not in self.blockData.getKeys(False): return False loc = self.getTableLoc(blockId) world = loc.getWorld() if mutation: element = self.element[blockId] world.playSound(loc, Sound.BLOCK_AMETHYST_BLOCK_CHIME, 1.0, 1.0) #播放声音 if element == u"grass": world.spawnParticle(Particle.SPORE_BLOSSOM_AIR, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0) elif element == u"fire": world.spawnParticle(Particle.FLAME, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0.05) elif element == u"water": world.spawnParticle(Particle.DOLPHIN, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 10, 0.05, 0, 0.05, 0) elif element == u"earth": world.spawnParticle(Particle.WAX_ON, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0.2, 0, 0.2, 0) elif element == u"thunder": world.spawnParticle(Particle.FLASH, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0) elif element == u"ice": world.spawnParticle(Particle.SNOWFLAKE, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0) elif element == u"wind": world.spawnParticle(Particle.CLOUD, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0, 0, 0, 0.02) else: world.spawnParticle(Particle.DRAGON_BREATH, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0.02, 0, 0.02, 0) else: world.spawnParticle(Particle.HAPPY_VILLAGER, loc.add(Vector(0.5,self.offY[blockId]+0.8,0.5)), 1, 0.1, 0, 0.1, 0) self.offY[blockId] -= 0.05 #增加Y偏移 if self.offY[blockId] <= 0: #若Y偏移小于等于0 self.stopTask(blockId) #停止任务 self.reikiCallEnd(blockId) #灵气台反馈 self.working[blockId] = False #设置为未工作 def selectElementAndItem(self, blockId): if str(blockId) not in self.blockData.getKeys(False): return None, None # 加权抽取元素 elements = ['grass', 'fire', 'water', 'earth', 'thunder', 'ice', 'wind'] elementWeights = {element: self.blockData.getInt(u"{}.{}".format(blockId, element)) for element in elements} selectedElement = self.weightedRandomSelection(elementWeights) # 根据元素获取对应物品列表 if selectedElement == 'grass': itemList = itemManager.grassItems elif selectedElement == 'fire': itemList = itemManager.fireItems elif selectedElement == 'water': itemList = itemManager.waterItems elif selectedElement == 'earth': itemList = itemManager.earthItems elif selectedElement == 'thunder': itemList = itemManager.thunderItems elif selectedElement == 'ice': itemList = itemManager.iceItems elif selectedElement == 'wind': itemList = itemManager.windItems else: return None, None # 加权抽取物品 itemWeights = {} for itemId in itemList: weight = itemManager.itemsData.getInt(u"{}.weight".format(itemId), 1) itemWeights[str(itemId)] = weight selectedItem = self.weightedRandomSelection(itemWeights) return selectedElement, selectedItem def weightedRandomSelection(self, weights): totalWeight = sum(weights.values()) randomNum = random.uniform(0, totalWeight) cumulativeWeight = 0 for item, weight in weights.items(): cumulativeWeight += weight if randomNum <= cumulativeWeight: return item def stopTask(self, blockId): if blockId in self.taskIds: taskId = self.taskIds[blockId] if taskId is not None: ps.scheduler.stopTask(taskId) self.taskIds[blockId] = None def dropItem(self, blockId, itemId=1): if str(blockId) not in self.blockData.getKeys(False): return False item = itemManager.getItemstack(itemId) if item is None: return False loc = self.getTableLoc(blockId) world = loc.getWorld() droppedItem = world.dropItem(loc.add(Vector(0.5,1,0.5)), item) droppedItem.setVelocity(Vector(0, 0, 0)) world.playSound(loc, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0, 1.0) return True #运势管理 def setTodayPro(self, pro=5.0): #设置当日概率 self.todayPro = pro def randomTodayPro(self): rand = random.uniform(MIN_TODAY_PRO,MAX_TODAY_PRO) self.setTodayPro(rand) def getTodayPro(self): #获取今日运势概率 return self.todayPro def getReikiTablePro(self, blockId): #获取灵气台概率 if str(blockId) not in self.blockData.getKeys(False): #若不存在该灵气台 return None timesOfUse = self.blockData.getInt("{}.timesOfUse".format(blockId), 0) #获取 timesOfMutation = self.blockData.getInt("{}.timesOfMutation".format(blockId), 0) #获取 pro = (float(timesOfUse - timesOfMutation + 50) / float(timesOfUse + 100)) * 10 #计算 return pro def getPlayerPro(self, player): #获取玩家概率 playerName = player.getName() playerData = ps.config.loadConfig("reiki/player.yml") timesOfUse = playerData.getInt("{}.timesOfUse".format(playerName), 0) #获取 timesOfMutation = playerData.getInt("{}.timesOfMutation".format(playerName), 0) #获取 pro = (float(timesOfUse - timesOfMutation + 50) / float(timesOfUse + 100)) * 10 #计算 luck = player.getPotionEffect(PotionEffectType.LUCK) unluck = player.getPotionEffect(PotionEffectType.UNLUCK) if luck is not None: luckLevel = luck.getAmplifier() + 1 luckBonus = min(luckLevel * 2, 14) pro += luckBonus if unluck is not None: unluckLevel = unluck.getAmplifier() + 1 unluckPenalty = min(unluckLevel * 2, 14) pro -= unluckPenalty return pro def getPro(self, player, blockId): #获取概率 pro = self.getPlayerPro(player) + self.getReikiTablePro(blockId) + self.getTodayPro() pro = max(0.0, min(pro, 100.0)) #限制概率范围 return pro blockManager = BlockManager() class PlayerManager: def __init__(self, player): self.player = player def getTargetFrameLocation(self): targetBlock = self.player.getTargetBlockExact(5) if targetBlock is not None: if targetBlock.getType() == Material.END_PORTAL_FRAME: loc = targetBlock.getLocation() if loc.getWorld().getName() == WORLD_NAME: return loc return None def drawPro(self, pro=5.0): #按概率判断成功 pro = max(0.0, min(pro, 100.0)) randomValue = random.uniform(0.0, 100.0) return randomValue <= pro def reikiCall(self, blockId, key=u"DANDELION"): #灵气召唤 pro = blockManager.getPro(self.player, blockId) #获取概率 mutation = self.drawPro(pro) #抽奖 if mutation: result = blockManager.reikiCall(self.player, blockId, key, mutation=True) else: result = blockManager.reikiCall(self.player, blockId, key, mutation=False) if result: return True else: return False def upgradeLuck(self): luck = self.player.getPotionEffect(PotionEffectType.LUCK) if luck is not None: luckLevel = luck.getAmplifier() + 1 # 效果等级从 0 开始,所以加 1 luckLevel = min(luckLevel, 6) # 最大等级为 7 self.player.addPotionEffect(PotionEffect(PotionEffectType.LUCK, 72000, luckLevel, True, False)) else: self.player.addPotionEffect(PotionEffect(PotionEffectType.LUCK, 72000, 0, True, False)) def addTimesOfUse(self): playerData = ps.config.loadConfig("reiki/player.yml") timesOfUse = playerData.getInt("{}.timesOfUse".format(self.player.getName()), 0) playerData.set("{}.timesOfUse".format(self.player.getName()), timesOfUse + 1) playerData.save() def addTimesOfMutation(self): playerData = ps.config.loadConfig("reiki/player.yml") timesOfMutation = playerData.getInt("{}.timesOfMutation".format(self.player.getName()), 0) playerData.set("{}.timesOfMutation".format(self.player.getName()), timesOfMutation + 1) playerData.save() def addTimesOfElement(self, element=u"grass"): if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]: #若元素不存在 return False playerData = ps.config.loadConfig("reiki/player.yml") timesOfElement = playerData.getInt("{}.timesOf{}".format(self.player.getName(), element.lower()), 0) playerData.set("{}.timesOf{}".format(self.player.getName(), element.lower()), timesOfElement + 1) playerData.save() def setGetting(self, value=True): playerData = ps.config.loadConfig("reiki/player.yml") playerData.set("{}.getting".format(self.player.getName()), value) playerData.save() class MenuReikiInfo(GUIController):# 单人房间菜单 def __init__(self, player, blockId): super(MenuReikiInfo, self).__init__(player) self.blockId = blockId self.tableName = blockManager.getTableName(blockId) self.setInfo("reiki.info", u"§0[灵气]{} 信息一览".format(self.tableName)) self.setGUIManager(guiManager) def render(self): player = self.getPlayer() playerName = player.getName() pro = blockManager.getPro(player, self.blockId) todayPro = blockManager.getTodayPro() playerPro = blockManager.getPlayerPro(player) reikiPro = blockManager.getReikiTablePro(self.blockId) playerData = ps.config.loadConfig("reiki/player.yml") playerTimesOfUse = playerData.getInt("{}.timesOfUse".format(playerName), 0) playerTimesOfMutation = playerData.getInt("{}.timesOfMutation".format(playerName), 0) playerMutationPro = (float(playerTimesOfMutation) / float(playerTimesOfUse)) * 100 if playerTimesOfUse > 0 else 0 blockTimesOfUse = blockManager.blockData.getInt("{}.timesOfUse".format(self.blockId), 0) blockTimesOfMutation = blockManager.blockData.getInt("{}.timesOfMutation".format(self.blockId), 0) blockMutationPro = (float(blockTimesOfMutation) / float(blockTimesOfUse)) * 100 if blockTimesOfUse > 0 else 0 self.set(2, playerHeadsAPI.getPlayerHead(playerName), u"§b§l✟ §e§l召唤历史 §b§l✟", u"§e个人总运势: §f{:.2f}% §7[{}/{}]".format(playerMutationPro, playerTimesOfMutation, playerTimesOfUse), u"§e本台总运势: §f{:.2f}% §7[{}/{}]".format(blockMutationPro, blockTimesOfMutation, blockTimesOfUse)) self.set(4, Material.END_PORTAL_FRAME, u"§5§l☯ §d§l本台运势 §5§l☯", u"§e当前运势: §f{:.2f}%".format(pro), u"§f", u"§e天时: §f{:.2f} §7[0, 10]".format(todayPro), u"§e地利: §f{:.2f} §7[0, 10)".format(reikiPro), u"§e人和: §f{:.2f} §7[0, 24)".format(playerPro), u"§f", u"§6>> §e点击查看所有灵气台信息 §6<<") self.set(6, Material.DANDELION, u"§7§l✿ §a§l召唤物图鉴 §7§l✿", u"§f", u"§6>> §e点击查阅图鉴 §6<<") self.set(19, Material.WHEAT_SEEDS, u"§7§l✿ §a§l草元素召唤次数 §7§l✿", u"§a本台次数: §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfgrass".format(self.blockId), 0), blockTimesOfMutation), u"§a个人次数: §f{}§7/{}".format(playerData.getInt("{}.timesOfgrass".format(playerName), 0), playerTimesOfMutation)) self.set(20, Material.BLAZE_POWDER, u"§7§l✿ §c§l火元素召唤次数 §7§l✿", u"§c本台次数: §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOffire".format(self.blockId), 0),blockTimesOfMutation), u"§c个人次数: §f{}§7/{}".format(playerData.getInt("{}.timesOffire".format(playerName), 0), playerTimesOfMutation)) self.set(21, Material.HEART_OF_THE_SEA, u"§7§l✿ §3§l水元素召唤次数 §7§l✿", u"§3本台次数: §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfwater".format(self.blockId), 0),blockTimesOfMutation), u"§3个人次数: §f{}§7/{}".format(playerData.getInt("{}.timesOfwater".format(playerName), 0), playerTimesOfMutation)) self.set(22, Material.COCOA_BEANS, u"§7§l✿ §6§l地元素召唤次数 §7§l✿", u"§6本台次数: §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfearth".format(self.blockId), 0),blockTimesOfMutation), u"§6个人次数: §f{}§7/{}".format(playerData.getInt("{}.timesOfearth".format(playerName), 0), playerTimesOfMutation)) self.set(23, Material.NETHER_STAR, u"§7§l✿ §e§l雷元素召唤次数 §7§l✿", u"§e本台次数: §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfthunder".format(self.blockId), 0),blockTimesOfMutation), u"§e个人次数: §f{}§7/{}".format(playerData.getInt("{}.timesOfthunder".format(playerName), 0), playerTimesOfMutation)) self.set(24, Material.SNOWBALL, u"§7§l✿ §b§l冰元素召唤次数 §7§l✿", u"§b本台次数: §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfice".format(self.blockId), 0),blockTimesOfMutation), u"§b个人次数: §f{}§7/{}".format(playerData.getInt("{}.timesOfice".format(playerName), 0), playerTimesOfMutation)) self.set(25, Material.FEATHER, u"§7§l✿ §f§l风元素召唤次数 §7§l✿", u"§f本台次数: §f{}§7/{}".format(blockManager.blockData.getInt("{}.timesOfwind".format(self.blockId), 0),blockTimesOfMutation), u"§f个人次数: §f{}§7/{}".format(playerData.getInt("{}.timesOfwind".format(playerName), 0), playerTimesOfMutation)) self.spawnSeparators(0, 18, vertical=True) self.spawnSeparators(8, 26, vertical=True) def onClick(self, e): e.setCancelled(True) clickInt = e.getSlot() player = self.getPlayer() if clickInt == 4: MenuReikiTable(player).openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 6: MenuItems(player).openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) class MenuItems(GUIController):# 物品图鉴 def __init__(self, player, page=1, element=u"none"): super(MenuItems, self).__init__(player) self.page = page self.element = element self.setInfo("reiki.items", u"§0[灵气]召唤物图鉴 第{}页".format(self.page)) self.setGUIManager(guiManager) def render(self): player = self.getPlayer() playerName = player.getName() if self.element.lower() == u"none": items = list(itemManager.getAllItems()) elif self.element.lower() == u"grass": items = list(itemManager.grassItems) elif self.element.lower() == u"fire": items = list(itemManager.fireItems) elif self.element.lower() == u"water": items = list(itemManager.waterItems) elif self.element.lower() == u"earth": items = list(itemManager.earthItems) elif self.element.lower() == u"thunder": items = list(itemManager.thunderItems) elif self.element.lower() == u"ice": items = list(itemManager.iceItems) elif self.element.lower() == u"wind": items = list(itemManager.windItems) else: items = list(itemManager.getAllItems()) itemsPerPage = 45 # 每页显示 45 个物品,最后一行用于控制 self.totalPages = (len(items) + itemsPerPage - 1) // itemsPerPage startIndex = (self.page - 1) * itemsPerPage endIndex = startIndex + itemsPerPage currentPageItems = items[startIndex:endIndex] for index, itemNumber in enumerate(currentPageItems): item = itemManager.getItemstack(itemNumber) display = itemManager.getItemDisplay(itemNumber) if item is None: item = Material.PAPER self.set(index, item, display, data=itemNumber) self.spawnSeparators(45, 53) # 填充最后一行默认黑色染色玻璃板 if self.page > 1: self.set(45, Material.WHITE_STAINED_GLASS_PANE, u"§a上一页") # 上一页按钮 self.set(46, Material.WHEAT_SEEDS, u"§6>> §a§l查看草元素召唤物 §6<<") self.set(47, Material.BLAZE_POWDER, u"§6>> §c§l查看火元素召唤物 §6<<") self.set(48, Material.HEART_OF_THE_SEA, u"§6>> §3§l查看水元素召唤物 §6<<") self.set(49, Material.COCOA_BEANS, u"§6>> §6§l查看地元素召唤物 §6<<") self.set(50, Material.NETHER_STAR, u"§6>> §e§l查看雷元素召唤物 §6<<") self.set(51, Material.SNOWBALL, u"§6>> §b§l查看冰元素召唤物 §6<<") self.set(52, Material.FEATHER, u"§6>> §f§l查看风元素召唤物 §6<<") if self.page < self.totalPages: self.set(53, Material.WHITE_STAINED_GLASS_PANE, u"§a下一页") # 下一页按钮 # 记录玩家当前页码和筛选设置 playerPage[playerName] = { "page": self.page, "element": self.element } def onClick(self, e): e.setCancelled(True) clickInt = e.getSlot() player = self.getPlayer() playerName = player.getName() playerPageInfo = playerPage.get(playerName, {"page": 1, "element": "none"}) currentPage = playerPageInfo["page"] element = playerPageInfo["element"] if clickInt == 45 and currentPage > 1: MenuItems(player, page=currentPage - 1, element=element).openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 46: MenuItems(player, page=1, element="grass").openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 47: MenuItems(player, page=1, element="fire").openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 48: MenuItems(player, page=1, element="water").openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 49: MenuItems(player, page=1, element="earth").openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 50: MenuItems(player, page=1, element="thunder").openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 51: MenuItems(player, page=1, element="ice").openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 52: MenuItems(player, page=1, element="wind").openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 53 and currentPage < self.totalPages: MenuItems(player, page=currentPage + 1, element=element).openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt < 45: if player.isOp(): item = e.getCurrentItem() if item is not None: guiValue = getGUIValue(item) if guiValue: itemId = guiValue inv = player.getInventory() if inv.firstEmpty() == -1: #如果背包满了 player.sendMessage(u"§d[灵气]§c背包已满,无法获取召唤物") player.playSound(player, Sound.ENTITY_VILLAGER_NO, 1.0, 1.0) return else: player.getInventory().addItem(itemManager.getItemstack(itemId)) player.sendMessage(u"§d[灵气]§f成功获取 {}".format(itemManager.getItemDisplay(itemId))) player.playSound(player, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0, 1.0) class MenuReikiTable(GUIController):# 灵气台 def __init__(self, player, page=1): super(MenuReikiTable, self).__init__(player) self.page = page self.setInfo("reiki.table", u"§0[灵气]灵气台 第{}页".format(self.page)) self.setGUIManager(guiManager) def render(self): player = self.getPlayer() playerName = player.getName() blocks = list(blockManager.blockData.getKeys(False)) blocksLoc = {} playerIsOP = player.isOp() for id in blocks: #移除没有的台并记录坐标 blockLoc = blockManager.getTableLoc(id) if blockLoc is None: blocks.remove(id) else: blocksLoc[id] = blockLoc blocksPerPage = 45 # 每页显示 45 个物品,最后一行用于控制 self.totalPages = (len(blocks) + blocksPerPage - 1) // blocksPerPage startIndex = (self.page - 1) * blocksPerPage endIndex = startIndex + blocksPerPage currentPageBlocks = blocks[startIndex:endIndex] for index, blockId in enumerate(currentPageBlocks): blockLoc = blocksLoc[blockId] display = blockManager.getTableName(blockId) reikiTablePro = blockManager.getReikiTablePro(blockId) blockX = blockLoc.getBlockX() blockY = blockLoc.getBlockY() blockZ = blockLoc.getBlockZ() lores = [ u"§e坐标: §f{}, §f{}, §f{}".format(blockX, blockY, blockZ), u"§e地利: §f{:.2f}".format(reikiTablePro) ] if playerIsOP: grass = blockManager.blockData.getInt("{}.grass".format(blockId), 0) fire = blockManager.blockData.getInt("{}.fire".format(blockId), 0) water = blockManager.blockData.getInt("{}.water".format(blockId), 0) earth = blockManager.blockData.getInt("{}.earth".format(blockId), 0) thunder = blockManager.blockData.getInt("{}.thunder".format(blockId), 0) ice = blockManager.blockData.getInt("{}.ice".format(blockId), 0) wind = blockManager.blockData.getInt("{}.wind".format(blockId), 0) lores.append(u"§8- 以下信息仅管理员可见") lores.append(u"§6ID: §f{}".format(blockId)) lores.append(u"§6元素值: §a草{} §c火{} §3水{} §6地{} §e雷{} §b冰{} §f风{}".format(grass, fire, water, earth, thunder, ice, wind)) lores.append(u"§6") lores.append(u"§6>> 点击传送至该灵气台 <<") self.set(index, Material.END_PORTAL_FRAME, u"§a§l{}".format(display), *lores, data=blockId) self.spawnSeparators(45, 53) # 填充最后一行默认黑色染色玻璃板 if self.page > 1: self.set(45, Material.WHITE_STAINED_GLASS_PANE, u"§a上一页") # 上一页按钮 if self.page < self.totalPages: self.set(53, Material.WHITE_STAINED_GLASS_PANE, u"§a下一页") # 下一页按钮 # 记录玩家当前页码 playerPage[playerName] = { "page": self.page } def onClick(self, e): e.setCancelled(True) clickInt = e.getSlot() player = self.getPlayer() playerName = player.getName() playerPageInfo = playerPage.get(playerName, {"page": 1}) currentPage = playerPageInfo["page"] if clickInt == 45 and currentPage > 1: MenuReikiTable(player, page=currentPage - 1).openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt == 53 and currentPage < self.totalPages: MenuReikiTable(player, page=currentPage + 1).openWithRender() player.playSound(player, Sound.ITEM_BOOK_PAGE_TURN, 1.0, 1.0) elif clickInt < 45: if player.isOp(): #OP传送 item = e.getCurrentItem() if item is not None: guiValue = getGUIValue(item) if guiValue: blockId = guiValue blockLoc = blockManager.getTableLoc(blockId) if blockLoc is None: player.sendMessage(u"§d[灵气]§c该灵气台不存在或已被移除") player.playSound(player, Sound.ENTITY_VILLAGER_NO, 1.0, 1.0) return player.teleport(blockLoc) player.sendMessage(u"§d[灵气]§f成功前往 {}".format(blockManager.getTableName(blockId))) player.playSound(player, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0, 1.0) def onInventoryClick(e): # 菜单点击 player = e.getWhoClicked() worldName = player.getWorld().getName() if worldName != WORLD_NAME: return inv = e.getClickedInventory() if inv is None: return invHolder = inv.getHolder() if isGUI(invHolder): guiManager.get(e.getWhoClicked(), e.getClickedInventory().getHolder().getName()).onClick(e) # 菜单控制 return cancelShiftClickFromPlayerInventory(e) def onInventoryClose(e): # 菜单关闭 inv = e.getInventory() if isGUI(inv.getHolder()): guiManager.remove(e.getPlayer()) # 关闭菜单时清空存储的控制器 def stop(): # 程序卸载时 closeGuiForAll() # 关菜单 ps.listener.registerListener(onInventoryClick, InventoryClickEvent) ps.listener.registerListener(onInventoryClose, InventoryCloseEvent) ps.listener.registerListener(denyAllInventoryDrag, InventoryDragEvent) def onPlayerInteract(event): player = event.getPlayer() worldName = player.getWorld().getName() if worldName != WORLD_NAME: return False if event.getHand() == EquipmentSlot.OFF_HAND: #禁止副手触发 return False clickedBlock = event.getClickedBlock() if clickedBlock is None: #防止空指针 return False if clickedBlock.getType() != Material.END_PORTAL_FRAME: #判断是否是灵气台 return False blockLoc = clickedBlock.getLocation() blockX = blockLoc.getBlockX() blockY = blockLoc.getBlockY() blockZ = blockLoc.getBlockZ() blockId = None for id in blockManager.blockData.getKeys(False): x = blockManager.blockData.getInt("{}.x".format(id)) if blockX == x: y = blockManager.blockData.getInt("{}.y".format(id)) if blockY == y: z = blockManager.blockData.getInt("{}.z".format(id)) if blockZ == z: blockId = id break if blockId is None: return False event.setCancelled(True) #确定是灵气台,取消事件 playerManager = PlayerManager(player) item = event.getItem() guiValue = getGUIValue(item) if guiValue is not None: reiki, key = guiValue.split(':') if reiki == u"reiki": if key == u"DANDELION": result = playerManager.reikiCall(blockId, key) if result: item.setAmount(item.getAmount()-1) return MenuReikiInfo(player, blockId).openWithRender() ps.listener.registerListener(onPlayerInteract, PlayerInteractEvent) def reikiCommand(sender, label, args): if isinstance(sender, Player): if sender.isOp(): if sender.getWorld().getName() != WORLD_NAME: sender.sendMessage(u"§d[灵气]§f请在世界 §e{} §f中使用此命令".format(WORLD_NAME)) return False playerManager = PlayerManager(sender) if len(args) < 1: sender.sendMessage(u"§d[灵气] §a管理员命令帮助:") sender.sendMessage(u"§d[灵气] §f/reiki add §e- 创建灵气台") sender.sendMessage(u"§d[灵气] §f/reiki del §e- 删除灵气台") sender.sendMessage(u"§d[灵气] §f/reiki list §e- 查看所有灵气台") sender.sendMessage(u"§d[灵气] §f/reiki item §e- 查看所有召唤物") sender.sendMessage(u"§d[灵气] §f/reiki set element <元素名> <值> §e- 设置灵气台元素值") sender.sendMessage(u"§d[灵气] §f/reiki set name <名称> §e- 设置灵气台名称") return False elif args[0] == u"add": #目视传送门框架,创建灵气台 blockLoc = playerManager.getTargetFrameLocation() if blockLoc is not None: blockId = blockManager.createReikiTable(blockLoc) if blockId is False: sender.sendMessage(u"§d[灵气]§f该位置已经有灵气台了") return False else: sender.sendMessage(u"§d[灵气]§f成功创建ID为{}的灵气台".format(blockId)) return True else: sender.sendMessage(u"§d[灵气]§f请看着一个末地传送门框架") return False elif args[0] == u"del": #目视传送门框架,删除灵气台 blockLoc = playerManager.getTargetFrameLocation() if blockLoc is not None: blockId = blockManager.getLocTable(blockLoc) if blockId is None: sender.sendMessage(u"§d[灵气]§f该位置没有灵气台") return False result = blockManager.delReikiTable(blockId) if result is False: sender.sendMessage(u"§d[灵气]§f未找到该灵气台") return False else: sender.sendMessage(u"§d[灵气]§f成功删除灵气台") return True else: sender.sendMessage(u"§d[灵气]§f请看着一个末地传送门框架") return False elif args[0] == u"list": MenuReikiTable(sender).openWithRender() return True elif args[0] == u"item": MenuItems(sender).openWithRender() return True elif args[0] == u"set": #目视传送门框架,设置灵气台 if len(args) > 2: blockLoc = playerManager.getTargetFrameLocation() if blockLoc is not None: blockId = blockManager.getLocTable(blockLoc) if blockId is None: sender.sendMessage(u"§d[灵气]§f该位置没有灵气台") return False setType = args[1] if setType == u"element": element = args[2] if element.lower() not in ["grass", "fire", "water", "earth", "thunder", "ice", "wind"]: sender.sendMessage(u"§d[灵气]§f元素不存在") return False value = args[3] try: value = int(value) except ValueError: sender.sendMessage(u"§d[灵气]§f数值必须为整数") return False result = blockManager.setTableElement(blockId, element, value) if result is False: sender.sendMessage(u"§d[灵气]§f设置失败") return False else: sender.sendMessage(u"§d[灵气]§f成功设置元素值") return True elif setType == u"name": name = u" ".join(args[2:]) result = blockManager.setTableName(blockId, name) if result is False: sender.sendMessage(u"§d[灵气]§f设置失败") return False else: sender.sendMessage(u"§d[灵气]§f成功设置名称") return True else: sender.sendMessage(u"§d[灵气]§f无效的参数") else: sender.sendMessage(u"§d[灵气]§f请看着一个末地传送门框架") else: sender.sendMessage(u"§d[灵气]§f请输入参数") return False else: sender.sendMessage(u"§d[灵气]§f无效的参数") return False return False ps.command.registerCommand(reikiCommand, "reiki")