Beiträge von Scrayos

    MadeByProxxy Es freut mich, dass es nun funktioniert!


    Ich würde dennoch ungerne ein paar der von IDK_WHO_AM_I aufgeworfenen Punkte unkommentiert so stehen lassen. Dieser Post richtet sich also nicht mehr direkt an dein Problem, ist für dich und zukünftige Leser ggf. dennoch interessant und bedenkenswert. Es geht um meine allgemeine Einstellung in Bezug auf Hilfe-/Frage-Posts und um die Relevanz von Codestyle sowie verbesserter Lesbarkeit.


    IDK_WHO_AM_I Ich vermute, dass du meine Kritik falsch aufgefasst hast, bzw. ich nicht klar genug gemacht habe, was ich damit bezwecken wollte. Es ging mir überhaupt nicht darum dich auch nur im entferntesten persönlich anzugreifen oder dich darin zu kritisieren, dass du Hilfe anbietest. Im Gegenteil: Ich finde es hervorragend, dass du dir die Zeit nimmst, um jemanden mit einem Problem unentgeltlich zu helfen. Das ist definitiv nicht selbstverständlich und sollte entsprechend honoriert werden.


    Auch deinen generellen Ansatz habe ich nicht negativ kommentiert, und darin sehe ich auch keinen Grund. Der allgemeine Algorithmus und dessen Funktion stimmt ja durchaus mit dem überein, was sich der Thread-Ersteller gewünscht hat. Dennoch sind mir, wie ich oberhalb ja bereits ausgeführt habe, einige Dinge aufgefallen, die ich so für nicht gut, oder zumindest nicht uneingeschränkt optimal halte. Und insbesondere weil du dir die Zeit genommen hast, hier jemandem zu helfen und weil ich hier mit einer Antwort nicht nur dich erreichen kann, sondern auch Leute, die beispielsweise über Google auf diese Frage aufmerksam werden, habe ich mir gerne die Zeit genommen um auch darauf zu antworten und damit ggf. auch für dich einen Mehrwert zu bieten. Leider scheinst du dich davon angegriffen gefühlt zu haben, und hast dich auch innerhalb des ersten Satzes gerechtfertigt. Das wäre gar nicht nötig gewesen, es ging mir ja nicht darum dir Unvermögen oder dergleichen zu unterstellen.


    Nun aber zu meiner Meinung zu deinen Rechtfertigungen:

    Das ist einfach nur Unsinn sowas als "Verbesserung" zu sehen den Erstens gehört es so das ein "neuer Code Block" eingerückt beginnt wer das nicht macht, "Schande über dich".

    Das halte ich so für zumindest kontrovers. Codestyle und Lesbarkeit ist häufig sogar wichtiger als Mikro-Optimierungen, Feature-Überschuss oder Erweiterbarkeit. Codestyle und gute Lesbarkeit sind der Schlüssel zu guter Zusammenarbeit und Wartbarkeit. Programme werden schließlich für Menschen und nicht für den Computer geschrieben. Und auch, wenn ich deine Argumentation bezüglich des eingefügten Code-Blocks nachvollziehen kann, so stellt sich mir – insbesondere in dem konkreten Code-Beispiel – wirklich kein eigenständiger, logischer, neuer Block dar. Der innere Block besteht schließlich nur aus einer einzelnen Bedingung. Und diese Bedingung steht auch noch im direkten Zusammenhang mit der vorigen Bedingung, da du hiermit lediglich sicherstellen möchtest, dass ein fehlender Eintrag niemals größer als die 60 sein kann, die Bedingung also in diesem Fall immer falsch sein muss.


    Unnötige Einrückungen wirken sich besonders negativ auf den Lesefluss aus, wenn sie dafür sorgen, dass der darin enthaltene Code weit jenseits der (gut) lesbaren 100 Zeichen/Spalten liegt. Unter anderem deshalb gilt es, Einrückungen sinnvoll einzusetzen und eben auch zu vermeiden, wenn die Einrückung an dieser Stelle keinen Mehrwert bietet. In diesem Beispiel ist das weniger wichtig, aber grundsätzlich wirken sich separate Code-Blocks und die Aufteilung in zwei separate Bedingungen auch auf die zyklomatische Komplexität aus, was ebenfalls vermieden werden sollte.


    Was die Klammern und den Hinweis auf die AFK-Logik betrifft, so vertrete ich die Auffassung, dass die Personen die hier Hilfe anbieten so umsichtig wie möglich auf möglichst viele Leser eingehen sollten. Natürlich kann man das nicht verlangen, ist doch jeder hier freiwillig, aber wünschenswert ist es dennoch. Das Weglassen der Klammern verwirrt hier ggf. den einen oder anderen Leser und liefert ihm im Umkehrschluss keinen Vorteil. Zusätzlich können hier durch Unachtsamkeit leicht Fehler entstehen. Und auch wenn du natürlich damit recht hast, das es hier nicht um das Schreiben fertiger Plugins geht, so tut es dennoch nicht weh, hier kurz auf solche Faktoren hinzuweisen, bzw. die Klammern zu setzen. Ich glaube einfach, dass du dem Leser damit keinen gefallen tust, weil vielleicht nicht jeder so umfassend um die syntaktischen Möglichkeiten von Java informiert ist, wie du es bist.


    Dennoch möchte ich abschließend ein weiteres Mal darauf hinweisen, dass ich es grundsätzlich begrüße und loben möchte, dass du hier Leuten hilfst, und das ja auch tatsächlich nicht schlecht oder verkehrt. Aber ich hielt es für nötig mich hier zu äußern, da mir Aussagen wie "Schande über dich" trotzdem negativ aufgestoßen sind. Ich wünsche dir ungeachtet dessen einen schönen Tag und hoffe du weißt meinen Post hier richtig einzuordnen. :)

    IDK_WHO_AM_I Ich stimme mit deiner Lösung soweit überein, bis auf zwei, drei kleinere Dinge:



    private HashMap<UUID, LocalDateTime> lastMovement;

    Eine LocalDateTime ist hier definitiv der falsche Datentyp. Du willst hier einen Moment (also einen spezifischen, unverwechselbaren Zeitpunkt) vergleichen. Es sollen ja immer 60 Sekunden vergangen sein und du willst überhaupt keine für Menschen lesbare Repräsentation dieser Zeit. Du möchtest einen Instant. Sie sind untereinander vollständig kompatibel, meinen aber wie gesagt vollständig unterschiedliche Dinge. Eine hervorragende Unterscheidung der neuen Zeit-Typen kannst du HIER erhalten.


    Code
    1. public void handleMovement(PlayerMoveEvent e) { if (e.getFrom().getBlockX() != e.getTo().getBlockX() || e.getFrom().getBlockY() != e.getTo().getBlockY() || e.getFrom().getBlockZ() != e.getTo().getBlockZ()) if (e.getFrom().getPitch() != e.getTo().getPitch() || e.getFrom().getYaw() != e.getTo().getYaw()) lastMovement.put(e.getPlayer().getUniqueId(), LocalDateTime.now()); }

    Die Bedingungen würde ich mir hier schenken. Es wird ohnehin nur ein Move-Event ausgelöst, wenn sich die Position wenigstens irgendwie von der vorigen Position unterscheidet, und ob es nun innerhalb des Blocks war, oder Block-Grenzen übergreifend macht es nur ungenauer. Würde ein Nutzer so vorher an der Blockgrenze stehen, dürfte er sich weniger bewegen um trotzdem noch als AFK markiert zu werden, als wenn er in der Mitte des Blocks gestanden hätte.


    Durch deine Abfragen würden auch Teleports an die exakt selbe Position in einer anderen Welt nicht berücksichtigt. Wenn man unbedingt eine Bedingung haben möchte, kann man auch einfach die From- und To-Positionen mit Equals vergleichen, da bekäme man dann sogar noch die bessere Verarbeitung von Float und Double geschenkt. Aber es ist wie gesagt überhaupt keine Bedingung nötig, wenn ohnehin jede Art der Veränderung berücksichtigt werden soll.


    if (lastMovement.containsKey(player.getUniqueId()))
    if (lastMovement.get(player.getUniqueId()).plusMinutes(1).isAfter(LocalDateTime.now()))
    Bukkit.broadcastMessage(String.format("§e%s hasn't moved since 60 seconds"));
    //TODO do something

    Hier rückst du unnötig oft ein und verwendest keine Klammern, was insbesondere in Anbetracht der Tatsache, dass man da auch gerne mal mehrere Dinge anstoßen möchte, schnell zu Fehlern führen kann. Abgesehen davon, würde ich es aber so regeln:

    Java
    1. Bukkit.getScheduler().scheduleSyncRepeatingTask(pluginInstance, () -> {
    2. final Instant now = Instant.now;
    3. Bukkit.getOnlinePlayers().forEach(player -> {
    4. Instant lastMovementMoment = lastMovement.get(player.getUniqueId());
    5. if (lastMovementMoment != null && Duration.between(lastMovementMoment, now).getSeconds() > INACTIVITY_SECOND_TRESHOLD) {
    6. // afk-logic here
    7. }
    8. });
    9. }, 0L, 20L);

    Erstmal hole ich hier nur einmal die aktuelle Zeit. Sich den aktuellen Zeitpunkt zu beschaffen ist zwar nicht teuer, aber auch nicht gratis. Insbesondere bei der Präzision, die die neuen Time-Objekte von Java 8 anstreben, wird die präziseste, verfügbare Zeit-Ressource verwendet, um so ein Objekt zu beziehen. Das kann gerne auch mal einen Syscall beinhalten, was zwar in Ordnung ist, aber eben auch nicht so schnell/günstig wie man ggf. meinen mag. Wir brauchen den aktuellen Zeitpunkt ohnehin nur einmal, da uns die Veränderungen im Nanosekunden-Bereich während des Vergleichs egal sind.


    Eben weil uns die Präzision unter einer Sekunde nicht interessiert, habe ich den Task-Intervall übrigens auch auf 20 angehoben. Es reicht für diesen Fall sicherlich vollkommen einmal in der Sekunde nachzuprüfen, ob sich etwas neues ergeben hat.


    Dann habe ich deine beiden Bedingungen zu einer Zusammengefasst, und dabei auch das Contains durch die Nullability der Get-Methode ersetzt. Wenn das Element nicht enthalten ist, wird null zurückgegeben. Wir nutzen null niemals als echte Value, es kann also nur daher kommen. So sparen wir uns das doppelte Hashing (das aber sowieso unglaublich günstig ist) und können den Code etwas entschlacken. Der zweite Teil der Bedingung nutzt jetzt eine Konstante für den Vergleich (hier müsste also 60 zugewiesen werden) und arbeitet mit dem ermittelten Moment.


    Die Lösung ist vor Allem deshalb besser, weil sie wie gesagt nur einmal den aktuellen Vergleichs-Zeitpunkt erstellt, und weil sie generell nicht so viele Elemente erstellt. Die neue java.time-API basiert auf unveränderbaren (Immutable) Objekten. Ein Aufruf wie "plusMinutes(long)" erstellt daher extra ein neues LocalDateTime-Objekt. Wir erstellen hier jetzt zwar auch eine Duration, die wir durch den direkten Vergleich der Sekunden verhindern könnten, erhalten dafür aber eine deutlich verbesserte Lesbarkeit.


    Was aber hier noch immer nicht bedacht wurde, und was auch deine Lösung nicht abgedeckt hatte, ist der Fall, dass der Nutzer bereits als "AFK" markiert wurde. Aktuell würde also immer wieder der Teil bei "// afk-logic here" für ihn ausgeführt. Da müsste man also ggf. noch drauf achten und entsprechend filtern, um nur die neuen AFK-Nutzer zu erhalten.

    Die Lösung mit der besten Performance wäre sicherlich ein Aufruf von https://papermc.io/javadocs/pa…/Entity.html#isOnGround-- (Entity#isOnGround). Allerdings gab es zumindest in der Vergangenheit bei der Nutzung im Zusammenhang mit Spielern einige Warnungen in den Javadocs, weswegen der Aufruf der Methode beim Spieler auch als Deprecated markiert war. Hierbei war das Problem, dass der "OnGround"-Status vom Client gesendet wurde, und daher mit modifizierten Clients sehr leicht gefälscht werden konnte. Diese Hinweise gibt es in den neueren Versionen (1.12+) allerdings nicht mehr, auch wenn ich mir nicht sicher bin ob das nun bedeutet, dass der Status auch bei Spielern selbst berechnet wird, immerhin wird der Status nach wie vor vom Client als Teil des Protokolls übertragen: https://wiki.vg/Protocol#Player_Position


    Ich würde diese Methode dennoch erstmal probieren (insbesondere sofern es nicht sooo kritisch ist, wenn es mit einem manipulierten Client umgehbar wäre) und nur falls diese Methode nicht deinen Ansprüchen genügt auf diese einfache, eigene Implementation zurückgreifen. Die Performance unterscheidet sich zwar wirklich nur minimal, da hier ebenfalls ausschließlich einfache mathematische Vergleiche und sehr schnelle Lookups mit linearer Laufzeit durchgeführt werden, aber die andere Methode ist extra für diesen Fall gedacht und lässt sich deutlich besser lesen, zumindest wenn man mich fragt. Die alternative Lösung wäre eben:


    Code
    1. // hier muss selbstverständlich eine echte variable genutzt werden
    2. Player yourPlayer;
    3. // die unterscheidung bei .isSolid() kannst du auf deinen individuellen fall anpassen
    4. // ggf. möchtest du ja zum beispiel spinnenweben und co. als "auf dem boden" zählen
    5. return yourPlayer.getLocation().getBlock().getRelative(BlockFace.DOWN).getType().isSolid();


    Diese Abfrage packst du dann in eine eigene Methode und fragst sie beim PlayerCommandPreprocessEvent und PlayerInteractEvent ab. Sollten sie nicht "auf dem Boden" sein, so brichst du das Event ab (Event#setCancelled(Boolean)).


    #push: Lange ist es her, dass dieses Thema aktualisiert wurde. Nun wurde der erste Post an unser neues PDF-Design angepasst und die Informationen sind ebenfalls auf dem neuesten Stand. Dabei haben wir uns von einer Menge Text getrennt und versucht die Informationen weiter aufzubereiten und auf das Wichtigste herunter zu brechen. Für das Thema wurde die PDF zudem in ein Bild konvertiert. Für die optimale Ansicht empfehlen wir jedoch die PDF im Original über einen Klick auf die Grafik oder das Banner oberhalb zu öffnen. Wir wollen dieses Thema ab sofort wieder häufiger mit Neuigkeiten versorgen und freuen uns mit dem aktualisierten Thema nun den Grundstein dafür gelegt zu haben!

    Äh, ...

    auch ich scheine deiner Argumentation nicht ganz folgen zu können. Meine Verwunderung über deine Argumentationskette begründet sich vor Allem darin, dass ja von der verlinkten Hytale-News-Seite auf das Hytale-Forum von MCSEU verlinkt wird, und nicht andersherum. Entsprechend wundert mich, dass du beklagst, dass im Impressum von MCSEU nichts hierzu vermerkt ist. Aber das wäre doch auch der falsche Ort, oder nicht?

    Ich könnte durchaus verstehen, wenn du eine Ungereimtheit in dem Fehlen eines Hinweises auf das externe Forum seitens der News-Seite sehen würdest. Es erschließt sich mir allerdings nicht, welchen Fehler MCSEU hier – abgesehen von dem falschen Routing beim Hytale-Forum und dem dadurch verschuldeten Nichtvorhandensein des Impressums – gemacht haben soll. Vielleicht könntest du da die Sachlage aus deiner Perspektive noch einmal näher darlegen.

    Heyho,


    die Zielgruppe besteht hauptsächlich aus denjenigen, die bereits eine der vielen "Bukkit-Tutorial-Reihen" angeschaut haben. Es geht mir also definitiv nicht darum Bukkit geschweige denn Java neu zu vermitteln, sondern viel mehr vorhandene Fehler oder schlechte Angewohnheiten auszubügeln, die sich durch die Tutorial oder im Laufe der Zeit eingeschlichen haben. Darüber hinaus möchte ich noch einige Ebenen auf das Tutorial-Wissen drauflegen. Das sieht man zum Beispiel an den Erklärungsvideos zu den Tools (Git, Checkstyle). Es geht mir hier also darum Menschen, die schon regelmäßig im Bukkit-Kontext agieren mit Wissen darüber zu versorgen, wie sie ihren Workflow optimieren können, bzw. wie in der Software-Entwicklung außerhalb von Minecraft gearbeitet wird.


    Ich habe also nicht den Anspruch "einsteiger-freundlich" zu sein, sondern viel mehr engagierte Entwickler dazu zu verhelfen weiter besser zu werden. Für solche Einstiegstutorials kann ich da zum Beispiel die Tutorials von BiVieh empfehlen.


    Vielen Dank für dein Feedback!

    Im Zuge meiner Update-Agenda, die ich für diesen Thread angekündigt habe, poste ich mal wieder das Video dieser Woche. Neue Videos erscheinen immer Sonntags gegen 12:00:



    Vielen Dank auch noch einmal für die Aufmerksamkeit und den anhaltenden Support!

    Vielen Dank für das nette Feedback!

    Und die Alarmglocken-Sache gibt es ja leider in Bezug auf viele Praktiken in der Bukkit-Szene. Und bei den Dingen, bei denen die Alarmglocken wirklich Sturm klingeln sollten (Reflection zum Beispiel), da werden falsche Dogmen gepredigt. Und das ist ja eben auch eine der Motivationen, die ich für dieses Projekt verfolge.


    Bezüglich deines Fun-Facts scheine ich etwas auf dem Schlauch zu stehen; kannst du das näher ausführen? Ich wäre mir keines "Überschreibens statischer Methoden" bewusst. Es sei denn, du meinst das Shadowing (Überdeckung) oder Overloading (Überladung). Bei statischen Methoden ist ja wegen des fehlenden Polymorphismus' zur Laufzeit sogar bei dieser Konstellation mit keiner Überschreibung zu rechnen:


    Vermutlich meintest du eines der oberhalb genannten Szenarien, aber beschreib' gerne nochmal genauer was du damit meinst. :)

    Guten Tag liebe Dev-Tek-Community,


    ich liebäugle schon seit geraumer Zeit mit dem Gedanken eine YouTube Leitfaden-Reihe zu kreieren. Nun habe ich mich endlich dazu motivieren können diesen Gedanken in die Tat umzusetzen. Getauft habe ich das Projekt Bukkit: Done The Right Way und es wird wie geplant auf YouTube publiziert. In diesem Beitrag möchte ich euch das grundsätzliche Projekt vorstellen, ein wenig über meine Motivation, die Eckdaten und die Ideen für die Zukunft sprechen.

    Motivation

    Meine Motivation für die Videoreihe begründet sich hauptsächlich in den vielen Fragen die ich in der Vergangenheit zu IntelliJ IDEA, Maven und Bukkit erhalten habe, sowie den Eindrücken, die ich beim "durchzappen" der bereits existierenden YouTube-Bukkit-Tutorials gewinnen durfte. Deshalb wähle ich für diese Reihe häufig einen vergleichenden Ansatz, bei dem ich mich bemühe externe, weiterführende Quellen und Literatur einzubinden und Bezüge zu falschen Programmier-Paradigmen und Common-Pitfalls herzustellen. Ich beschränke mich bei diesen Tutorials größtenteils auf den Java/Bukkit-Bereich, werde allerdings versuchen hier auch den Ausblick bzw. die Brücke zu Java zu schaffen.

    Eckdaten

    Da ich nicht alle Build-Systeme, IDEs, Minecraft-Versionen, Bukkit-Forks und Java-Versionen abdecken kann, habe ich mich gleich zu Anfang auf ein Set aus Versionen und Tools festgelegt, dass ich möglichst konstant über die Video-Reihe hinweg pflegen möchte. Ich verwende als BuildSystem Maven v3, die IDE meines Vertrauens ist IntelliJ IDEA (immer auf neuester Version), es wird mit Minecraft 1.13 auf dem Bukkit-Fork PaperSpigot gearbeitet und dafür nutze ich Java 11. Sobald die Tutorials sich in Richtung weiterer Technologien wie Datenbanken, Collections oder Networking bewegen, werde ich auch hierfür Versionen festlegen, bei denen ich versuche den Grad zwischen Stabilität und Modernität abzuwägen. Gerichtet ist diese Leitfaden-Reihe primär an Personen die schon ein wenig Erfahrung mit Java haben und ggf. sogar schon ein bisschen in die Bukkit-Programmierung hineingeschnuppert haben. Dennoch ist natürlich jeder eingeladen sich die Videos anzuschauen, hier ist dann ggf. nur ein wenig eigene Recherche nötig

    Pläne für die Zukunft

    Der Plan den ich hierbei verfolge sieht es vor, besonders jene Themen zu beleuchten, die häufig ausgelassen, ignoriert oder falsch interpretiert werden. Ich hege den Anspruch an mich selbst, bei den Themen die ich anspreche ein ausgewogenes Gesamtbild zu vermitteln und damit niemanden mit der "Erklärung" abzutun: "Ja, das kopierste halt so rein. Ist nicht wichtig warum.". Denn das Warum ist das eigentlich wichtigste und ist der Grundstein für jegliches eigenständiges Lernen. Obwohl mein Ziel natürlich ist, Wissen zu vermitteln und einen offenen Dialog über die verschiedenen Technologien zu starten, habe ich dennoch kein Problem damit, wenn jemand den im Video erstellten Code einfach kopiert. Ob man hieraus etwas lernen möchte, oder einfach schnell ein Problem beheben möchte ist jedem selbst überlassen und ich würde es mir niemals anmaßen jemandem vorzuschreiben, wie er meinen Content zu konsumieren hat. Deshalb stelle ich den Code nach jeder Folge auf Github und markiere die einzelnen Episoden mit Git-Tags.


    Für die Zukunft sind Themen wie beispielsweise: Maven: Extended Cut (also mehr als Basis-Informationen), Git, IntelliJ IDEA: Poweruser (also Produktivitäts-/Setup-Kniffe), Unit-Testing, Quality Assurance mit Checkstyle, Spotbugs und PMD sowie SonarQube und weitere angedacht. Aber natürlich werden auch die Basis-Themen wie Commands, Datenbanken, Networking, etc. abgedeckt und ich werde so gut es geht versuchen zusätzliche, über den Standard hinausgehende Informationen zu vermitteln.


    Hier findet ihr die Video-Reihe auf YouTube: YouTube-Playlist
    Hier ist die Organisation auf Github: https://github.com/BukkitDTRW

    Und hier sind die ersten Videos als Einbettung:





    Solltet ihr Lob, Kritik oder einfach neutrales Feedback hierzu loswerden, meldet euch gerne in den Kommentaren. Ich freue mich bereits von euch zu hören und werde vermutlich wöchentlich neue Videos hochladen!


    Ich bedanke mich ganz herzlich für das Lesen dieser Vorstellung und wünsche euch viel Spaß beim Schauen!

    Du kannst aber auch den https://... Link nutzen der geht bei den JetBrains Produkten.

    Gut möglich, dass das als Workaround funktionieren mag, ich arbeite in IntelliJ IDEA und CLion aber mit der SSH-Referenz und es funktioniert dennoch fantastisch. Ich denke es ist daher wichtig hier klar zu stellen, dass es eben nicht ausschließlich mit den HTTP(S)-Referenzen funktioniert (sollten sie denn funktionieren), sondern dass der Fehler eine andere Ursache hat, und keine schlichte Limitation der Software ist.

    #push: Während andere nun vollends im sogenannten "Sommerloch" angekommen sind, sich in den Ferien befinden oder der Urlaubsplanung frönen, wird gerade die neue Version unseres internen Networkings, des Berechtigungssystems sowie der Nutzerstruktur fertiggestellt. Ich habe mich vor einigen Monaten dazu entschlossen diese Bereiche grundlegend zu überarbeiten, da ich möchte, dass Entwickler bei uns den Umgang mit unseren APIs als konsistent, verlässlich und einfach wahrnehmen. Und auch wenn dies schon im Vorhinein teilweise der Fall war, so mussten Entwickler bei uns dennoch noch einiges über die bloße Nutzung der API bedenken. Durch unsere nun nahezu 100% abdeckende – äußerst umfangreiche und (hoffentlich) präzise – Dokumentation und die voranschreitende, konsistentere Trennung zwischen API und Implementation dürfte das Entwickeln in Zukunft wesentlich einfacher, übersichtlicher und – aus eigener Erfahrung – spaßiger ablaufen!


    Die diesmalige Grafik – die auch ein ungewöhnliches Format mit sich bringt – ist ein Screenshot des "Structure"-Views auf IntelliJ IDEA eines Markdown-Dokuments, an dem ich gerade – wenn ich nicht selbst programmiere – erstelle, um außenstehenden sowie Bewerbern unseren Workflow, unsere Einstellung sowie unsere Tools näher zu bringen. Die Titel können sich sicher noch ändern, und es kommt noch einiges dazu, als kleine Übersicht kann es aber auch jetzt schon genommen werden.




    Ich freue mich bereits darauf in einiger Zeit das fertige Dokument präsentieren zu können. Da ich hier allerdings detailliert auf die einzelnen Bereiche, unsere Arbeitsweise und unsere Ideale eingehen möchte, kann dies sicherlich noch ein wenig dauern! Bis dahin möchte ich aber schon einmal allen ein schönes Rest-Wochenende wünschen!

    Hab' den Thread jetzt nur überflogen, würde dir aber langfristig einen Pool wie zum Beispiel HikariCP nahelegen. Klar kann ich auch verstehen, dass du es "mal selbst ausprobieren" möchtest, aber für Anwendungen die Irgendwann produktiv ausgeführt werden sollen, kann ich nur davon abraten selbst etwas zu konstruieren. Man kann sehr kleine Pools nutzen (theoretisch selbst mit einer Verbindung, ich empfehle allerdings minimal zwei, damit Verbindungen erneuert werden können, ohne dass diese Operation blockt) und wird damit den kompletten Wartungsaufwand los.


    Connection-Pooling ist - ob man es nun glauben mag, oder nicht - ein recht komplexes Thema und sollte daher nach Möglichkeit in eine Lib ausgelagert werden. Pooling liefert dir zudem den Vorteil, dass du in asynchronen Umgebungen - ohne gesonderte Rücksicht nehmen zu müssen - auch einfach Verbindungen vom Pool beziehen kannst. Die Wartung findet asynchron statt und die Verbindungen werden vor der Rückgabe geprüft, ggf. erneuert und zurückgesetzt.


    Zusätzlich profitierst du von einer einfachen Config um deine Verbindungen mit bestimmten Properties initialisieren zu lassen - was du ggf. auch tun solltest. Properties erlauben dir die Session auf deinen Usecase abzustimmen, Server-Optionen nur für diese speziellen Verbindungen zu überschreiben und eleganter mit der Datenbank interagieren zu können. Ich kann verstehen, wenn du erst einmal "nur" mit MySQL irgendwie arbeiten möchtest, würde dir jedoch wirklich nahelegen diesen Schritt irgendwann zu wagen. MySQL (und im speziellen MariaDB) hat so viele Möglichkeiten um das Maximum aus deiner Applikation rauszukitzeln und dir das Leben leichter zu machen, da sollte man dies nicht einfach ignorieren.


    Ich wünsche dir viel Erfolg mit deinem Vorhaben!



    PS: Die Nutzung sähe mit einem Pool dann beispielsweise so aus:

    Java
    1. try (final Connection conn = JCLibrary.getInstance().getMysqlHandlerProxy().getConnection()) {
    2. PreparedStatement stmt = conn.prepareStatement("UPDATE players_servers SET lastseen = ?, experience = ? WHERE playerID = ? AND serverID = ?");
    3. stmt.setInt(1, (int) (System.currentTimeMillis() / 1000L));
    4. stmt.setInt(2, user.getTotalPlayTime());
    5. stmt.setString(3, user.getID().toString());
    6. stmt.setByte(4, (byte) ServerType.getThisByPort().getID());
    7. stmt.executeUpdate();
    8. } catch (SQLException ex) {
    9. JCLibrary.getInstance().getSLF4JLogger().error("Es ist ein Fehler beim Speichern des JCUsers \"{}\" aufgetreten.", user.getID(), ex);
    10. }

    Erstaunlich wie da die Interessen auseinander zu gehen scheinen. Diese Funktion war immer die Erste, die ich deaktiviert habe. Der Kommentar liefert doch - sofern er nicht im Copyright integriert ist - keinen echten Mehrwert, oder? Ich meine die Informationen kann man doch auch Problemlos aus Git ziehen und der Kommentar wirkt sich - so wie er standardmäßig ist - ja nicht einmal aufs JavaDoc oder so aus.


    Ist das ausschließlich persönliche Präferenz oder hat das bei dir/euch einen echten Workflow-Hintergrund? Ich frage einfach aus Interesse, nicht als Kritik. Soll sich jeder Kommentare generieren lassen wo er mag, aber es interessiert mich eben :)

    #push: Da hier auf Dev-Tek ja der Vorstellungsbereich gestrichen wurde und innerhalb des Themas noch auf den ehemaligen Vorstellungsbeitrag verwies, habe ich mich heute mal der Einpflegung dieses Beitrages in diesen Thread angenommen. Der Startpost ist hierdurch unglücklicherweise nochmal ein gutes Stück länger geworden, dafür gibt es nun einen einzigen Thread indem so ziemlich alles steht und von dem zentral alle Verweise ausgehen. Außerdem habe ich die Hinweise auf den tl;dr-Teil verdeutlicht, damit sich hoffentlich niemand davon abschrecken lässt. Konkret hinzugefügt zu diesem Beitrag habe ich die Abschnitte "Vorstellung", "Konzept" und "Team".


    Ich halte gerade den Bereich "Konzept" für lesenswert, da hier nun erstmal konkret auf eines unserer Konzepte (in diesem Fall den PvP-Server) eingegangen wird und auch die Motivationsgründe für einige Design-Entscheidungen genannt werden.


    Als Grafik habe ich dieses Mal einen Work-in-Progress Tabellen-Auszug zu unserer neuen Rang-Struktur ausgewählt. Wir haben innerhalb der letzten Team-Besprechung besprochen unsere Ränge einer Generalüberholung zu unterziehen (Mehr zum neuen System im Bereich "Team") und das ist das Ergebnis. Die Ränge stehen nun soweit fest, die Beschreibungen werde ich aber wohl noch weiter verbessern müssen. Sie sollen auch für Personen die mit der typischen Minecraft-Rang-Struktur nicht vertraut sind, intuitiv zu verstehen sein und müssen zwischen 260 und 300 Zeichen umfassen (das passt jetzt schon).




    Ich freue mich, hier nach wie vor auf viel Unterstützung zu treffen und wünsche allen ein schönes Wochenende!

    Das könntest du zum Beispiel über ein Platzhalter-GameProfile realisieren. GameProfiles sind essenziell ja eigentlich nur UUID + Name + Properties. Du kannst allerdings zum Beispiel auch nur die UUID setzen. Wenn das GameProfile mit dieser UUIDdann dem FakePlayer zuweist, kannst du ihn daran erkennen.

    Mit dieser Methode kannst du die Leerzeichen in einem String entfernen.

    Äh, nein. Diese Methode entfernt lediglich anführende und nachfolgende Whitespaces.


    Returns a string whose value is this string, with any leading and trailing whitespace removed.

    If this String object represents an empty character sequence, or the first and last characters of character sequence represented by this String object both have codes greater than '\u0020' (the space character), then a reference to this String object is returned.

    Otherwise, if there is no character with a code greater than '\u0020' in the string, then a String object representing an empty string is returned.

    Otherwise, let k be the index of the first character in the string whose code is greater than '\u0020', and let m be the index of the last character in the string whose code is greater than '\u0020'. A String object is returned, representing the substring of this string that begins with the character at index k and ends with the character at index m-that is, the result of this.substring(k, m + 1).

    This method may be used to trim whitespace (as defined above) from the beginning and end of a string.

    Das würde also in dem von dir genannten Fall rein gar nichts ändern. Hier würde man wohl am ehesten auf die replace-Methode zurückkommen: myString.replaceAll("\\s+","");

    Uns ist natürlich durchaus bewusst, dass kein Minecraftserver der Welt einzigartig ist.

    Ich wollte mich als du den Post veröffentlicht hast eigentlich schon dazu äußern, habe es dann allerdings aus den Augen verloren. Deshalb möchte ich dies nun nachholen:

    Ich denke das ist eine sehr pessimistische (nahezu nihilistische) Interpretation des Begriffs einzigartig. Ich denke viel mehr, dass jeder Server auf seine Art einzigartig ist. Selbst wenn sich 100% der angebotenen Spielmodi doppeln sollte, so machen sie die abweichenden Maps, die andere Interpretation des Spielmodus oder einfach der Support-Umgang einzigartig. Natürlich gibt es Server, deren Alleinstellungsmerkmal ausgeprägter ist, und Server, die eher dazu neigen anderen Servern zu gleichen. Nichtsdestotrotz halte ich es für uninspiriert und falsch, hier jegliche Einzigartigkeit von vornherein auszuschließen.


    Um meine Beweggründe für diesen Kommentar mal ein wenig zu beleuchten: Es geht mir hier tatsächlich darum, dass ich denke, mit Aussagen wie diesen Verkauft ihr euch unter Wert und findet vermutlich nicht die Bewerber die euch zustehen. In den sechs Jahren, die ich meinen Server mittlerweile betreibe, habe ich immer wieder festgestellt, dass das Wichtigste zur Gewinnung von Teammitgliedern und Spielern, die Begeisterungsfähigkeit der Verantwortlichen ist. Mit »niemand ist einzigartig « wird weder jemand begeistert, noch sagt dies irgendetwas Gutes über euch aus. Mir sagt es zum Beispiel: "Hey, da setzt jemand den Anspruch an sein Projekt aber niedrig an, wenn er Einzigartigkeit schon einmal ausschließt". Und das ist genau das Problem bei solchen Äußerungen.


    Versteht mich nicht falsch, ich verstehe den Zwang der Relativierung in der heutigen Serverszene. Sobald man seinem Projekt in einer Ausschreiben einen hohen Wert beimisst, läuft man Gefahr hierfür kritisiert zu werden (siehe: „potential“). Aber wenn nicht ihr von der Qualität, Einzigartigkeit und Arbeit schwärmt, die euer Projekt vereint, wer denn bitte dann?! Wenn ihr jemanden davon überzeugen möchtet, bei euch zu programmieren, dann müsst ihr ihm das Gefühl geben, dass seine Zeit hier sinnvoll investiert ist. Besser noch: Ihr gebt ihm das Gefühl, das er an etwas Großartigem mitwirkt, einem absoluten Novum. Und das bewirkt man eben nicht mit »niemand ist einzigartig«.