Skip to content

Instantly share code, notes, and snippets.

@Namnodorel
Last active November 6, 2019 15:32
Show Gist options
  • Save Namnodorel/fbf72c7ae871115d78c9a6aa76c693b6 to your computer and use it in GitHub Desktop.
Save Namnodorel/fbf72c7ae871115d78c9a6aa76c693b6 to your computer and use it in GitHub Desktop.
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.event.NPCSpawnEvent;
import net.citizensnpcs.api.npc.NPC;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.Plugin;
import pl.betoncraft.betonquest.*;
import pl.betoncraft.betonquest.api.QuestEvent;
import pl.betoncraft.betonquest.config.Config;
import pl.betoncraft.betonquest.config.ConfigPackage;
import pl.betoncraft.betonquest.utils.PlayerConverter;
import java.util.HashMap;
import java.util.HashSet;
public class NPCHider implements Listener, Runnable{
private static NPCHider instance;
private EntityHider hider;
private HashMap<Integer, HashSet<ConditionID>> npcs;
private ConfigurationSection configSection;
private Integer updateInterval;
public static void init(Plugin plugin){
if(instance == null){
instance = new NPCHider(plugin);
}
}
private NPCHider(Plugin plugin){
configSection = BetonQuest.getInstance().getConfig().getConfigurationSection("hide_npcs");
if (configSection == null){
return;
}
hider = new EntityHider(plugin, EntityHider.Policy.BLACKLIST);
npcs = new HashMap<>();
loadFromConfig();
Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this, 0L, 20 * updateInterval);
}
private void loadFromConfig(){
for(ConfigPackage cfgPackage : Config.getPackages().values()){
if(cfgPackage.getCustom().getConfig() == null || cfgPackage.getCustom().getConfig().getConfigurationSection("hide_npcs") == null){
continue;
}
for (String npcID : cfgPackage.getCustom().getConfig().getConfigurationSection("hide_npcs").getKeys(false)) {
try {
int id = Integer.parseInt(npcID);
NPC npc = CitizensAPI.getNPCRegistry().getById(id);
if(npc != null){
HashSet<ConditionID> conditions = new HashSet<>();
String conditionsString = cfgPackage.getCustom().getConfig().getConfigurationSection("hide_npcs").getString(npcID);
for(String condition : conditionsString.split(",")){
conditions.add(new ConditionID(cfgPackage, condition));
}
if(npcs.containsKey(id)){
npcs.get(id).addAll(conditions);
}else{
npcs.put(id, conditions);
}
}else{
System.out.println("[NPCHider]: An NPC with the id " + npcID + " does not exist!");
}
} catch (NumberFormatException e) {
System.err.println("[NPCHider]: Given NPC ID " + npcID + " is not a valid number!");
} catch (ObjectNotFoundException e){
System.err.println("[NPCHider]: " + e.getMessage());
}
}
}
updateInterval = configSection.getInt("updateInterval");
}
//These methods check the conditions and apply according visibilities immediately,
//and need to go through more or less entities and conditions depending on how specific
//the arguments are
public void applyVisibility(Player p, Integer npcID){
boolean hidden = true;
if(npcs.get(npcID).isEmpty()){
hidden = false;
}else{
for(ConditionID condition : npcs.get(npcID)){
if(!BetonQuest.condition(PlayerConverter.getID(p), condition)){
hidden = false;
break;
}
}
}
NPC npc = CitizensAPI.getNPCRegistry().getById(npcID);
if(npc.isSpawned()){
if(hidden){
hider.hideEntity(p, npc.getEntity());
}else{
hider.showEntity(p, npc.getEntity());
}
}
}
public void applyVisibility(Player p){
for(Integer npcID : npcs.keySet()){
applyVisibility(p, npcID);
}
}
public void applyVisibility(NPC npc){
for(Player p : Bukkit.getOnlinePlayers()){
applyVisibility(p, npc.getId());
}
}
public void applyVisibility(){
for(Player p : Bukkit.getOnlinePlayers()){
for(Integer npcID : npcs.keySet()){
applyVisibility(p, npcID);
}
}
}
public static NPCHider getInstance() {
return instance;
}
@Override
public void run() {
applyVisibility();
}
//We want to have the visibility applied immediately, NPCs shouldn't spawn, stay there for a second and only then disappear
@EventHandler
public void onNPCSpawn(NPCSpawnEvent event) {
applyVisibility(event.getNPC());
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
applyVisibility(event.getPlayer());
}
//Optional; in case something changed and the updated visibilities need to be applied immediately for that player
public static class UpdateVisibilityNowEvent extends QuestEvent {
public UpdateVisibilityNowEvent(Instruction instruction) throws InstructionParseException {
super(instruction);
}
@Override
public void run(String id) throws QuestRuntimeException {
NPCHider.getInstance().applyVisibility(PlayerConverter.getPlayer(id));
}
}
//Optional; I implemented it because in some cases there are temporary NPCs which shouldn't be
//Visible to everyone
public static class WriteHideConditionEvent extends QuestEvent {
private Integer npcID;
private HashSet<ConditionID> conditions;
public WriteHideConditionEvent(Instruction instruction) throws InstructionParseException {
super(instruction);
super.staticness = true;
super.persistent = true;
npcID = instruction.getInt();
conditions = new HashSet<>();
conditions.addAll(instruction.getList(instruction.getOptional("cons"), instruction::getCondition));
}
@Override
public void run(String s) throws QuestRuntimeException {
NPC npc = CitizensAPI.getNPCRegistry().getById(npcID);
if(npc != null){
NPCHider.getInstance().npcs.put(npcID, conditions);
NPCHider.getInstance().applyVisibility(npc);
}else{
System.out.println("[NPCHider]: An NPC with the id " + npcID + " does not exist!");
}
}
}
}
@MWFIAE
Copy link

MWFIAE commented Oct 26, 2017

@Namnodorel

I find minecraft very interesting as base as the more difficult parts are already handled for you and you only have to concentrate on new features etc.
No more messing with sockets, rendering or textures (only if you want an own resourcepack, but thats purely optional). There are even ready plugins one can use/modify and all the limitations are only making it more interesting to play with in my opinion ;)

PS: Denizens scripts are just gibberish for me, thanks nonetheless!
PPS: I figured one would have massiv problems with citizens, but building it from the ground up doesn't sound to good either...

@Namnodorel
Copy link
Author

I'd rather go with speaking english, in case anyone wants to read the conversation who isn't German ;D Yes, stuff like sockets and rendering are done already, but Minecraft feels so much like a dirty hack in many "higher level" cases... An example I got really angry about is that the nametags of each and every entity in MC are stored in their nametag-attribute... Except for players. Players' nametags are stored on the scoreboard, whyever that is. Rendering works, but is extremely slow... With shaders installed, the FPS of MC can go really low, and that's not because of the used PC or that MC has been written in Java; it simply because MC was written so inefficiently. The selection of what needs a packet and which information is stored in them is also really weird. I don't necessarily mean it is better to make a whole new game, but rather base big projects off a different one. But we're really getting off-topic xD

@MWFIAE
Copy link

MWFIAE commented Oct 26, 2017

Meh, boring :p (I translated my comment though)

What game do you have in mind? ^^

And I agree that minecraft/bukkit is sometimes really messy, but nothing too bad I guess. overdesigning a problem is sometimes just as bad :3

At least we are not spamming in the betonquest issues ;)

@RiledUpCrow
Copy link

@MWFIAE I wouldn't mind a bit of interesting spam ๐Ÿ˜„
@Namnodorel You gave me a few ideas for making instances. We'll see if anything comes out of it. And thank you for sharing this, I'll include it in the plugin ๐Ÿ‘

@Namnodorel
Copy link
Author

Namnodorel commented Oct 26, 2017

@MWFIAE Might be true, but I have yet to come across a problem that needs less thought put into it :P Messing with entities, packets and NMS has been a big headache for me multiple times.

Since I have no new big project planned currently nothing too specific, but Terasology looks promising to me if I want "Minecraft, just programmed better". If just sockets and rendering are the problem, I would love to try out libgdx some day. I mean, you can literally make a game in Java and it runs on anything from iPhone to Windows... A dream come true! :D And since it's an engine there's no need to mess with low-level stuff.

@Co0sh Great ^^ I'm glad to help. I've recently tried DungeonsXL (the description looked very good), but since it is so very very early access and more built for minigame-like dungeons that instances in an RPG I decided not to use it. You might still find it interesting though :) I especially liked the multiple (and random, if you want to) floors and signs to place stuff like spawners and checkpoints in the dungeon/instance.

@MWFIAE
Copy link

MWFIAE commented Oct 27, 2017

@Namnodorel
I messed with Unity and Unreal-Engine a few times in the past which are even better equipped engines, but the problem with the whole moddeling/texturing/etc. still remains and I'm not very good with this artist stuff :p

@Co0sh
Nah, you don't have time for spam.
I already try to help all the other people in the issues so that you have more time to resolve my own issues and implementing features I could make good use of :3 (selfish me :3 )

@Namnodorel
Copy link
Author

@MWFIAE Me neither, but that can be learned. I found https://cgcookie.com/ to be a good resource for learning to model stuff. And you can still use the plenty of presets existing- in MC, you're using a number of "presets" as well, right? :D

@MWFIAE
Copy link

MWFIAE commented Oct 28, 2017

@Namnodorel looks good, will take a look at it sometime if I have some real free time :)
Yeah, but it's not the same, as all presets are from the same source and don't look wild mixed... You know what I mean, right?

@Namnodorel
Copy link
Author

Namnodorel commented Oct 29, 2017

@MWFIAE Yes, kinda. You can get them to look quite similar if you are picky about which presets you use. Buut of course it takes significantly more time to find the right stuff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment