1+ "use client"
2+
3+ import React , { useState , useEffect , useRef } from "react"
4+ import { motion } from "framer-motion"
5+ import { CodeBlock } from "fumadocs-ui/components/codeblock"
6+ import { DynamicCodeBlock } from "fumadocs-ui/components/dynamic-codeblock"
7+ import Image from "next/image"
8+ import { TypeTable } from "fumadocs-ui/components/type-table"
9+ import { Book , Check , Circle , Clock , Cross , File , GitBranch , Github , LucideGitPullRequest , Plus , Share , X } from "lucide-react"
10+ import Link from "next/link"
11+ import { SiKotlin } from "react-icons/si"
12+ import { IoLibrary } from "react-icons/io5"
13+ import { BiSolidError } from "react-icons/bi"
14+ import { MdList } from "react-icons/md"
15+ import ParallaxLogo from "./parallax"
16+ import { SplitMB } from "@/app/components/Split-media-body"
17+ import TypingCodeBlock from "@/app/components/typing-code-block"
18+ import LatestVersion from "@/app/components/latest-version"
19+ import { RiGitRepositoryLine } from "react-icons/ri"
20+
21+ type CodeExample = {
22+ code : string ,
23+ title : string ,
24+ }
25+
26+ const examples : CodeExample [ ] = [
27+ {
28+ "title" : "Spawn NPC" ,
29+ "code" : "location.spawnNPC(\n name = \"FakePlayer\",\n skin = Skin(texture, signature)\n).onClick {\n sender.sendMessage(clickType.name)\n}.setScale(10.0)"
30+ } ,
31+ {
32+ "title" : "Nick Player" ,
33+ "code" : "player.setName(newName)\nplayer.setSkin(Skin(texture, signature))"
34+ } ,
35+ {
36+ "title" : "Sidebar/Scoreboard" ,
37+ "code" : "sidebar(\"Survival\") {\n addEmptyLine()\n addUpdatablePlayerLine { \"${ChatColor.AQUA}${it.name}\" }\n addUpdatablePlayerTimerLine(20) { \"${ChatColor.RED}Kills : ${ChatColor.GRAY}${it.getStatistic(Statistic.PLAYER_KILLS)}\" }\n addUpdatablePlayerTimerLine(20) { \"${ChatColor.DARK_PURPLE}Deaths : ${ChatColor.GRAY}${it.getStatistic(Statistic.DEATHS)}\" }\n addUpdatablePlayerTimerLine(20) { \"${ChatColor.DARK_AQUA}Ping : ${ChatColor.GRAY}${it.ping}\" }\n addEmptyLine()\n addUpdatablePlayerTimerLine(20) { \"${ChatColor.AQUA}Rank : ${ChatColor.GRAY}OWNER\" }\n addUpdatableTimerLine(20) { \"${ChatColor.AQUA}Online : ${ChatColor.GRAY}${Bukkit.getOnlinePlayers().size}\" }\n addEmptyLine()\n}"
38+ } ,
39+ {
40+ "title" : "Scheduler" ,
41+ "code" : "delay(20) {\n Bukkit.broadcastMessage(\"Hello World!!\")\n}"
42+ }
43+ ]
44+
45+
46+ export default function LynxPage ( ) {
47+
48+ const [ codeExample , setCodeExample ] = useState < CodeExample | null > ( null )
49+
50+ useEffect ( ( ) => {
51+ setCodeExample ( examples [ Math . floor ( Math . random ( ) * examples . length ) ] )
52+ } , [ ] )
53+
54+ return (
55+ < main className = "p-4 pt-0 flex min-h-screen relative flex-col bg-neutral-900 text-center overflow-hidden" >
56+ < motion . header initial = { { opacity : 0 } } animate = { { opacity : 1 } } transition = { { duration : 1 } } className = "container outline-2 rounded-b-xl outline-neutral-700 bg-gradient-to-r from-blue-900 to-violet-700 mx-auto relative overflow-hidden h-100 w-full py-4 items-center justify-center flex flex-col" >
57+ < div className = "z-0 absolute inset-0 w-full opacity-50 skew-5 scale-150 bg-dotted-black" > </ div >
58+ < div className = "z-0 absolute inset-0 w-full bg-gradient-to-r opacity-75 from-blue-500 via-transparent to-violet-500" > </ div >
59+ < div className = "z-1 w-full h-full inset-0 absolute flex flex-col items-center justify-center " >
60+ < Amazing delay = { 0 } />
61+ </ div >
62+ </ motion . header >
63+
64+ < motion . div
65+ className = "rounded-xl p-0 h-auto max-w-4xl mx-auto shadow-md text-left"
66+ initial = { { translateY : - 75 , opacity : 0 } }
67+ animate = { { translateY : - 75 , opacity : 1 } }
68+ transition = { { delay : 1 , duration : 1 , ease : "anticipate" } }
69+ >
70+ { codeExample && < h2 className = "text-xl bg-neutral-800/75 border-2 border-b-0 border-neutral-800/25 backdrop-blur-3xl mb-0 rounded-none rounded-t-md px-4 py-1 w-fit" > { codeExample ?. title } </ h2 > }
71+ { codeExample && < TypingCodeBlock
72+ text = { codeExample ?. code || "" }
73+ onComplete = { ( ) => { } }
74+ speed = { 5 }
75+ className = { "rounded-tl-none rounded-b-2xl border-neutral-800/25" }
76+ /> }
77+ </ motion . div >
78+
79+ < section className = "mt-0 w-full relative container flex flex-row items-center justify-center mx-auto gap-4 md:gap-8" >
80+ < Link href = { "/docs/lynx/latest" } className = "hover:underline flex flex-row gap-2 text-xl items-center" > < Book /> Documentation</ Link >
81+ < Link href = { "https://github.com/UndefinedCreations/Lynx" } className = "hover:underline flex flex-row gap-2 text-xl items-center" > < Github /> Github</ Link >
82+ < Link href = { "https://repo.undefinedcreations.com/#/releases/com/undefined/lynx" } className = "hover:underline flex flex-row gap-2 text-xl items-center" > < RiGitRepositoryLine /> Repository</ Link >
83+ </ section >
84+
85+ < section className = "mt-6 w-full relative container flex flex-row items-center justify-center mx-auto gap-2" >
86+ < LatestVersion groupId = "com.undefined" artifactId = "lynx" />
87+ < LatestVersion groupId = "com.undefined" artifactId = "lynx" type = "version" />
88+ </ section >
89+
90+
91+ < Divider />
92+ < section className = "mb-32 h-fit" >
93+ < SplitMB
94+ media = { { type : "image" , src :"https://cdn.undefinedcreations.com/undefinedcreations/website/group-photo.png" } }
95+ title = "Spawn NPCs"
96+ description = "You can spawn player specific NPCs. You can use this to create mirrored NPC skins, make the npc look at the player, or simply hide unimportant ones from other players."
97+ direction = "right"
98+ // link={{label: "See Example", href: "/docs/lynx/latest/modules/display/examples/custom-gui"}}
99+ />
100+ </ section >
101+ < section className = "mb-32 h-fit" >
102+ < SplitMB
103+ media = { { type : "image" , src :"https://cdn.undefinedcreations.com/undefinedcreations/website/idk_what_this_is.gif" } }
104+ title = "Edit players names"
105+ description = "You can even nick players with protocols to make client specific changes. Imagine giving different names to teammates in a minigame or a friend prefix."
106+ direction = "left"
107+ classNames = { { media : "object-center scale-125" } }
108+ // link={{label: "See Example", href: "/docs/lynx/latest/modules/display/examples/custom-gui"}}
109+ />
110+ </ section >
111+ < section className = "mb-32 h-fit" >
112+ < SplitMB
113+ media = { { type : "image" , src :"https://cdn.undefinedcreations.com/undefinedcreations/website/sidebar.png" } }
114+ title = "Client-side sidebar"
115+ description = "Easy to create with no flickering and a scoreboard per player Due to its smart client-side implementation this sidebar will only be rendered on the client as the server only handles delivering its content."
116+ direction = "right"
117+ classNames = { { media : "object-right scale-100" } }
118+ />
119+ </ section >
120+ < section className = "mb-32" >
121+ < SplitMB
122+ media = { { type : "image" , src :"https://cdn.undefinedcreations.com/lynx/display/cusotm-gui-example.gif" } }
123+ title = "Easily create complex & performant features"
124+ description = "In this example Lynx leverages NMS and Packet Display Entities to create, player-specific GUIs without using Spigot's performance-heavy API, saving server resources."
125+ direction = "left"
126+ classNames = { { media : "object-contain max-w-fit rounded-md mx-auto flex items-center justify-center" } }
127+ link = { { label : "See Example" , href : "/docs/lynx/latest/modules/display/examples/custom-gui" } }
128+ />
129+ </ section >
130+
131+ < Divider />
132+
133+
134+ </ main >
135+ )
136+ }
137+
138+ function Divider ( ) {
139+ return (
140+ < div className = "container mx-auto w-full my-24 h-0.5 bg-gradient-to-r to-transparent via-neutral-700 from-transparent" />
141+ )
142+ }
143+
144+ // Title animation
145+ function Amazing ( { delay } : { delay : number } ) {
146+ return (
147+ < React . Fragment >
148+ < motion . div
149+ initial = { { scale : 2 , opacity : 0 , letterSpacing : "64px" } }
150+ animate = { { scale : 1 , opacity : 1 , letterSpacing : [ "4px" ] } }
151+ transition = { { duration : 1 , delay, ease : "anticipate" } }
152+ className = "font-black text-shadow-title text-white text-6xl md:7xl lg:text-8xl xl:text-9xl"
153+ >
154+ < p className = "flex flex-row items-center" > < Image src = { "/logos/lynx.svg" } className = "scale-100 size-20 lg:size-48" quality = { 100 } width = { 256 } height = { 256 } alt = "stellar-logo" /> Lynx</ p >
155+ </ motion . div >
156+ < motion . div
157+ initial = { { scale : 2 , opacity : 0 , } }
158+ animate = { { scale : 1 , opacity : 1 , } }
159+ transition = { { duration : 1 , delay : 0.5 , ease : "anticipate" } }
160+ className = "font-black text-white text-9xl"
161+ >
162+ < p className = "text-white mb-16 px-4 py-1 rounded-lg text-lg md:text-xl lg:text-2xl font-semibold text-shadow-title" > General Purpose API for future servers</ p >
163+ </ motion . div >
164+ </ React . Fragment >
165+ )
166+ }
0 commit comments