Coder Social home page Coder Social logo

adepierre / botcraft Goto Github PK

View Code? Open in Web Editor NEW
376.0 376.0 37.0 75 MB

Botcraft is a cross-platform C++ library to create bots that connect and interact with Minecraft servers with (optional) integrated OpenGL renderer

License: GNU General Public License v3.0

CMake 3.55% C++ 93.63% Shell 0.02% JavaScript 0.46% CSS 2.20% HTML 0.14%
bot client cpp minecraft opengl

botcraft's People

Contributors

abasgames avatar adepierre avatar constantins2001 avatar gaspardculis avatar jackobisreal avatar maxsupermanhd avatar nikisalli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

botcraft's Issues

killaura example?

For mob farms will be great to have simplest hostile mobs killaura example for easy deploy

ProtocolCraft::Slot writes NBT data incorrectly (1.16.3)

Example:

auto inv = inventory_manager->GetPlayerInventory();
auto slots = inv->GetSlots();
for (int i = 0; i < slots.size(); i++)
{
    auto items = AssetsManager::getInstance().Items();
    auto slot = slots[i];
    auto item = items[slot.GetItemID()];

    if (item->GetName() != "minecraft:air")
    {
        printf("SLOT NBT:\n");
        printf("%s\n", slot.GetNBT().SerializeImpl().serialize(true).c_str());
        printf("Slot: %i, ID: %i, Name: %s, Count: %i\n", i, slot.GetItemID(), item->GetName().c_str(), slot.GetItemCount());
        std::shared_ptr<ProtocolCraft::ClickWindow> Packet(new ClickWindow);
        Packet->SetWindowId(0);
        Packet->SetSlot(i);
        Packet->SetButton(1);
        Packet->SetActionNumber(1);
        Packet->SetMode(4);
        Packet->SetClickedItem(slot);
        network_manager->Send(Packet);

        break;
    }
}

(sorry for the messy code)

This code will drop the first item slot in the client. It works fine for any item without NBT data attached to it.

If the item has attached nbt data (ex. flint & steel, enchanted armor, etc.) the server will disconnect you with this:

Internal Exception: io.netty.handler.codec.DecoderException: io.netty.handler.codec.EncoderException: java.io.IOException: Root tag must be a named compound tag

Also I love your library had a lot of fun making fun bots with your API =]

After joining server getting runtime error

terminate called after throwing an instance of 'std::runtime_error'
  what():  Not enough input in ReadString

Thread 2 "2_ChatCommandEx" received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffff6da9700 (LWP 239202)]
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff78a2859 in __GI_abort () at abort.c:79
#2  0x00007ffff7b28951 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff7b3447c in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff7b344e7 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff7b34799 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff7e54e53 in ProtocolCraft::ReadString[abi:cxx11](__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > >&, unsigned long&) (iter=8 '\b', 
    length=@0x7ffff6da8d28: 2476) at /home/max/p/Botcraft/protocolCraft/src/BinaryReadWrite.cpp:109
#7  0x00007ffff7ec8766 in ProtocolCraft::Recipe::ReadImpl (this=0x7fffe8013078, iter=8 '\b', length=@0x7ffff6da8d28: 2476) at /home/max/p/Botcraft/protocolCraft/include/protocolCraft/Types/Recipes/Recipe.hpp:54
#8  0x00007ffff7ebe0b3 in ProtocolCraft::NetworkType::Read (length=@0x7ffff6da8d28: 2476, iter=8 '\b', this=<optimized out>) at /home/max/p/Botcraft/protocolCraft/include/protocolCraft/NetworkType.hpp:16
#9  ProtocolCraft::ClientboundUpdateRecipesPacket::ReadImpl (this=0x7fffe80227a0, iter=8 '\b', length=@0x7ffff6da8d28: 2476)
    at /home/max/p/Botcraft/protocolCraft/include/protocolCraft/Messages/Play/Clientbound/ClientboundUpdateRecipesPacket.hpp:54
#10 0x00007ffff7eb9201 in ProtocolCraft::NetworkType::Read (length=@0x7ffff6da8d28: 2476, iter=8 '\b', this=<optimized out>) at /home/max/p/Botcraft/protocolCraft/include/protocolCraft/NetworkType.hpp:16
#11 Botcraft::NetworkManager::ProcessPacket (this=0x555561b0dd20, packet=...) at /home/max/p/Botcraft/botcraft/src/Network/NetworkManager.cpp:222
#12 0x00007ffff7eb946b in Botcraft::NetworkManager::WaitForNewPackets (this=0x555561b0dd20) at /home/max/p/Botcraft/botcraft/src/Network/NetworkManager.cpp:195
#13 0x00007ffff7b60d84 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#14 0x00007ffff7c74609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#15 0x00007ffff799f293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Timeout from server after 15 seconds

I am trying to run example 2 on a local vanilla server and it does not work. It seems there is some heavy enough task to keep 1 core occupied for more that 15 seconds after logging on. Testing on Apple MacBook 13 inch Core 2 Duo (running server in background too) (upgraded to 16GB of ram so no issues here). Tried to interrupt with gdb and look what is causing trouble but only facing timers.
Any idea on this?
pic

Connecting to LAN games without Mojang Authentication

Offline servers allow you to connect with any username without authenticating with Mojang. This functionality could be implemented into botcraft as currently it makes an authentication attempt even if the password is blank "", and whilst the server is in offline-mode.

Cmake glfw3 error

Determining if the pthread_create exist failed with the following output:
Change Dir: /home/abas/Botcraft/build/3rdparty/glfw/CMakeFiles/CMakeTmp

Run Build Command:"/usr/bin/make" "cmTC_4e528/fast"
/usr/bin/make -f CMakeFiles/cmTC_4e528.dir/build.make CMakeFiles/cmTC_4e528.dir/build
make[1]: Entering directory '/home/abas/Botcraft/build/3rdparty/glfw/CMakeFiles/CMakeTmp'
Building C object CMakeFiles/cmTC_4e528.dir/CheckSymbolExists.c.o
/usr/bin/cc -o CMakeFiles/cmTC_4e528.dir/CheckSymbolExists.c.o -c /home/abas/Botcraft/build/3rdparty/glfw/CMakeFiles/CMakeTmp/CheckSymbolExists.c
Linking C executable cmTC_4e528
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_4e528.dir/link.txt --verbose=1
/usr/bin/cc -rdynamic CMakeFiles/cmTC_4e528.dir/CheckSymbolExists.c.o -o cmTC_4e528
/usr/bin/ld: CMakeFiles/cmTC_4e528.dir/CheckSymbolExists.c.o: in function main': CheckSymbolExists.c:(.text+0x1b): undefined reference to pthread_create'
collect2: error: ld returned 1 exit status
make[1]: *** [CMakeFiles/cmTC_4e528.dir/build.make:87: cmTC_4e528] Error 1
make[1]: Leaving directory '/home/abas/Botcraft/build/3rdparty/glfw/CMakeFiles/CMakeTmp'
make: *** [Makefile:121: cmTC_4e528/fast] Error 2

File /home/abas/Botcraft/build/3rdparty/glfw/CMakeFiles/CMakeTmp/CheckSymbolExists.c:
/* */
#include <pthread.h>

int main(int argc, char** argv)
{
(void)argv;
#ifndef pthread_create
return ((int*)(&pthread_create))[argc];
#else
(void)argc;
return 0;
#endif
}

Determining if the function pthread_create exists in the pthreads failed with the following output:
Change Dir: /home/abas/Botcraft/build/3rdparty/glfw/CMakeFiles/CMakeTmp

Run Build Command:"/usr/bin/make" "cmTC_1179c/fast"
/usr/bin/make -f CMakeFiles/cmTC_1179c.dir/build.make CMakeFiles/cmTC_1179c.dir/build
make[1]: Entering directory '/home/abas/Botcraft/build/3rdparty/glfw/CMakeFiles/CMakeTmp'
Building C object CMakeFiles/cmTC_1179c.dir/CheckFunctionExists.c.o
/usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create -o CMakeFiles/cmTC_1179c.dir/CheckFunctionExists.c.o -c /usr/share/cmake-3.13/Modules/CheckFunctionExists.c
Linking C executable cmTC_1179c
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_1179c.dir/link.txt --verbose=1
/usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create -rdynamic CMakeFiles/cmTC_1179c.dir/CheckFunctionExists.c.o -o cmTC_1179c -lpthreads
/usr/bin/ld: cannot find -lpthreads
collect2: error: ld returned 1 exit status
make[1]: *** [CMakeFiles/cmTC_1179c.dir/build.make:87: cmTC_1179c] Error 1
make[1]: Leaving directory '/home/abas/Botcraft/build/3rdparty/glfw/CMakeFiles/CMakeTmp'
make: *** [Makefile:121: cmTC_1179c/fast] Error 2

Silently not connecting to server

Sometimes it does, sometimes it does not, not reliable, server is ok and I'm passing authorization.
Some state of demo at the moment of not loading world:
1
2
3
Just nothing happens...

Where to find system chat messages?

I was joining on few servers out in the wild and there is some messages that are not quiet "chat", where I can find hook to them?

Btw, is there a discord server or something for real time / more comfortable chat?

"Not enough input in ReadString" at all Examples files

I missclicked a bunch before writing it down lol.

Anyway, I'm getting this error when trying to execute one of those examples:

Usage: 0_HelloWorld [address](127.0.0.1:25565) [login](BCHelloWorld) [password]()
Warning, your version of botcraft hasn't been compiled with GUI enabled, setting use_renderer_ to false
Loading blocks from file...
Done!
Loading biomes from file...
Done!
Loading items from file...
Done!
Clearing cache from memory...
Done!
Starting connection process
Trying to connect to 127.0.0.1:25565
Connected to server.
terminate called after throwing an instance of 'std::runtime_error'
  what():  Not enough input in ReadString

I'm still learning C++, so I don't get this stuff that well.

make all Error

I ran into an error while following the build instructions, any help would be appreciated. :)

gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)

Error occured while running make all:
https://pastebin.com/EmRTBngL

No entity information

Would be cool to have entity manager parse entity data packets in order to get what entities are, want to make a simple player detector that will log players and chat on the server.

Lua Scripting API

Lua is a popular embedded scripting language.

It would be very awesome if lua scripting was provided in botcraft. It would make the bot creation process a lot easier, no need to compile or anything of that sort.

I recreated the hello world bot example in lua:

local client = InterfaceClient.new(true, false)
client:SetAutoRespawn(true)
client:Connect(ip, port, login, password)
wait(5)
client:Say("Hi there!")
wait(5)
client:Disconnect()

I put together a quick example of how this could work using the sol2 library:

sol::state lua;
lua.open_libraries(
    sol::lib::base, 
    sol::lib::bit32, 
    sol::lib::coroutine, 
    sol::lib::io, 
    sol::lib::math, 
    sol::lib::os, 
    sol::lib::package, 
    sol::lib::string, 
    sol::lib::table, 
    sol::lib::utf8);


sol::usertype<Botcraft::InterfaceClient> InterfaceClient_bind = lua.new_usertype<Botcraft::InterfaceClient>("InterfaceClient",
    sol::constructors<Botcraft::InterfaceClient(const bool, const bool)>());

lua["wait"] = [](long seconds) -> bool 
{
    std::this_thread::sleep_for(std::chrono::seconds(seconds));
    return true;
};

InterfaceClient_bind["Connect"] = &Botcraft::InterfaceClient::Connect;
InterfaceClient_bind["Disconnect"] = &Botcraft::InterfaceClient::Disconnect;
InterfaceClient_bind["Say"] = &Botcraft::InterfaceClient::Say;
InterfaceClient_bind["Respawn"] = &Botcraft::InterfaceClient::Respawn;
InterfaceClient_bind["SetAutoRespawn"] = &Botcraft::InterfaceClient::SetAutoRespawn;

I enjoy the thought of people being able to share their minecraft bots with a short lua script.

How to Install?

Sorry if this is a stupid question but I tried opening this project in visual studio and doing the cmake thing which I think just builds the .lib files. I then referenced the .lib files and the header files in a new visual studio project. But I just keep on getting thrown errors saying that a bunch of new source files are missing and it cant open the include files I did list. Any help would be appreciated.

Connecting to a DNS configured server

I'm attempting to connect to a server with a DNS (Hypixel.net, for example) but receive the error:
Error when connecting to server. Error code :asio.system:125

One workaround I found was to get the ip from a ping request, but this only worked for servers without dns encryption.

How to raycast to an entity?

I found World::Raycast but it works only with blocks, is it possible to make an entity raycast that will work similar to this?

Undefined reference?

Hey, sorry I know this is probably a really stupid question but everytime I try to link I get undefined reference to Botcraft::BaseClient::Handle(ProtocolCraft::ClientboundContainerAckPacket&)`. I'm really sorry I know there's probably a simple solution that I'm missing out on but everytime I run make i encounter this error.

Right now I have an empty main file but my files look something like this:

#include <iostream>
#include "KitteaMinecraftClient.h"

using namespace Botcraft;
using namespace ProtocolCraft;

KitteaMinecraftClient::KitteaMinecraftClient(const bool use_renderer_, const bool is_afk_) : InterfaceClient(use_renderer_, is_afk_) {

}

KitteaMinecraftClient::~KitteaMinecraftClient() {

}

void KitteaMinecraftClient::Handle(ClientboundChatPacket &msg) {
    Botcraft::BaseClient::Handle(msg);
}
#pragma once
#include <botcraft/Game/InterfaceClient.hpp>

class KitteaMinecraftClient: public Botcraft::InterfaceClient {
public:
    KitteaMinecraftClient(const bool use_renderer_, const bool is_afk_);
    ~KitteaMinecraftClient();

protected:
    virtual void Handle(ProtocolCraft::ClientboundChatPacket &msg) override;
};
cmake_minimum_required(VERSION 3.16)
project(kittea_bot)

set(CMAKE_CXX_STANDARD 20)
add_executable(kittea-bot src/main.cpp src/KitteaMinecraftClient.cpp)
target_link_directories(kittea-bot PUBLIC /usr/local/bin)

target_link_libraries(kittea-bot dpp)
target_link_libraries(kittea-bot botcraft)
target_include_directories(kittea-bot PRIVATE
        include
)

set_target_properties(kittea-bot PROPERTIES
        CXX_STANDARD 20
        CXX_STANDARD_REQUIRED ON
)

Unable to build project

I ran into an error while following the build instructions, any help would be appreciated. :)

OS: Ubuntu 20.04.1 LTS 64 bit

Used the following CMake variables:
GAME_VERSION=1.16.3
BOTCRAFT_INSTALL_ASSETS=ON
BOTCRAFT_BUILD_EXAMPLES=ON
BOTCRAFT_COMPRESSION=ON
BOTCRAFT_ENCRYPTION=ON

Error occured while running make all:
https://pastebin.com/XerM1hmF

protocol only

Is there a set of the code with only the protocol, for those who want to make seperate renderers?

Add example on how to use Botcraft to PLAY minecraft

I want to use Botcraft to play minecraft normally, like with a mouse and keyboard to interact with the world, how do I do that? all I see in examples is code that is being used to bot minecraft.

could you post code that shows how to do that?

Compilation error

/home/kenguru/Botcraft/botcraft/src/Network/Authentifier.cpp:692:31: error: ‘sleep_for’ is not a member of ‘std::this_thread’ 692 | std::this_thread::sleep_for(std::chrono::seconds(pool_interval + 1));
may be is necessary to add '#include ' and '-D_GLIBCXX_USE_NANOSLEEP'?

Confusing CMake error.

Hey there!

Having a fun issue when compiling the program.

I followed your example here:
#45

When making the program, I encountered the error:

CMake Error at Botcraft/botcraft/CMakeLists.txt:127 (add_library):
  Target "botcraft" links to target "ZLIB::ZLIB" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

Full log:
https://hastebin.com/yujutikefi.yaml

Thanks!

Microsoft authorization fail

Today I tried to use my Microsoft account and was greeted with 400 Bad request with contents {"error":"IllegalArgumentException","errorMessage":"Access Token can not be null or empty."}, however all tokens were in place and printing before executing request showed them perfectly fine.

Maybe fields are named wrong or it is missing one of them? How can I debug it further or find docs on this @adepierre?

Unable to compile - Zlib

Hello,

I'm unable to compile your project (tried Windows and WSL).
It seems like ZLIB is missing / improperly configured in the CMake file.

image

Many thanks for your assistance!

wrong position used in map, dirty-fixes

It looks like the Chunk::block_entities_data map has the world position as a key (example, I have a world where at position 9, 68, -11 there is a sign), but when I step through the function calls the Chunk::GetBlockEntityData gets the position within the chunk (9, 68, 5), and therefore it doesn't find the sign in the entities data map. I have dirty-fixed it by changing lines 591 and 603 in Botcraft\botcraft\src\Game\World\World.cpp to not use your pos.x % chunk_width... snake but instead just handing down the original positions. I am a bit afraid of adding a pull request because I wasn't able to find the code filling up that map in the first place so I have no idea if my "fixes" break anything, can you tell me where that code is? I have also changed another thing in the InventoryManager that fixed the actual issue I had without being able to verify that I haven't accidentally broke something, do you have any tests or something like that I could use?

client crashes

Warning, your version of botcraft hasn't been compiled with GUI enabled, setting use_renderer_ to false
Loading blocks from file...
Error reading info block file at ../Assets/1.17.1/custom/Blocks_info.json
[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal
Done!
Loading biomes from file...
Error reading biome file at ../Assets/1.17.1/custom/Biomes.json
[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal
Done!
Loading items from file...
Error reading item file at ../Assets/1.17.1/custom/Items.json
[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal
Done!
Clearing cache from memory...
Done!
Starting connection process using login and password
Trying to connect to mc.vega-craft.ru:25565
Connected to server.
fish: Job 1, 'bin/1_UserControlledExample --a…' terminated by signal SIGSEGV (Address boundary error)

Can't run any example, fails with similar output

Botcraft doesn't seem to connect in anyway - status code 403

So I have everything built and compiled, but the code from the examples don't connect to any server at all.
I'm running both the examples binaries and the server at an Ubuntu 18.04.5 LTS. both are using protocol 498 (1.14.4)

1. If I don't put arguments, it connects but automatically disconnects after.

a
Console:

root@dayos:/usr/local/bin# ./2_ChatCommandExample
No command arguments. Using default options.
Usage: 2_ChatCommandExample [address](127.0.0.1:25565) [login](BCChatCommand) [password]()
Loading blocks from file...
Done!
Loading biomes from file...
Done!
Loading items from file...
Done!
Clearing cache from memory...
Done!
Known commands:
    Pathfinding to position:
        name goto x y z
    Stop current pathfinding:
        name stop
    Check perimeter for spawnable blocks and save spawnable positions to file:
        name check_perimeter [x y z (default = player position)] radius (default = 128) [check_lighting (default = true)]
    Disconnect:
        name die
    Place a block:
        name place_block minecraft:item x y z
    Interact (right click) a block:
        name interact x y z
Starting connection process
Trying to connect to 127.0.0.1:25565
Connected to server.
terminate called after throwing an instance of 'std::runtime_error'
  what():  Not enough input in ReadString
Aborted (core dumped)

2. If I put the default options as arguments at those same files (but changing the password, as the lack of it returns the first error), it doesn't connect at all

root@dayos:/usr/local/bin# ./2_ChatCommandExample 127.0.0.1:25565 BCChatCommand password
Loading blocks from file...
Done!
Loading biomes from file...
Done!
Loading items from file...
Done!
Clearing cache from memory...
Done!
Known commands:
    Pathfinding to position:
        name goto x y z
    Stop current pathfinding:
        name stop
    Check perimeter for spawnable blocks and save spawnable positions to file:
        name check_perimeter [x y z (default = player position)] radius (default = 128) [check_lighting (default = true)]
    Disconnect:
        name die
    Place a block:
        name place_block minecraft:item x y z
    Interact (right click) a block:
        name interact x y z
Starting connection process
Trying to connect to 127.0.0.1:25565
Connected to server.
Authentication response returned with status code 403

3. 1_UserControlledExample seems to work, but it doesn't connect either

Console:

root@dayos:/usr/local/bin# ./1_UserControlledExample 0 127.0.0.1:25565 BCUserControl password
Warning, your version of botcraft hasn't been compiled with GUI enabled, setting use_renderer_ to false
Loading blocks from file...
Done!
Loading biomes from file...
Done!
Loading items from file...
Done!
Clearing cache from memory...
Done!
Client created!
Creating world...
Done!

I'm assuming that it might be because I'm not using GUI, but I found this relevant anyway.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.